From a78f24cb66824500307fb7dd5bd876319b49c48f Mon Sep 17 00:00:00 2001 From: 0xvv Date: Wed, 21 Aug 2024 16:16:58 +0200 Subject: [PATCH] deploy script for safe --- .../1_deploy_fee_recipient_implementation.ts | 2 +- deploy/2_deploy_staking_contract.ts | 2 +- ...ploy_mainnet_vault_staking_contract_fix.ts | 2 +- ...eploy_exit_and_withdrawals_contract_fix.ts | 2 +- deploy/6_deploy_safe_staking_contract.ts | 133 ++++++++++++++++++ hardhat.config.ts | 20 ++- 6 files changed, 154 insertions(+), 7 deletions(-) create mode 100644 deploy/6_deploy_safe_staking_contract.ts diff --git a/deploy/1_deploy_fee_recipient_implementation.ts b/deploy/1_deploy_fee_recipient_implementation.ts index 9975262..3afd391 100644 --- a/deploy/1_deploy_fee_recipient_implementation.ts +++ b/deploy/1_deploy_fee_recipient_implementation.ts @@ -16,7 +16,7 @@ const func: DeployFunction = async function ({ }; func.skip = async function ({ deployments, network }: HardhatRuntimeEnvironment): Promise { - const shouldSkip = (await isDeployed("FeeRecipient", deployments)) || network.name.endsWith("_consensys"); + const shouldSkip = (await isDeployed("FeeRecipient", deployments)) || network.name.endsWith("_consensys") || network.name.endsWith("_safe"); if (shouldSkip) { console.log("Skipped"); } diff --git a/deploy/2_deploy_staking_contract.ts b/deploy/2_deploy_staking_contract.ts index 6b0cb0c..93a4c98 100644 --- a/deploy/2_deploy_staking_contract.ts +++ b/deploy/2_deploy_staking_contract.ts @@ -179,7 +179,7 @@ func.skip = async function ({ deployments, network }: HardhatRuntimeEnvironment) const shouldSkip = ((await isDeployed("ConsensusLayerFeeDispatcher_Proxy", deployments)) && (await isDeployed("ExecutionLayerFeeDispatcher_Proxy", deployments)) && - (await isDeployed("StakingContract_Proxy", deployments))) || network.name.endsWith("_consensys"); + (await isDeployed("StakingContract_Proxy", deployments))) || network.name.endsWith("_consensys") || network.name.endsWith("_safe"); if (shouldSkip) { console.log("Skipped"); } diff --git a/deploy/3_deploy_mainnet_vault_staking_contract_fix.ts b/deploy/3_deploy_mainnet_vault_staking_contract_fix.ts index 24ba23c..4ddc8d2 100644 --- a/deploy/3_deploy_mainnet_vault_staking_contract_fix.ts +++ b/deploy/3_deploy_mainnet_vault_staking_contract_fix.ts @@ -18,7 +18,7 @@ const func: DeployFunction = async function ({ }; func.skip = async function ({ deployments, network }: HardhatRuntimeEnvironment): Promise { - const shouldSkip = await isDeployed("StakingContract_1.1_Implementation", deployments) || network.name !== "mainnet_vault" || network.name.endsWith("_consensys") + const shouldSkip = await isDeployed("StakingContract_1.1_Implementation", deployments) || network.name !== "mainnet_vault" || network.name.endsWith("_consensys") || network.name.endsWith("_safe") if (shouldSkip) { console.log("Skipped"); } diff --git a/deploy/4_deploy_exit_and_withdrawals_contract_fix.ts b/deploy/4_deploy_exit_and_withdrawals_contract_fix.ts index 43c63c0..8f54e01 100644 --- a/deploy/4_deploy_exit_and_withdrawals_contract_fix.ts +++ b/deploy/4_deploy_exit_and_withdrawals_contract_fix.ts @@ -24,7 +24,7 @@ const func: DeployFunction = async function ({ }; func.skip = async function ({ deployments, network }: HardhatRuntimeEnvironment): Promise { - const shouldSkip = (await isDeployed("StakingContract_1.2_Implementation", deployments) && await isDeployed("ConsensusLayerFeeDispatcher_1.2_Implementation", deployments)) || network.name.endsWith("_consensys"); + const shouldSkip = (await isDeployed("StakingContract_1.2_Implementation", deployments) && await isDeployed("ConsensusLayerFeeDispatcher_1.2_Implementation", deployments)) || network.name.endsWith("_consensys") || network.name.endsWith("_safe"); if (shouldSkip) { console.log("Skipped"); } diff --git a/deploy/6_deploy_safe_staking_contract.ts b/deploy/6_deploy_safe_staking_contract.ts new file mode 100644 index 0000000..f70ce6c --- /dev/null +++ b/deploy/6_deploy_safe_staking_contract.ts @@ -0,0 +1,133 @@ +import { getContractAddress } from "ethers/lib/utils"; +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { isDeployed } from "../ts_utils/index"; + +const getMaxFeeBps = (network: string): number => { + switch (network) { + case "holesky_dev_safe": + return 1000; + case "mainnet_safe": + return 1000; //10% max user fee + + default: + return 1000; + } +}; + +const getMaxOperatorFeeBps = (network: string): number => { + switch (network) { + case "holesky_dev_safe": + return 10000; + case "mainnet_safe": + return 10000; // Leave the possibility of doing the split onchain in the future + + default: + return 0; + } +}; + +const getFeeBps = (network: string): number => { + switch (network) { + case "holesky_dev_safe": + return 600; + case "mainnet_safe": + return 600; //6% end-user fee + + default: + return 600; + } +}; + +const getOperatorFeeBps = (network: string): number => { + switch (network) { + case "holesky_dev_safe": + return 0; + case "mainnet_safe": + return 0; // at the start all the fees go to the treasury + + default: + return 0; + } +}; + +const func: DeployFunction = async function ({ + deployments, + getNamedAccounts, + ethers, + network, +}: HardhatRuntimeEnvironment) { + const { deployer, admin, depositContract, treasury } = await getNamedAccounts(); + + //1. Deploy Minimal Recipient + const feeRecipientDeployment = await deployments.deploy("FeeRecipient", { + from: deployer, + log: true + }); + + //2. Compute future staking contract address + const signer = await ethers.getSigner(deployer); + const txCount = await signer.getTransactionCount(); + const futureStakingContractAddress = getContractAddress({ + from: deployer, + nonce: txCount + 4, // staking contract proxy is in 5 txs + }); + + //3. Deploy ConsensusLayerFeeDispatcher without proxy + const clfdDeployment = (await deployments.deploy("ConsensusLayerFeeDispatcher", { + from: deployer, + log: true, + args: [0], + })); + + + const clf = await ethers.getContractAt("ConsensusLayerFeeDispatcher", clfdDeployment.address); + await (await clf.initCLD(futureStakingContractAddress)).wait(); + + //4. Deploy ExecutionLayerFeeDispatcher without proxy + const elfdDeployment = await deployments.deploy("ExecutionLayerFeeDispatcher", { + from: deployer, + log: true, + args: [0], + }); + + const elf = await ethers.getContractAt("ExecutionLayerFeeDispatcher", elfdDeployment.address); + await (await elf.initELD(futureStakingContractAddress)).wait(); + + + //5. Deploy StakingContract without proxy + const stakingContractDeployment = await deployments.deploy("StakingContract", { + from: deployer, + log: true, + }); + + const stakingContract = await ethers.getContractAt("StakingContract", stakingContractDeployment.address); + + const initStaking_1 = await stakingContract.initialize_1( + admin, + treasury, + depositContract, + elfdDeployment.address, + clfdDeployment.address, + feeRecipientDeployment.address, + getFeeBps(network.name), + getOperatorFeeBps(network.name), + getMaxFeeBps(network.name), + getMaxOperatorFeeBps(network.name), + ); + await initStaking_1.wait(); + + if (stakingContractDeployment.address.toLowerCase() !== futureStakingContractAddress.toLowerCase()) { + throw new Error("Invalid future deployment address for staking contract"); + } +}; + +func.skip = async function ({ deployments, network }: HardhatRuntimeEnvironment): Promise { + const shouldSkip = network.name !== "holesky_dev_safe" && network.name !== "mainnet_safe"; + if (shouldSkip) { + console.log("Skipped"); + } + return shouldSkip; +}; + +export default func; diff --git a/hardhat.config.ts b/hardhat.config.ts index 7ef415d..c0a2a3f 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -20,6 +20,14 @@ const hhuc: HardhatUserConfig = { sources: "./src/contracts", }, networks: { + mainnet_safe: { + url: process.env.RPC_URL || "", + accounts: [process.env.PK || ""], + }, + holesky_dev_safe: { + url: process.env.RPC_URL || "", + accounts: [process.env.PK || ""], + }, goerli_consensys: { url: process.env.RPC_URL || "", accounts: [process.env.PK || ""], @@ -114,8 +122,10 @@ const hhuc: HardhatUserConfig = { mainnet_enzyme: "0x45DAD754897ef0b2780349AD7c7000c72717b24E", mainnet_komainu: "0xCf53Ef5be9C713585D2fEF40e72D9c7C4fE1D5F2", mainnet_consensys: "0x5Bc5ec5130f66f13d5C21ac6811A7e624ED3C7c6", + mainnet_safe: "0x60CFAC5cD4aEed165023A81F57A0bc92D7CfEb6E", holesky_devnet: "0xb3eb29AC481FCFAFA7008A4acf04737c7d6733EA", - holesky_testnet: "0xe6fe1936Fa8120e57c7Dee1733693B59b392672c" + holesky_testnet: "0xe6fe1936Fa8120e57c7Dee1733693B59b392672c", + holesky_dev_safe: "0xdA53Ce2F763A3270638127CEA2826e32Cd3428e5", }, depositContract: { default: 4, @@ -130,8 +140,10 @@ const hhuc: HardhatUserConfig = { mainnet_enzyme: "0x00000000219ab540356cBB839Cbe05303d7705Fa", mainnet_komainu: "0x00000000219ab540356cBB839Cbe05303d7705Fa", mainnet_consensys: "0x00000000219ab540356cBB839Cbe05303d7705Fa", + mainnet_safe: "0x00000000219ab540356cBB839Cbe05303d7705Fa", holesky_devnet: "0x4242424242424242424242424242424242424242", - holesky_testnet: "0x4242424242424242424242424242424242424242" + holesky_testnet: "0x4242424242424242424242424242424242424242", + holesky_dev_safe: "0x4242424242424242424242424242424242424242", }, treasury: { default: 5, @@ -146,8 +158,10 @@ const hhuc: HardhatUserConfig = { mainnet_enzyme: "0x1ad1fc9964c551f456238Dd88D6a38344B5319D7", mainnet_komainu: "0xCdB0570d55Ebe8c8d678e090F86fa73729EF8Fc7", mainnet_consensys: "0xb631dB8b5D95947025b77bFB44De32eFA8bc15Da", + mainnet_safe: "0xF9beDA1d78916CC89D4B3F6beF092Dc1D302112b", holesky_devnet: "0xb3eb29AC481FCFAFA7008A4acf04737c7d6733EA", - holesky_testnet: "0xe6fe1936Fa8120e57c7Dee1733693B59b392672c" + holesky_testnet: "0xe6fe1936Fa8120e57c7Dee1733693B59b392672c", + holesky_dev_safe: "0xdA53Ce2F763A3270638127CEA2826e32Cd3428e5", }, }, };