diff --git a/contracts/0.4.24/template/LidoTemplate.sol b/contracts/0.4.24/template/LidoTemplate.sol index 0d81fea6a..2e801d493 100644 --- a/contracts/0.4.24/template/LidoTemplate.sol +++ b/contracts/0.4.24/template/LidoTemplate.sol @@ -379,13 +379,12 @@ contract LidoTemplate is IsContract { bytes32 appId = _getAppId(SIMPLE_DVT_APP_NAME, deployState.lidoRegistryEnsNode); dao.setApp(dao.APP_BASES_NAMESPACE(), appId, _impl); - bytes32 stakingRouterRole = deployState.operators.STAKING_ROUTER_ROLE(); address app = address(apmRepos.simpleDVT); // grant perm for staking router // https://github.com/lidofinance/lido-dao/blob/291ea9e191f62692f0a17d6af77b66de0abe0a53/scripts/simpledvt/02-clone-nor.js#L220 - acl.createPermission(_stakingRouter, app,deployState.operators.STAKING_ROUTER_ROLE(),this); + acl.createPermission(_stakingRouter, app,stakingRouterRole,this); acl.grantPermission(deployState.agent, app, stakingRouterRole); _transferPermissionFromTemplate(acl, app, deployState.voting, stakingRouterRole); @@ -393,9 +392,6 @@ contract LidoTemplate is IsContract { // https://github.com/lidofinance/lido-dao/blob/291ea9e191f62692f0a17d6af77b66de0abe0a53/scripts/simpledvt/02-clone-nor.js#L228 acl.createPermission(deployState.agent, app, deployState.operators.MANAGE_SIGNING_KEYS(), deployState.voting); acl.createPermission(deployState.agent, app, deployState.operators.SET_NODE_OPERATOR_LIMIT_ROLE(), deployState.voting); - - // TODO: grant perms to easy track factories ? - // https://github.com/lidofinance/lido-dao/blob/291ea9e191f62692f0a17d6af77b66de0abe0a53/scripts/simpledvt/02-clone-nor.js#L257 } function issueTokens( diff --git a/lib/protocol/helpers/index.ts b/lib/protocol/helpers/index.ts index be5b6a4ac..66c854bbb 100644 --- a/lib/protocol/helpers/index.ts +++ b/lib/protocol/helpers/index.ts @@ -14,6 +14,5 @@ export { report, } from "./accounting"; -export { sdvtEnsureOperators } from "./sdvt.helper"; - -export { norEnsureOperators } from "./nor.helper"; +export { sdvtEnsureOperators } from "./sdvt"; +export { norEnsureOperators } from "./nor"; diff --git a/lib/protocol/helpers/nor.helper.ts b/lib/protocol/helpers/nor.ts similarity index 100% rename from lib/protocol/helpers/nor.helper.ts rename to lib/protocol/helpers/nor.ts diff --git a/lib/protocol/helpers/sdvt.helper.ts b/lib/protocol/helpers/sdvt.ts similarity index 99% rename from lib/protocol/helpers/sdvt.helper.ts rename to lib/protocol/helpers/sdvt.ts index 9d58304fa..85b1981ac 100644 --- a/lib/protocol/helpers/sdvt.helper.ts +++ b/lib/protocol/helpers/sdvt.ts @@ -6,7 +6,7 @@ import { impersonate, log, streccak, trace } from "lib"; import { ether } from "../../units"; import { ProtocolContext } from "../types"; -import { getOperatorManagerAddress, getOperatorName, getOperatorRewardAddress } from "./nor.helper"; +import { getOperatorManagerAddress, getOperatorName, getOperatorRewardAddress } from "./nor"; const MIN_OPS_COUNT = 3n; const MIN_OP_KEYS_COUNT = 10n; diff --git a/scripts/scratch/deployed-testnet-defaults.json b/scripts/scratch/deployed-testnet-defaults.json index 5717913dd..e3524eff1 100644 --- a/scripts/scratch/deployed-testnet-defaults.json +++ b/scripts/scratch/deployed-testnet-defaults.json @@ -132,6 +132,12 @@ "stuckPenaltyDelay": 172800 } }, + "simpleDvt": { + "deployParameters": { + "stakingModuleTypeId": "curated-onchain-v1", + "stuckPenaltyDelay": 432000 + } + }, "withdrawalQueueERC721": { "deployParameters": { "name": "Lido: stETH Withdrawal NFT", diff --git a/scripts/scratch/steps.json b/scripts/scratch/steps.json index ca746d565..c4c125df4 100644 --- a/scripts/scratch/steps.json +++ b/scripts/scratch/steps.json @@ -10,12 +10,12 @@ "scratch/steps/0070-deploy-dao", "scratch/steps/0080-issue-tokens", "scratch/steps/0090-deploy-non-aragon-contracts", - "scratch/steps/0095-deploy-simple-dvt", - "scratch/steps/0100-gate-seal", - "scratch/steps/0110-finalize-dao", - "scratch/steps/0120-initialize-non-aragon-contracts", - "scratch/steps/0130-grant-roles", - "scratch/steps/0140-plug-curated-staking-module", - "scratch/steps/0150-transfer-roles" + "scratch/steps/0100-deploy-simple-dvt", + "scratch/steps/0110-gate-seal", + "scratch/steps/0120-finalize-dao", + "scratch/steps/0130-initialize-non-aragon-contracts", + "scratch/steps/0140-grant-roles", + "scratch/steps/0150-plug-staking-modules", + "scratch/steps/0160-transfer-roles" ] } diff --git a/scripts/scratch/steps/0095-deploy-simple-dvt.ts b/scripts/scratch/steps/0100-deploy-simple-dvt.ts similarity index 93% rename from scripts/scratch/steps/0095-deploy-simple-dvt.ts rename to scripts/scratch/steps/0100-deploy-simple-dvt.ts index 97186db4d..3d1c965e5 100644 --- a/scripts/scratch/steps/0095-deploy-simple-dvt.ts +++ b/scripts/scratch/steps/0100-deploy-simple-dvt.ts @@ -9,9 +9,6 @@ import { readNetworkState, Sk } from "lib/state-file"; const SIMPLE_DVT_APP_NAME = "simple-dvt"; -const SIMPLE_DVT_MODULE_TYPE = "curated-onchain-v1"; -const SIMPLE_DVT_MODULE_PENALTY_DELAY = 86400; // 1 day - const NULL_CONTENT_URI = "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; @@ -86,10 +83,11 @@ async function deploySimpleDvt(deployer: string) { state[Sk.appSimpleDvt].proxy.address, ); + const { stuckPenaltyDelay, stakingModuleTypeId } = state.simpleDvt.deployParameters; const simpleDvtInitOptions = [ lidoLocatorAddress, - "0x" + Buffer.from(SIMPLE_DVT_MODULE_TYPE).toString("hex").padEnd(64, "0"), - SIMPLE_DVT_MODULE_PENALTY_DELAY, + "0x" + Buffer.from(stakingModuleTypeId).toString("hex").padEnd(64, "0"), + stuckPenaltyDelay, ]; await makeTx(proxy, "initialize", simpleDvtInitOptions, { from: deployer }); @@ -104,7 +102,13 @@ async function deploySimpleDvt(deployer: string) { }); } -async function validateSimpleDvt(deployer: string) { +export async function main() { + const deployer = (await ethers.provider.getSigner()).address; + + await deployEmptyAppProxy(deployer, SIMPLE_DVT_APP_NAME); + + await deploySimpleDvt(deployer); + const state = readNetworkState({ deployer }); const proxyAddress = state[Sk.appSimpleDvt].proxy.address; @@ -125,13 +129,3 @@ async function validateSimpleDvt(deployer: string) { expect(await app.hasInitialized()).to.be.true; expect(await app.getLocator()).to.equal(state[Sk.lidoLocator].proxy.address); } - -export async function main() { - const deployer = (await ethers.provider.getSigner()).address; - - await deployEmptyAppProxy(deployer, SIMPLE_DVT_APP_NAME); - - await deploySimpleDvt(deployer); - - await validateSimpleDvt(deployer); -} diff --git a/scripts/scratch/steps/0100-gate-seal.ts b/scripts/scratch/steps/0110-gate-seal.ts similarity index 100% rename from scripts/scratch/steps/0100-gate-seal.ts rename to scripts/scratch/steps/0110-gate-seal.ts diff --git a/scripts/scratch/steps/0110-finalize-dao.ts b/scripts/scratch/steps/0120-finalize-dao.ts similarity index 100% rename from scripts/scratch/steps/0110-finalize-dao.ts rename to scripts/scratch/steps/0120-finalize-dao.ts diff --git a/scripts/scratch/steps/0120-initialize-non-aragon-contracts.ts b/scripts/scratch/steps/0130-initialize-non-aragon-contracts.ts similarity index 100% rename from scripts/scratch/steps/0120-initialize-non-aragon-contracts.ts rename to scripts/scratch/steps/0130-initialize-non-aragon-contracts.ts diff --git a/scripts/scratch/steps/0130-grant-roles.ts b/scripts/scratch/steps/0140-grant-roles.ts similarity index 51% rename from scripts/scratch/steps/0130-grant-roles.ts rename to scripts/scratch/steps/0140-grant-roles.ts index 39c073b7a..b6deb8af6 100644 --- a/scripts/scratch/steps/0130-grant-roles.ts +++ b/scripts/scratch/steps/0140-grant-roles.ts @@ -1,5 +1,7 @@ import { ethers } from "hardhat"; +import { Burner, StakingRouter, ValidatorsExitBusOracle, WithdrawalQueueERC721 } from "typechain-types"; + import { loadContract } from "lib/contract"; import { makeTx } from "lib/deploy"; import { log } from "lib/log"; @@ -10,7 +12,9 @@ export async function main() { const state = readNetworkState({ deployer }); const lidoAddress = state[Sk.appLido].proxy.address; + const agentAddress = state[Sk.appAgent].proxy.address; const nodeOperatorsRegistryAddress = state[Sk.appNodeOperatorsRegistry].proxy.address; + const simpleDvtApp = state[Sk.appSimpleDvt].proxy.address; const gateSealAddress = state.gateSeal.address; const burnerAddress = state[Sk.burner].address; const stakingRouterAddress = state[Sk.stakingRouter].proxy.address; @@ -20,50 +24,50 @@ export async function main() { const depositSecurityModuleAddress = state[Sk.depositSecurityModule].address; // StakingRouter - const stakingRouter = await loadContract("StakingRouter", stakingRouterAddress); + const stakingRouter = await loadContract("StakingRouter", stakingRouterAddress); await makeTx( stakingRouter, "grantRole", - [await stakingRouter.getFunction("STAKING_MODULE_PAUSE_ROLE")(), depositSecurityModuleAddress], + [await stakingRouter.STAKING_MODULE_PAUSE_ROLE(), depositSecurityModuleAddress], { from: deployer }, ); await makeTx( stakingRouter, "grantRole", - [await stakingRouter.getFunction("STAKING_MODULE_RESUME_ROLE")(), depositSecurityModuleAddress], + [await stakingRouter.STAKING_MODULE_RESUME_ROLE(), depositSecurityModuleAddress], { from: deployer }, ); await makeTx( stakingRouter, "grantRole", - [await stakingRouter.getFunction("REPORT_EXITED_VALIDATORS_ROLE")(), accountingOracleAddress], - { from: deployer }, - ); - await makeTx( - stakingRouter, - "grantRole", - [await stakingRouter.getFunction("REPORT_REWARDS_MINTED_ROLE")(), lidoAddress], + [await stakingRouter.REPORT_EXITED_VALIDATORS_ROLE(), accountingOracleAddress], { from: deployer }, ); + await makeTx(stakingRouter, "grantRole", [await stakingRouter.REPORT_REWARDS_MINTED_ROLE(), lidoAddress], { + from: deployer, + }); + await makeTx(stakingRouter, "grantRole", [await stakingRouter.STAKING_MODULE_MANAGE_ROLE(), agentAddress], { + from: deployer, + }); // ValidatorsExitBusOracle if (gateSealAddress) { - const validatorsExitBusOracle = await loadContract("ValidatorsExitBusOracle", validatorsExitBusOracleAddress); - await makeTx( - validatorsExitBusOracle, - "grantRole", - [await validatorsExitBusOracle.getFunction("PAUSE_ROLE")(), gateSealAddress], - { from: deployer }, + const validatorsExitBusOracle = await loadContract( + "ValidatorsExitBusOracle", + validatorsExitBusOracleAddress, ); + await makeTx(validatorsExitBusOracle, "grantRole", [await validatorsExitBusOracle.PAUSE_ROLE(), gateSealAddress], { + from: deployer, + }); } else { log(`GateSeal is not specified or deployed: skipping assigning PAUSE_ROLE of validatorsExitBusOracle`); log.emptyLine(); } // WithdrawalQueue - const withdrawalQueue = await loadContract("WithdrawalQueueERC721", withdrawalQueueAddress); + const withdrawalQueue = await loadContract("WithdrawalQueueERC721", withdrawalQueueAddress); if (gateSealAddress) { - await makeTx(withdrawalQueue, "grantRole", [await withdrawalQueue.getFunction("PAUSE_ROLE")(), gateSealAddress], { + await makeTx(withdrawalQueue, "grantRole", [await withdrawalQueue.PAUSE_ROLE(), gateSealAddress], { from: deployer, }); } else { @@ -71,24 +75,21 @@ export async function main() { log.emptyLine(); } - await makeTx(withdrawalQueue, "grantRole", [await withdrawalQueue.getFunction("FINALIZE_ROLE")(), lidoAddress], { + await makeTx(withdrawalQueue, "grantRole", [await withdrawalQueue.FINALIZE_ROLE(), lidoAddress], { from: deployer, }); - await makeTx( - withdrawalQueue, - "grantRole", - [await withdrawalQueue.getFunction("ORACLE_ROLE")(), accountingOracleAddress], - { from: deployer }, - ); + await makeTx(withdrawalQueue, "grantRole", [await withdrawalQueue.ORACLE_ROLE(), accountingOracleAddress], { + from: deployer, + }); // Burner - const burner = await loadContract("Burner", burnerAddress); + const burner = await loadContract("Burner", burnerAddress); // NB: REQUEST_BURN_SHARES_ROLE is already granted to Lido in Burner constructor - await makeTx( - burner, - "grantRole", - [await burner.getFunction("REQUEST_BURN_SHARES_ROLE")(), nodeOperatorsRegistryAddress], - { from: deployer }, - ); + await makeTx(burner, "grantRole", [await burner.REQUEST_BURN_SHARES_ROLE(), nodeOperatorsRegistryAddress], { + from: deployer, + }); + await makeTx(burner, "grantRole", [await burner.REQUEST_BURN_SHARES_ROLE(), simpleDvtApp], { + from: deployer, + }); } diff --git a/scripts/scratch/steps/0140-plug-curated-staking-module.ts b/scripts/scratch/steps/0150-plug-staking-modules.ts similarity index 72% rename from scripts/scratch/steps/0140-plug-curated-staking-module.ts rename to scripts/scratch/steps/0150-plug-staking-modules.ts index f9180f1f0..db804b77f 100644 --- a/scripts/scratch/steps/0140-plug-curated-staking-module.ts +++ b/scripts/scratch/steps/0150-plug-staking-modules.ts @@ -5,10 +5,15 @@ import { makeTx } from "lib/deploy"; import { streccak } from "lib/keccak"; import { readNetworkState, Sk } from "lib/state-file"; +const STAKING_MODULE_MANAGE_ROLE = streccak("STAKING_MODULE_MANAGE_ROLE"); + const NOR_STAKING_MODULE_TARGET_SHARE_BP = 10000; // 100% const NOR_STAKING_MODULE_MODULE_FEE_BP = 500; // 5% const NOR_STAKING_MODULE_TREASURY_FEE_BP = 500; // 5% -const STAKING_MODULE_MANAGE_ROLE = streccak("STAKING_MODULE_MANAGE_ROLE"); + +const SDVT_STAKING_MODULE_TARGET_SHARE_BP = 50; // 0.5% +const SDVT_STAKING_MODULE_MODULE_FEE_BP = 800; // 8% +const SDVT_STAKING_MODULE_TREASURY_FEE_BP = 200; // 2% export async function main() { const deployer = (await ethers.provider.getSigner()).address; @@ -20,6 +25,7 @@ export async function main() { "NodeOperatorsRegistry", state[Sk.appNodeOperatorsRegistry].proxy.address, ); + const simpleDvt = await loadContract("NodeOperatorsRegistry", state[Sk.appSimpleDvt].proxy.address); // Grant STAKING_MODULE_MANAGE_ROLE to deployer await makeTx(stakingRouter, "grantRole", [STAKING_MODULE_MANAGE_ROLE, deployer], { from: deployer }); @@ -38,6 +44,19 @@ export async function main() { { from: deployer }, ); + await makeTx( + stakingRouter, + "addStakingModule", + [ + state.simpleDvt.deployParameters.stakingModuleTypeId, + simpleDvt.address, + SDVT_STAKING_MODULE_TARGET_SHARE_BP, + SDVT_STAKING_MODULE_MODULE_FEE_BP, + SDVT_STAKING_MODULE_TREASURY_FEE_BP, + ], + { from: deployer }, + ); + // Renounce STAKING_MODULE_MANAGE_ROLE from deployer await makeTx(stakingRouter, "renounceRole", [STAKING_MODULE_MANAGE_ROLE, deployer], { from: deployer }); } diff --git a/scripts/scratch/steps/0150-transfer-roles.ts b/scripts/scratch/steps/0160-transfer-roles.ts similarity index 100% rename from scripts/scratch/steps/0150-transfer-roles.ts rename to scripts/scratch/steps/0160-transfer-roles.ts