Commit 1595335c authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat: introduce ManageDrippie script (#10708)

Adds a new script called ManageDrippie that, surprise surprise,
manages Drippie tasks. Replacement for the old stuff that existed
inside of DeployPeriphery because the old stuff was too janky and
relied on making a bunch of smart contract modifications every
time you wanted to add a new drip. Drips can now be added easily
by modifying a JSON configuration file.
parent 2919e064
{
"drippie": "0xd6F935Bd272BEE05bD64096D82970482EF16D64b",
"gelato": "0x859E31b3848Ec384012EECc72C5c49821008296C",
"note": "Object attributes below are prefixed with numbers because of how foundry parses JSON into structs in alphabetical order",
"drips": [
{
"00__name": "FaucetBridgedDrip_opmainnet_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_base_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0xfd0Bf71F60660E2f608ed56e1659C450eB113120",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_zora_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0x5376f1D543dcbB5BD416c56C189e4cB7399fCcCB",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_pgn_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0xFaE6abCAF30D23e233AC7faF747F2fC3a5a6Bfa3",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_orderly_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0x1Af0494040d6904A9F3EE21921de4b359C736333",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_mode_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0xbC5C679879B2965296756CD959C3C739769995E2",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_lyra_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
},
{
"00__name": "FaucetBridgedDrip_lisk_V1",
"01__dripcheck": "CheckTrue",
"02__checkparams": {},
"03__recipient": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5",
"04__value": 34000000000000000000,
"05__interval": 86400,
"06__data": "0x000000000000000000000000f21d42203af9af1c86e1e8ac501b41f5bc004a0a0000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"
}
]
}
{
"drippie": "0xd6F935Bd272BEE05bD64096D82970482EF16D64b",
"gelato": "0x859E31b3848Ec384012EECc72C5c49821008296C",
"note": "Object attributes below are prefixed with numbers because of how foundry parses JSON into structs in alphabetical order",
"drips": [
{
"00__name": "FaucetDrip_V1",
"01__dripcheck": "CheckBalanceLow",
"02__checkparams": {
"01__target": "0xF21d42203AF9af1C86E1e8ac501B41f5bc004A0a",
"02__threshold": 100000000000000000000
},
"03__recipient": "0xF21d42203AF9af1C86E1e8ac501B41f5bc004A0a",
"04__value": 20000000000000000000,
"05__interval": 3600,
"06__data": ""
},
{
"00__name": "FaucetDrip_V2",
"01__dripcheck": "CheckBalanceLow",
"02__checkparams": {
"01__target": "0xF21d42203AF9af1C86E1e8ac501B41f5bc004A0a",
"02__threshold": 20000000000000000000
},
"03__recipient": "0xF21d42203AF9af1C86E1e8ac501B41f5bc004A0a",
"04__value": 500000000000000000000,
"05__interval": 604800,
"06__data": ""
},
{
"00__name": "FaucetAdminDrip_V1",
"01__dripcheck": "CheckBalanceLow",
"02__checkparams": {
"01__target": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6",
"02__threshold": 100000000000000000
},
"03__recipient": "0x212E789D4523D4BAF464f8Fb2A9B9dff2B36e5A6",
"04__value": 1000000000000000000,
"05__interval": 86400,
"06__data": ""
},
{
"00__name": "FaucetGelatoDrip_V1",
"01__dripcheck": "CheckGelatoLow",
"02__checkparams": {
"00__treasury": "0x7506C12a824d73D9b08564d5Afc22c949434755e",
"01__threshold": 100000000000000000,
"02__recipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF"
},
"03__recipient": "0x7506C12a824d73D9b08564d5Afc22c949434755e",
"04__value": 1000000000000000000,
"05__interval": 86400,
"06__data": "0x0000000000000000000000000e9b4649eb0760a4f01646636e032d68cfde58ff"
}
]
}
{
"drippie": "0xd6F935Bd272BEE05bD64096D82970482EF16D64b",
"gelato": "0x2A6C106ae13B558BB9E2Ec64Bd2f1f7BEFF3A5E0",
"note": "Object attributes below are prefixed with numbers because of how foundry parses JSON into structs in alphabetical order",
"drips": [
{
"00__name": "OperationsSequencerDrip_V1",
"01__dripcheck": "CheckBalanceLow",
"02__checkparams": {
"01__target": "0x8F23BB38F531600e5d8FDDaAEC41F13FaB46E98c",
"02__threshold": 100000000000000000000
},
"03__recipient": "0x8F23BB38F531600e5d8FDDaAEC41F13FaB46E98c",
"04__value": 20000000000000000000,
"05__interval": 86400,
"06__data": ""
},
{
"00__name": "OperationsProposerDrip_V1",
"01__dripcheck": "CheckBalanceLow",
"02__checkparams": {
"01__target": "0x49277EE36A024120Ee218127354c4a3591dc90A9",
"02__threshold": 100000000000000000000
},
"03__recipient": "0x49277EE36A024120Ee218127354c4a3591dc90A9",
"04__value": 20000000000000000000,
"05__interval": 86400,
"06__data": ""
},
{
"00__name": "OperationsGelatoDrip_V1",
"01__dripcheck": "CheckGelatoLow",
"02__checkparams": {
"00__treasury": "0x7506C12a824d73D9b08564d5Afc22c949434755e",
"01__threshold": 1000000000000000000,
"02__recipient": "0x03C256F7Ae7518D0fe489F257ab4b928D37CBE16"
},
"03__recipient": "0x7506C12a824d73D9b08564d5Afc22c949434755e",
"04__value": 1000000000000000000,
"05__interval": 86400,
"06__data": "0x00000000000000000000000003c256f7ae7518d0fe489f257ab4b928d37cbe16"
},
{
"00__name": "OperationsSecretsDrip_V1",
"01__dripcheck": "CheckSecrets",
"02__checkparams": {
"00__delay": 43200,
"01__secretHashMustExist": "0x565fa8c7daa859353b5b328b97b12c7d66c5832b2a24d4e0f739a65ad266a46f",
"02__secretHashMustNotExist": "0xbc362b01d69a85dff1793803dde67df1f338f37a36fdc73dddf27283d215e614"
},
"03__recipient": "0x03C256F7Ae7518D0fe489F257ab4b928D37CBE16",
"04__value": 1000000000000000000,
"05__interval": 3600,
"06__data": ""
}
]
}
{
"create2DeploymentSalt": "0.0.2",
"create2DeploymentSalt": "0.0.3",
"gelatoAutomateContract": "0x2A6C106ae13B558BB9E2Ec64Bd2f1f7BEFF3A5E0",
"gelatoTreasuryContract": "0x7506C12a824d73D9b08564d5Afc22c949434755e",
"operationsDrippieOwner": "0x03C256F7Ae7518D0fe489F257ab4b928D37CBE16",
"operationsSequencerDripV1Target": "0x8F23BB38F531600e5d8FDDaAEC41F13FaB46E98c",
"operationsSequencerDripV1Value": 20000000000000000000,
"operationsSequencerDripV1Interval": 86400,
"operationsSequencerDripV1Threshold": 100000000000000000000,
"operationsGelatoDripV1Recipient": "0x03C256F7Ae7518D0fe489F257ab4b928D37CBE16",
"operationsGelatoDripV1Value": 1000000000000000000,
"operationsGelatoDripV1Interval": 86400,
"operationsGelatoDripV1Threshold": 500000000000000000,
"operationsSecretsDripV1Delay": 43200,
"operationsSecretsDripV1MustExist": "0x565fa8c7daa859353b5b328b97b12c7d66c5832b2a24d4e0f739a65ad266a46f",
"operationsSecretsDripV1MustNotExist": "0xbc362b01d69a85dff1793803dde67df1f338f37a36fdc73dddf27283d215e614",
"operationsSecretsDripV1Target": "0x03C256F7Ae7518D0fe489F257ab4b928D37CBE16",
"operationsSecretsDripV1Value": 1000000000000000000,
"operationsSecretsDripV1Interval": 3600,
"faucetDrippieOwner": "0x10ab157483dd308f8B38aCF2ad823dfD255F56b5",
"faucetDripV1Value": 20000000000000000000,
"faucetDripV1Interval": 3600,
"faucetDripV1Threshold": 100000000000000000000,
"faucetDripV2Value": 500000000000000000000,
"faucetDripV2Interval": 604800,
"faucetDripV2Threshold": 20000000000000000000,
"faucetAdminDripV1Value": 1000000000000000000,
"faucetAdminDripV1Interval": 86400,
"faucetAdminDripV1Threshold": 100000000000000000,
"faucetGelatoRecipient": "0x0E9b4649eB0760A4F01646636E032D68cFDe58FF",
"faucetGelatoBalanceV1DripInterval": 86400,
"faucetGelatoBalanceV1Value": 1000000000000000000,
"faucetGelatoThreshold": 100000000000000000,
"smallOpChainFaucetDripValue": 34000000000000000000,
"smallOpChainFaucetDripInterval": 86400,
"largeOpChainFaucetDripValue": 34000000000000000000,
"largeOpChainFaucetDripInterval": 86400,
"opChainAdminWalletDripValue": 1000000000000000000,
"opChainAdminWalletDripInterval": 2592000,
......@@ -49,21 +17,7 @@
"faucetOffchainAuthModuleTtl": 86400,
"faucetOffchainAuthModuleAmount": 50000000000000000,
"opL1BridgeAddress": "0xFBb0621E0B23b5478B630BD55a5f21f67730B0F1",
"baseL1BridgeAddress": "0xfd0Bf71F60660E2f608ed56e1659C450eB113120",
"zoraL1BridgeAddress": "0x5376f1D543dcbB5BD416c56C189e4cB7399fCcCB",
"pgnL1BridgeAddress": "0xFaE6abCAF30D23e233AC7faF747F2fC3a5a6Bfa3",
"orderlyL1BridgeAddress": "0x1Af0494040d6904A9F3EE21921de4b359C736333",
"modeL1BridgeAddress": "0xbC5C679879B2965296756CD959C3C739769995E2",
"lyraL1BridgeAddress": "0x915f179A77FB2e1AeA8b56Ebc0D75A7e1A8a7A17",
"liskL1BridgeAddress": "0x1Fb30e446eA791cd1f011675E5F3f5311b70faF5",
"deployDripchecks": true,
"deployFaucetContracts": false,
"deployOperationsContracts": true,
"installOpChainFaucetsDrips": false,
"archivePreviousOpChainFaucetsDrips": false,
"dripVersion": 3,
"previousDripVersion": 2
"deployOperationsContracts": true
}
......@@ -17,46 +17,12 @@ contract PeripheryDeployConfig is Script {
// Configuration for Gelato.
address public gelatoAutomateContract;
address public gelatoTreasuryContract;
// Configuration for standard operations Drippie contract.
address public operationsDrippieOwner;
address public operationsSequencerDripV1Target;
uint256 public operationsSequencerDripV1Value;
uint256 public operationsSequencerDripV1Interval;
uint256 public operationsSequencerDripV1Threshold;
address public operationsGelatoDripV1Recipient;
uint256 public operationsGelatoDripV1Value;
uint256 public operationsGelatoDripV1Interval;
uint256 public operationsGelatoDripV1Threshold;
uint256 public operationsSecretsDripV1Delay;
bytes32 public operationsSecretsDripV1MustExist;
bytes32 public operationsSecretsDripV1MustNotExist;
address public operationsSecretsDripV1Target;
uint256 public operationsSecretsDripV1Value;
uint256 public operationsSecretsDripV1Interval;
// Configuration for the faucet Drippie contract.
address public faucetDrippieOwner;
uint256 public faucetDripV1Value;
uint256 public faucetDripV1Interval;
uint256 public faucetDripV1Threshold;
uint256 public faucetDripV2Value;
uint256 public faucetDripV2Interval;
uint256 public faucetDripV2Threshold;
uint256 public faucetAdminDripV1Value;
uint256 public faucetAdminDripV1Interval;
uint256 public faucetAdminDripV1Threshold;
address public faucetGelatoRecipient;
uint256 public faucetGelatoBalanceV1DripInterval;
uint256 public faucetGelatoBalanceV1Value;
uint256 public faucetGelatoThreshold;
uint256 public smallOpChainFaucetDripValue;
uint256 public smallOpChainFaucetDripInterval;
uint256 public largeOpChainFaucetDripValue;
uint256 public largeOpChainFaucetDripInterval;
uint256 public opChainAdminWalletDripValue;
uint256 public opChainAdminWalletDripInterval;
// Configuration for the Faucet contract.
address public faucetAdmin;
......@@ -67,28 +33,10 @@ contract PeripheryDeployConfig is Script {
uint256 public faucetOffchainAuthModuleTtl;
uint256 public faucetOffchainAuthModuleAmount;
// Configuration for the L1 bridges.
address public opL1BridgeAddress;
address public baseL1BridgeAddress;
address public zoraL1BridgeAddress;
address public pgnL1BridgeAddress;
address public orderlyL1BridgeAddress;
address public modeL1BridgeAddress;
address public lyraL1BridgeAddress;
address public liskL1BridgeAddress;
address[6] public smallFaucetsL1BridgeAddresses;
address[2] public largeFaucetsL1BridgeAddresses;
// Configuration booleans.
bool public deployDripchecks;
bool public deployFaucetContracts;
bool public deployOperationsContracts;
bool public installOpChainFaucetsDrips;
bool public archivePreviousOpChainFaucetsDrips;
// Configuration for the drip version.
uint256 public dripVersion;
uint256 public previousDripVersion;
constructor(string memory _path) {
console.log("PeripheryDeployConfig: reading file %s", _path);
......@@ -104,46 +52,12 @@ contract PeripheryDeployConfig is Script {
// Configuration for Gelato.
gelatoAutomateContract = stdJson.readAddress(_json, "$.gelatoAutomateContract");
gelatoTreasuryContract = stdJson.readAddress(_json, "$.gelatoTreasuryContract");
// Configuration for the standard operations Drippie contract.
operationsDrippieOwner = stdJson.readAddress(_json, "$.operationsDrippieOwner");
operationsSequencerDripV1Target = stdJson.readAddress(_json, "$.operationsSequencerDripV1Target");
operationsSequencerDripV1Value = stdJson.readUint(_json, "$.operationsSequencerDripV1Value");
operationsSequencerDripV1Interval = stdJson.readUint(_json, "$.operationsSequencerDripV1Interval");
operationsSequencerDripV1Threshold = stdJson.readUint(_json, "$.operationsSequencerDripV1Threshold");
operationsGelatoDripV1Recipient = stdJson.readAddress(_json, "$.operationsGelatoDripV1Recipient");
operationsGelatoDripV1Value = stdJson.readUint(_json, "$.operationsGelatoDripV1Value");
operationsGelatoDripV1Interval = stdJson.readUint(_json, "$.operationsGelatoDripV1Interval");
operationsGelatoDripV1Threshold = stdJson.readUint(_json, "$.operationsGelatoDripV1Threshold");
operationsSecretsDripV1Delay = stdJson.readUint(_json, "$.operationsSecretsDripV1Delay");
operationsSecretsDripV1MustExist = stdJson.readBytes32(_json, "$.operationsSecretsDripV1MustExist");
operationsSecretsDripV1MustNotExist = stdJson.readBytes32(_json, "$.operationsSecretsDripV1MustNotExist");
operationsSecretsDripV1Target = stdJson.readAddress(_json, "$.operationsSecretsDripV1Target");
operationsSecretsDripV1Value = stdJson.readUint(_json, "$.operationsSecretsDripV1Value");
operationsSecretsDripV1Interval = stdJson.readUint(_json, "$.operationsSecretsDripV1Interval");
// Configuration for the faucet Drippie contract.
faucetDrippieOwner = stdJson.readAddress(_json, "$.faucetDrippieOwner");
faucetDripV1Value = stdJson.readUint(_json, "$.faucetDripV1Value");
faucetDripV1Interval = stdJson.readUint(_json, "$.faucetDripV1Interval");
faucetDripV1Threshold = stdJson.readUint(_json, "$.faucetDripV1Threshold");
faucetDripV2Value = stdJson.readUint(_json, "$.faucetDripV2Value");
faucetDripV2Interval = stdJson.readUint(_json, "$.faucetDripV2Interval");
faucetDripV2Threshold = stdJson.readUint(_json, "$.faucetDripV2Threshold");
faucetAdminDripV1Value = stdJson.readUint(_json, "$.faucetAdminDripV1Value");
faucetAdminDripV1Interval = stdJson.readUint(_json, "$.faucetAdminDripV1Interval");
faucetAdminDripV1Threshold = stdJson.readUint(_json, "$.faucetAdminDripV1Threshold");
faucetGelatoRecipient = stdJson.readAddress(_json, "$.faucetGelatoRecipient");
faucetGelatoBalanceV1DripInterval = stdJson.readUint(_json, "$.faucetGelatoBalanceV1DripInterval");
faucetGelatoBalanceV1Value = stdJson.readUint(_json, "$.faucetGelatoBalanceV1Value");
faucetGelatoThreshold = stdJson.readUint(_json, "$.faucetGelatoThreshold");
smallOpChainFaucetDripValue = stdJson.readUint(_json, "$.smallOpChainFaucetDripValue");
smallOpChainFaucetDripInterval = stdJson.readUint(_json, "$.smallOpChainFaucetDripInterval");
largeOpChainFaucetDripValue = stdJson.readUint(_json, "$.largeOpChainFaucetDripValue");
largeOpChainFaucetDripInterval = stdJson.readUint(_json, "$.largeOpChainFaucetDripInterval");
opChainAdminWalletDripValue = stdJson.readUint(_json, "$.opChainAdminWalletDripValue");
opChainAdminWalletDripInterval = stdJson.readUint(_json, "$.opChainAdminWalletDripInterval");
// Configuration for the Faucet contract.
faucetAdmin = stdJson.readAddress(_json, "$.faucetAdmin");
......@@ -154,41 +68,9 @@ contract PeripheryDeployConfig is Script {
faucetOffchainAuthModuleTtl = stdJson.readUint(_json, "$.faucetOffchainAuthModuleTtl");
faucetOffchainAuthModuleAmount = stdJson.readUint(_json, "$.faucetOffchainAuthModuleAmount");
// Configuration for the L1 bridges.
opL1BridgeAddress = stdJson.readAddress(_json, "$.opL1BridgeAddress");
baseL1BridgeAddress = stdJson.readAddress(_json, "$.baseL1BridgeAddress");
zoraL1BridgeAddress = stdJson.readAddress(_json, "$.zoraL1BridgeAddress");
pgnL1BridgeAddress = stdJson.readAddress(_json, "$.pgnL1BridgeAddress");
orderlyL1BridgeAddress = stdJson.readAddress(_json, "$.orderlyL1BridgeAddress");
liskL1BridgeAddress = stdJson.readAddress(_json, "$.liskL1BridgeAddress");
modeL1BridgeAddress = stdJson.readAddress(_json, "$.modeL1BridgeAddress");
lyraL1BridgeAddress = stdJson.readAddress(_json, "$.lyraL1BridgeAddress");
largeFaucetsL1BridgeAddresses[0] = opL1BridgeAddress;
largeFaucetsL1BridgeAddresses[1] = baseL1BridgeAddress;
smallFaucetsL1BridgeAddresses[0] = zoraL1BridgeAddress;
smallFaucetsL1BridgeAddresses[1] = pgnL1BridgeAddress;
smallFaucetsL1BridgeAddresses[2] = orderlyL1BridgeAddress;
smallFaucetsL1BridgeAddresses[3] = modeL1BridgeAddress;
smallFaucetsL1BridgeAddresses[4] = lyraL1BridgeAddress;
smallFaucetsL1BridgeAddresses[5] = liskL1BridgeAddress;
// Configuration booleans.
deployDripchecks = stdJson.readBool(_json, "$.deployDripchecks");
deployFaucetContracts = stdJson.readBool(_json, "$.deployFaucetContracts");
deployOperationsContracts = stdJson.readBool(_json, "$.deployOperationsContracts");
installOpChainFaucetsDrips = stdJson.readBool(_json, "$.installOpChainFaucetsDrips");
archivePreviousOpChainFaucetsDrips = stdJson.readBool(_json, "$.archivePreviousOpChainFaucetsDrips");
// Configuration for the drip version.
dripVersion = stdJson.readUint(_json, "$.dripVersion");
previousDripVersion = stdJson.readUint(_json, "$.previousDripVersion");
}
function getSmallFaucetsL1BridgeAddressesCount() public view returns (uint256 count) {
return smallFaucetsL1BridgeAddresses.length;
}
function getLargeFaucetsL1BridgeAddressesCount() public view returns (uint256 count) {
return largeFaucetsL1BridgeAddresses.length;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Script } from "forge-std/Script.sol";
import { console2 as console } from "forge-std/console2.sol";
import { stdJson } from "forge-std/StdJson.sol";
import { IAutomate as IGelato } from "gelato/interfaces/IAutomate.sol";
import { Artifacts } from "scripts/Artifacts.s.sol";
import { Drippie } from "src/periphery/drippie/Drippie.sol";
import { CheckBalanceLow } from "src/periphery/drippie/dripchecks/CheckBalanceLow.sol";
import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol";
import { CheckSecrets } from "src/periphery/drippie/dripchecks/CheckSecrets.sol";
/// @title DrippieConfig
/// @notice Loads Drippie configuration from a JSON file.
contract DrippieConfig is Script, Artifacts {
/// @notice Error emitted when an unknown drip check is encountered.
error UnknownDripCheck(string name);
/// @notice Drip configuration with only name and dripcheck.
struct CoreDripConfig {
string name;
string dripcheck;
}
/// @notice Full drip configuration.
struct FullDripConfig {
string name;
string dripcheck;
bytes checkparams;
address recipient;
uint256 value;
uint256 interval;
bytes data;
}
/// @notice JSON configuration file represented as string.
string internal _json;
/// @notice Drippie contract.
Drippie public drippie;
/// @notice Gelato automation contract.
IGelato public gelato;
/// @notice Drip configuration array.
FullDripConfig[] public drips;
/// @param _path Path to the configuration file.
constructor(string memory _path) {
// Make sure artifacts are set up.
Artifacts.setUp();
// Load the configuration file.
console.log("DrippieConfig: reading file %s", _path);
try vm.readFile(_path) returns (string memory data) {
_json = data;
} catch {
console.log("WARNING: unable to read config, do not deploy unless you are not using config");
return;
}
// Load the Drippie contract address.
drippie = Drippie(payable(stdJson.readAddress(_json, "$.drippie")));
// Load the Gelato contract address.
gelato = IGelato(stdJson.readAddress(_json, "$.gelato"));
// Determine the number of drips.
// In an ideal world we'd be able to load this array in one go by parsing it as an array
// of structs that include the checkparams as bytes. Unfortunately, Foundry parses the
// checkparams as a tuple which can't be parsed in a generic way (since Solidity does not
// support generics). As a result, we first parse the array as a simplified struct that
// only includes the first two fields so that we can determine the number of drips. We then
// iterate over the array and parse the full struct for each drip somewhat manually.
CoreDripConfig[] memory corecfg = abi.decode(stdJson.parseRaw(_json, "$.drips"), (CoreDripConfig[]));
console.log("DrippieConfig: found %d drips", corecfg.length);
// Iterate and parse all of the drips.
for (uint256 i = 0; i < corecfg.length; i++) {
// Log so we know what's being loaded.
string memory name = corecfg[i].name;
console.log("DrippieConfig: attempting to load config for %s", name);
// Make sure the dripcheck is deployed.
string memory dripcheck = corecfg[i].dripcheck;
console.log("DrippieConfig: attempting to get address for %s", dripcheck);
mustGetAddress(dripcheck);
// Generate the base JSON path string.
string memory p = string.concat("$.drips[", vm.toString(i), "]");
// Load the checkparams as bytes.
bytes memory checkparams = stdJson.parseRaw(_json, string.concat(p, ".02__checkparams"));
// Determine if the parameters are decodable.
console.log("DrippieConfig: attempting to decode check parameters for %s", name);
if (strcmp(dripcheck, "CheckBalanceLow")) {
abi.decode(checkparams, (CheckBalanceLow.Params));
} else if (strcmp(dripcheck, "CheckGelatoLow")) {
abi.decode(checkparams, (CheckGelatoLow.Params));
} else if (strcmp(dripcheck, "CheckSecrets")) {
abi.decode(checkparams, (CheckSecrets.Params));
} else if (strcmp(dripcheck, "CheckTrue")) {
// No parameters to decode.
} else {
console.log("ERROR: unknown drip configuration %s", dripcheck);
revert UnknownDripCheck(dripcheck);
}
// Parse all the easy stuff first.
console.log("DrippieConfig: attempting to load core configuration for %s", name);
FullDripConfig memory dripcfg = FullDripConfig({
name: name,
dripcheck: dripcheck,
checkparams: checkparams,
recipient: stdJson.readAddress(_json, string.concat(p, ".03__recipient")),
value: stdJson.readUint(_json, string.concat(p, ".04__value")),
interval: stdJson.readUint(_json, string.concat(p, ".05__interval")),
data: stdJson.parseRaw(_json, string.concat(p, ".06__data"))
});
// Ok we're good to go.
drips.push(dripcfg);
}
}
/// @notice Returns the number of drips in the configuration.
function dripsLength() public view returns (uint256) {
return drips.length;
}
/// @notice Returns the drip configuration at the given index as ABI-encoded bytes.
function drip(uint256 _index) public view returns (bytes memory) {
return abi.encode(drips[_index]);
}
/// @notice Check if two strings are equal.
/// @param _a First string.
/// @param _b Second string.
/// @return True if the strings are equal, false otherwise.
function strcmp(string memory _a, string memory _b) internal pure returns (bool) {
return keccak256(bytes(_a)) == keccak256(bytes(_b));
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { console2 as console } from "forge-std/console2.sol";
import { Script } from "forge-std/Script.sol";
import { IAutomate as IGelato } from "gelato/interfaces/IAutomate.sol";
import { LibDataTypes as GelatoDataTypes } from "gelato/libraries/LibDataTypes.sol";
import { LibTaskId as GelatoTaskId } from "gelato/libraries/LibTaskId.sol";
import { GelatoBytes } from "gelato/vendor/gelato/GelatoBytes.sol";
import { Config } from "scripts/Config.sol";
import { Artifacts } from "scripts/Artifacts.s.sol";
import { DrippieConfig } from "scripts/periphery/drippie/DrippieConfig.s.sol";
import { Drippie } from "src/periphery/drippie/Drippie.sol";
import { IDripCheck } from "src/periphery/drippie/IDripCheck.sol";
/// @title ManageDrippie
/// @notice Script for managing drips in the Drippie contract.
contract ManageDrippie is Script, Artifacts {
/// @notice Struct that contains the data for a Gelato task.
struct GelatoTaskData {
address taskCreator;
address execAddress;
bytes execData;
GelatoDataTypes.ModuleData moduleData;
address feeToken;
}
/// @notice Drippie configuration.
DrippieConfig public cfg;
/// @notice Modifier that wraps a function in broadcasting.
modifier broadcast() {
vm.startBroadcast(msg.sender);
_;
vm.stopBroadcast();
}
/// @notice Sets up the deployment script.
function setUp() public override {
Artifacts.setUp();
cfg = new DrippieConfig(Config.deployConfigPath());
console.log("Config path: %s", Config.deployConfigPath());
}
/// @notice Runs the management script.
function run() public {
console.log("ManageDrippie: running");
installDrips();
}
/// @notice Installs drips in the drippie contract.
function installDrips() public broadcast {
console.log("ManageDrippie: installing Drippie config");
for (uint256 i = 0; i < cfg.dripsLength(); i++) {
DrippieConfig.FullDripConfig memory drip = abi.decode(cfg.drip(i), (DrippieConfig.FullDripConfig));
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1);
actions[0] = Drippie.DripAction({ target: payable(drip.recipient), data: drip.data, value: drip.value });
_installDrip({
_gelato: cfg.gelato(),
_drippie: cfg.drippie(),
_name: drip.name,
_config: Drippie.DripConfig({
reentrant: false,
interval: drip.interval,
dripcheck: IDripCheck(mustGetAddress(drip.dripcheck)),
checkparams: drip.checkparams,
actions: actions
})
});
}
}
/// @notice Generates the data for a Gelato task that would trigger a drip.
/// @param _drippie The drippie contract.
/// @param _name The name of the drip.
/// @return _taskData Gelato task data.
function _makeGelatoDripTaskData(
Drippie _drippie,
string memory _name
)
internal
view
returns (GelatoTaskData memory _taskData)
{
// Get the drip interval.
uint256 dripInterval = _drippie.getDripInterval(_name);
// Set up module types.
GelatoDataTypes.Module[] memory modules = new GelatoDataTypes.Module[](2);
modules[0] = GelatoDataTypes.Module.PROXY;
modules[1] = GelatoDataTypes.Module.TRIGGER;
// Create arguments for the PROXY and TRIGGER modules.
bytes[] memory args = new bytes[](2);
args[0] = abi.encode(_name);
args[1] = abi.encode(
GelatoDataTypes.TriggerModuleData({
triggerType: GelatoDataTypes.TriggerType.TIME,
triggerConfig: abi.encode(GelatoDataTypes.Time({ nextExec: 0, interval: uint128(dripInterval) }))
})
);
// Create the task data.
_taskData = GelatoTaskData({
taskCreator: msg.sender,
execAddress: address(_drippie),
execData: abi.encodeCall(Drippie.drip, (_name)),
moduleData: GelatoDataTypes.ModuleData({ modules: modules, args: args }),
feeToken: address(0)
});
}
/// @notice Starts a gelato drip task.
/// @param _gelato The gelato contract.
/// @param _drippie The drippie contract.
/// @param _name The name of the drip being triggered.
function _startGelatoDripTask(IGelato _gelato, Drippie _drippie, string memory _name) internal {
GelatoTaskData memory taskData = _makeGelatoDripTaskData({ _drippie: _drippie, _name: _name });
_gelato.createTask({
execAddress: taskData.execAddress,
execData: taskData.execData,
moduleData: taskData.moduleData,
feeToken: taskData.feeToken
});
}
/// @notice Pauses a gelato drip task.
/// @param _gelato The gelato contract.
/// @param _drippie The drippie contract.
/// @param _name The name of the drip being triggered.
function _pauseGelatoDripTask(IGelato _gelato, Drippie _drippie, string memory _name) internal {
GelatoTaskData memory taskData = _makeGelatoDripTaskData({ _drippie: _drippie, _name: _name });
_gelato.cancelTask(
GelatoTaskId.getTaskId({
taskCreator: taskData.taskCreator,
execAddress: taskData.execAddress,
execSelector: GelatoBytes.memorySliceSelector(taskData.execData),
moduleData: taskData.moduleData,
feeToken: taskData.feeToken
})
);
}
/// @notice Installs a drip in the drippie contract.
/// @param _gelato The gelato contract.
/// @param _drippie The drippie contract.
/// @param _name The name of the drip.
/// @param _config The configuration of the drip.
function _installDrip(
IGelato _gelato,
Drippie _drippie,
string memory _name,
Drippie.DripConfig memory _config
)
internal
{
if (_drippie.getDripStatus(_name) == Drippie.DripStatus.NONE) {
console.log("installing %s", _name);
_drippie.create(_name, _config);
_startGelatoDripTask(_gelato, _drippie, _name);
console.log("%s installed successfully", _name);
} else {
console.log("%s already installed", _name);
}
// Grab the status again now that we've installed the drip.
Drippie.DripStatus status = _drippie.getDripStatus(_name);
if (status == Drippie.DripStatus.PAUSED) {
console.log("activating %s", _name);
_drippie.status(_name, Drippie.DripStatus.ACTIVE);
console.log("%s activated successfully", _name);
} else if (status == Drippie.DripStatus.ACTIVE) {
console.log("%s already active", _name);
} else {
// TODO: Better way to handle this?
console.log("WARNING: % could not be activated", _name);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment