Commit e5ee5e3d authored by smartcontracts's avatar smartcontracts Committed by GitHub

maint(ct): clean up periphery deploy script (#10276)

Cleans up the deploy script for periphery contracts. Script was
a bit messy and we need a cleaned up version so that we can
safely deploy and manage Drippie for the Challenger.
parent feb9b5f7
...@@ -10,6 +10,8 @@ import { PeripheryDeployConfig } from "scripts/PeripheryDeployConfig.s.sol"; ...@@ -10,6 +10,8 @@ import { PeripheryDeployConfig } from "scripts/PeripheryDeployConfig.s.sol";
import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
import { Proxy } from "src/universal/Proxy.sol"; import { Proxy } from "src/universal/Proxy.sol";
import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
import { Faucet } from "src/periphery/faucet/Faucet.sol"; import { Faucet } from "src/periphery/faucet/Faucet.sol";
import { Drippie } from "src/periphery/drippie/Drippie.sol"; import { Drippie } from "src/periphery/drippie/Drippie.sol";
import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol"; import { CheckGelatoLow } from "src/periphery/drippie/dripchecks/CheckGelatoLow.sol";
...@@ -24,22 +26,20 @@ import { Config } from "scripts/Config.sol"; ...@@ -24,22 +26,20 @@ import { Config } from "scripts/Config.sol";
contract DeployPeriphery is Script, Artifacts { contract DeployPeriphery is Script, Artifacts {
PeripheryDeployConfig cfg; PeripheryDeployConfig cfg;
/// @notice The name of the script, used to ensure the right deploy artifacts /// @notice The name of the script, used to ensure the right deploy artifacts are used.
/// are used.
function name() public pure returns (string memory name_) { function name() public pure returns (string memory name_) {
name_ = "DeployPeriphery"; name_ = "DeployPeriphery";
} }
/// @notice Sets up the deployment script.
function setUp() public override { function setUp() public override {
Artifacts.setUp(); Artifacts.setUp();
string memory path = string.concat(vm.projectRoot(), "/periphery-deploy-config/", deploymentContext, ".json"); string memory path = string.concat(vm.projectRoot(), "/periphery-deploy-config/", deploymentContext, ".json");
cfg = new PeripheryDeployConfig(path); cfg = new PeripheryDeployConfig(path);
console.log("Deployment context: %s", deploymentContext); console.log("Deployment context: %s", deploymentContext);
} }
/// @notice Deploy all of the periphery contracts /// @notice Deploy all of the periphery contracts.
function run() public { function run() public {
console.log("Deploying all periphery contracts"); console.log("Deploying all periphery contracts");
...@@ -58,14 +58,13 @@ contract DeployPeriphery is Script, Artifacts { ...@@ -58,14 +58,13 @@ contract DeployPeriphery is Script, Artifacts {
} }
} }
/// @notice Deploy all of the proxies /// @notice Deploy all of the proxies.
function deployProxies() public { function deployProxies() public {
deployProxyAdmin(); deployProxyAdmin();
deployFaucetProxy(); deployFaucetProxy();
} }
/// @notice Deploy all of the implementations /// @notice Deploy all of the implementations.
function deployImplementations() public { function deployImplementations() public {
deployFaucet(); deployFaucet();
deployFaucetDrippie(); deployFaucetDrippie();
...@@ -83,145 +82,106 @@ contract DeployPeriphery is Script, Artifacts { ...@@ -83,145 +82,106 @@ contract DeployPeriphery is Script, Artifacts {
vm.stopBroadcast(); vm.stopBroadcast();
} }
/// @notice Deploy the ProxyAdmin /// @notice Deploy ProxyAdmin.
function deployProxyAdmin() public broadcast returns (address addr_) { function deployProxyAdmin() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("ProxyAdmin")); addr_ = _deployCreate2({
bytes32 initCodeHash = keccak256(abi.encodePacked(type(ProxyAdmin).creationCode, abi.encode(msg.sender))); _name: "ProxyAdmin",
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _creationCode: type(ProxyAdmin).creationCode,
if (preComputedAddress.code.length > 0) { _constructorParams: abi.encode(msg.sender)
console.log("ProxyAdmin already deployed at %s", preComputedAddress); });
save("ProxyAdmin", preComputedAddress);
addr_ = preComputedAddress;
} else {
ProxyAdmin admin = new ProxyAdmin{ salt: salt }({ _owner: msg.sender });
require(admin.owner() == msg.sender);
save("ProxyAdmin", address(admin)); ProxyAdmin admin = ProxyAdmin(addr_);
console.log("ProxyAdmin deployed at %s", address(admin)); require(admin.owner() == msg.sender);
addr_ = address(admin);
}
} }
/// @notice Deploy the FaucetProxy /// @notice Deploy FaucetProxy.
function deployFaucetProxy() public broadcast returns (address addr_) { function deployFaucetProxy() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("FaucetProxy")); addr_ = _deployCreate2({
address proxyAdmin = mustGetAddress("ProxyAdmin"); _name: "FaucetProxy",
bytes32 initCodeHash = keccak256(abi.encodePacked(type(Proxy).creationCode, abi.encode(proxyAdmin))); _creationCode: type(Proxy).creationCode,
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _constructorParams: abi.encode(mustGetAddress("ProxyAdmin"))
if (preComputedAddress.code.length > 0) { });
console.log("FaucetProxy already deployed at %s", preComputedAddress);
save("FaucetProxy", preComputedAddress);
addr_ = preComputedAddress;
} else {
Proxy proxy = new Proxy{ salt: salt }({ _admin: proxyAdmin });
require(EIP1967Helper.getAdmin(address(proxy)) == proxyAdmin);
save("FaucetProxy", address(proxy));
console.log("FaucetProxy deployed at %s", address(proxy));
addr_ = address(proxy); Proxy proxy = Proxy(payable(addr_));
} require(EIP1967Helper.getAdmin(address(proxy)) == mustGetAddress("ProxyAdmin"));
} }
/// @notice Deploy the faucet contract. /// @notice Deploy the Faucet contract.
function deployFaucet() public broadcast returns (address addr_) { function deployFaucet() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("Faucet")); addr_ = _deployCreate2({
bytes32 initCodeHash = keccak256(abi.encodePacked(type(Faucet).creationCode, abi.encode(cfg.faucetAdmin()))); _name: "Faucet",
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _creationCode: type(Faucet).creationCode,
if (preComputedAddress.code.length > 0) { _constructorParams: abi.encode(cfg.faucetAdmin())
console.log("Faucet already deployed at %s", preComputedAddress); });
save("Faucet", preComputedAddress);
addr_ = preComputedAddress;
} else {
Faucet faucet = new Faucet{ salt: salt }(cfg.faucetAdmin());
require(faucet.ADMIN() == cfg.faucetAdmin());
save("Faucet", address(faucet));
console.log("Faucet deployed at %s", address(faucet));
addr_ = address(faucet); Faucet faucet = Faucet(payable(addr_));
} require(faucet.ADMIN() == cfg.faucetAdmin());
} }
/// @notice Deploy drippie contract. /// @notice Deploy the Drippie contract.
function deployFaucetDrippie() public broadcast returns (address addr_) { function deployFaucetDrippie() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("FaucetDrippie")); addr_ = _deployCreate2({
bytes32 initCodeHash = _name: "FaucetDrippie",
keccak256(abi.encodePacked(type(Drippie).creationCode, abi.encode(cfg.faucetDrippieOwner()))); _creationCode: type(Drippie).creationCode,
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _constructorParams: abi.encode(cfg.faucetDrippieOwner())
if (preComputedAddress.code.length > 0) { });
console.log("FaucetDrippie already deployed at %s", preComputedAddress);
save("FaucetDrippie", preComputedAddress);
addr_ = preComputedAddress;
} else {
Drippie drippie = new Drippie{ salt: salt }(cfg.faucetDrippieOwner());
save("FaucetDrippie", address(drippie)); Drippie drippie = Drippie(payable(addr_));
console.log("FaucetDrippie deployed at %s", address(drippie)); require(drippie.owner() == cfg.faucetDrippieOwner());
}
addr_ = address(drippie); /// @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 CheckTrue contract. /// @notice Deploy Off-Chain Authentication Module.
function deployCheckTrue() public broadcast returns (address addr_) { function deployOffChainAuthModule() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("CheckTrue")); addr_ = _deployCreate2({
bytes32 initCodeHash = keccak256(abi.encodePacked(type(CheckTrue).creationCode)); _name: "OffChainAuthModule",
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _creationCode: type(AdminFaucetAuthModule).creationCode,
if (preComputedAddress.code.length > 0) { _constructorParams: abi.encode(cfg.faucetOffchainAuthModuleAdmin(), "OffChainAuthModule", "1")
console.log("CheckTrue already deployed at %s", preComputedAddress); });
save("CheckTrue", preComputedAddress);
addr_ = preComputedAddress;
} else {
CheckTrue checkTrue = new CheckTrue{ salt: salt }();
save("CheckTrue", address(checkTrue)); AdminFaucetAuthModule module = AdminFaucetAuthModule(addr_);
console.log("CheckTrue deployed at %s", address(checkTrue)); require(module.ADMIN() == cfg.faucetOffchainAuthModuleAdmin());
}
addr_ = address(checkTrue); /// @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. /// @notice Deploy CheckBalanceLow contract.
function deployCheckBalanceLow() public broadcast returns (address addr_) { function deployCheckBalanceLow() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("CheckBalanceLow")); addr_ = _deployCreate2({
bytes32 initCodeHash = keccak256(abi.encodePacked(type(CheckBalanceLow).creationCode)); _name: "CheckBalanceLow",
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _creationCode: type(CheckBalanceLow).creationCode,
if (preComputedAddress.code.length > 0) { _constructorParams: hex""
console.log("CheckBalanceLow already deployed at %s", preComputedAddress); });
save("CheckBalanceLow", preComputedAddress);
addr_ = preComputedAddress;
} else {
CheckBalanceLow checkBalanceLow = new CheckBalanceLow{ salt: salt }();
save("CheckBalanceLow", address(checkBalanceLow));
console.log("CheckBalanceLow deployed at %s", address(checkBalanceLow));
addr_ = address(checkBalanceLow);
}
} }
/// @notice Deploy CheckGelatoLow contract. /// @notice Deploy CheckGelatoLow contract.
function deployCheckGelatoLow() public broadcast returns (address addr_) { function deployCheckGelatoLow() public broadcast returns (address addr_) {
bytes32 salt = keccak256(bytes("CheckGelatoLow")); addr_ = _deployCreate2({
bytes32 initCodeHash = keccak256(abi.encodePacked(type(CheckGelatoLow).creationCode)); _name: "CheckGelatoLow",
address preComputedAddress = computeCreate2Address(salt, initCodeHash); _creationCode: type(CheckGelatoLow).creationCode,
if (preComputedAddress.code.length > 0) { _constructorParams: hex""
console.log("CheckGelatoLow already deployed at %s", preComputedAddress); });
save("CheckGelatoLow", preComputedAddress);
addr_ = preComputedAddress;
} else {
CheckGelatoLow checkGelatoLow = new CheckGelatoLow{ salt: salt }();
save("CheckGelatoLow", address(checkGelatoLow));
console.log("CheckGelatoLow deployed at %s", address(checkGelatoLow));
addr_ = address(checkGelatoLow);
}
} }
/// @notice Initialize the Faucet /// @notice Initialize the Faucet.
function initializeFaucet() public broadcast { function initializeFaucet() public broadcast {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin")); ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
address faucetProxy = mustGetAddress("FaucetProxy"); address faucetProxy = mustGetAddress("FaucetProxy");
...@@ -236,20 +196,19 @@ contract DeployPeriphery is Script, Artifacts { ...@@ -236,20 +196,19 @@ contract DeployPeriphery is Script, Artifacts {
require(Faucet(payable(faucetProxy)).ADMIN() == Faucet(payable(faucet)).ADMIN()); require(Faucet(payable(faucetProxy)).ADMIN() == Faucet(payable(faucet)).ADMIN());
} }
/// @notice installs the drip configs in the faucet drippie contract. /// @notice Installs the drip configs in the faucet drippie contract.
function installFaucetDrippieConfigs() public { function installFaucetDrippieConfigs() public {
Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); Drippie drippie = Drippie(mustGetAddress("FaucetDrippie"));
console.log("Installing faucet drips at %s", address(drippie)); console.log("Installing faucet drips at %s", address(drippie));
installFaucetDripV1(); installFaucetDripV1();
installFaucetDripV2(); installFaucetDripV2();
installFaucetAdminDripV1(); installFaucetAdminDripV1();
installFaucetGelatoBalanceV1(); installFaucetGelatoBalanceV2();
console.log("Faucet drip configs successfully installed"); console.log("Faucet drip configs successfully installed");
} }
/// @notice installs drip configs that deposit funds to all OP Chain faucets. This function /// @notice Installs drip configs that deposit funds to all OP Chain faucets. This function
/// should only be called on an L1 testnet. /// should only be called on an L1 testnet.
function installOpChainFaucetsDrippieConfigs() public { function installOpChainFaucetsDrippieConfigs() public {
uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey(); uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey();
vm.startBroadcast(drippieOwnerPrivateKey); vm.startBroadcast(drippieOwnerPrivateKey);
...@@ -260,234 +219,165 @@ contract DeployPeriphery is Script, Artifacts { ...@@ -260,234 +219,165 @@ contract DeployPeriphery is Script, Artifacts {
installLargeOpChainFaucetsDrips(); installLargeOpChainFaucetsDrips();
installSmallOpChainAdminWalletDrips(); installSmallOpChainAdminWalletDrips();
installLargeOpChainAdminWalletDrips(); installLargeOpChainAdminWalletDrips();
vm.stopBroadcast();
console.log("OP chain faucet drip configs successfully installed"); console.log("OP chain faucet drip configs successfully installed");
}
/// @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(); vm.stopBroadcast();
console.log("OP chain faucet drip configs successfully installed");
} }
/// @notice installs drips that send funds to small OP chain faucets on the scheduled interval. /// @notice Installs drips that send funds to small OP chain faucets on the scheduled interval.
function installSmallOpChainFaucetsDrips() public { function installSmallOpChainFaucetsDrips() public {
address faucetProxy = mustGetAddress("FaucetProxy"); for (uint256 i = 0; i < cfg.getSmallFaucetsL1BridgeAddressesCount(); i++) {
uint256 arrayLength = cfg.getSmallFaucetsL1BridgeAddressesCount();
for (uint256 i = 0; i < arrayLength; i++) {
address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i); address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i);
_installDepositEthToDrip( _installDepositEthToDrip({
faucetProxy, _drippie: Drippie(mustGetAddress("FaucetDrippie")),
l1BridgeAddress, _name: _makeFaucetDripName(l1BridgeAddress, cfg.dripVersion()),
cfg.smallOpChainFaucetDripValue(), _bridge: l1BridgeAddress,
cfg.smallOpChainFaucetDripInterval(), _target: mustGetAddress("FaucetProxy"),
_faucetDripName(l1BridgeAddress, cfg.dripVersion()) _value: cfg.smallOpChainFaucetDripValue(),
); _interval: cfg.smallOpChainFaucetDripInterval()
});
} }
} }
/// @notice installs drips that send funds to the admin wallets for small OP chain faucets /// @notice Installs drips that send funds to large OP chain faucets on the scheduled interval.
/// on the scheduled interval. function installLargeOpChainFaucetsDrips() public {
for (uint256 i = 0; i < cfg.getLargeFaucetsL1BridgeAddressesCount(); i++) {
address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i);
_installDepositEthToDrip({
_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 { function installSmallOpChainAdminWalletDrips() public {
require( require(
cfg.faucetOnchainAuthModuleAdmin() == cfg.faucetOffchainAuthModuleAdmin(), cfg.faucetOnchainAuthModuleAdmin() == cfg.faucetOffchainAuthModuleAdmin(),
"installSmallOpChainAdminWalletDrips: Only handles identical admin wallet addresses" "installSmallOpChainAdminWalletDrips: Only handles identical admin wallet addresses"
); );
address adminWallet = cfg.faucetOnchainAuthModuleAdmin();
uint256 arrayLength = cfg.getSmallFaucetsL1BridgeAddressesCount(); for (uint256 i = 0; i < cfg.getSmallFaucetsL1BridgeAddressesCount(); i++) {
for (uint256 i = 0; i < arrayLength; i++) {
address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i); address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i);
_installDepositEthToDrip( _installDepositEthToDrip({
adminWallet, _drippie: Drippie(mustGetAddress("FaucetDrippie")),
l1BridgeAddress, _name: _makeAdminWalletDripName(l1BridgeAddress, cfg.dripVersion()),
cfg.opChainAdminWalletDripValue(), _bridge: l1BridgeAddress,
cfg.opChainAdminWalletDripInterval(), _target: cfg.faucetOnchainAuthModuleAdmin(),
_adminWalletDripName(l1BridgeAddress, cfg.dripVersion()) _value: cfg.opChainAdminWalletDripValue(),
); _interval: cfg.opChainAdminWalletDripInterval()
});
} }
} }
/// @notice installs drips that send funds to the admin wallets for large OP chain faucets /// @notice Installs drips that send funds to the admin wallets for large OP chain faucets
/// on the scheduled interval. /// on the scheduled interval.
function installLargeOpChainAdminWalletDrips() public { function installLargeOpChainAdminWalletDrips() public {
require( require(
cfg.faucetOnchainAuthModuleAdmin() == cfg.faucetOffchainAuthModuleAdmin(), cfg.faucetOnchainAuthModuleAdmin() == cfg.faucetOffchainAuthModuleAdmin(),
"installLargeOpChainAdminWalletDrips: Only handles identical admin wallet addresses" "installLargeOpChainAdminWalletDrips: Only handles identical admin wallet addresses"
); );
address adminWallet = cfg.faucetOnchainAuthModuleAdmin();
uint256 arrayLength = cfg.getLargeFaucetsL1BridgeAddressesCount();
for (uint256 i = 0; i < arrayLength; i++) {
address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i);
_installDepositEthToDrip(
adminWallet,
l1BridgeAddress,
cfg.opChainAdminWalletDripValue(),
cfg.opChainAdminWalletDripInterval(),
_adminWalletDripName(l1BridgeAddress, cfg.dripVersion())
);
}
}
/// @notice installs drips that send funds to large OP chain faucets on the scheduled interval. for (uint256 i = 0; i < cfg.getLargeFaucetsL1BridgeAddressesCount(); i++) {
function installLargeOpChainFaucetsDrips() public {
address faucetProxy = mustGetAddress("FaucetProxy");
uint256 arrayLength = cfg.getLargeFaucetsL1BridgeAddressesCount();
for (uint256 i = 0; i < arrayLength; i++) {
address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i); address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i);
_installDepositEthToDrip( _installDepositEthToDrip({
faucetProxy, _drippie: Drippie(mustGetAddress("FaucetDrippie")),
l1BridgeAddress, _name: _makeAdminWalletDripName(l1BridgeAddress, cfg.dripVersion()),
cfg.largeOpChainFaucetDripValue(), _bridge: l1BridgeAddress,
cfg.largeOpChainFaucetDripInterval(), _target: cfg.faucetOnchainAuthModuleAdmin(),
_faucetDripName(l1BridgeAddress, cfg.dripVersion()) _value: cfg.opChainAdminWalletDripValue(),
); _interval: cfg.opChainAdminWalletDripInterval()
});
} }
} }
/// @notice installs the FaucetDripV1 drip on the faucet drippie contract. /// @notice Installs the FaucetDripV1 drip on the faucet drippie contract.
function installFaucetDripV1() public broadcast { function installFaucetDripV1() public broadcast {
Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); _installBalanceLowDrip({
string memory dripName = "FaucetDripV1"; _drippie: Drippie(mustGetAddress("FaucetDrippie")),
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.NONE) { _name: "FaucetDripV1",
console.log("installing %s", dripName); _target: mustGetAddress("FaucetProxy"),
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); _value: cfg.faucetDripV1Value(),
actions[0] = _interval: cfg.faucetDripV1Interval(),
Drippie.DripAction({ target: mustGetAddress("FaucetProxy"), data: "", value: cfg.faucetDripV1Value() }); _threshold: cfg.faucetDripV1Threshold()
drippie.create({ });
_name: dripName,
_config: Drippie.DripConfig({
reentrant: false,
interval: cfg.faucetDripV1Interval(),
dripcheck: CheckBalanceLow(mustGetAddress("CheckBalanceLow")),
checkparams: abi.encode(
CheckBalanceLow.Params({ target: mustGetAddress("FaucetProxy"), threshold: cfg.faucetDripV1Threshold() })
),
actions: actions
})
});
console.log("%s installed successfully", dripName);
} else {
console.log("%s already installed.", dripName);
}
_activateIfPausedDrip(drippie, dripName);
} }
/// @notice installs the FaucetDripV2 drip on the faucet drippie contract. /// @notice Installs the FaucetDripV2 drip on the faucet drippie contract.
function installFaucetDripV2() public broadcast { function installFaucetDripV2() public broadcast {
Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); _installBalanceLowDrip({
string memory dripName = "FaucetDripV2"; _drippie: Drippie(mustGetAddress("FaucetDrippie")),
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.NONE) { _name: "FaucetDripV2",
console.log("installing %s", dripName); _target: mustGetAddress("FaucetProxy"),
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); _value: cfg.faucetDripV2Value(),
actions[0] = _interval: cfg.faucetDripV2Interval(),
Drippie.DripAction({ target: mustGetAddress("FaucetProxy"), data: "", value: cfg.faucetDripV2Value() }); _threshold: cfg.faucetDripV2Threshold()
drippie.create({ });
_name: dripName,
_config: Drippie.DripConfig({
reentrant: false,
interval: cfg.faucetDripV2Interval(),
dripcheck: CheckBalanceLow(mustGetAddress("CheckBalanceLow")),
checkparams: abi.encode(
CheckBalanceLow.Params({ target: mustGetAddress("FaucetProxy"), threshold: cfg.faucetDripV2Threshold() })
),
actions: actions
})
});
console.log("%s installed successfully", dripName);
} else {
console.log("%s already installed.", dripName);
}
_activateIfPausedDrip(drippie, dripName);
} }
/// @notice installs the FaucetAdminDripV1 drip on the faucet drippie contract. /// @notice Installs the FaucetAdminDripV1 drip on the faucet drippie contract.
function installFaucetAdminDripV1() public broadcast { function installFaucetAdminDripV1() public broadcast {
Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); _installBalanceLowDrip({
string memory dripName = "FaucetAdminDripV1"; _drippie: Drippie(mustGetAddress("FaucetDrippie")),
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.NONE) { _name: "FaucetAdminDripV1",
console.log("installing %s", dripName); _target: mustGetAddress("FaucetProxy"),
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); _value: cfg.faucetAdminDripV1Value(),
actions[0] = Drippie.DripAction({ _interval: cfg.faucetAdminDripV1Interval(),
target: mustGetAddress("FaucetProxy"), _threshold: cfg.faucetAdminDripV1Threshold()
data: "", });
value: cfg.faucetAdminDripV1Value() }
});
drippie.create({ /// @notice Installs the GelatoBalanceV2 drip on the faucet drippie contract.
_name: dripName, function installFaucetGelatoBalanceV2() public broadcast {
_config: Drippie.DripConfig({ Drippie.DripAction[] memory actions = new Drippie.DripAction[](1);
reentrant: false, actions[0] = Drippie.DripAction({
interval: cfg.faucetAdminDripV1Interval(), target: payable(cfg.faucetGelatoTreasury()),
dripcheck: CheckBalanceLow(mustGetAddress("CheckBalanceLow")), data: abi.encodeWithSignature(
checkparams: abi.encode( "depositFunds(address,address,uint256)",
CheckBalanceLow.Params({ cfg.faucetGelatoRecipient(),
target: mustGetAddress("FaucetProxy"), // Gelato represents ETH as 0xeeeee....eeeee
threshold: cfg.faucetAdminDripV1Threshold() 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE,
}) cfg.faucetGelatoBalanceV1Value()
), ),
actions: actions value: cfg.faucetGelatoBalanceV1Value()
}) });
}); _installDrip({
console.log("%s installed successfully", dripName); _drippie: Drippie(mustGetAddress("FaucetDrippie")),
} else { _name: "GelatoBalanceV2",
console.log("%s already installed.", dripName); _config: Drippie.DripConfig({
} reentrant: false,
interval: cfg.faucetGelatoBalanceV1DripInterval(),
_activateIfPausedDrip(drippie, dripName); dripcheck: CheckGelatoLow(mustGetAddress("CheckGelatoLow")),
checkparams: abi.encode(
CheckGelatoLow.Params({
recipient: cfg.faucetGelatoRecipient(),
threshold: cfg.faucetGelatoThreshold(),
treasury: cfg.faucetGelatoTreasury()
})
),
actions: actions
})
});
} }
/// @notice installs the GelatoBalanceV1 drip on the faucet drippie contract. /// @notice Archives the previous OP Chain drip configs.
function installFaucetGelatoBalanceV1() public broadcast { function archivePreviousOpChainFaucetsDrippieConfigs() public {
uint256 drippieOwnerPrivateKey = Config.drippieOwnerPrivateKey();
vm.startBroadcast(drippieOwnerPrivateKey);
Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); Drippie drippie = Drippie(mustGetAddress("FaucetDrippie"));
string memory dripName = "GelatoBalanceV2"; console.log("Archiving OP Chain faucet drips at %s", address(drippie));
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.NONE) { archivePreviousSmallOpChainFaucetsDrips();
console.log("installing %s", dripName); archivePreviousLargeOpChainFaucetsDrips();
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1);
actions[0] = Drippie.DripAction({ vm.stopBroadcast();
target: payable(cfg.faucetGelatoTreasury()),
data: abi.encodeWithSignature(
"depositFunds(address,address,uint256)",
cfg.faucetGelatoRecipient(),
// Gelato represents ETH as 0xeeeee....eeeee
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE,
cfg.faucetGelatoBalanceV1Value()
),
value: cfg.faucetGelatoBalanceV1Value()
});
drippie.create({
_name: dripName,
_config: Drippie.DripConfig({
reentrant: false,
interval: cfg.faucetGelatoBalanceV1DripInterval(),
dripcheck: CheckGelatoLow(mustGetAddress("CheckGelatoLow")),
checkparams: abi.encode(
CheckGelatoLow.Params({
recipient: cfg.faucetGelatoRecipient(),
threshold: cfg.faucetGelatoThreshold(),
treasury: cfg.faucetGelatoTreasury()
})
),
actions: actions
})
});
console.log("%s installed successfully", dripName);
} else {
console.log("%s already installed.", dripName);
}
_activateIfPausedDrip(drippie, dripName); console.log("OP chain faucet drip configs successfully installed");
} }
function archivePreviousSmallOpChainFaucetsDrips() public { function archivePreviousSmallOpChainFaucetsDrips() public {
...@@ -495,10 +385,14 @@ contract DeployPeriphery is Script, Artifacts { ...@@ -495,10 +385,14 @@ contract DeployPeriphery is Script, Artifacts {
uint256 arrayLength = cfg.getSmallFaucetsL1BridgeAddressesCount(); uint256 arrayLength = cfg.getSmallFaucetsL1BridgeAddressesCount();
for (uint256 i = 0; i < arrayLength; i++) { for (uint256 i = 0; i < arrayLength; i++) {
address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i); address l1BridgeAddress = cfg.smallFaucetsL1BridgeAddresses(i);
_pauseIfActivatedDrip(drippie, _faucetDripName(l1BridgeAddress, cfg.previousDripVersion())); drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED);
_pauseIfActivatedDrip(drippie, _adminWalletDripName(l1BridgeAddress, cfg.previousDripVersion())); drippie.status(
_archiveIfPausedDrip(drippie, _faucetDripName(l1BridgeAddress, cfg.previousDripVersion())); _makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED
_archiveIfPausedDrip(drippie, _adminWalletDripName(l1BridgeAddress, cfg.previousDripVersion())); );
drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED);
drippie.status(
_makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED
);
} }
} }
...@@ -507,213 +401,197 @@ contract DeployPeriphery is Script, Artifacts { ...@@ -507,213 +401,197 @@ contract DeployPeriphery is Script, Artifacts {
uint256 arrayLength = cfg.getLargeFaucetsL1BridgeAddressesCount(); uint256 arrayLength = cfg.getLargeFaucetsL1BridgeAddressesCount();
for (uint256 i = 0; i < arrayLength; i++) { for (uint256 i = 0; i < arrayLength; i++) {
address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i); address l1BridgeAddress = cfg.largeFaucetsL1BridgeAddresses(i);
_pauseIfActivatedDrip(drippie, _faucetDripName(l1BridgeAddress, cfg.previousDripVersion())); drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED);
_pauseIfActivatedDrip(drippie, _adminWalletDripName(l1BridgeAddress, cfg.previousDripVersion())); drippie.status(
_archiveIfPausedDrip(drippie, _faucetDripName(l1BridgeAddress, cfg.previousDripVersion())); _makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.PAUSED
_archiveIfPausedDrip(drippie, _adminWalletDripName(l1BridgeAddress, cfg.previousDripVersion())); );
} drippie.status(_makeFaucetDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED);
} drippie.status(
_makeAdminWalletDripName(l1BridgeAddress, cfg.previousDripVersion()), Drippie.DripStatus.ARCHIVED
function _activateIfPausedDrip(Drippie drippie, string memory dripName) internal { );
require(
drippie.getDripStatus(dripName) == Drippie.DripStatus.ACTIVE
|| drippie.getDripStatus(dripName) == Drippie.DripStatus.PAUSED,
"attempting to activate a drip that is not currently paused or activated"
);
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.PAUSED) {
console.log("%s is paused, activating", dripName);
drippie.status(dripName, Drippie.DripStatus.ACTIVE);
console.log("%s activated", dripName);
require(drippie.getDripStatus(dripName) == Drippie.DripStatus.ACTIVE);
} else {
console.log("%s already activated", dripName);
}
}
function _pauseIfActivatedDrip(Drippie drippie, string memory dripName) internal {
require(
drippie.getDripStatus(dripName) == Drippie.DripStatus.ACTIVE
|| drippie.getDripStatus(dripName) == Drippie.DripStatus.PAUSED,
"attempting to pause a drip that is not currently paused or activated"
);
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.ACTIVE) {
console.log("%s is active, pausing", dripName);
drippie.status(dripName, Drippie.DripStatus.PAUSED);
console.log("%s paused", dripName);
require(drippie.getDripStatus(dripName) == Drippie.DripStatus.PAUSED);
} else {
console.log("%s already paused", dripName);
}
}
function _archiveIfPausedDrip(Drippie drippie, string memory dripName) internal {
require(
drippie.getDripStatus(dripName) == Drippie.DripStatus.PAUSED
|| drippie.getDripStatus(dripName) == Drippie.DripStatus.ARCHIVED,
"attempting to archive a drip that is not currently paused or archived"
);
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.PAUSED) {
console.log("%s is paused, archiving", dripName);
drippie.status(dripName, Drippie.DripStatus.ARCHIVED);
console.log("%s archived", dripName);
require(drippie.getDripStatus(dripName) == Drippie.DripStatus.ARCHIVED);
} else {
console.log("%s already archived", dripName);
}
}
/// @notice deploys the On-Chain Authentication Module
function deployOnChainAuthModule() public broadcast returns (address addr_) {
string memory moduleName = "OnChainAuthModule";
string memory version = "1";
bytes32 salt = keccak256(bytes("OnChainAuthModule"));
bytes32 initCodeHash = keccak256(
abi.encodePacked(
type(AdminFaucetAuthModule).creationCode,
abi.encode(cfg.faucetOnchainAuthModuleAdmin(), moduleName, version)
)
);
address preComputedAddress = computeCreate2Address(salt, initCodeHash);
if (preComputedAddress.code.length > 0) {
console.log("OnChainAuthModule already deployed at %s", preComputedAddress);
save("OnChainAuthModule", preComputedAddress);
addr_ = preComputedAddress;
} else {
AdminFaucetAuthModule onChainAuthModule =
new AdminFaucetAuthModule{ salt: salt }(cfg.faucetOnchainAuthModuleAdmin(), moduleName, version);
require(onChainAuthModule.ADMIN() == cfg.faucetOnchainAuthModuleAdmin());
save("OnChainAuthModule", address(onChainAuthModule));
console.log("OnChainAuthModule deployed at %s", address(onChainAuthModule));
addr_ = address(onChainAuthModule);
}
}
/// @notice deploys the Off-Chain Authentication Module
function deployOffChainAuthModule() public broadcast returns (address addr_) {
string memory moduleName = "OffChainAuthModule";
string memory version = "1";
bytes32 salt = keccak256(bytes("OffChainAuthModule"));
bytes32 initCodeHash = keccak256(
abi.encodePacked(
type(AdminFaucetAuthModule).creationCode,
abi.encode(cfg.faucetOffchainAuthModuleAdmin(), moduleName, version)
)
);
address preComputedAddress = computeCreate2Address(salt, initCodeHash);
if (preComputedAddress.code.length > 0) {
console.logBytes32(initCodeHash);
console.log("OffChainAuthModule already deployed at %s", preComputedAddress);
save("OffChainAuthModule", preComputedAddress);
addr_ = preComputedAddress;
} else {
AdminFaucetAuthModule offChainAuthModule =
new AdminFaucetAuthModule{ salt: salt }(cfg.faucetOffchainAuthModuleAdmin(), moduleName, version);
require(offChainAuthModule.ADMIN() == cfg.faucetOffchainAuthModuleAdmin());
save("OffChainAuthModule", address(offChainAuthModule));
console.log("OffChainAuthModule deployed at %s", address(offChainAuthModule));
addr_ = address(offChainAuthModule);
} }
} }
/// @notice installs the OnChain AuthModule on the Faucet contract. /// @notice Installs the OnChain AuthModule on the Faucet contract.
function installOnChainAuthModule() public broadcast { function installOnChainAuthModule() public broadcast {
string memory moduleName = "OnChainAuthModule"; _installAuthModule({
Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); _faucet: Faucet(mustGetAddress("FaucetProxy")),
AdminFaucetAuthModule onChainAuthModule = AdminFaucetAuthModule(mustGetAddress(moduleName)); _name: "OnChainAuthModule",
if (faucet.isModuleEnabled(onChainAuthModule)) { _config: Faucet.ModuleConfig({
console.log("%s already installed.", moduleName); name: "OnChainAuthModule",
} else {
console.log("Installing %s", moduleName);
Faucet.ModuleConfig memory myModuleConfig = Faucet.ModuleConfig({
name: moduleName,
enabled: true, enabled: true,
ttl: cfg.faucetOnchainAuthModuleTtl(), ttl: cfg.faucetOnchainAuthModuleTtl(),
amount: cfg.faucetOnchainAuthModuleAmount() amount: cfg.faucetOnchainAuthModuleAmount()
}); })
faucet.configure(onChainAuthModule, myModuleConfig); });
console.log("%s installed successfully", moduleName);
}
} }
/// @notice installs the OffChain AuthModule on the Faucet contract. /// @notice Installs the OffChain AuthModule on the Faucet contract.
function installOffChainAuthModule() public broadcast { function installOffChainAuthModule() public broadcast {
string memory moduleName = "OffChainAuthModule"; _installAuthModule({
Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); _faucet: Faucet(mustGetAddress("FaucetProxy")),
AdminFaucetAuthModule offChainAuthModule = AdminFaucetAuthModule(mustGetAddress(moduleName)); _name: "OffChainAuthModule",
if (faucet.isModuleEnabled(offChainAuthModule)) { _config: Faucet.ModuleConfig({
console.log("%s already installed.", moduleName); name: "OffChainAuthModule",
} else {
console.log("Installing %s", moduleName);
Faucet.ModuleConfig memory myModuleConfig = Faucet.ModuleConfig({
name: moduleName,
enabled: true, enabled: true,
ttl: cfg.faucetOffchainAuthModuleTtl(), ttl: cfg.faucetOffchainAuthModuleTtl(),
amount: cfg.faucetOffchainAuthModuleAmount() amount: cfg.faucetOffchainAuthModuleAmount()
}); })
faucet.configure(offChainAuthModule, myModuleConfig); });
console.log("%s installed successfully", moduleName);
}
} }
/// @notice installs all of the auth module in the faucet contract. /// @notice Installs all of the auth modules in the faucet contract.
function installFaucetAuthModulesConfigs() public { function installFaucetAuthModulesConfigs() public {
Faucet faucet = Faucet(mustGetAddress("FaucetProxy")); Faucet faucet = Faucet(mustGetAddress("FaucetProxy"));
console.log("Installing auth modules at %s", address(faucet)); console.log("Installing auth modules at %s", address(faucet));
installOnChainAuthModule(); installOnChainAuthModule();
installOffChainAuthModule(); installOffChainAuthModule();
console.log("Faucet Auth Module configs successfully installed"); console.log("Faucet Auth Module configs successfully installed");
} }
function _faucetDripName(address _l1Bridge, uint256 version) internal pure returns (string memory) { /// @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 dripNamePrefixWithBridgeAddress = string.concat("faucet-drip-", vm.toString(_l1Bridge));
string memory versionSuffix = string.concat("-", vm.toString(version)); string memory versionSuffix = string.concat("-", vm.toString(_version));
return string.concat(dripNamePrefixWithBridgeAddress, versionSuffix); return string.concat(dripNamePrefixWithBridgeAddress, versionSuffix);
} }
function _adminWalletDripName(address _l1Bridge, uint256 version) internal pure returns (string memory) { /// @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 dripNamePrefixWithBridgeAddress = string.concat("faucet-admin-drip-", vm.toString(_l1Bridge));
string memory versionSuffix = string.concat("-", vm.toString(version)); string memory versionSuffix = string.concat("-", vm.toString(_version));
return string.concat(dripNamePrefixWithBridgeAddress, versionSuffix); return string.concat(dripNamePrefixWithBridgeAddress, versionSuffix);
} }
function _installDepositEthToDrip( // @notice Deploys a contract using the CREATE2 opcode.
address _depositTo, // @param _name The name of the contract.
address _l1Bridge, // @param _creationCode The contract creation code.
uint256 _dripValue, // @param _constructorParams The constructor parameters.
uint256 _dripInterval, function _deployCreate2(
string memory dripName string memory _name,
bytes memory _creationCode,
bytes memory _constructorParams
) )
internal internal
returns (address addr_)
{ {
Drippie drippie = Drippie(mustGetAddress("FaucetDrippie")); bytes32 salt = keccak256(bytes(_name));
if (drippie.getDripStatus(dripName) == Drippie.DripStatus.NONE) { bytes memory initCode = abi.encodePacked(_creationCode, _constructorParams);
console.log("installing %s", dripName); address preComputedAddress = computeCreate2Address(salt, keccak256(initCode));
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1); if (preComputedAddress.code.length > 0) {
actions[0] = Drippie.DripAction({ console.log("%s already deployed at %s", _name, preComputedAddress);
target: payable(_l1Bridge), save(_name, preComputedAddress);
data: abi.encodeWithSignature("depositETHTo(address,uint32,bytes)", _depositTo, 200000, ""), addr_ = preComputedAddress;
value: _dripValue } else {
}); assembly {
drippie.create({ addr_ := create2(0, add(initCode, 0x20), mload(initCode), salt)
_name: dripName, }
_config: Drippie.DripConfig({ require(addr_ != address(0), "deployment failed");
reentrant: false, save(_name, addr_);
interval: _dripInterval, console.log("%s deployed at %s", _name, addr_);
dripcheck: CheckTrue(mustGetAddress("CheckTrue")), }
checkparams: abi.encode(""), }
actions: actions
}) /// @notice Installs an auth module in the faucet.
}); /// @param _faucet The faucet contract.
console.log("%s installed successfully", dripName); /// @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 Installs a drip in the drippie contract.
/// @param _drippie The drippie contract.
/// @param _name The name of the drip.
/// @param _config The configuration of the drip.
function _installDrip(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);
console.log("%s installed successfully", _name);
} else { } else {
console.log("%s already installed.", dripName); console.log("%s already installed", _name);
} }
_activateIfPausedDrip(drippie, dripName); // 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 _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(
Drippie _drippie,
string memory _name,
address payable _target,
uint256 _value,
uint256 _interval,
uint256 _threshold
)
internal
{
Drippie.DripAction[] memory actions = new Drippie.DripAction[](1);
actions[0] = Drippie.DripAction({ target: _target, data: "", value: _value });
_installDrip({
_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 _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(
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({
_drippie: _drippie,
_name: _name,
_config: Drippie.DripConfig({
reentrant: false,
interval: _interval,
dripcheck: CheckTrue(mustGetAddress("CheckTrue")),
checkparams: abi.encode(""),
actions: actions
})
});
} }
} }
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