From 5e38bb192197d9d2888a0b2011c5753785bfd44c Mon Sep 17 00:00:00 2001 From: maxim Date: Tue, 4 Jun 2024 17:22:10 +0200 Subject: [PATCH 1/7] feat: upgrade accounting oracle --- configs/deployed-holesky-devnet.json | 27 ++++----- programs/omnibus-scripts/index.ts | 1 + programs/omnibus-scripts/upgrade-ao.ts | 79 ++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 programs/omnibus-scripts/upgrade-ao.ts diff --git a/configs/deployed-holesky-devnet.json b/configs/deployed-holesky-devnet.json index e7dd654..8715885 100644 --- a/configs/deployed-holesky-devnet.json +++ b/configs/deployed-holesky-devnet.json @@ -7,14 +7,14 @@ "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol", "address": "0xe38B18b7656f47Dd65c86D17d828fF1c9499ABC9", "constructorArgs": [ - "0xC192F327C92CAa62790f2ccc1648b824db641F95", + "0x6e99b6E2ccB4DfaeA9EaE7C6F7AC694bF45f90D1", "0xB498933ADAaCC74dCf8f1291Cce0C46e66FAAf41", "0x" ] }, "implementation": { "contract": "contracts/0.8.9/oracle/AccountingOracle.sol", - "address": "0xC192F327C92CAa62790f2ccc1648b824db641F95", + "address": "0x6e99b6E2ccB4DfaeA9EaE7C6F7AC694bF45f90D1", "constructorArgs": [ "0x5bF85BadDac33F91B38617c18a3F829f912Ca060", "0xFfC41725C09407E4713FB4d02bc814c40ed15FD1", @@ -144,7 +144,7 @@ "app:node-operators-registry": { "implementation": { "contract": "contracts/0.4.24/nos/NodeOperatorsRegistry.sol", - "address": "0x1De515A9453FABf35D65f649079ea109d5D70383", + "address": "0xc1bcf8fb7352751ba84754158b43347166f8cdfd", "constructorArgs": [] }, "aragonApp": { @@ -461,7 +461,7 @@ }, "implementation": { "contract": "contracts/0.8.9/LidoLocator.sol", - "address": "0xD141C08fD5355b4db880C7a23209ec6b0455f140", + "address": "0x3fb931564DD070cf6C89a3d1e95B9601F64f4C34", "constructorArgs": [ [ "0xe38B18b7656f47Dd65c86D17d828fF1c9499ABC9", @@ -469,7 +469,7 @@ "0x3691a90399f0D0C0d031BB8eB3aB8F121b6cdDC9", "0x233fCE0ED7Df9ac4D05D72f24bf2EF5dC284C2B7", "0xFfC41725C09407E4713FB4d02bc814c40ed15FD1", - "0x3f40cb2aFEc35e8Ae59D35182071872dEb6f73B5", + "0xcC305F5A25BFd87518D8b39CfeE3E9B85D7cE606", "0x233fCE0ED7Df9ac4D05D72f24bf2EF5dC284C2B7", "0x13543040D5100ca3b6c5301b5B9A76C1d1950823", "0x7a290b0153eD799bc86202B7e59317a18Ed36a93", @@ -527,23 +527,24 @@ }, "oracleReportSanityChecker": { "deployParameters": { - "churnValidatorsPerDayLimit": 1500, + "exitedValidatorsPerDayLimit": 1500, "oneOffCLBalanceDecreaseBPLimit": 500, "annualBalanceIncreaseBPLimit": 1000, "simulatedShareRateDeviationBPLimit": 250, - "maxValidatorExitRequestsPerReport": 2000, - "maxAccountingExtraDataListItemsCount": 100, - "maxNodeOperatorsPerExtraDataItemCount": 100, + "maxValidatorExitRequestsPerReport": 25, + "maxAccountingExtraDataListItemsCount": 3, + "maxNodeOperatorsPerExtraDataItemCount": 4, "requestTimestampMargin": 128, - "maxPositiveTokenRebase": 5000000 + "maxPositiveTokenRebase": 5000000, + "appearedValidatorsPerDayLimit": 1500 }, "contract": "contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol", - "address": "0x3f40cb2aFEc35e8Ae59D35182071872dEb6f73B5", + "address": "0xcC305F5A25BFd87518D8b39CfeE3E9B85D7cE606", "constructorArgs": [ "0x5bF85BadDac33F91B38617c18a3F829f912Ca060", "0xB498933ADAaCC74dCf8f1291Cce0C46e66FAAf41", - [1500, 500, 1000, 250, 2000, 100, 100, 128, 5000000], - [[], [], [], [], [], [], [], [], [], []] + [1500, 500, 1000, 250, 25, 3, 4, 128, 5000000, 1500], + [[], [], [], [], [], [], [], [], [], [], []] ] }, "scratchDeployGasUsed": "122457977", diff --git a/programs/omnibus-scripts/index.ts b/programs/omnibus-scripts/index.ts index cdbdf36..ebc799e 100644 --- a/programs/omnibus-scripts/index.ts +++ b/programs/omnibus-scripts/index.ts @@ -1,3 +1,4 @@ export * from './csm'; export * from './staking-router-2'; export * from './upgrade-dsm'; +export * from './upgrade-ao'; diff --git a/programs/omnibus-scripts/upgrade-ao.ts b/programs/omnibus-scripts/upgrade-ao.ts new file mode 100644 index 0000000..48dd365 --- /dev/null +++ b/programs/omnibus-scripts/upgrade-ao.ts @@ -0,0 +1,79 @@ +import { accountingOracleAddress, getAppProxyContract, locatorContract, norAddress } from '@contracts'; +import { encodeFromAgent, updateAragonApp, votingNewVote } from '@scripts'; +import { CallScriptAction, encodeCallScript, forwardVoteFromTm } from '@utils'; +import { Interface } from 'ethers'; + +const LOCATOR_IMPLEMENTAION = '0x3fb931564DD070cf6C89a3d1e95B9601F64f4C34'; +const AO_IMPLEMENTATION = '0x6e99b6E2ccB4DfaeA9EaE7C6F7AC694bF45f90D1'; + +const NOR_IMPLEMENTATION = '0xc1bcf8fb7352751ba84754158b43347166f8cdfd'; +const NOR_CONTENT_URI = + '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; +const NOR_VERSION = ['3', '0', '0']; + +export const accountingOracleV2 = async () => { + const iface = new Interface([ + 'function finalizeUpgrade_v2(uint256)', + 'function finalizeUpgrade_v3()', + 'function proxy__upgradeTo(address)', + ]); + + // 1. Update locator implementation + const locatorProxyAddress = await locatorContract.getAddress(); + const [, locatorScript] = encodeFromAgent({ + to: locatorProxyAddress, + data: iface.encodeFunctionData('proxy__upgradeTo', [LOCATOR_IMPLEMENTAION]), + }); + + // 2. Update accounting oracle implementation + const [, accountingOracleScript] = encodeFromAgent({ + to: accountingOracleAddress, + data: iface.encodeFunctionData('proxy__upgradeTo', [AO_IMPLEMENTATION]), + }); + + // 3. Call finalize upgrade on Accounting Oracle + const accountingOracleFinalizeScript: CallScriptAction = { + to: accountingOracleAddress, + data: iface.encodeFunctionData('finalizeUpgrade_v2', [2]), + }; + + // 4, 5. Update NOR implementation + const norProxyContract = getAppProxyContract(async () => norAddress); + const norAppId = await norProxyContract.appId(); + const [, norNewVersionCall, norSetAppCall] = await updateAragonApp( + NOR_VERSION, + NOR_IMPLEMENTATION, + NOR_CONTENT_URI, + norAppId, + ); + + // 6. Call finalize upgrade on NOR + const norFinalizeScript: CallScriptAction = { + to: norAddress, + data: iface.encodeFunctionData('finalizeUpgrade_v3', []), + }; + + // Collect all calls + const calls: CallScriptAction[] = [ + locatorScript, + accountingOracleScript, + accountingOracleFinalizeScript, + norNewVersionCall, + norSetAppCall, + norFinalizeScript, + ]; + + const description = [ + `1. Update locator implementation to ${LOCATOR_IMPLEMENTAION} with new sanity checker`, + `2. Update accounting oracle implementation ${AO_IMPLEMENTATION}`, + `3. Call finalize upgrade on Accounting Oracle`, + `4. Create new NOR version with address ${NOR_IMPLEMENTATION}`, + `5. Update NOR app to new version`, + `6. Call finalize upgrade on NOR`, + ].join('\n'); + + const voteEvmScript = encodeCallScript(calls); + const [newVoteCalldata] = votingNewVote(voteEvmScript, description); + + await forwardVoteFromTm(newVoteCalldata); +}; From af60ebd0dd19a6d62020e6519d2857c2460aab73 Mon Sep 17 00:00:00 2001 From: Eddort Date: Mon, 10 Jun 2024 13:03:44 +0200 Subject: [PATCH 2/7] feat: devnet1 --- configs/deployed-holesky-devnet1.json | 683 ++++++++++++++++++++++++++ 1 file changed, 683 insertions(+) create mode 100644 configs/deployed-holesky-devnet1.json diff --git a/configs/deployed-holesky-devnet1.json b/configs/deployed-holesky-devnet1.json new file mode 100644 index 0000000..425a789 --- /dev/null +++ b/configs/deployed-holesky-devnet1.json @@ -0,0 +1,683 @@ +{ + "accountingOracle": { + "deployParameters": { + "consensusVersion": 1 + }, + "proxy": { + "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol", + "address": "0x7e475D5B0039840A8C91a6cCfEf763f93010ae4A", + "constructorArgs": [ + "0xc4ADbF6a4fB71D6e360B575f7aac731D60bFb5fF", + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x" + ] + }, + "implementation": { + "contract": "contracts/0.8.9/oracle/AccountingOracle.sol", + "address": "0xc4ADbF6a4fB71D6e360B575f7aac731D60bFb5fF", + "constructorArgs": [ + "0x3F8ae3A6452DC4F7df1E391df39618a9aCF715A6", + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "0x886876B5836BC2B2fa664b80B8cE5c0fF8f0c848", + 12, + 1695902400 + ] + } + }, + "apmRegistryFactory": { + "contract": "@aragon/os/contracts/factory/APMRegistryFactory.sol", + "address": "0xb2CaFB106Ca2ED06F492d5Dd2E0055089C6a894a", + "constructorArgs": [ + "0xE0Fc6541aee99E9aC58553d9C82Af7Ea10C7bc32", + "0x7689FD8D23972176af76B5dc593Bd953dE0740DF", + "0xF37E60D53cEbaaE1b4BEe259245dE9B023b76FC1", + "0x06fC9eB15CaEbf5422ba6a8bBa1A268315A4A318", + "0xaF39245288f94E0bCea7c2c6a7455cfA25C2C3b4", + "0x0000000000000000000000000000000000000000" + ] + }, + "app:aragon-agent": { + "implementation": { + "contract": "@aragon/apps-agent/contracts/Agent.sol", + "address": "0x0Ea07A9496299d31CDb54aaecD61E7750E0460C1", + "constructorArgs": [] + }, + "aragonApp": { + "name": "aragon-agent", + "fullName": "aragon-agent.lidopm.eth", + "id": "0x701a4fd1f5174d12a0f1d9ad2c88d0ad11ab6aad0ac72b7d9ce621815f8016a9" + }, + "proxy": { + "address": "0x636857002fD7975c7B40c0558d4f4834c4390fc6", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0x701a4fd1f5174d12a0f1d9ad2c88d0ad11ab6aad0ac72b7d9ce621815f8016a9", + "0x8129fc1c" + ] + } + }, + "app:aragon-finance": { + "implementation": { + "contract": "@aragon/apps-finance/contracts/Finance.sol", + "address": "0xf354aD122F8FC05004758882daC2186eae590028", + "constructorArgs": [] + }, + "aragonApp": { + "name": "aragon-finance", + "fullName": "aragon-finance.lidopm.eth", + "id": "0x5c9918c99c4081ca9459c178381be71d9da40e49e151687da55099c49a4237f1" + }, + "proxy": { + "address": "0xa8D51Daa3691d69B554868Be17bD26379fc447ed", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0x5c9918c99c4081ca9459c178381be71d9da40e49e151687da55099c49a4237f1", + "0x1798de81000000000000000000000000636857002fd7975c7b40c0558d4f4834c4390fc60000000000000000000000000000000000000000000000000000000000278d00" + ] + } + }, + "app:aragon-token-manager": { + "implementation": { + "contract": "@aragon/apps-lido/apps/token-manager/contracts/TokenManager.sol", + "address": "0x957a1678738eEE99dcEcaC998F7F412F4B244fa6", + "constructorArgs": [] + }, + "aragonApp": { + "name": "aragon-token-manager", + "fullName": "aragon-token-manager.lidopm.eth", + "id": "0xcd567bdf93dd0f6acc3bc7f2155f83244d56a65abbfbefb763e015420102c67b" + }, + "proxy": { + "address": "0xD276A2078a8Ade6ADe8a26BAf550fBf4C1bEd578", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0xcd567bdf93dd0f6acc3bc7f2155f83244d56a65abbfbefb763e015420102c67b", + "0x" + ] + } + }, + "app:aragon-voting": { + "implementation": { + "contract": "@aragon/apps-lido/apps/voting/contracts/Voting.sol", + "address": "0xA80B6DcE9b0f62991EC65e72DfDf9dc656589266", + "constructorArgs": [] + }, + "aragonApp": { + "name": "aragon-voting", + "fullName": "aragon-voting.lidopm.eth", + "id": "0x0abcd104777321a82b010357f20887d61247493d89d2e987ff57bcecbde00e1e" + }, + "proxy": { + "address": "0xcC269aA6688287aA33800fC048A60f418adFcf73", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0x0abcd104777321a82b010357f20887d61247493d89d2e987ff57bcecbde00e1e", + "0x13e09453000000000000000000000000769e1aadf75ab0368d539c69c4461e1d663bca4100000000000000000000000000000000000000000000000006f05b59d3b2000000000000000000000000000000000000000000000000000000b1a2bc2ec500000000000000000000000000000000000000000000000000000000000000000384000000000000000000000000000000000000000000000000000000000000012c" + ] + } + }, + "app:lido": { + "implementation": { + "contract": "contracts/0.4.24/Lido.sol", + "address": "0xc174576C136DCC459b62Bb6515243c6150580239", + "constructorArgs": [] + }, + "aragonApp": { + "name": "lido", + "fullName": "lido.lidopm.eth", + "id": "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320" + }, + "proxy": { + "address": "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0x3ca7c3e38968823ccb4c78ea688df41356f182ae1d159e4ee608d30d68cef320", + "0x" + ] + } + }, + "app:node-operators-registry": { + "implementation": { + "contract": "contracts/0.4.24/nos/NodeOperatorsRegistry.sol", + "address": "0x85A18A4fc633b0a4e7ed39Ea9C137a8837d5c0A3", + "constructorArgs": [] + }, + "aragonApp": { + "name": "node-operators-registry", + "fullName": "node-operators-registry.lidopm.eth", + "id": "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d" + }, + "proxy": { + "address": "0xb1F4fA5E229317A50dDe640964257ECd178A544c", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0x7071f283424072341f856ac9e947e7ec0eb68719f757a7e785979b6b8717579d", + "0x" + ] + } + }, + "app:oracle": { + "implementation": { + "contract": "contracts/0.4.24/oracle/LegacyOracle.sol", + "address": "0x6Ce77CB4C32Bd6dc7dFA0E8801F916Ecb1148B1a", + "constructorArgs": [] + }, + "aragonApp": { + "name": "oracle", + "fullName": "oracle.lidopm.eth", + "id": "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93" + }, + "proxy": { + "address": "0x886876B5836BC2B2fa664b80B8cE5c0fF8f0c848", + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0x8b47ba2a8454ec799cd91646e7ec47168e91fd139b23f017455f3e5898aaba93", + "0x" + ] + } + }, + "aragon-acl": { + "implementation": { + "contract": "@aragon/os/contracts/acl/ACL.sol", + "address": "0xe1906142a28701aA4A09856c2fe31eE9cE660Bb2", + "constructorArgs": [] + }, + "proxy": { + "address": "0x0Cf4dB0E7575FfF708E9E65086f3151DC56BF6f9", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a", + "0x00" + ], + "contract": "@aragon/os/contracts/apps/AppProxyUpgradeable.sol" + }, + "aragonApp": { + "name": "aragon-acl", + "id": "0xe3262375f45a6e2026b7e7b18c2b807434f2508fe1a2a3dfb493c7df8f4aad6a" + } + }, + "aragon-apm-registry": { + "implementation": { + "contract": "@aragon/os/contracts/apm/APMRegistry.sol", + "address": "0x7689FD8D23972176af76B5dc593Bd953dE0740DF", + "constructorArgs": [] + }, + "proxy": { + "address": "0x1a4dfE1e24CC0E3401527894a9A6AAed03837c37" + } + }, + "aragon-evm-script-registry": { + "proxy": { + "address": "0xd6e71F72b46D41CFE9Bd889A5813BE7350d13209", + "constructorArgs": [ + "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61", + "0x00" + ], + "contract": "@aragon/os/contracts/apps/AppProxyPinned.sol" + }, + "aragonApp": { + "name": "aragon-evm-script-registry", + "id": "0xddbcfd564f642ab5627cf68b9b7d374fb4f8a36e941a75d89c87998cef03bd61" + }, + "implementation": { + "address": "0xDF2709E2f8A605bE69F96dFbE706C606Bc0e3106", + "contract": "@aragon/os/contracts/evmscript/EVMScriptRegistry.sol", + "constructorArgs": [] + } + }, + "aragon-kernel": { + "implementation": { + "contract": "@aragon/os/contracts/kernel/Kernel.sol", + "address": "0x2a61f3f7Ebb02bb503FD7A36C89A685841ede0Ba", + "constructorArgs": [ + true + ] + }, + "proxy": { + "address": "0x040Cf3EF1caB45c1210368EaB4f6095D8ebc5e45", + "contract": "@aragon/os/contracts/kernel/KernelProxy.sol", + "constructorArgs": [ + "0x2a61f3f7Ebb02bb503FD7A36C89A685841ede0Ba" + ] + } + }, + "aragon-repo-base": { + "contract": "@aragon/os/contracts/apm/Repo.sol", + "address": "0xF37E60D53cEbaaE1b4BEe259245dE9B023b76FC1", + "constructorArgs": [] + }, + "aragonEnsLabelName": "aragonpm", + "aragonID": { + "address": "0x7C54fAf2a47E83237f9509589274Af44F5bD1AF3", + "contract": "@aragon/id/contracts/FIFSResolvingRegistrar.sol", + "constructorArgs": [ + "0xaF39245288f94E0bCea7c2c6a7455cfA25C2C3b4", + "0x166Ae5Aa0AE00dD40A7b087d95ac09A0556dff7d", + "0x7e74a86b6e146964fb965db04dc2590516da77f720bb6759337bf5632415fd86" + ] + }, + "burner": { + "deployParameters": { + "totalCoverSharesBurnt": "0", + "totalNonCoverSharesBurnt": "0" + }, + "contract": "contracts/0.8.9/Burner.sol", + "address": "0x06fea1a264aAE7c8a91a010d8Bf3a525901fC99D", + "constructorArgs": [ + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x636857002fD7975c7B40c0558d4f4834c4390fc6", + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "0", + "0" + ] + }, + "callsScript": { + "address": "0xeF1273c126e1CB127E5a0f9932850F4fB9C72B7E", + "contract": "@aragon/os/contracts/evmscript/executors/CallsScript.sol", + "constructorArgs": [] + }, + "chainId": 17000, + "chainSpec": { + "slotsPerEpoch": 32, + "secondsPerSlot": 12, + "genesisTime": 1695902400, + "depositContract": "0x4242424242424242424242424242424242424242" + }, + "createAppReposTx": "0x2cc212c681830833c2826f57e4537aed73cfa9422c350675c803406cb39768bf", + "daoAragonId": "lido-dao", + "daoFactory": { + "address": "0xE0Fc6541aee99E9aC58553d9C82Af7Ea10C7bc32", + "contract": "@aragon/os/contracts/factory/DAOFactory.sol", + "constructorArgs": [ + "0x2a61f3f7Ebb02bb503FD7A36C89A685841ede0Ba", + "0xe1906142a28701aA4A09856c2fe31eE9cE660Bb2", + "0xF5Eb85a9FAcC308C7811cc4AFF52Cb0ecd4160F6" + ] + }, + "daoInitialSettings": { + "voting": { + "minSupportRequired": "500000000000000000", + "minAcceptanceQuorum": "50000000000000000", + "voteDuration": 900, + "objectionPhaseDuration": 300 + }, + "fee": { + "totalPercent": 10, + "treasuryPercent": 50, + "nodeOperatorsPercent": 50 + }, + "token": { + "name": "TEST Lido DAO Token", + "symbol": "TLDO" + } + }, + "deployer": "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "depositSecurityModule": { + "deployParameters": { + "maxDepositsPerBlock": 150, + "minDepositBlockDistance": 5, + "pauseIntentValidityPeriodBlocks": 6646, + "usePredefinedAddressInstead": null + }, + "contract": "contracts/0.8.9/DepositSecurityModule.sol", + "address": "0xE9c9FFcC3E837815C99bb661f147B337A8E0C79D", + "constructorArgs": [ + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "0x4242424242424242424242424242424242424242", + "0x0E223ecE606E619132629C898fCa85C138B50Ff3", + 150, + 5, + 6646 + ] + }, + "dummyEmptyContract": { + "contract": "contracts/0.8.9/test_helpers/DummyEmptyContract.sol", + "address": "0xFa82F2e507db21d23c9ba810d2a8C2405738af57", + "constructorArgs": [] + }, + "eip712StETH": { + "contract": "contracts/0.8.9/EIP712StETH.sol", + "address": "0x8e0A176DA59A06618c13151f6eeCC33f5Af5E26f", + "constructorArgs": [ + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F" + ] + }, + "ens": { + "address": "0xaF39245288f94E0bCea7c2c6a7455cfA25C2C3b4", + "constructorArgs": [ + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae" + ], + "contract": "@aragon/os/contracts/lib/ens/ENS.sol" + }, + "ensFactory": { + "contract": "@aragon/os/contracts/factory/ENSFactory.sol", + "address": "0x9D5Bc65B7d7D4A063982bB19ae650AA16FA6992E", + "constructorArgs": [] + }, + "ensNode": { + "nodeName": "aragonpm.eth", + "nodeIs": "0x9065c3e7f7b7ef1ef4e53d2d0b8e0cef02874ab020c1ece79d5f0d3d0111c0ba" + }, + "ensSubdomainRegistrar": { + "implementation": { + "contract": "@aragon/os/contracts/ens/ENSSubdomainRegistrar.sol", + "address": "0x06fC9eB15CaEbf5422ba6a8bBa1A268315A4A318", + "constructorArgs": [] + } + }, + "evmScriptRegistryFactory": { + "contract": "@aragon/os/contracts/factory/EVMScriptRegistryFactory.sol", + "address": "0xF5Eb85a9FAcC308C7811cc4AFF52Cb0ecd4160F6", + "constructorArgs": [] + }, + "executionLayerRewardsVault": { + "contract": "contracts/0.8.9/LidoExecutionLayerRewardsVault.sol", + "address": "0x4e9449097Ff46F783Ee60835e68Aa95Be176C353", + "constructorArgs": [ + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "0x636857002fD7975c7B40c0558d4f4834c4390fc6" + ] + }, + "gateSeal": { + "address": null, + "factoryAddress": null, + "sealDuration": 518400, + "expiryTimestamp": 1714521600, + "sealingCommittee": [] + }, + "hashConsensusForAccountingOracle": { + "deployParameters": { + "fastLaneLengthSlots": 10, + "epochsPerFrame": 12 + }, + "contract": "contracts/0.8.9/oracle/HashConsensus.sol", + "address": "0x68e5987e595F7b6B1eEF87C857993900a7010D68", + "constructorArgs": [ + 32, + 12, + 1695902400, + 12, + 10, + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x7e475D5B0039840A8C91a6cCfEf763f93010ae4A" + ] + }, + "hashConsensusForValidatorsExitBusOracle": { + "deployParameters": { + "fastLaneLengthSlots": 10, + "epochsPerFrame": 4 + }, + "contract": "contracts/0.8.9/oracle/HashConsensus.sol", + "address": "0x0C4cdb56020e69939F8a7c4882eA8194F082B4bd", + "constructorArgs": [ + 32, + 12, + 1695902400, + 4, + 10, + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x1C2382f846DbF89D7d64DA5dD47b4f83076ef803" + ] + }, + "ldo": { + "address": "0x769E1aAdF75AB0368D539c69c4461e1D663bcA41", + "contract": "@aragon/minime/contracts/MiniMeToken.sol", + "constructorArgs": [ + "0xE28D9adC3FD9408e8A16323a58eC613BE560A195", + "0x0000000000000000000000000000000000000000", + 0, + "TEST Lido DAO Token", + 18, + "TLDO", + true + ] + }, + "legacyOracle": { + "deployParameters": { + "lastCompletedEpochId": 0 + } + }, + "lidoApm": { + "deployArguments": [ + "0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae", + "0x90a9580abeb24937fc658e497221c81ce8553b560304f9525821f32b17dbdaec" + ], + "deployTx": "0x810638eee9778d41d8123a5ecb01330ed45d919fe4308630d43e4455dfbb4d92", + "address": "0x844b184802E302e2bAe6f2D683de1acD42F9bcbe" + }, + "lidoApmEnsName": "lidopm.eth", + "lidoApmEnsRegDurationSec": 94608000, + "lidoLocator": { + "proxy": { + "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol", + "address": "0x3F8ae3A6452DC4F7df1E391df39618a9aCF715A6", + "constructorArgs": [ + "0xFa82F2e507db21d23c9ba810d2a8C2405738af57", + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x" + ] + }, + "implementation": { + "contract": "contracts/0.8.9/LidoLocator.sol", + "address": "0x4d50CAC7d2da8c40212D43DcbfB74f921D763af4", + "constructorArgs": [ + [ + "0x7e475D5B0039840A8C91a6cCfEf763f93010ae4A", + "0xE9c9FFcC3E837815C99bb661f147B337A8E0C79D", + "0x4e9449097Ff46F783Ee60835e68Aa95Be176C353", + "0x886876B5836BC2B2fa664b80B8cE5c0fF8f0c848", + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "0xa256cd21d18ebf6099c2B97ddC0Dfc36D7650fAE", + "0x886876B5836BC2B2fa664b80B8cE5c0fF8f0c848", + "0x06fea1a264aAE7c8a91a010d8Bf3a525901fC99D", + "0x0E223ecE606E619132629C898fCa85C138B50Ff3", + "0x636857002fD7975c7B40c0558d4f4834c4390fc6", + "0x1C2382f846DbF89D7d64DA5dD47b4f83076ef803", + "0xc8d7CcbfDc6843bE8227e2Fd36A535F43B9aA7b5", + "0x285fa3Cac35761d183FFff76cBd9776327FC3D49", + "0xD6Bf04C4f563FA260f05C5EB621C991e8B20AB11" + ] + ] + } + }, + "lidoTemplate": { + "contract": "contracts/0.4.24/template/LidoTemplate.sol", + "address": "0x0bA6AE2c53fdd200b8CE1A25019a7F009f3b7E49", + "constructorArgs": [ + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0xE0Fc6541aee99E9aC58553d9C82Af7Ea10C7bc32", + "0xaF39245288f94E0bCea7c2c6a7455cfA25C2C3b4", + "0xE28D9adC3FD9408e8A16323a58eC613BE560A195", + "0x7C54fAf2a47E83237f9509589274Af44F5bD1AF3", + "0xb2CaFB106Ca2ED06F492d5Dd2E0055089C6a894a" + ], + "deployBlock": 1708079 + }, + "lidoTemplateCreateStdAppReposTx": "0x20a36c418f2687631415c13d4bb86f0581401db6c666ea06a547ac7fb318123f", + "lidoTemplateNewDaoTx": "0x9fab156586eac0cfb04fa88c2798439fb7cd6787ce09fdebe5d46ac7b4f29150", + "miniMeTokenFactory": { + "address": "0xE28D9adC3FD9408e8A16323a58eC613BE560A195", + "contract": "@aragon/minime/contracts/MiniMeToken.sol", + "constructorArgs": [] + }, + "networkId": 17000, + "nodeOperatorsRegistry": { + "deployParameters": { + "stakingModuleTypeId": "curated-onchain-v1", + "stuckPenaltyDelay": 172800 + } + }, + "oracleDaemonConfig": { + "deployParameters": { + "NORMALIZED_CL_REWARD_PER_EPOCH": 64, + "NORMALIZED_CL_REWARD_MISTAKE_RATE_BP": 1000, + "REBASE_CHECK_NEAREST_EPOCH_DISTANCE": 1, + "REBASE_CHECK_DISTANT_EPOCH_DISTANCE": 23, + "VALIDATOR_DELAYED_TIMEOUT_IN_SLOTS": 7200, + "VALIDATOR_DELINQUENT_TIMEOUT_IN_SLOTS": 28800, + "NODE_OPERATOR_NETWORK_PENETRATION_THRESHOLD_BP": 100, + "PREDICTION_DURATION_IN_SLOTS": 50400, + "FINALIZATION_MAX_NEGATIVE_REBASE_EPOCH_SHIFT": 1350 + }, + "contract": "contracts/0.8.9/OracleDaemonConfig.sol", + "address": "0xD6Bf04C4f563FA260f05C5EB621C991e8B20AB11", + "constructorArgs": [ + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + [] + ] + }, + "oracleReportSanityChecker": { + "deployParameters": { + "churnValidatorsPerDayLimit": 1500, + "oneOffCLBalanceDecreaseBPLimit": 500, + "annualBalanceIncreaseBPLimit": 1000, + "simulatedShareRateDeviationBPLimit": 250, + "maxValidatorExitRequestsPerReport": 2000, + "maxAccountingExtraDataListItemsCount": 100, + "maxNodeOperatorsPerExtraDataItemCount": 100, + "requestTimestampMargin": 128, + "maxPositiveTokenRebase": 5000000 + }, + "contract": "contracts/0.8.9/sanity_checks/OracleReportSanityChecker.sol", + "address": "0xa256cd21d18ebf6099c2B97ddC0Dfc36D7650fAE", + "constructorArgs": [ + "0x3F8ae3A6452DC4F7df1E391df39618a9aCF715A6", + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + [ + 1500, + 500, + 1000, + 250, + 2000, + 100, + 100, + 128, + 5000000 + ], + [ + [], + [], + [], + [], + [], + [], + [], + [], + [], + [] + ] + ] + }, + "scratchDeployGasUsed": "120354336", + "stakingRouter": { + "proxy": { + "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol", + "address": "0x0E223ecE606E619132629C898fCa85C138B50Ff3", + "constructorArgs": [ + "0x1b1e765E172da905A93d984801a02B24C05C8E9B", + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x" + ] + }, + "implementation": { + "contract": "contracts/0.8.9/StakingRouter.sol", + "address": "0x1b1e765E172da905A93d984801a02B24C05C8E9B", + "constructorArgs": [ + "0x4242424242424242424242424242424242424242" + ] + } + }, + "validatorsExitBusOracle": { + "deployParameters": { + "consensusVersion": 1 + }, + "proxy": { + "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol", + "address": "0x1C2382f846DbF89D7d64DA5dD47b4f83076ef803", + "constructorArgs": [ + "0x49236eE25c8dc0575c8f74D573807f501255BaAb", + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x" + ] + }, + "implementation": { + "contract": "contracts/0.8.9/oracle/ValidatorsExitBusOracle.sol", + "address": "0x49236eE25c8dc0575c8f74D573807f501255BaAb", + "constructorArgs": [ + 12, + 1695902400, + "0x3F8ae3A6452DC4F7df1E391df39618a9aCF715A6" + ] + } + }, + "vestingParams": { + "unvestedTokensAmount": "0", + "holders": { + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae": "940000000000000000000000", + "0x636857002fD7975c7B40c0558d4f4834c4390fc6": "60000000000000000000000" + }, + "start": 0, + "cliff": 0, + "end": 0, + "revokable": false + }, + "withdrawalQueueERC721": { + "deployParameters": { + "name": "Lido: stETH Withdrawal NFT", + "symbol": "unstETH", + "baseUri": null + }, + "proxy": { + "contract": "contracts/0.8.9/proxy/OssifiableProxy.sol", + "address": "0xc8d7CcbfDc6843bE8227e2Fd36A535F43B9aA7b5", + "constructorArgs": [ + "0x7849A33A11DC94E50b0d16E2741e6F558941FA64", + "0x214bA7BE329267fBF53c40768c5a9E77E3a9d6Ae", + "0x" + ] + }, + "implementation": { + "contract": "contracts/0.8.9/WithdrawalQueueERC721.sol", + "address": "0x7849A33A11DC94E50b0d16E2741e6F558941FA64", + "constructorArgs": [ + "0x6106CBA64006FfDd869E10fD0bdAD33393E230FD", + "Lido: stETH Withdrawal NFT", + "unstETH" + ] + } + }, + "withdrawalVault": { + "implementation": { + "contract": "contracts/0.8.9/WithdrawalVault.sol", + "address": "0x4ee2cF7eA3F865793B6D626a6CDd816fB1eAc5f9", + "constructorArgs": [ + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F", + "0x636857002fD7975c7B40c0558d4f4834c4390fc6" + ] + }, + "proxy": { + "contract": "contracts/0.8.4/WithdrawalsManagerProxy.sol", + "address": "0x285fa3Cac35761d183FFff76cBd9776327FC3D49", + "constructorArgs": [ + "0xcC269aA6688287aA33800fC048A60f418adFcf73", + "0x4ee2cF7eA3F865793B6D626a6CDd816fB1eAc5f9" + ] + }, + "address": "0x285fa3Cac35761d183FFff76cBd9776327FC3D49" + }, + "wstETH": { + "contract": "contracts/0.6.12/WstETH.sol", + "address": "0x6106CBA64006FfDd869E10fD0bdAD33393E230FD", + "constructorArgs": [ + "0x4e97Cc8B850f3CE6E06899A09141e9C5EC5eFD3F" + ] + } +} From 83dba6e72c044007a968612af705a08b6b442adb Mon Sep 17 00:00:00 2001 From: George Avsetsin Date: Tue, 11 Jun 2024 14:54:31 +0300 Subject: [PATCH 3/7] feat: sr-v2 upgrade script for devnet-1 --- configs/extra-deployed-holesky-devnet1.json | 1 + programs/omnibus-scripts/csm.ts | 117 ---------- programs/omnibus-scripts/index.ts | 3 - programs/omnibus-scripts/staking-router-2.ts | 226 ++++++++++++++++--- programs/omnibus-scripts/upgrade-ao.ts | 79 ------- programs/omnibus-scripts/upgrade-dsm.ts | 54 ----- 6 files changed, 197 insertions(+), 283 deletions(-) create mode 100644 configs/extra-deployed-holesky-devnet1.json delete mode 100644 programs/omnibus-scripts/csm.ts delete mode 100644 programs/omnibus-scripts/upgrade-ao.ts delete mode 100644 programs/omnibus-scripts/upgrade-dsm.ts diff --git a/configs/extra-deployed-holesky-devnet1.json b/configs/extra-deployed-holesky-devnet1.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/configs/extra-deployed-holesky-devnet1.json @@ -0,0 +1 @@ +{} diff --git a/programs/omnibus-scripts/csm.ts b/programs/omnibus-scripts/csm.ts deleted file mode 100644 index 971b20f..0000000 --- a/programs/omnibus-scripts/csm.ts +++ /dev/null @@ -1,117 +0,0 @@ -import { - aragonAgentAddress, - burnerAddress, - burnerContract, - stakingRouterAddress, - stakingRouterContract, -} from '@contracts'; -import { provider } from '@providers'; -import { encodeFromAgent, votingNewVote } from '@scripts'; -import { CallScriptAction, encodeCallScript, forwardVoteFromTm, getRoleHash } from '@utils'; -import { Contract, Interface } from 'ethers'; - -const CS_MODULE_ADDRESS = '0xddB08564C699D5392a9E9a3C8E2Ab9D7C1949CB6'; -const CS_ACCOUNTING_ADDRESS = '0x9808a94167b30c2F71d2863dbdB8eD9B65ED1DBe'; -const CSM_ORACLE_HASH_CONSENSUS_ADDRESS = '0x8e1249fA85dfe4d6ecdCD56230F9c81Ede6D354a'; - -const MODULE_NAME = 'CommunityStaking'; -const STAKE_SHARE_LIMIT = 2000; // 20% -const PRIORITY_EXIT_SHARE_THRESHOLD = 2500; // 25% -const STAKING_MODULE_FEE = 800; // 8% -const TREASURY_FEE = 200; // 2% -const MAX_DEPOSITS_PER_BLOCK = 30; -const MIN_DEPOSIT_BLOCK_DISTANCE = 25; - -const CSM_ORACLE_INITIAL_EPOCH = 47480; - -export const CSM = async () => { - const iface = new Interface([ - 'function addStakingModule(string,address,uint256,uint256,uint256,uint256,uint256,uint256)', - 'function grantRole(bytes32,address)', - 'function revokeRole(bytes32,address)', - 'function RESUME_ROLE() view returns (bytes32)', - 'function resume()', - 'function updateInitialEpoch(uint256)', - ]); - - // 1. Grant staking module manage role to agent - const moduleManageRoleHash = await getRoleHash(stakingRouterContract, 'STAKING_MODULE_MANAGE_ROLE'); - const [, moduleManageRoleGrantScript] = encodeFromAgent({ - to: stakingRouterAddress, - data: iface.encodeFunctionData('grantRole', [moduleManageRoleHash, aragonAgentAddress]), - }); - - // 2. Add staking module - const [, addModuleScript] = encodeFromAgent({ - to: stakingRouterAddress, - data: iface.encodeFunctionData('addStakingModule', [ - MODULE_NAME, - CS_MODULE_ADDRESS, - STAKE_SHARE_LIMIT, - PRIORITY_EXIT_SHARE_THRESHOLD, - STAKING_MODULE_FEE, - TREASURY_FEE, - MAX_DEPOSITS_PER_BLOCK, - MIN_DEPOSIT_BLOCK_DISTANCE, - ]), - }); - - // 3. Grant request burn role to CSAccounting contract - const requestBurnRoleHash = await getRoleHash(burnerContract, 'REQUEST_BURN_SHARES_ROLE'); - const [, requestBurnRoleGrantScript] = encodeFromAgent({ - to: burnerAddress, - data: iface.encodeFunctionData('grantRole', [requestBurnRoleHash, CS_ACCOUNTING_ADDRESS]), - }); - - // 4. Grant resume role to agent - const contract = new Contract(CS_MODULE_ADDRESS, iface, provider); - const resumeRoleHash = await getRoleHash(contract, 'RESUME_ROLE'); - const resumeRoleGrantScript: CallScriptAction = { - to: CS_MODULE_ADDRESS, - data: iface.encodeFunctionData('grantRole', [resumeRoleHash, aragonAgentAddress]), - }; - - // 5. Resume staking module - const [, resumeScript] = encodeFromAgent({ - to: CS_MODULE_ADDRESS, - data: iface.encodeFunctionData('resume', []), - }); - - // 6. Revoke resume role from agent - const resumeRoleRevokeScript: CallScriptAction = { - to: CS_MODULE_ADDRESS, - data: iface.encodeFunctionData('revokeRole', [resumeRoleHash, aragonAgentAddress]), - }; - - // 7. Update initial epoch - const updateInitialEpochScript: CallScriptAction = { - to: CSM_ORACLE_HASH_CONSENSUS_ADDRESS, - data: iface.encodeFunctionData('updateInitialEpoch', [CSM_ORACLE_INITIAL_EPOCH]), - }; - - // Collect all calls - const calls: CallScriptAction[] = [ - moduleManageRoleGrantScript, - addModuleScript, - requestBurnRoleGrantScript, - resumeRoleGrantScript, - resumeScript, - resumeRoleRevokeScript, - updateInitialEpochScript, - ]; - - const description = [ - `1. Grant staking module manage role to agent`, - `2. Add CSM with address ${CS_MODULE_ADDRESS} to the staking router`, - `3. Grant request burn shares role CSAccounting contract with address ${CS_ACCOUNTING_ADDRESS}`, - `4. Grant resume role to agent`, - `5. Resume CSModule`, - `6. Revoke resume role from agent`, - `7. Update initial epoch of CSM Oracle to ${CSM_ORACLE_INITIAL_EPOCH}`, - ].join('\n'); - - const voteEvmScript = encodeCallScript(calls); - const [newVoteCalldata] = votingNewVote(voteEvmScript, description); - - await forwardVoteFromTm(newVoteCalldata); -}; diff --git a/programs/omnibus-scripts/index.ts b/programs/omnibus-scripts/index.ts index ebc799e..20ce88a 100644 --- a/programs/omnibus-scripts/index.ts +++ b/programs/omnibus-scripts/index.ts @@ -1,4 +1 @@ -export * from './csm'; export * from './staking-router-2'; -export * from './upgrade-dsm'; -export * from './upgrade-ao'; diff --git a/programs/omnibus-scripts/staking-router-2.ts b/programs/omnibus-scripts/staking-router-2.ts index 9cab929..e2605fe 100644 --- a/programs/omnibus-scripts/staking-router-2.ts +++ b/programs/omnibus-scripts/staking-router-2.ts @@ -1,4 +1,10 @@ import { + accountingOracleAddress, + aragonAgentAddress, + burnerAddress, + burnerContract, + exitBusOracleAddress, + exitBusOracleContract, getAppProxyContract, locatorContract, norAddress, @@ -10,101 +16,261 @@ import { encodeFromAgent, updateAragonApp, votingNewVote } from '@scripts'; import { CallScriptAction, encodeCallScript, forwardVoteFromTm, getRoleHash } from '@utils'; import { Contract, Interface } from 'ethers'; -const LOCATOR_IMPLEMENTAION = '0xa12Fd7c4c75D78E208B203EDc96053E33BdBFab8'; +// SR 2 -const OLD_DSM = '0x336c1efd15284104a04e705f430e4d4a7fc2c6c1'; -const NEW_DSM = '0xb8ae82f7bff2553baf158b7a911dc10162045c53'; +const LOCATOR_IMPLEMENTAION = '0xcf720cb5635523ed1de57bb0d984445f6b7ca628'; +const STAKING_ROUTER_IMPLEMENTATION = '0x43DAe324195BcCf10999673092522084Fc46116E'; +const AO_IMPLEMENTATION = '0x382ec3b6471ca45821332c47a1740939a0ac4359'; -const STAKING_ROUTER_IMPLEMENTATION = '0xb1867e93aea81975cf11b8415ccd70e9b07e09a6'; +const OLD_DSM = '0xE9c9FFcC3E837815C99bb661f147B337A8E0C79D'; +const NEW_DSM = '0x9078C4e99A3b29f77164Da4892f68abA498cF5D9'; -const NOR_IMPLEMENTATION = '0x287278aaac35e5e52b0f7266872139812d32679b'; -const NOR_CONTENT_URI = - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; +const NOR_IMPLEMENTATION = '0xcd4569620ac8c0eb8821d16c714c8b1a7b3f10a8'; +const NOR_CONTENT_URI = '0x' + '00'.repeat(51); const NOR_VERSION = ['2', '0', '0']; const PRIORITY_EXIT_SHARE_THRESHOLDS_BP = [10_000]; +const MAX_DEPOSITS_PER_BLOCK = [50]; +const MIN_DEPOSIT_BLOCK_DISTANCES = [25]; + +const AO_CONSENSUS_VERSION = 2; +const VEBO_CONSENSUS_VERSION = 2; + +// CSM + +const CS_MODULE_ADDRESS = '0xb43fD1a6932345e5A0dc72a2b397c09f3390c1D0'; +const CS_ACCOUNTING_ADDRESS = '0x9bd601f8b7A0F24fA58f6502EEC077Dc753476f6'; +const CS_ORACLE_HASH_CONSENSUS_ADDRESS = '0xd2776403ADbc77958DD3DF490cDbCD2f4dFCf021'; + +const CS_MODULE_NAME = 'CommunityStaking'; +const CS_STAKE_SHARE_LIMIT = 2000; // 20% +const CS_PRIORITY_EXIT_SHARE_THRESHOLD = 2500; // 25% +const CS_STAKING_MODULE_FEE = 800; // 8% +const CS_TREASURY_FEE = 200; // 2% +const CS_MAX_DEPOSITS_PER_BLOCK = 30; +const CS_MIN_DEPOSIT_BLOCK_DISTANCE = 25; + +const CS_ORACLE_INITIAL_EPOCH = 57606; // 57600 for ao and vebo export const stakingRouterV2 = async () => { const iface = new Interface([ - 'function finalizeUpgrade_v2(uint256[])', 'function proxy__upgradeTo(address)', + 'function finalizeUpgrade_v2(uint256[],uint256[],uint256[])', + 'function finalizeUpgrade_v2(uint256)', + 'function finalizeUpgrade_v3()', 'function revokeRole(bytes32,address)', 'function grantRole(bytes32,address)', 'function STAKING_MODULE_UNVETTING_ROLE() view returns (bytes32)', + 'function RESUME_ROLE() view returns (bytes32)', + 'function resume()', + 'function updateInitialEpoch(uint256)', + 'function addStakingModule(string,address,uint256,uint256,uint256,uint256,uint256,uint256)', + 'function setConsensusVersion(uint256)', ]); - // 1. Update locator implementation + /** + * SR 2 + */ + + // 1. Update Locator implementation const locatorProxyAddress = await locatorContract.getAddress(); - const [, locatorScript] = encodeFromAgent({ + const [, locatorUpgradeScript] = encodeFromAgent({ to: locatorProxyAddress, data: iface.encodeFunctionData('proxy__upgradeTo', [LOCATOR_IMPLEMENTAION]), }); // 2. Revoke pause role from old DSM - const pauseRoleHash = await getRoleHash(stakingRouterContract, 'STAKING_MODULE_PAUSE_ROLE'); - const [, pauseRoleRevokeScript] = encodeFromAgent({ + const srPauseRoleHash = await getRoleHash(stakingRouterContract, 'STAKING_MODULE_PAUSE_ROLE'); + const [, pauseRoleRevokeFromOldDSMScript] = encodeFromAgent({ to: stakingRouterAddress, - data: iface.encodeFunctionData('revokeRole', [pauseRoleHash, OLD_DSM]), + data: iface.encodeFunctionData('revokeRole', [srPauseRoleHash, OLD_DSM]), }); // 3. Revoke resume role from old DSM - const resumeRoleHash = await getRoleHash(stakingRouterContract, 'STAKING_MODULE_RESUME_ROLE'); - const [, resumeRoleRevokeScript] = encodeFromAgent({ + const srResumeRoleHash = await getRoleHash(stakingRouterContract, 'STAKING_MODULE_RESUME_ROLE'); + const [, resumeRoleRevokeFromOldDSMScript] = encodeFromAgent({ to: stakingRouterAddress, - data: iface.encodeFunctionData('revokeRole', [resumeRoleHash, OLD_DSM]), + data: iface.encodeFunctionData('revokeRole', [srResumeRoleHash, OLD_DSM]), }); // 4. Grant unvetting role to new DSM const stakingRouterImplContract = new Contract(STAKING_ROUTER_IMPLEMENTATION, iface, provider); const unvettingRoleHash = await getRoleHash(stakingRouterImplContract, 'STAKING_MODULE_UNVETTING_ROLE'); - const [, unvettingRoleGrantScript] = encodeFromAgent({ + const [, unvettingRoleGrantToDSMScript] = encodeFromAgent({ to: stakingRouterAddress, data: iface.encodeFunctionData('grantRole', [unvettingRoleHash, NEW_DSM]), }); - // 5. Update staking router implementation + // 5. Update SR implementation const [, stakingRouterUpdateScript] = encodeFromAgent({ to: stakingRouterAddress, data: iface.encodeFunctionData('proxy__upgradeTo', [STAKING_ROUTER_IMPLEMENTATION]), }); - // 6. Call finalize upgrade on Staking Router + // 6. Call finalize upgrade on SR const stakingRouterFinalizeScript: CallScriptAction = { to: stakingRouterAddress, - data: iface.encodeFunctionData('finalizeUpgrade_v2', [PRIORITY_EXIT_SHARE_THRESHOLDS_BP]), + data: iface.encodeFunctionData('finalizeUpgrade_v2(uint256[],uint256[],uint256[])', [ + PRIORITY_EXIT_SHARE_THRESHOLDS_BP, + MAX_DEPOSITS_PER_BLOCK, + MIN_DEPOSIT_BLOCK_DISTANCES, + ]), }; // 7, 8. Update NOR implementation const norProxyContract = getAppProxyContract(async () => norAddress); const norAppId = await norProxyContract.appId(); - const [, norNewVersionCall, norSetAppCall] = await updateAragonApp( + const [, norNewVersionBumpScript, norSetAppScript] = await updateAragonApp( NOR_VERSION, NOR_IMPLEMENTATION, NOR_CONTENT_URI, norAppId, ); + // 9. Call finalize upgrade on NOR + const norFinalizeScript: CallScriptAction = { + to: norAddress, + data: iface.encodeFunctionData('finalizeUpgrade_v3', []), + }; + + // 10. Update AO implementation + const [, accountingOracleUpgradeScript] = encodeFromAgent({ + to: accountingOracleAddress, + data: iface.encodeFunctionData('proxy__upgradeTo', [AO_IMPLEMENTATION]), + }); + + // 11. Call finalize upgrade on AO + const accountingOracleFinalizeScript: CallScriptAction = { + to: accountingOracleAddress, + data: iface.encodeFunctionData('finalizeUpgrade_v2(uint256)', [AO_CONSENSUS_VERSION]), + }; + + // 12. Grant manage consensus role to agent + const manageConsensusRoleHash = await getRoleHash(exitBusOracleContract, 'MANAGE_CONSENSUS_VERSION_ROLE'); + const [, manageConsensusRoleGrantToAgentScript] = encodeFromAgent({ + to: exitBusOracleAddress, + data: iface.encodeFunctionData('grantRole', [manageConsensusRoleHash, aragonAgentAddress]), + }); + + // 13. Update VEBO consensus version + const [, exitBusOracleVersionScript] = encodeFromAgent({ + to: exitBusOracleAddress, + data: iface.encodeFunctionData('setConsensusVersion', [VEBO_CONSENSUS_VERSION]), + }); + + /** + * CSM + */ + + // 14. Grant staking module manage role to agent + const srModuleManageRoleHash = await getRoleHash(stakingRouterContract, 'STAKING_MODULE_MANAGE_ROLE'); + const [, moduleManageRoleGrantToAgentScript] = encodeFromAgent({ + to: stakingRouterAddress, + data: iface.encodeFunctionData('grantRole', [srModuleManageRoleHash, aragonAgentAddress]), + }); + + // 15. Add staking module + const [, addStakingModuleScript] = encodeFromAgent({ + to: stakingRouterAddress, + data: iface.encodeFunctionData('addStakingModule', [ + CS_MODULE_NAME, + CS_MODULE_ADDRESS, + CS_STAKE_SHARE_LIMIT, + CS_PRIORITY_EXIT_SHARE_THRESHOLD, + CS_STAKING_MODULE_FEE, + CS_TREASURY_FEE, + CS_MAX_DEPOSITS_PER_BLOCK, + CS_MIN_DEPOSIT_BLOCK_DISTANCE, + ]), + }); + + // 16. Grant request burn role to CSAccounting contract + const burnerRequestBurnRoleHash = await getRoleHash(burnerContract, 'REQUEST_BURN_SHARES_ROLE'); + const [, requestBurnRoleGrantScript] = encodeFromAgent({ + to: burnerAddress, + data: iface.encodeFunctionData('grantRole', [burnerRequestBurnRoleHash, CS_ACCOUNTING_ADDRESS]), + }); + + // 17. Grant resume role to agent + const csModuleContract = new Contract(CS_MODULE_ADDRESS, iface, provider); + const csmResumeRoleHash = await getRoleHash(csModuleContract, 'RESUME_ROLE'); + const resumeRoleGrantScript: CallScriptAction = { + to: CS_MODULE_ADDRESS, + data: iface.encodeFunctionData('grantRole', [csmResumeRoleHash, aragonAgentAddress]), + }; + + // 18. Resume staking module + const [, resumeScript] = encodeFromAgent({ + to: CS_MODULE_ADDRESS, + data: iface.encodeFunctionData('resume', []), + }); + + // 19. Revoke resume role from agent + const resumeRoleRevokeScript: CallScriptAction = { + to: CS_MODULE_ADDRESS, + data: iface.encodeFunctionData('revokeRole', [csmResumeRoleHash, aragonAgentAddress]), + }; + + // 20. Update initial epoch + const updateInitialEpochScript: CallScriptAction = { + to: CS_ORACLE_HASH_CONSENSUS_ADDRESS, + data: iface.encodeFunctionData('updateInitialEpoch', [CS_ORACLE_INITIAL_EPOCH]), + }; + + // TODO: easy track part of the script + // Collect all calls const calls: CallScriptAction[] = [ - locatorScript, - pauseRoleRevokeScript, - resumeRoleRevokeScript, - unvettingRoleGrantScript, + // SR + locatorUpgradeScript, + pauseRoleRevokeFromOldDSMScript, + resumeRoleRevokeFromOldDSMScript, + unvettingRoleGrantToDSMScript, stakingRouterUpdateScript, stakingRouterFinalizeScript, - norNewVersionCall, - norSetAppCall, + norNewVersionBumpScript, + norSetAppScript, + norFinalizeScript, + accountingOracleUpgradeScript, + accountingOracleFinalizeScript, + manageConsensusRoleGrantToAgentScript, + exitBusOracleVersionScript, + + // CSM + moduleManageRoleGrantToAgentScript, + addStakingModuleScript, + requestBurnRoleGrantScript, + resumeRoleGrantScript, + resumeScript, + resumeRoleRevokeScript, + updateInitialEpochScript, ]; const description = [ - `1. Update locator implementation to ${LOCATOR_IMPLEMENTAION} with new DSM ${NEW_DSM}`, + // SR + `1. Update locator implementation to ${LOCATOR_IMPLEMENTAION} with new DSM and Sanity Checker`, `2. Revoke pause role from old DSM ${OLD_DSM}`, `3. Revoke resume role from old DSM ${OLD_DSM}`, `4. Grant unvetting role to new DSM ${NEW_DSM}`, - `5. Update staking router implementation to ${STAKING_ROUTER_IMPLEMENTATION}`, - `6. Finalize upgrade with priority exit share thresholds: ${PRIORITY_EXIT_SHARE_THRESHOLDS_BP}`, + `5. Update SR implementation to ${STAKING_ROUTER_IMPLEMENTATION}`, + `6. Finalize SR upgrade`, `7. Create new NOR version with address ${NOR_IMPLEMENTATION}`, `8. Update NOR app to new version`, + `9. Finalize NOR upgrade`, + `10. Update AO implementation to ${AO_IMPLEMENTATION}`, + `11. Finalize AO upgrade and set consensus version to ${AO_CONSENSUS_VERSION}`, + `12. Update VEBO consensus version to ${VEBO_CONSENSUS_VERSION}`, + `13. Grant manage consensus role to agent ${aragonAgentAddress}`, + + // CSM + `14. Grant staking module manage role to agent ${aragonAgentAddress}`, + `15. Add staking module ${CS_MODULE_NAME} with address ${CS_MODULE_ADDRESS}`, + `16. Grant request burn shares role to CSAccounting contract with address ${CS_ACCOUNTING_ADDRESS}`, + `17. Grant resume role to agent ${aragonAgentAddress}`, + `18. Resume staking module`, + `19. Revoke resume role from agent ${aragonAgentAddress}`, + `20. Update initial epoch to ${CS_ORACLE_INITIAL_EPOCH}`, + // TODO: easy track part of the script ].join('\n'); const voteEvmScript = encodeCallScript(calls); diff --git a/programs/omnibus-scripts/upgrade-ao.ts b/programs/omnibus-scripts/upgrade-ao.ts deleted file mode 100644 index 48dd365..0000000 --- a/programs/omnibus-scripts/upgrade-ao.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { accountingOracleAddress, getAppProxyContract, locatorContract, norAddress } from '@contracts'; -import { encodeFromAgent, updateAragonApp, votingNewVote } from '@scripts'; -import { CallScriptAction, encodeCallScript, forwardVoteFromTm } from '@utils'; -import { Interface } from 'ethers'; - -const LOCATOR_IMPLEMENTAION = '0x3fb931564DD070cf6C89a3d1e95B9601F64f4C34'; -const AO_IMPLEMENTATION = '0x6e99b6E2ccB4DfaeA9EaE7C6F7AC694bF45f90D1'; - -const NOR_IMPLEMENTATION = '0xc1bcf8fb7352751ba84754158b43347166f8cdfd'; -const NOR_CONTENT_URI = - '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'; -const NOR_VERSION = ['3', '0', '0']; - -export const accountingOracleV2 = async () => { - const iface = new Interface([ - 'function finalizeUpgrade_v2(uint256)', - 'function finalizeUpgrade_v3()', - 'function proxy__upgradeTo(address)', - ]); - - // 1. Update locator implementation - const locatorProxyAddress = await locatorContract.getAddress(); - const [, locatorScript] = encodeFromAgent({ - to: locatorProxyAddress, - data: iface.encodeFunctionData('proxy__upgradeTo', [LOCATOR_IMPLEMENTAION]), - }); - - // 2. Update accounting oracle implementation - const [, accountingOracleScript] = encodeFromAgent({ - to: accountingOracleAddress, - data: iface.encodeFunctionData('proxy__upgradeTo', [AO_IMPLEMENTATION]), - }); - - // 3. Call finalize upgrade on Accounting Oracle - const accountingOracleFinalizeScript: CallScriptAction = { - to: accountingOracleAddress, - data: iface.encodeFunctionData('finalizeUpgrade_v2', [2]), - }; - - // 4, 5. Update NOR implementation - const norProxyContract = getAppProxyContract(async () => norAddress); - const norAppId = await norProxyContract.appId(); - const [, norNewVersionCall, norSetAppCall] = await updateAragonApp( - NOR_VERSION, - NOR_IMPLEMENTATION, - NOR_CONTENT_URI, - norAppId, - ); - - // 6. Call finalize upgrade on NOR - const norFinalizeScript: CallScriptAction = { - to: norAddress, - data: iface.encodeFunctionData('finalizeUpgrade_v3', []), - }; - - // Collect all calls - const calls: CallScriptAction[] = [ - locatorScript, - accountingOracleScript, - accountingOracleFinalizeScript, - norNewVersionCall, - norSetAppCall, - norFinalizeScript, - ]; - - const description = [ - `1. Update locator implementation to ${LOCATOR_IMPLEMENTAION} with new sanity checker`, - `2. Update accounting oracle implementation ${AO_IMPLEMENTATION}`, - `3. Call finalize upgrade on Accounting Oracle`, - `4. Create new NOR version with address ${NOR_IMPLEMENTATION}`, - `5. Update NOR app to new version`, - `6. Call finalize upgrade on NOR`, - ].join('\n'); - - const voteEvmScript = encodeCallScript(calls); - const [newVoteCalldata] = votingNewVote(voteEvmScript, description); - - await forwardVoteFromTm(newVoteCalldata); -}; diff --git a/programs/omnibus-scripts/upgrade-dsm.ts b/programs/omnibus-scripts/upgrade-dsm.ts deleted file mode 100644 index 54ab45a..0000000 --- a/programs/omnibus-scripts/upgrade-dsm.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { locatorContract, stakingRouterAddress } from '@contracts'; -import { provider } from '@providers'; -import { encodeFromAgent, votingNewVote } from '@scripts'; -import { CallScriptAction, encodeCallScript, forwardVoteFromTm, getRoleHash } from '@utils'; -import { Contract, Interface } from 'ethers'; - -const LOCATOR_IMPLEMENTAION = '0xD141C08fD5355b4db880C7a23209ec6b0455f140'; - -const OLD_DSM = '0xB8ae82F7BFF2553bAF158B7a911DC10162045C53'; -const NEW_DSM = '0xe009CC787AdF692526d93AA12a37935fEcAD5ee0'; - -export const upgradeDSM = async () => { - const iface = new Interface([ - 'function revokeRole(bytes32,address)', - 'function proxy__upgradeTo(address)', - 'function grantRole(bytes32,address)', - 'function STAKING_MODULE_UNVETTING_ROLE() view returns (bytes32)', - ]); - - // 1. Update locator implementation - const locatorProxyAddress = await locatorContract.getAddress(); - const [, locatorScript] = encodeFromAgent({ - to: locatorProxyAddress, - data: iface.encodeFunctionData('proxy__upgradeTo', [LOCATOR_IMPLEMENTAION]), - }); - - // 2. Revoke unvetting role from old DSM - const stakingRouterImplContract = new Contract(stakingRouterAddress, iface, provider); - const unvettingRoleHash = await getRoleHash(stakingRouterImplContract, 'STAKING_MODULE_UNVETTING_ROLE'); - const [, resumeRoleRevokeScript] = encodeFromAgent({ - to: stakingRouterAddress, - data: iface.encodeFunctionData('revokeRole', [unvettingRoleHash, OLD_DSM]), - }); - - // 3. Grant unvetting role to new DSM - const [, unvettingRoleGrantScript] = encodeFromAgent({ - to: stakingRouterAddress, - data: iface.encodeFunctionData('grantRole', [unvettingRoleHash, NEW_DSM]), - }); - - // Collect all calls - const calls: CallScriptAction[] = [locatorScript, resumeRoleRevokeScript, unvettingRoleGrantScript]; - - const description = [ - `1. Update locator implementation to ${LOCATOR_IMPLEMENTAION} with new DSM ${NEW_DSM}`, - `2. Revoke unvetting role from old DSM ${OLD_DSM}`, - `3. Grant unvetting role to new DSM ${NEW_DSM}`, - ].join('\n'); - - const voteEvmScript = encodeCallScript(calls); - const [newVoteCalldata] = votingNewVote(voteEvmScript, description); - - await forwardVoteFromTm(newVoteCalldata); -}; From b13caa9e7bec2a2d14bff111ca5b9b86ae0479ef Mon Sep 17 00:00:00 2001 From: George Avsetsin Date: Tue, 11 Jun 2024 20:27:18 +0300 Subject: [PATCH 4/7] feat: add et factory to srv2 devnet omnibus --- programs/omnibus-scripts/staking-router-2.ts | 21 +++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/programs/omnibus-scripts/staking-router-2.ts b/programs/omnibus-scripts/staking-router-2.ts index e2605fe..3320eab 100644 --- a/programs/omnibus-scripts/staking-router-2.ts +++ b/programs/omnibus-scripts/staking-router-2.ts @@ -14,7 +14,7 @@ import { import { provider } from '@providers'; import { encodeFromAgent, updateAragonApp, votingNewVote } from '@scripts'; import { CallScriptAction, encodeCallScript, forwardVoteFromTm, getRoleHash } from '@utils'; -import { Contract, Interface } from 'ethers'; +import { concat, Contract, Interface } from 'ethers'; // SR 2 @@ -41,6 +41,7 @@ const VEBO_CONSENSUS_VERSION = 2; const CS_MODULE_ADDRESS = '0xb43fD1a6932345e5A0dc72a2b397c09f3390c1D0'; const CS_ACCOUNTING_ADDRESS = '0x9bd601f8b7A0F24fA58f6502EEC077Dc753476f6'; const CS_ORACLE_HASH_CONSENSUS_ADDRESS = '0xd2776403ADbc77958DD3DF490cDbCD2f4dFCf021'; +const CS_SETTLE_EL_STEALING_ADDRESS = '0x611b010b2fA34eE4E8cb1cf7d166402c219BF3C2'; const CS_MODULE_NAME = 'CommunityStaking'; const CS_STAKE_SHARE_LIMIT = 2000; // 20% @@ -52,6 +53,10 @@ const CS_MIN_DEPOSIT_BLOCK_DISTANCE = 25; const CS_ORACLE_INITIAL_EPOCH = 57606; // 57600 for ao and vebo +// ET + +const EASYTRACK_ADDRESS = '0x12077456B1BAB9836bf05D6994D5a47c7A096204'; + export const stakingRouterV2 = async () => { const iface = new Interface([ 'function proxy__upgradeTo(address)', @@ -66,6 +71,7 @@ export const stakingRouterV2 = async () => { 'function updateInitialEpoch(uint256)', 'function addStakingModule(string,address,uint256,uint256,uint256,uint256,uint256,uint256)', 'function setConsensusVersion(uint256)', + 'function addEVMScriptFactory(address,bytes)', ]); /** @@ -217,7 +223,15 @@ export const stakingRouterV2 = async () => { data: iface.encodeFunctionData('updateInitialEpoch', [CS_ORACLE_INITIAL_EPOCH]), }; - // TODO: easy track part of the script + // 21. Add CS settle EL stealing factory to ET + const settleIface = new Interface(['function settleELRewardsStealingPenalty(uint256[])']); + const settleSelector = settleIface.getFunction('settleELRewardsStealingPenalty')?.selector; + if (!settleSelector) throw new Error('Could not find settleELRewardsStealingPenalty selector'); + const csSettleFactoryBytes = concat([CS_MODULE_ADDRESS, settleSelector]); + const addCSSettlingFactoryToETScript: CallScriptAction = { + to: EASYTRACK_ADDRESS, + data: iface.encodeFunctionData('addEVMScriptFactory', [CS_SETTLE_EL_STEALING_ADDRESS, csSettleFactoryBytes]), + }; // Collect all calls const calls: CallScriptAction[] = [ @@ -244,6 +258,7 @@ export const stakingRouterV2 = async () => { resumeScript, resumeRoleRevokeScript, updateInitialEpochScript, + addCSSettlingFactoryToETScript, ]; const description = [ @@ -270,7 +285,7 @@ export const stakingRouterV2 = async () => { `18. Resume staking module`, `19. Revoke resume role from agent ${aragonAgentAddress}`, `20. Update initial epoch to ${CS_ORACLE_INITIAL_EPOCH}`, - // TODO: easy track part of the script + `21. Add CS settle EL stealing factory to ET with address ${CS_SETTLE_EL_STEALING_ADDRESS}`, ].join('\n'); const voteEvmScript = encodeCallScript(calls); From 563fca04eac0cb7ecd22f098721da3fbb577eac3 Mon Sep 17 00:00:00 2001 From: George Avsetsin Date: Wed, 12 Jun 2024 12:23:23 +0300 Subject: [PATCH 5/7] feat: update csm deploy for devnet-1 --- programs/omnibus-scripts/staking-router-2.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/programs/omnibus-scripts/staking-router-2.ts b/programs/omnibus-scripts/staking-router-2.ts index 3320eab..80466c2 100644 --- a/programs/omnibus-scripts/staking-router-2.ts +++ b/programs/omnibus-scripts/staking-router-2.ts @@ -38,10 +38,10 @@ const VEBO_CONSENSUS_VERSION = 2; // CSM -const CS_MODULE_ADDRESS = '0xb43fD1a6932345e5A0dc72a2b397c09f3390c1D0'; -const CS_ACCOUNTING_ADDRESS = '0x9bd601f8b7A0F24fA58f6502EEC077Dc753476f6'; -const CS_ORACLE_HASH_CONSENSUS_ADDRESS = '0xd2776403ADbc77958DD3DF490cDbCD2f4dFCf021'; -const CS_SETTLE_EL_STEALING_ADDRESS = '0x611b010b2fA34eE4E8cb1cf7d166402c219BF3C2'; +const CS_MODULE_ADDRESS = '0x26aBc20a47f7e8991F1d26Bf0fC2bE8f24E9eF2A'; +const CS_ACCOUNTING_ADDRESS = '0x782c7c96959bE2258a7b67439435885b39946c9E'; +const CS_ORACLE_HASH_CONSENSUS_ADDRESS = '0x64c48254123A4c62278Fa671BEA32B45099Aeb9b'; +const CS_SETTLE_EL_STEALING_ADDRESS = '0xC86D7B14BE8c1E8718EaC65F95306A71d0E75aA8'; const CS_MODULE_NAME = 'CommunityStaking'; const CS_STAKE_SHARE_LIMIT = 2000; // 20% @@ -51,7 +51,7 @@ const CS_TREASURY_FEE = 200; // 2% const CS_MAX_DEPOSITS_PER_BLOCK = 30; const CS_MIN_DEPOSIT_BLOCK_DISTANCE = 25; -const CS_ORACLE_INITIAL_EPOCH = 57606; // 57600 for ao and vebo +const CS_ORACLE_INITIAL_EPOCH = 58050; // 57600 for ao and vebo // ET From f04cd7c5239a90eb385f279faf34e86c18ea5ab4 Mon Sep 17 00:00:00 2001 From: George Avsetsin Date: Fri, 14 Jun 2024 10:42:03 +0300 Subject: [PATCH 6/7] feat: etherscan signatures fetching --- programs/etherscan.ts | 21 +++++++++ programs/etherscan/index.ts | 1 + programs/etherscan/signatures.ts | 61 +++++++++++++++++++++++++++ programs/index.ts | 1 + programs/simple-dvt.ts | 19 ++++++++- programs/staking-module/simple-dvt.ts | 46 ++++++++++++++++++++ programs/staking-router.ts | 42 +++++++++++++++++- 7 files changed, 189 insertions(+), 2 deletions(-) create mode 100644 programs/etherscan.ts create mode 100644 programs/etherscan/index.ts create mode 100644 programs/etherscan/signatures.ts diff --git a/programs/etherscan.ts b/programs/etherscan.ts new file mode 100644 index 0000000..229bfad --- /dev/null +++ b/programs/etherscan.ts @@ -0,0 +1,21 @@ +import { program } from '@command'; +import { fetchEtherscanSignatureDetailsForAddress } from './etherscan/'; +import { logger } from '@utils'; + +const etherscan = program.command('etherscan').description('etherscan commands'); + +etherscan + .command('verified-signatures') + .aliases(['signatures']) + .argument('
', 'address') + .action(async (address) => { + const signedMessages = await fetchEtherscanSignatureDetailsForAddress(address); + + signedMessages.map(({ message, signature }) => { + logger.log(''); + logger.log('Message: ', message); + logger.log('Signature:', signature); + }); + + logger.log(''); + }); diff --git a/programs/etherscan/index.ts b/programs/etherscan/index.ts new file mode 100644 index 0000000..7f69aae --- /dev/null +++ b/programs/etherscan/index.ts @@ -0,0 +1 @@ +export * from './signatures'; diff --git a/programs/etherscan/signatures.ts b/programs/etherscan/signatures.ts new file mode 100644 index 0000000..f70d59e --- /dev/null +++ b/programs/etherscan/signatures.ts @@ -0,0 +1,61 @@ +import { isAddress } from 'ethers'; + +export const fetchEtherscanSignatureDetailsForAddress = async (address: string) => { + const signatureIds = await fetchEtherscanSignatureIdsForAddress(address); + const signatureDetails = await Promise.all(signatureIds.map((signatureId) => fetchSignatureDetailsById(signatureId))); + return signatureDetails; +}; + +export const fetchEtherscanSignatureIdsForAddress = async (address: string) => { + if (!isAddress(address)) { + throw new Error('Invalid address'); + } + + const pageContent = await fetchEtherscanPageContent(`verifiedSignatures?q=${address}`); + const signatureIds = extractSignatureIdsFromText(pageContent); + return signatureIds; +}; + +export const fetchSignatureDetailsById = async (id: number) => { + if (typeof id !== 'number') { + throw new Error('Invalid id'); + } + + const pageContent = await fetchEtherscanPageContent(`verifySig/${id}`); + const details = extractSignatureDetailsFromText(pageContent); + return details; +}; + +export const extractSignatureIdsFromText = (content: string) => { + const regexp = /href="\/verifySig\/([0-9]+)"/g; + const matches = [...content.matchAll(regexp)]; + const ids = matches.map(([, id]) => Number(id)); + return ids; +}; + +export const extractSignatureDetailsFromText = (content: string) => { + const regexp = /(class="form-control">([^<]+)<\/textarea>)|(type="text" value="([^"]+)")/g; + const matches = [...content.matchAll(regexp)]; + const details = matches.map(([, , textareaValue, , inputValue]) => (textareaValue || inputValue).trim()); + + if (details.length !== 3) { + throw new Error('Failed to extract details'); + } + + return { + address: details[0], + message: details[1], + signature: details[2], + }; +}; + +export const fetchEtherscanPageContent = async (path: string) => { + const url = `https://etherscan.io/${path}`; + const result = await fetch(url); + + if (!result.ok || result.status !== 200) { + throw new Error('Failed to fetch'); + } + + return await result.text(); +}; diff --git a/programs/index.ts b/programs/index.ts index 9e18e47..a9ead10 100644 --- a/programs/index.ts +++ b/programs/index.ts @@ -9,6 +9,7 @@ export * from './csm'; export * from './deposit-contract'; export * from './deposit-data'; export * from './dsm'; +export * from './etherscan'; export * from './exit-bus-consensus'; export * from './exit-bus-oracle'; export * from './ldo'; diff --git a/programs/simple-dvt.ts b/programs/simple-dvt.ts index 0bac0ff..0adae93 100644 --- a/programs/simple-dvt.ts +++ b/programs/simple-dvt.ts @@ -2,7 +2,7 @@ import { program } from '@command'; import { simpleDVTContract } from '@contracts'; import { addAragonAppSubCommands, addCuratedModuleSubCommands, addLogsCommands, addParsingCommands } from './common'; import { getLatestBlockRange } from '@utils'; -import { check0xSplit, checkGnosisSafe, checkWrapperContract } from './staking-module'; +import { check0xSplit, checkGnosisSafe, checkSignatures, checkWrapperContract } from './staking-module'; const simpleDVT = program .command('simple-dvt') @@ -39,3 +39,20 @@ simpleDVT await checkGnosisSafe(managerAddress, splitWalletAccounts); }); + +simpleDVT + .command('check-cluster') + .description('check split contracts') + .argument('', 'cluster name') + .argument('', 'cluster reward address') + .argument('', 'cluster manager address') + .option('-b, --blocks ', 'blocks', '1000000000') + .action(async (clusterName, rewardAddress, managerAddress, { blocks }) => { + const [fromBlock, toBlock] = await getLatestBlockRange(blocks); + + const { splitWalletAddress } = await checkWrapperContract(rewardAddress, fromBlock, toBlock); + const { splitWalletAccounts } = await check0xSplit(splitWalletAddress, fromBlock, toBlock); + const { gnosisOwners } = await checkGnosisSafe(managerAddress, splitWalletAccounts); + + await checkSignatures(clusterName, gnosisOwners); + }); diff --git a/programs/staking-module/simple-dvt.ts b/programs/staking-module/simple-dvt.ts index 609c8a9..e0aa484 100644 --- a/programs/staking-module/simple-dvt.ts +++ b/programs/staking-module/simple-dvt.ts @@ -18,6 +18,7 @@ import { } from '@contracts'; import chalk from 'chalk'; import Table from 'cli-table3'; +import { fetchEtherscanSignatureDetailsForAddress } from '../etherscan/'; const header = chalk.white.bold; @@ -234,4 +235,49 @@ export const checkGnosisSafe = async (safeAddress: string, splitAccounts: string logger.log(''); logger.log(ownersTable.toString()); logger.log(''); + + return { gnosisOwners: sortedGnosisOwners }; +}; + +export const checkSignatures = async (clusterName: string, addresses: string[]) => { + logger.log(''); + logger.log(header('Last signatures from etherscan')); + logger.log(''); + + for (const address of addresses) { + try { + logger.log(header(address)); + + const signedMessages = await fetchEtherscanSignatureDetailsForAddress(address); + + if (!signedMessages.length) { + logger.log(''); + logger.error('No signed messages found'); + continue; + } + + const signedClusterMessages = signedMessages.filter(({ message }) => message.includes(clusterName)); + + if (signedClusterMessages.length) { + signedClusterMessages.map(({ message, signature }) => { + logger.log(''); + logger.log('Message: ', chalk.green(message)); + logger.log('Signature:', signature); + }); + } else { + signedMessages.map(({ message, signature }) => { + logger.log(''); + logger.log('Message: ', message); + logger.log('Signature:', signature); + }); + } + + logger.log(''); + } catch (error) { + logger.log(''); + logger.error('Failed to fetch signatures'); + } finally { + logger.log(''); + } + } }; diff --git a/programs/staking-router.ts b/programs/staking-router.ts index 48af8be..8e1c4f9 100644 --- a/programs/staking-router.ts +++ b/programs/staking-router.ts @@ -1,9 +1,10 @@ import { program } from '@command'; import { stakingRouterContract } from '@contracts'; import { authorizedCall, logger } from '@utils'; -import { Result, parseEther } from 'ethers'; +import { Contract, Interface, Result, parseEther } from 'ethers'; import { addAccessControlSubCommands, addLogsCommands, addOssifiableProxyCommands, addParsingCommands } from './common'; import { getNodeOperators, getStakingModules } from './staking-module'; +import { wallet } from '@providers'; const router = program .command('staking-router') @@ -62,6 +63,45 @@ router await authorizedCall(stakingRouterContract, 'updateStakingModule', [moduleId, targetShare, moduleFee, treasuryFee]); }); +router + .command('update-module-v2') + .description('updates staking module parameters') + .argument('', 'module id') + .option('-s, --stake-share-limit ', 'stake share limit in basis points: 100 = 1%, 10000 = 100%', '10000') + .option( + '-p, --priority-exit-share-threshold ', + 'priority exit share threshold in basis points: 100 = 1%, 10000 = 100%', + '10000', + ) + .option('-f, --module-fee ', 'module share in basis points: 100 = 1%, 10000 = 100%', '500') + .option('-t, --treasury-fee ', 'treasury share in basis points: 100 = 1%, 10000 = 100%', '500') + .option('-m, --max-deposits-per-block ', 'max deposits per block') + .option('-d, --min-deposit-block-distance ', 'min deposit block distance') + .action(async (moduleId, options) => { + const { + stakeShareLimit, + priorityExitShareThreshold, + moduleFee, + treasuryFee, + maxDepositsPerBlock, + minDepositBlockDistance, + } = options; + const iface = new Interface([ + 'function updateStakingModule(uint256,uint256,uint256,uint256,uint256,uint256,uint256)', + ]); + const contract = new Contract(await stakingRouterContract.getAddress(), iface, wallet); + + await authorizedCall(contract, 'updateStakingModule', [ + moduleId, + stakeShareLimit, + priorityExitShareThreshold, + moduleFee, + treasuryFee, + maxDepositsPerBlock, + minDepositBlockDistance, + ]); + }); + router .command('update-refunded-validators') .description('updates refunded validators count') From 0e8d41ee81b3264e44fbe3d4f8c195620015f2e1 Mon Sep 17 00:00:00 2001 From: George Avsetsin Date: Fri, 14 Jun 2024 11:03:45 +0300 Subject: [PATCH 7/7] fix: joining messages highlinting --- programs/staking-module/simple-dvt.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/programs/staking-module/simple-dvt.ts b/programs/staking-module/simple-dvt.ts index e0aa484..70d50bc 100644 --- a/programs/staking-module/simple-dvt.ts +++ b/programs/staking-module/simple-dvt.ts @@ -256,10 +256,10 @@ export const checkSignatures = async (clusterName: string, addresses: string[]) continue; } - const signedClusterMessages = signedMessages.filter(({ message }) => message.includes(clusterName)); + const joiningMessages = signedMessages.filter(({ message }) => isJoiningMessage(message, clusterName)); - if (signedClusterMessages.length) { - signedClusterMessages.map(({ message, signature }) => { + if (joiningMessages.length) { + joiningMessages.map(({ message, signature }) => { logger.log(''); logger.log('Message: ', chalk.green(message)); logger.log('Signature:', signature); @@ -267,7 +267,7 @@ export const checkSignatures = async (clusterName: string, addresses: string[]) } else { signedMessages.map(({ message, signature }) => { logger.log(''); - logger.log('Message: ', message); + logger.log('Message: ', chalk.yellow(message)); logger.log('Signature:', signature); }); } @@ -281,3 +281,7 @@ export const checkSignatures = async (clusterName: string, addresses: string[]) } } }; + +const isJoiningMessage = (message: string, clusterName: string) => { + return message.includes(clusterName) && message.includes('is joining'); +};