diff --git a/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-faucet-bridges.json b/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-faucet-bridges.json new file mode 100644 index 000000000000..d48f8c053317 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-faucet-bridges.json @@ -0,0 +1,80 @@ +{ + "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" + } + ] +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-faucet-core.json b/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-faucet-core.json new file mode 100644 index 000000000000..1a1ef010eca8 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-faucet-core.json @@ -0,0 +1,57 @@ +{ + "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" + } + ] +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-ops.json b/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-ops.json new file mode 100644 index 000000000000..6b38dd37b4a2 --- /dev/null +++ b/packages/contracts-bedrock/periphery-deploy-config/drippie-config/sepolia-ops.json @@ -0,0 +1,58 @@ +{ + "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": "" + } + ] +} diff --git a/packages/contracts-bedrock/periphery-deploy-config/sepolia.json b/packages/contracts-bedrock/periphery-deploy-config/sepolia.json index 7c2a8f18f50a..6bf925b7f090 100644 --- a/packages/contracts-bedrock/periphery-deploy-config/sepolia.json +++ b/packages/contracts-bedrock/periphery-deploy-config/sepolia.json @@ -1,43 +1,11 @@ { - "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 } diff --git a/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol b/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol deleted file mode 100644 index e0e8d0dbf596..000000000000 --- a/packages/contracts-bedrock/scripts/DeployPeriphery.s.sol +++ /dev/null @@ -1,859 +0,0 @@ -// 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 { PeripheryDeployConfig } from "scripts/PeripheryDeployConfig.s.sol"; - -import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; -import { Proxy } from "src/universal/Proxy.sol"; -import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; -import { Faucet } from "src/periphery/faucet/Faucet.sol"; -import { Drippie } from "src/periphery/drippie/Drippie.sol"; -import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol"; -import { CheckBalanceLow } from "src/periphery/drippie/dripchecks/CheckBalanceLow.sol"; -import { CheckTrue } from "src/periphery/drippie/dripchecks/CheckTrue.sol"; -import { CheckSecrets } from "src/periphery/drippie/dripchecks/CheckSecrets.sol"; -import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; - -import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; - -/// @title DeployPeriphery -/// @notice Script used to deploy periphery contracts. -contract DeployPeriphery is Script, Artifacts { - /// @notice Error emitted when an address mismatch is detected. - error AddressMismatch(string, address, address); - - /// @notice Struct that contains the data for a Gelato task. - struct GelatoTaskData { - address taskCreator; - address execAddress; - bytes execData; - GelatoDataTypes.ModuleData moduleData; - address feeToken; - } - - /// @notice Deployment configuration. - PeripheryDeployConfig cfg; - - /// @notice Sets up the deployment script. - function setUp() public override { - Artifacts.setUp(); - cfg = new PeripheryDeployConfig(Config.deployConfigPath()); - console.log("Config path: %s", Config.deployConfigPath()); - } - - /// @notice Deploy all of the periphery contracts. - function run() public { - console.log("Deploying periphery contracts"); - - // Optionally deploy the base dripcheck contracts. - if (cfg.deployDripchecks()) { - deployCheckTrue(); - deployCheckBalanceLow(); - deployCheckGelatoLow(); - deployCheckSecrets(); - } - - // Optionally deploy the faucet contracts. - if (cfg.deployFaucetContracts()) { - // Deploy faucet contracts. - deployProxyAdmin(); - deployFaucetProxy(); - deployFaucet(); - deployFaucetDrippie(); - deployOnChainAuthModule(); - deployOffChainAuthModule(); - - // Initialize the faucet. - initializeFaucet(); - installFaucetAuthModulesConfigs(); - - // Optionally install OP Chain drip configs. - if (cfg.installOpChainFaucetsDrips()) { - installOpChainFaucetsDrippieConfigs(); - } - - // Optionally archive old drip configs. - if (cfg.archivePreviousOpChainFaucetsDrips()) { - archivePreviousOpChainFaucetsDrippieConfigs(); - } - } - - // Optionally deploy the operations contracts. - if (cfg.deployOperationsContracts()) { - deployOperationsDrippie(); - } - } - - /// @notice Modifier that wraps a function in broadcasting. - modifier broadcast() { - vm.startBroadcast(); - _; - vm.stopBroadcast(); - } - - /// @notice Deploy ProxyAdmin. - function deployProxyAdmin() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "ProxyAdmin", - _creationCode: type(ProxyAdmin).creationCode, - _constructorParams: abi.encode(msg.sender) - }); - - ProxyAdmin admin = ProxyAdmin(addr_); - require(admin.owner() == msg.sender); - } - - /// @notice Deploy FaucetProxy. - function deployFaucetProxy() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "FaucetProxy", - _creationCode: type(Proxy).creationCode, - _constructorParams: abi.encode(mustGetAddress("ProxyAdmin")) - }); - - Proxy proxy = Proxy(payable(addr_)); - require(EIP1967Helper.getAdmin(address(proxy)) == mustGetAddress("ProxyAdmin")); - } - - /// @notice Deploy the Faucet contract. - function deployFaucet() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "Faucet", - _creationCode: type(Faucet).creationCode, - _constructorParams: abi.encode(cfg.faucetAdmin()) - }); - - Faucet faucet = Faucet(payable(addr_)); - require(faucet.ADMIN() == cfg.faucetAdmin()); - } - - /// @notice Deploy the Drippie contract. - function deployFaucetDrippie() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "FaucetDrippie", - _creationCode: type(Drippie).creationCode, - _constructorParams: abi.encode(cfg.faucetDrippieOwner()) - }); - - Drippie drippie = Drippie(payable(addr_)); - require(drippie.owner() == cfg.faucetDrippieOwner()); - } - - /// @notice Deploy the Drippie contract for standard operations. - function deployOperationsDrippie() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "OperationsDrippie", - _creationCode: type(Drippie).creationCode, - _constructorParams: abi.encode(cfg.operationsDrippieOwner()) - }); - - Drippie drippie = Drippie(payable(addr_)); - require(drippie.owner() == cfg.operationsDrippieOwner()); - } - - /// @notice Deploy On-Chain Authentication Module. - function deployOnChainAuthModule() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "OnChainAuthModule", - _creationCode: type(AdminFaucetAuthModule).creationCode, - _constructorParams: abi.encode(cfg.faucetOnchainAuthModuleAdmin(), "OnChainAuthModule", "1") - }); - - AdminFaucetAuthModule module = AdminFaucetAuthModule(addr_); - require(module.ADMIN() == cfg.faucetOnchainAuthModuleAdmin()); - } - - /// @notice Deploy Off-Chain Authentication Module. - function deployOffChainAuthModule() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "OffChainAuthModule", - _creationCode: type(AdminFaucetAuthModule).creationCode, - _constructorParams: abi.encode(cfg.faucetOffchainAuthModuleAdmin(), "OffChainAuthModule", "1") - }); - - AdminFaucetAuthModule module = AdminFaucetAuthModule(addr_); - require(module.ADMIN() == cfg.faucetOffchainAuthModuleAdmin()); - } - - /// @notice Deploy CheckTrue contract. - function deployCheckTrue() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "CheckTrue", - _creationCode: type(CheckTrue).creationCode, - _constructorParams: hex"" - }); - } - - /// @notice Deploy CheckBalanceLow contract. - function deployCheckBalanceLow() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "CheckBalanceLow", - _creationCode: type(CheckBalanceLow).creationCode, - _constructorParams: hex"" - }); - } - - /// @notice Deploy CheckGelatoLow contract. - function deployCheckGelatoLow() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "CheckGelatoLow", - _creationCode: type(CheckGelatoLow).creationCode, - _constructorParams: hex"" - }); - } - - /// @notice Deploy CheckSecrets contract. - function deployCheckSecrets() public broadcast returns (address addr_) { - addr_ = _deployCreate2({ - _name: "CheckSecrets", - _creationCode: type(CheckSecrets).creationCode, - _constructorParams: hex"" - }); - } - - /// @notice Initialize the Faucet. - function initializeFaucet() public broadcast { - ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin")); - address faucetProxy = mustGetAddress("FaucetProxy"); - address faucet = mustGetAddress("Faucet"); - address implementationAddress = proxyAdmin.getProxyImplementation(faucetProxy); - if (implementationAddress == faucet) { - console.log("Faucet proxy implementation already set"); - } else { - proxyAdmin.upgrade({ _proxy: payable(faucetProxy), _implementation: faucet }); - } - - require(Faucet(payable(faucetProxy)).ADMIN() == Faucet(payable(faucet)).ADMIN()); - } - - /// @notice Installs the drip configs in the operations Drippie contract. - function installOperationsDrippieConfigs() public { - Drippie drippie = Drippie(mustGetAddress("OperationsDrippie")); - console.log("Installing operations drips at %s", address(drippie)); - installOperationsSequencerDripV1(); - installOperationsGelatoDripV1(); - installOperationsSecretsDripV1(); - console.log("Operations drip configs successfully installed"); - } - - /// @notice Installs the drip configs in the faucet Drippie contract. - function installFaucetDrippieConfigs() public { - Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); - console.log("Installing faucet drips at %s", address(drippie)); - installFaucetDripV1(); - installFaucetDripV2(); - installFaucetAdminDripV1(); - installFaucetGelatoBalanceV2(); - console.log("Faucet drip configs successfully installed"); - } - - /// @notice Installs drip configs that deposit funds to all OP Chain faucets. This function - /// should only be called on an L1 testnet. - function installOpChainFaucetsDrippieConfigs() public { - uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey(); - vm.startBroadcast(drippieOwnerPrivateKey); - - Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); - console.log("Installing OP Chain faucet drips at %s", address(drippie)); - installSmallOpChainFaucetsDrips(); - installLargeOpChainFaucetsDrips(); - installSmallOpChainAdminWalletDrips(); - installLargeOpChainAdminWalletDrips(); - console.log("OP chain faucet drip configs successfully installed"); - - vm.stopBroadcast(); - } - - /// @notice Installs drips that send funds to small OP chain faucets on the scheduled interval. - function installSmallOpChainFaucetsDrips() public { - for (uint256 i = 0; i < cfg.getSmallFaucetsL1BridgeAddressesCount(); i++) { - address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i); - _installDepositEthToDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: _makeFaucetDripName(l1BridgeAddress, cfg.dripVersion()), - _bridge: l1BridgeAddress, - _target: mustGetAddress("FaucetProxy"), - _value: cfg.smallOpChainFaucetDripValue(), - _interval: cfg.smallOpChainFaucetDripInterval() - }); - } - } - - /// @notice Installs drips that send funds to large OP chain faucets on the scheduled interval. - function installLargeOpChainFaucetsDrips() public { - for (uint256 i = 0; i < cfg.getLargeFaucetsL1BridgeAddressesCount(); i++) { - address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i); - _installDepositEthToDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: _makeFaucetDripName(l1BridgeAddress, cfg.dripVersion()), - _bridge: l1BridgeAddress, - _target: mustGetAddress("FaucetProxy"), - _value: cfg.largeOpChainFaucetDripValue(), - _interval: cfg.largeOpChainFaucetDripInterval() - }); - } - } - - /// @notice Installs drips that send funds to the admin wallets for small OP chain faucets - /// on the scheduled interval. - function installSmallOpChainAdminWalletDrips() public { - require( - cfg.faucetOnchainAuthModuleAdmin() == cfg.faucetOffchainAuthModuleAdmin(), - "installSmallOpChainAdminWalletDrips: Only handles identical admin wallet addresses" - ); - - for (uint256 i = 0; i < cfg.getSmallFaucetsL1BridgeAddressesCount(); i++) { - address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i); - _installDepositEthToDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: _makeAdminWalletDripName(l1BridgeAddress, cfg.dripVersion()), - _bridge: l1BridgeAddress, - _target: cfg.faucetOnchainAuthModuleAdmin(), - _value: cfg.opChainAdminWalletDripValue(), - _interval: cfg.opChainAdminWalletDripInterval() - }); - } - } - - /// @notice Installs drips that send funds to the admin wallets for large OP chain faucets - /// on the scheduled interval. - function installLargeOpChainAdminWalletDrips() public { - require( - cfg.faucetOnchainAuthModuleAdmin() == cfg.faucetOffchainAuthModuleAdmin(), - "installLargeOpChainAdminWalletDrips: Only handles identical admin wallet addresses" - ); - - for (uint256 i = 0; i < cfg.getLargeFaucetsL1BridgeAddressesCount(); i++) { - address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i); - _installDepositEthToDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: _makeAdminWalletDripName(l1BridgeAddress, cfg.dripVersion()), - _bridge: l1BridgeAddress, - _target: cfg.faucetOnchainAuthModuleAdmin(), - _value: cfg.opChainAdminWalletDripValue(), - _interval: cfg.opChainAdminWalletDripInterval() - }); - } - } - - /// @notice Installs the OperationsSequencerDripV1 drip on the operations drippie contract. - function installOperationsSequencerDripV1() public broadcast { - _installBalanceLowDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("OperationsDrippie")), - _name: "OperationsSequencerDripV1", - _target: cfg.operationsSequencerDripV1Target(), - _value: cfg.operationsSequencerDripV1Value(), - _interval: cfg.operationsSequencerDripV1Interval(), - _threshold: cfg.operationsSequencerDripV1Threshold() - }); - } - - /// @notice Installs the OperationsGelatoDripV1 drip on the operations drippie contract. - function installOperationsGelatoDripV1() public broadcast { - _installGelatoDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("OperationsDrippie")), - _name: "OperationsGelatoDripV1", - _treasury: cfg.gelatoTreasuryContract(), - _recipient: cfg.operationsGelatoDripV1Recipient(), - _value: cfg.operationsGelatoDripV1Value(), - _interval: cfg.operationsGelatoDripV1Interval(), - _threshold: cfg.operationsGelatoDripV1Threshold() - }); - } - - /// @notice Installs the OperationsSecretsDripV1 drip on the operations drippie contract. - function installOperationsSecretsDripV1() public broadcast { - _installSecretsDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("OperationsDrippie")), - _name: "OperationsSecretsDripV1", - _delay: cfg.operationsSecretsDripV1Delay(), - _secretHashMustExist: cfg.operationsSecretsDripV1MustExist(), - _secretHashMustNotExist: cfg.operationsSecretsDripV1MustNotExist(), - _target: cfg.operationsSecretsDripV1Target(), - _value: cfg.operationsSecretsDripV1Value(), - _interval: cfg.operationsSecretsDripV1Interval() - }); - } - - /// @notice Installs the FaucetDripV1 drip on the faucet drippie contract. - function installFaucetDripV1() public broadcast { - _installBalanceLowDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: "FaucetDripV1", - _target: mustGetAddress("FaucetProxy"), - _value: cfg.faucetDripV1Value(), - _interval: cfg.faucetDripV1Interval(), - _threshold: cfg.faucetDripV1Threshold() - }); - } - - /// @notice Installs the FaucetDripV2 drip on the faucet drippie contract. - function installFaucetDripV2() public broadcast { - _installBalanceLowDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: "FaucetDripV2", - _target: mustGetAddress("FaucetProxy"), - _value: cfg.faucetDripV2Value(), - _interval: cfg.faucetDripV2Interval(), - _threshold: cfg.faucetDripV2Threshold() - }); - } - - /// @notice Installs the FaucetAdminDripV1 drip on the faucet drippie contract. - function installFaucetAdminDripV1() public broadcast { - _installBalanceLowDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: "FaucetAdminDripV1", - _target: mustGetAddress("FaucetProxy"), - _value: cfg.faucetAdminDripV1Value(), - _interval: cfg.faucetAdminDripV1Interval(), - _threshold: cfg.faucetAdminDripV1Threshold() - }); - } - - /// @notice Installs the GelatoBalanceV2 drip on the faucet drippie contract. - function installFaucetGelatoBalanceV2() public broadcast { - _installGelatoDrip({ - _gelato: IGelato(cfg.gelatoAutomateContract()), - _drippie: Drippie(mustGetAddress("FaucetDrippie")), - _name: "GelatoBalanceV2", - _treasury: cfg.gelatoTreasuryContract(), - _recipient: cfg.faucetGelatoRecipient(), - _value: cfg.faucetGelatoBalanceV1Value(), - _interval: cfg.faucetGelatoBalanceV1DripInterval(), - _threshold: cfg.faucetGelatoThreshold() - }); - } - - /// @notice Archives the previous OP Chain drip configs. - function archivePreviousOpChainFaucetsDrippieConfigs() public { - uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey(); - vm.startBroadcast(drippieOwnerPrivateKey); - - Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); - console.log("Archiving OP Chain faucet drips at %s", address(drippie)); - archivePreviousSmallOpChainFaucetsDrips(); - archivePreviousLargeOpChainFaucetsDrips(); - - vm.stopBroadcast(); - - console.log("OP chain faucet drip configs successfully installed"); - } - - /// @notice Archives the previous small OP Chain faucet drips. - function archivePreviousSmallOpChainFaucetsDrips() public { - Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); - uint256 arrayLength = cfg.getSmallFaucetsL1BridgeAddressesCount(); - for (uint256 i = 0; i < arrayLength; i++) { - address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i); - drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED); - drippie.status( - _makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED - ); - drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED); - drippie.status( - _makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED - ); - } - } - - /// @notice Archives the previous large OP Chain faucet drips. - function archivePreviousLargeOpChainFaucetsDrips() public { - Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); - uint256 arrayLength = cfg.getLargeFaucetsL1BridgeAddressesCount(); - for (uint256 i = 0; i < arrayLength; i++) { - address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i); - drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED); - drippie.status( - _makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED - ); - drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED); - drippie.status( - _makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED - ); - } - } - - /// @notice Installs the OnChain AuthModule on the Faucet contract. - function installOnChainAuthModule() public broadcast { - _installAuthModule({ - _faucet: Faucet(mustGetAddress("FaucetProxy")), - _name: "OnChainAuthModule", - _config: Faucet.ModuleConfig({ - name: "OnChainAuthModule", - enabled: true, - ttl: cfg.faucetOnchainAuthModuleTtl(), - amount: cfg.faucetOnchainAuthModuleAmount() - }) - }); - } - - /// @notice Installs the OffChain AuthModule on the Faucet contract. - function installOffChainAuthModule() public broadcast { - _installAuthModule({ - _faucet: Faucet(mustGetAddress("FaucetProxy")), - _name: "OffChainAuthModule", - _config: Faucet.ModuleConfig({ - name: "OffChainAuthModule", - enabled: true, - ttl: cfg.faucetOffchainAuthModuleTtl(), - amount: cfg.faucetOffchainAuthModuleAmount() - }) - }); - } - - /// @notice Installs all of the auth modules in the faucet contract. - function installFaucetAuthModulesConfigs() public { - Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); - console.log("Installing auth modules at %s", address(faucet)); - installOnChainAuthModule(); - installOffChainAuthModule(); - console.log("Faucet Auth Module configs successfully installed"); - } - - /// @notice Generates a drip name for a chain/faucet drip. - /// @param _l1Bridge The address of the L1 bridge. - /// @param _version The version of the drip. - function _makeFaucetDripName(address _l1Bridge, uint256 _version) internal pure returns (string memory) { - string memory dripNamePrefixWithBridgeAddress = string.concat("faucet-drip-", vm.toString(_l1Bridge)); - string memory versionSuffix = string.concat("-", vm.toString(_version)); - return string.concat(dripNamePrefixWithBridgeAddress, versionSuffix); - } - - /// @notice Generates a drip name for a chain/admin wallet drip. - /// @param _l1Bridge The address of the L1 bridge. - /// @param _version The version of the drip. - function _makeAdminWalletDripName(address _l1Bridge, uint256 _version) internal pure returns (string memory) { - string memory dripNamePrefixWithBridgeAddress = string.concat("faucet-admin-drip-", vm.toString(_l1Bridge)); - string memory versionSuffix = string.concat("-", vm.toString(_version)); - return string.concat(dripNamePrefixWithBridgeAddress, versionSuffix); - } - - /// @notice Deploys a contract using the CREATE2 opcode. - /// @param _name The name of the contract. - /// @param _creationCode The contract creation code. - /// @param _constructorParams The constructor parameters. - function _deployCreate2( - string memory _name, - bytes memory _creationCode, - bytes memory _constructorParams - ) - internal - returns (address addr_) - { - bytes32 salt = keccak256(abi.encodePacked(bytes(_name), cfg.create2DeploymentSalt())); - bytes memory initCode = abi.encodePacked(_creationCode, _constructorParams); - address preComputedAddress = vm.computeCreate2Address(salt, keccak256(initCode)); - if (preComputedAddress.code.length > 0) { - console.log("%s already deployed at %s", _name, preComputedAddress); - address savedAddress = getAddress(_name); - if (savedAddress == address(0)) { - save(_name, preComputedAddress); - } else if (savedAddress != preComputedAddress) { - revert AddressMismatch(_name, preComputedAddress, savedAddress); - } - addr_ = preComputedAddress; - } else { - assembly { - addr_ := create2(0, add(initCode, 0x20), mload(initCode), salt) - } - require(addr_ != address(0), "deployment failed"); - save(_name, addr_); - console.log("%s deployed at %s", _name, addr_); - } - } - - /// @notice Installs an auth module in the faucet. - /// @param _faucet The faucet contract. - /// @param _name The name of the auth module. - /// @param _config The configuration of the auth module. - function _installAuthModule(Faucet _faucet, string memory _name, Faucet.ModuleConfig memory _config) internal { - AdminFaucetAuthModule module = AdminFaucetAuthModule(mustGetAddress(_name)); - if (_faucet.isModuleEnabled(module)) { - console.log("%s already installed.", _name); - } else { - console.log("Installing %s", _name); - _faucet.configure(module, _config); - console.log("%s installed successfully", _name); - } - } - - /// @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); - } - - // Attempt to activate the drip. - _drippie.status(_name, Drippie.DripStatus.ACTIVE); - } - - /// @notice Installs a drip that sends ETH to an address if the balance is below a threshold. - /// @param _gelato The gelato contract. - /// @param _drippie The drippie contract. - /// @param _name The name of the drip. - /// @param _target The target address. - /// @param _value The amount of ETH to send. - /// @param _interval The interval that must elapse between drips. - /// @param _threshold The balance threshold. - function _installBalanceLowDrip( - IGelato _gelato, - Drippie _drippie, - string memory _name, - address _target, - uint256 _value, - uint256 _interval, - uint256 _threshold - ) - internal - { - Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); - actions[0] = Drippie.DripAction({ target: payable(_target), data: "", value: _value }); - _installDrip({ - _gelato: _gelato, - _drippie: _drippie, - _name: _name, - _config: Drippie.DripConfig({ - reentrant: false, - interval: _interval, - dripcheck: CheckBalanceLow(mustGetAddress("CheckBalanceLow")), - checkparams: abi.encode(CheckBalanceLow.Params({ target: _target, threshold: _threshold })), - actions: actions - }) - }); - } - - /// @notice Installs a drip that sends ETH through the L1StandardBridge on an interval. - /// @param _gelato The gelato contract. - /// @param _drippie The drippie contract. - /// @param _name The name of the drip. - /// @param _bridge The address of the bridge. - /// @param _target The target address. - /// @param _value The amount of ETH to send. - function _installDepositEthToDrip( - IGelato _gelato, - Drippie _drippie, - string memory _name, - address _bridge, - address _target, - uint256 _value, - uint256 _interval - ) - internal - { - Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); - actions[0] = Drippie.DripAction({ - target: payable(_bridge), - data: abi.encodeCall(L1StandardBridge.depositETHTo, (_target, 200000, "")), - value: _value - }); - _installDrip({ - _gelato: _gelato, - _drippie: _drippie, - _name: _name, - _config: Drippie.DripConfig({ - reentrant: false, - interval: _interval, - dripcheck: CheckTrue(mustGetAddress("CheckTrue")), - checkparams: abi.encode(""), - actions: actions - }) - }); - } - - /// @notice Installs a drip that sends ETH to the Gelato treasury if the balance is below a - /// threshold. Balance gets deposited into the account of the recipient. - /// @param _gelato The gelato contract. - /// @param _drippie The drippie contract. - /// @param _name The name of the drip. - /// @param _treasury The address of the Gelato treasury. - /// @param _recipient The address of the recipient. - /// @param _value The amount of ETH to send. - /// @param _interval The interval that must elapse between drips. - function _installGelatoDrip( - IGelato _gelato, - Drippie _drippie, - string memory _name, - address _treasury, - address _recipient, - uint256 _value, - uint256 _interval, - uint256 _threshold - ) - internal - { - Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); - actions[0] = Drippie.DripAction({ - target: payable(_treasury), - data: abi.encodeWithSignature("depositNative(address)", _recipient), - value: _value - }); - _installDrip({ - _gelato: _gelato, - _drippie: _drippie, - _name: _name, - _config: Drippie.DripConfig({ - reentrant: false, - interval: _interval, - dripcheck: CheckGelatoLow(mustGetAddress("CheckGelatoLow")), - checkparams: abi.encode( - CheckGelatoLow.Params({ recipient: _recipient, threshold: _threshold, treasury: _treasury }) - ), - actions: actions - }) - }); - } - - /// @notice Installs a drip that sends ETH to an account if one given secret is revealed and - /// another is not. Drip will stop if the second secret is revealed. - /// @param _gelato The gelato contract. - /// @param _drippie The drippie contract. - /// @param _name The name of the drip. - /// @param _delay The delay before the drip starts after the first secret is revealed. - /// @param _secretHashMustExist The hash of the secret that must exist. - /// @param _secretHashMustNotExist The hash of the secret that must not exist. - /// @param _target The target address. - /// @param _value The amount of ETH to send. - /// @param _interval The interval that must elapse between drips. - function _installSecretsDrip( - IGelato _gelato, - Drippie _drippie, - string memory _name, - uint256 _delay, - bytes32 _secretHashMustExist, - bytes32 _secretHashMustNotExist, - address _target, - uint256 _value, - uint256 _interval - ) - internal - { - Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); - actions[0] = Drippie.DripAction({ target: payable(_target), data: "", value: _value }); - _installDrip({ - _gelato: _gelato, - _drippie: _drippie, - _name: _name, - _config: Drippie.DripConfig({ - reentrant: false, - interval: _interval, - dripcheck: CheckSecrets(mustGetAddress("CheckSecrets")), - checkparams: abi.encode( - CheckSecrets.Params({ - delay: _delay, - secretHashMustExist: _secretHashMustExist, - secretHashMustNotExist: _secretHashMustNotExist - }) - ), - actions: actions - }) - }); - } -} diff --git a/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol b/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol deleted file mode 100644 index 044806404e40..000000000000 --- a/packages/contracts-bedrock/scripts/PeripheryDeployConfig.s.sol +++ /dev/null @@ -1,194 +0,0 @@ -// 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"; - -/// @title PeripheryDeployConfig -/// @notice Represents the configuration required to deploy the periphery contracts. It is expected -/// to read the file from JSON. A future improvement would be to have fallback -/// values if they are not defined in the JSON themselves. -contract PeripheryDeployConfig is Script { - string internal _json; - - // General configuration. - string public create2DeploymentSalt; - - // 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; - address public faucetOnchainAuthModuleAdmin; - uint256 public faucetOnchainAuthModuleTtl; - uint256 public faucetOnchainAuthModuleAmount; - address public faucetOffchainAuthModuleAdmin; - 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); - 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; - } - - // General configuration. - create2DeploymentSalt = stdJson.readString(_json, "$.create2DeploymentSalt"); - - // 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"); - faucetOnchainAuthModuleAdmin = stdJson.readAddress(_json, "$.faucetOnchainAuthModuleAdmin"); - faucetOnchainAuthModuleTtl = stdJson.readUint(_json, "$.faucetOnchainAuthModuleTtl"); - faucetOnchainAuthModuleAmount = stdJson.readUint(_json, "$.faucetOnchainAuthModuleAmount"); - faucetOffchainAuthModuleAdmin = stdJson.readAddress(_json, "$.faucetOffchainAuthModuleAdmin"); - 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; - } -} diff --git a/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol b/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol new file mode 100644 index 000000000000..834af21231f1 --- /dev/null +++ b/packages/contracts-bedrock/scripts/periphery/deploy/DeployPeriphery.s.sol @@ -0,0 +1,300 @@ +// 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 { Config } from "scripts/Config.sol"; +import { Artifacts } from "scripts/Artifacts.s.sol"; +import { PeripheryDeployConfig } from "scripts/periphery/deploy/PeripheryDeployConfig.s.sol"; + +import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; +import { Proxy } from "src/universal/Proxy.sol"; +import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; +import { Faucet } from "src/periphery/faucet/Faucet.sol"; +import { Drippie } from "src/periphery/drippie/Drippie.sol"; +import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol"; +import { CheckBalanceLow } from "src/periphery/drippie/dripchecks/CheckBalanceLow.sol"; +import { CheckTrue } from "src/periphery/drippie/dripchecks/CheckTrue.sol"; +import { CheckSecrets } from "src/periphery/drippie/dripchecks/CheckSecrets.sol"; +import { AdminFaucetAuthModule } from "src/periphery/faucet/authmodules/AdminFaucetAuthModule.sol"; + +import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; + +/// @title DeployPeriphery +/// @notice Script used to deploy periphery contracts. +contract DeployPeriphery is Script, Artifacts { + /// @notice Error emitted when an address mismatch is detected. + error AddressMismatch(string, address, address); + + /// @notice Deployment configuration. + PeripheryDeployConfig cfg; + + /// @notice Sets up the deployment script. + function setUp() public override { + Artifacts.setUp(); + cfg = new PeripheryDeployConfig(Config.deployConfigPath()); + console.log("Config path: %s", Config.deployConfigPath()); + } + + /// @notice Deploy all of the periphery contracts. + function run() public { + console.log("Deploying periphery contracts"); + + // Optionally deploy the base dripcheck contracts. + if (cfg.deployDripchecks()) { + deployCheckTrue(); + deployCheckBalanceLow(); + deployCheckGelatoLow(); + deployCheckSecrets(); + } + + // Optionally deploy the faucet contracts. + if (cfg.deployFaucetContracts()) { + // Deploy faucet contracts. + deployProxyAdmin(); + deployFaucetProxy(); + deployFaucet(); + deployFaucetDrippie(); + deployOnChainAuthModule(); + deployOffChainAuthModule(); + + // Initialize the faucet. + initializeFaucet(); + installFaucetAuthModulesConfigs(); + } + + // Optionally deploy the operations contracts. + if (cfg.deployOperationsContracts()) { + deployOperationsDrippie(); + } + } + + /// @notice Modifier that wraps a function in broadcasting. + modifier broadcast() { + vm.startBroadcast(); + _; + vm.stopBroadcast(); + } + + /// @notice Deploy ProxyAdmin. + function deployProxyAdmin() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "ProxyAdmin", + _creationCode: type(ProxyAdmin).creationCode, + _constructorParams: abi.encode(msg.sender) + }); + + ProxyAdmin admin = ProxyAdmin(addr_); + require(admin.owner() == msg.sender); + } + + /// @notice Deploy FaucetProxy. + function deployFaucetProxy() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "FaucetProxy", + _creationCode: type(Proxy).creationCode, + _constructorParams: abi.encode(mustGetAddress("ProxyAdmin")) + }); + + Proxy proxy = Proxy(payable(addr_)); + require(EIP1967Helper.getAdmin(address(proxy)) == mustGetAddress("ProxyAdmin")); + } + + /// @notice Deploy the Faucet contract. + function deployFaucet() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "Faucet", + _creationCode: type(Faucet).creationCode, + _constructorParams: abi.encode(cfg.faucetAdmin()) + }); + + Faucet faucet = Faucet(payable(addr_)); + require(faucet.ADMIN() == cfg.faucetAdmin()); + } + + /// @notice Deploy the Drippie contract. + function deployFaucetDrippie() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "FaucetDrippie", + _creationCode: type(Drippie).creationCode, + _constructorParams: abi.encode(cfg.faucetDrippieOwner()) + }); + + Drippie drippie = Drippie(payable(addr_)); + require(drippie.owner() == cfg.faucetDrippieOwner()); + } + + /// @notice Deploy the Drippie contract for standard operations. + function deployOperationsDrippie() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "OperationsDrippie", + _creationCode: type(Drippie).creationCode, + _constructorParams: abi.encode(cfg.operationsDrippieOwner()) + }); + + Drippie drippie = Drippie(payable(addr_)); + require(drippie.owner() == cfg.operationsDrippieOwner()); + } + + /// @notice Deploy On-Chain Authentication Module. + function deployOnChainAuthModule() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "OnChainAuthModule", + _creationCode: type(AdminFaucetAuthModule).creationCode, + _constructorParams: abi.encode(cfg.faucetOnchainAuthModuleAdmin(), "OnChainAuthModule", "1") + }); + + AdminFaucetAuthModule module = AdminFaucetAuthModule(addr_); + require(module.ADMIN() == cfg.faucetOnchainAuthModuleAdmin()); + } + + /// @notice Deploy Off-Chain Authentication Module. + function deployOffChainAuthModule() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "OffChainAuthModule", + _creationCode: type(AdminFaucetAuthModule).creationCode, + _constructorParams: abi.encode(cfg.faucetOffchainAuthModuleAdmin(), "OffChainAuthModule", "1") + }); + + AdminFaucetAuthModule module = AdminFaucetAuthModule(addr_); + require(module.ADMIN() == cfg.faucetOffchainAuthModuleAdmin()); + } + + /// @notice Deploy CheckTrue contract. + function deployCheckTrue() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "CheckTrue", + _creationCode: type(CheckTrue).creationCode, + _constructorParams: hex"" + }); + } + + /// @notice Deploy CheckBalanceLow contract. + function deployCheckBalanceLow() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "CheckBalanceLow", + _creationCode: type(CheckBalanceLow).creationCode, + _constructorParams: hex"" + }); + } + + /// @notice Deploy CheckGelatoLow contract. + function deployCheckGelatoLow() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "CheckGelatoLow", + _creationCode: type(CheckGelatoLow).creationCode, + _constructorParams: hex"" + }); + } + + /// @notice Deploy CheckSecrets contract. + function deployCheckSecrets() public broadcast returns (address addr_) { + addr_ = _deployCreate2({ + _name: "CheckSecrets", + _creationCode: type(CheckSecrets).creationCode, + _constructorParams: hex"" + }); + } + + /// @notice Initialize the Faucet. + function initializeFaucet() public broadcast { + ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin")); + address faucetProxy = mustGetAddress("FaucetProxy"); + address faucet = mustGetAddress("Faucet"); + address implementationAddress = proxyAdmin.getProxyImplementation(faucetProxy); + if (implementationAddress == faucet) { + console.log("Faucet proxy implementation already set"); + } else { + proxyAdmin.upgrade({ _proxy: payable(faucetProxy), _implementation: faucet }); + } + + require(Faucet(payable(faucetProxy)).ADMIN() == Faucet(payable(faucet)).ADMIN()); + } + + /// @notice Installs the OnChain AuthModule on the Faucet contract. + function installOnChainAuthModule() public broadcast { + _installAuthModule({ + _faucet: Faucet(mustGetAddress("FaucetProxy")), + _name: "OnChainAuthModule", + _config: Faucet.ModuleConfig({ + name: "OnChainAuthModule", + enabled: true, + ttl: cfg.faucetOnchainAuthModuleTtl(), + amount: cfg.faucetOnchainAuthModuleAmount() + }) + }); + } + + /// @notice Installs the OffChain AuthModule on the Faucet contract. + function installOffChainAuthModule() public broadcast { + _installAuthModule({ + _faucet: Faucet(mustGetAddress("FaucetProxy")), + _name: "OffChainAuthModule", + _config: Faucet.ModuleConfig({ + name: "OffChainAuthModule", + enabled: true, + ttl: cfg.faucetOffchainAuthModuleTtl(), + amount: cfg.faucetOffchainAuthModuleAmount() + }) + }); + } + + /// @notice Installs all of the auth modules in the faucet contract. + function installFaucetAuthModulesConfigs() public { + Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); + console.log("Installing auth modules at %s", address(faucet)); + installOnChainAuthModule(); + installOffChainAuthModule(); + console.log("Faucet Auth Module configs successfully installed"); + } + + /// @notice Deploys a contract using the CREATE2 opcode. + /// @param _name The name of the contract. + /// @param _creationCode The contract creation code. + /// @param _constructorParams The constructor parameters. + function _deployCreate2( + string memory _name, + bytes memory _creationCode, + bytes memory _constructorParams + ) + internal + returns (address addr_) + { + bytes32 salt = keccak256(abi.encodePacked(bytes(_name), cfg.create2DeploymentSalt())); + bytes memory initCode = abi.encodePacked(_creationCode, _constructorParams); + address preComputedAddress = vm.computeCreate2Address(salt, keccak256(initCode)); + if (preComputedAddress.code.length > 0) { + console.log("%s already deployed at %s", _name, preComputedAddress); + address savedAddress = getAddress(_name); + if (savedAddress == address(0)) { + save(_name, preComputedAddress); + } else if (savedAddress != preComputedAddress) { + revert AddressMismatch(_name, preComputedAddress, savedAddress); + } + addr_ = preComputedAddress; + } else { + assembly { + addr_ := create2(0, add(initCode, 0x20), mload(initCode), salt) + } + require(addr_ != address(0), "deployment failed"); + save(_name, addr_); + console.log("%s deployed at %s", _name, addr_); + } + } + + /// @notice Installs an auth module in the faucet. + /// @param _faucet The faucet contract. + /// @param _name The name of the auth module. + /// @param _config The configuration of the auth module. + function _installAuthModule(Faucet _faucet, string memory _name, Faucet.ModuleConfig memory _config) internal { + AdminFaucetAuthModule module = AdminFaucetAuthModule(mustGetAddress(_name)); + if (_faucet.isModuleEnabled(module)) { + console.log("%s already installed.", _name); + } else { + console.log("Installing %s", _name); + _faucet.configure(module, _config); + console.log("%s installed successfully", _name); + } + } +} diff --git a/packages/contracts-bedrock/scripts/periphery/deploy/PeripheryDeployConfig.s.sol b/packages/contracts-bedrock/scripts/periphery/deploy/PeripheryDeployConfig.s.sol new file mode 100644 index 000000000000..a4a6e2bfa379 --- /dev/null +++ b/packages/contracts-bedrock/scripts/periphery/deploy/PeripheryDeployConfig.s.sol @@ -0,0 +1,76 @@ +// 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"; + +/// @title PeripheryDeployConfig +/// @notice Represents the configuration required to deploy the periphery contracts. It is expected +/// to read the file from JSON. A future improvement would be to have fallback +/// values if they are not defined in the JSON themselves. +contract PeripheryDeployConfig is Script { + string internal _json; + + // General configuration. + string public create2DeploymentSalt; + + // Configuration for Gelato. + address public gelatoAutomateContract; + + // Configuration for standard operations Drippie contract. + address public operationsDrippieOwner; + + // Configuration for the faucet Drippie contract. + address public faucetDrippieOwner; + + // Configuration for the Faucet contract. + address public faucetAdmin; + address public faucetOnchainAuthModuleAdmin; + uint256 public faucetOnchainAuthModuleTtl; + uint256 public faucetOnchainAuthModuleAmount; + address public faucetOffchainAuthModuleAdmin; + uint256 public faucetOffchainAuthModuleTtl; + uint256 public faucetOffchainAuthModuleAmount; + + // Configuration booleans. + bool public deployDripchecks; + bool public deployFaucetContracts; + bool public deployOperationsContracts; + + constructor(string memory _path) { + console.log("PeripheryDeployConfig: 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; + } + + // General configuration. + create2DeploymentSalt = stdJson.readString(_json, "$.create2DeploymentSalt"); + + // Configuration for Gelato. + gelatoAutomateContract = stdJson.readAddress(_json, "$.gelatoAutomateContract"); + + // Configuration for the standard operations Drippie contract. + operationsDrippieOwner = stdJson.readAddress(_json, "$.operationsDrippieOwner"); + + // Configuration for the faucet Drippie contract. + faucetDrippieOwner = stdJson.readAddress(_json, "$.faucetDrippieOwner"); + + // Configuration for the Faucet contract. + faucetAdmin = stdJson.readAddress(_json, "$.faucetAdmin"); + faucetOnchainAuthModuleAdmin = stdJson.readAddress(_json, "$.faucetOnchainAuthModuleAdmin"); + faucetOnchainAuthModuleTtl = stdJson.readUint(_json, "$.faucetOnchainAuthModuleTtl"); + faucetOnchainAuthModuleAmount = stdJson.readUint(_json, "$.faucetOnchainAuthModuleAmount"); + faucetOffchainAuthModuleAdmin = stdJson.readAddress(_json, "$.faucetOffchainAuthModuleAdmin"); + faucetOffchainAuthModuleTtl = stdJson.readUint(_json, "$.faucetOffchainAuthModuleTtl"); + faucetOffchainAuthModuleAmount = stdJson.readUint(_json, "$.faucetOffchainAuthModuleAmount"); + + // Configuration booleans. + deployDripchecks = stdJson.readBool(_json, "$.deployDripchecks"); + deployFaucetContracts = stdJson.readBool(_json, "$.deployFaucetContracts"); + deployOperationsContracts = stdJson.readBool(_json, "$.deployOperationsContracts"); + } +} diff --git a/packages/contracts-bedrock/scripts/periphery/drippie/DrippieConfig.s.sol b/packages/contracts-bedrock/scripts/periphery/drippie/DrippieConfig.s.sol new file mode 100644 index 000000000000..32b1310d42c1 --- /dev/null +++ b/packages/contracts-bedrock/scripts/periphery/drippie/DrippieConfig.s.sol @@ -0,0 +1,148 @@ +// 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)); + } +} diff --git a/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol b/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol new file mode 100644 index 000000000000..dee96d689ffb --- /dev/null +++ b/packages/contracts-bedrock/scripts/periphery/drippie/ManageDrippie.s.sol @@ -0,0 +1,182 @@ +// 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); + } + } +}