From 5051b1ef99734a8f62db55ec593bd5e6fab4e083 Mon Sep 17 00:00:00 2001 From: Aleksandr Kuperman Date: Tue, 17 Sep 2024 18:05:41 +0100 Subject: [PATCH 1/3] chore: updating deployment scripts to change owner in staking contracts --- hardhat.config.js | 2 +- ...21_22_service_staking_change_ownerships.js | 80 +++++++++++++++++++ .../l2/globals_ethereum_mainnet.json | 3 +- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 scripts/deployment/l2/deploy_21_22_service_staking_change_ownerships.js diff --git a/hardhat.config.js b/hardhat.config.js index 1121130e..6dd839bd 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -155,7 +155,7 @@ module.exports = { chainId: 10, urls: { apiURL: "https://api-optimistic.etherscan.io/api", - browserURL: "https://sepolia-optimistic.etherscan.io" + browserURL: "https://optimistic.etherscan.io" }, }, { diff --git a/scripts/deployment/l2/deploy_21_22_service_staking_change_ownerships.js b/scripts/deployment/l2/deploy_21_22_service_staking_change_ownerships.js new file mode 100644 index 00000000..812e91cf --- /dev/null +++ b/scripts/deployment/l2/deploy_21_22_service_staking_change_ownerships.js @@ -0,0 +1,80 @@ +/*global process*/ + +const { ethers } = require("hardhat"); +const { LedgerSigner } = require("@anders-t/ethers-ledger"); + +async function main() { + const fs = require("fs"); + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + let parsedData = JSON.parse(dataFromJSON); + const useLedger = parsedData.useLedger; + const derivationPath = parsedData.derivationPath; + const providerName = parsedData.providerName; + const gasPriceInGwei = parsedData.gasPriceInGwei; + const stakingVerifierAddress = parsedData.stakingVerifierAddress; + const stakingFactoryAddress = parsedData.stakingFactoryAddress; + const bridgeMediatorAddress = parsedData.bridgeMediatorAddress; + + let networkURL = parsedData.networkURL; + if (providerName === "mainnet") { + if (!process.env.ALCHEMY_API_KEY_MAINNET) { + console.log("set ALCHEMY_API_KEY_MAINNET env variable"); + } + networkURL += process.env.ALCHEMY_API_KEY_MAINNET; + } + if (providerName === "polygon") { + if (!process.env.ALCHEMY_API_KEY_MATIC) { + console.log("set ALCHEMY_API_KEY_MATIC env variable"); + } + networkURL += process.env.ALCHEMY_API_KEY_MATIC; + } else if (providerName === "polygonAmoy") { + if (!process.env.ALCHEMY_API_KEY_AMOY) { + console.log("set ALCHEMY_API_KEY_AMOY env variable"); + return; + } + networkURL += process.env.ALCHEMY_API_KEY_AMOY; + } + + const provider = new ethers.providers.JsonRpcProvider(networkURL); + const signers = await ethers.getSigners(); + + let EOA; + if (useLedger) { + EOA = new LedgerSigner(provider, derivationPath); + } else { + EOA = signers[0]; + } + // EOA address + const deployer = await EOA.getAddress(); + console.log("EOA is:", deployer); + + // Get all the contracts + const stakingVerifier = await ethers.getContractAt("StakingVerifier", stakingVerifierAddress); + const stakingFactory = await ethers.getContractAt("StakingFactory", stakingFactoryAddress); + + // Gas pricing + const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei"); + + // Transaction signing and execution + // 21. EOA to transfer ownership rights of StakingVerifier to BridgeMediator calling `changeOwner(BridgeMediator)`; + console.log("21. You are signing the following transaction: StakingVerifier.connect(EOA).changeOwner()"); + let result = await stakingVerifier.connect(EOA).changeOwner(bridgeMediatorAddress, { gasPrice }); + // Transaction details + console.log("Contract address:", stakingVerifierAddress); + console.log("Transaction:", result.hash); + + // 22. EOA to transfer ownership rights of StakingFactory to BridgeMediator calling `changeOwner(BridgeMediator)`; + console.log("22. You are signing the following transaction: StakingFactory.connect(EOA).changeOwner()"); + result = await stakingFactory.connect(EOA).changeOwner(bridgeMediatorAddress, { gasPrice }); + // Transaction details + console.log("Contract address:", stakingFactoryAddress); + console.log("Transaction:", result.hash); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/scripts/deployment/l2/globals_ethereum_mainnet.json b/scripts/deployment/l2/globals_ethereum_mainnet.json index 279eb1be..e8715239 100644 --- a/scripts/deployment/l2/globals_ethereum_mainnet.json +++ b/scripts/deployment/l2/globals_ethereum_mainnet.json @@ -4,7 +4,8 @@ "derivationPath": "m/44'/60'/2'/0/0", "providerName": "mainnet", "networkURL": "https://eth-mainnet.g.alchemy.com/v2/", - "gasPriceInGwei": "15", + "gasPriceInGwei": "30", + "bridgeMediatorAddress": "0x3C1fF68f5aa342D296d4DEe4Bb1cACCA912D95fE", "serviceRegistryAddress": "0x48b6af7B12C71f09e2fC8aF4855De4Ff54e775cA", "serviceRegistryTokenUtilityAddress": "0x3Fb926116D454b95c669B6Bf2E7c3bad8d19affA", "olasAddress": "0x0001A500A6B18995B03f44bb040A5fFc28E45CB0", From 905aaeef69534fd72e5094fcbcae62f3d66c7703 Mon Sep 17 00:00:00 2001 From: Aleksandr Kuperman Date: Wed, 18 Sep 2024 01:26:00 +0100 Subject: [PATCH 2/3] chore: adding script for the staking limits proposal on gnosis --- .../l2/globals_arbitrum_sepolia.json | 2 +- .../deployment/l2/globals_gnosis_mainnet.json | 2 +- ...0_staking_verifier_change_limits_gnosis.js | 91 +++++++++++++++++++ 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js diff --git a/scripts/deployment/l2/globals_arbitrum_sepolia.json b/scripts/deployment/l2/globals_arbitrum_sepolia.json index dc3a84e0..51cf1945 100644 --- a/scripts/deployment/l2/globals_arbitrum_sepolia.json +++ b/scripts/deployment/l2/globals_arbitrum_sepolia.json @@ -1 +1 @@ -{"contractVerification":true,"useLedger":false,"derivationPath":"m/44'/60'/2'/0/0","providerName":"arbitrumSepolia","networkURL":"https://sepolia-rollup.arbitrum.io/rpc","gasPriceInGwei":"1","gnosisSafeAddress":"0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552","gnosisSafeProxyFactoryAddress":"0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2","baseURI":"https://gateway.autonolas.tech/ipfs/","serviceRegistryName":"Service Registry","serviceRegistrySymbol":"AUTONOLAS-SERVICE-V1","bridgeMediatorAddress":"0x45d995F302D0B5cF52ec0eDD3945321Eb0f84ee6","serviceRegistryAddress":"0x31D3202d8744B16A120117A053459DDFAE93c855","gnosisSafeMultisigImplementationAddress":"0x19936159B528C66750992C3cBcEd2e71cF4E4824","gnosisSafeSameAddressMultisigImplementationAddress":"0x10100e74b7F706222F8A7C0be9FC7Ae1717Ad8B2","operatorWhitelistAddress":"0x29086141ecdc310058fc23273F8ef7881d20C2f7","serviceRegistryTokenUtilityAddress":"0xeB49bE5DF00F74bd240DE4535DDe6Bc89CEfb994","serviceManagerTokenAddress":"0x5BA58970c2Ae16Cf6218783018100aF2dCcFc915","olasAddress":"0x2AeD71638128A3811F5e5971a397fFe6A8587caa","multisigProxyHash130":"0xb89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b000","stakingTokenAddress":"0xea930a028793FeBE9F6A2CFb62c95620dB91da71","stakingNativeTokenAddress":"0xA9D794548486D15BfbCe2b8b5F5518b739fa8A4b","livenessRatio":"700000000000000","stakingActivityCheckerAddress":"0x661E609d03bb63819f2F47b9202E15e1826f5B5f","minStakingDepositLimit":"1000000000000000000000","timeForEmissionsLimit":"2592000","numServicesLimit":"100","apyLimit":"3000000000000000000","stakingVerifierAddress":"0x9385d4E53c72a858C451D41f58Fcb8C070bDd18A","stakingFactoryAddress":"0xd64Cf67500b7d15A41E02DDeb40F3A73CB533eB5"} \ No newline at end of file +{"contractVerification":true,"useLedger":false,"derivationPath":"m/44'/60'/2'/0/0","providerName":"arbitrumSepolia","networkURL":"https://sepolia-rollup.arbitrum.io/rpc","gasPriceInGwei":"1","gnosisSafeAddress":"0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552","gnosisSafeProxyFactoryAddress":"0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2","baseURI":"https://gateway.autonolas.tech/ipfs/","serviceRegistryName":"Service Registry","serviceRegistrySymbol":"AUTONOLAS-SERVICE-V1","bridgeMediatorAddress":"0x31D3202d8744B16A120117A053459DDFAE93c855","serviceRegistryAddress":"0x31D3202d8744B16A120117A053459DDFAE93c855","gnosisSafeMultisigImplementationAddress":"0x19936159B528C66750992C3cBcEd2e71cF4E4824","gnosisSafeSameAddressMultisigImplementationAddress":"0x10100e74b7F706222F8A7C0be9FC7Ae1717Ad8B2","operatorWhitelistAddress":"0x29086141ecdc310058fc23273F8ef7881d20C2f7","serviceRegistryTokenUtilityAddress":"0xeB49bE5DF00F74bd240DE4535DDe6Bc89CEfb994","serviceManagerTokenAddress":"0x5BA58970c2Ae16Cf6218783018100aF2dCcFc915","olasAddress":"0x2AeD71638128A3811F5e5971a397fFe6A8587caa","multisigProxyHash130":"0xb89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b000","stakingTokenAddress":"0xea930a028793FeBE9F6A2CFb62c95620dB91da71","stakingNativeTokenAddress":"0xA9D794548486D15BfbCe2b8b5F5518b739fa8A4b","livenessRatio":"700000000000000","stakingActivityCheckerAddress":"0x661E609d03bb63819f2F47b9202E15e1826f5B5f","minStakingDepositLimit":"1000000000000000000000","timeForEmissionsLimit":"2592000","numServicesLimit":"100","apyLimit":"3000000000000000000","stakingVerifierAddress":"0x9385d4E53c72a858C451D41f58Fcb8C070bDd18A","stakingFactoryAddress":"0xd64Cf67500b7d15A41E02DDeb40F3A73CB533eB5"} \ No newline at end of file diff --git a/scripts/deployment/l2/globals_gnosis_mainnet.json b/scripts/deployment/l2/globals_gnosis_mainnet.json index e692e004..c6ace691 100644 --- a/scripts/deployment/l2/globals_gnosis_mainnet.json +++ b/scripts/deployment/l2/globals_gnosis_mainnet.json @@ -24,7 +24,7 @@ "multisigProxyHash130": "0xb89c1b3bdf2cf8827818646bce9a8f6e372885f8c55e5c07acbd307cb133b000", "stakingNativeTokenAddress":"", "stakingTokenAddress":"0xEa00be6690a871827fAfD705440D20dd75e67AB1", - "minStakingDepositLimit":"1000000000000000000000", + "minStakingDepositLimit":"10000000000000000000000", "timeForEmissionsLimit":"2592000", "numServicesLimit":"100", "apyLimit":"3000000000000000000", diff --git a/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js b/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js new file mode 100644 index 00000000..9a3401c6 --- /dev/null +++ b/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js @@ -0,0 +1,91 @@ +/*global process*/ + +const { ethers } = require("ethers"); + +async function main() { + const fs = require("fs"); + // Polygon mainnet globals file + const globalsFile = "globals.json"; + const dataFromJSON = fs.readFileSync(globalsFile, "utf8"); + const parsedData = JSON.parse(dataFromJSON); + + const ALCHEMY_API_KEY_MAINNET = process.env.ALCHEMY_API_KEY_MAINNET; + const mainnetURL = "https://eth-mainnet.g.alchemy.com/v2/" + ALCHEMY_API_KEY_MAINNET; + const mainnetProvider = new ethers.providers.JsonRpcProvider(mainnetURL); + await mainnetProvider.getBlockNumber().then((result) => { + console.log("Current block number mainnet: " + result); + }); + + const gnosisURL = "https://rpc.gnosischain.com"; + const gnosisProvider = new ethers.providers.JsonRpcProvider(gnosisURL); + await gnosisProvider.getBlockNumber().then((result) => { + console.log("Current block number gnosis: " + result); + }); + + + // AMBProxy address on mainnet + const AMBProxyAddress = parsedData.AMBContractProxyForeignAddress; + const AMBProxyJSON = "abis/bridges/gnosis/EternalStorageProxy.json"; + let contractFromJSON = fs.readFileSync(AMBProxyJSON, "utf8"); + const AMBProxyABI = JSON.parse(contractFromJSON); + const AMBProxy = new ethers.Contract(AMBProxyAddress, AMBProxyABI, mainnetProvider); + + // Test deployed HomeMediator address on chiado + const homeMediatorAddress = parsedData.bridgeMediatorAddress; + const homeMediatorJSON = "abis/bridges/gnosis/HomeMediator.json"; + contractFromJSON = fs.readFileSync(homeMediatorJSON, "utf8"); + let parsedFile = JSON.parse(contractFromJSON); + const homeMediatorABI = parsedFile["abi"]; + const homeMediator = new ethers.Contract(homeMediatorAddress, homeMediatorABI, gnosisProvider); + + // StakingVerifier address on gnosis + const stakingVerifierAddress = parsedData.stakingVerifierAddress; + const stakingVerifierJSON = "artifacts/contracts/staking/StakingVerifier.sol/StakingVerifier.json"; + contractFromJSON = fs.readFileSync(stakingVerifierJSON, "utf8"); + parsedFile = JSON.parse(contractFromJSON); + const stakingVerifierABI = parsedFile["abi"]; + const stakingVerifier = new ethers.Contract(stakingVerifierAddress, stakingVerifierABI, gnosisProvider); + + // Timelock contract across the bridge must change the manager address + const rawPayload = stakingVerifier.interface.encodeFunctionData("changeStakingLimits", + [parsedData.minStakingDepositLimit, parsedData.timeForEmissionsLimit, parsedData.numServicesLimit, + parsedData.apyLimit]); + // Pack the second part of data + const target = stakingVerifierAddress; + const value = 0; + const payload = ethers.utils.arrayify(rawPayload); + const data = ethers.utils.solidityPack( + ["address", "uint96", "uint32", "bytes"], + [target, value, payload.length, payload] + ); + + // Proposal preparation + console.log("Proposal 10. Change staking limits for gnosis StakingVerifier\n"); + const mediatorPayload = await homeMediator.interface.encodeFunctionData("processMessageFromForeign", [data]); + + // AMBContractProxyHomeAddress on gnosis mainnet: 0x75Df5AF045d91108662D8080fD1FEFAd6aA0bb59 + // Function to call by homeMediator: processMessageFromForeign + console.log("AMBContractProxyHomeAddress to call homeMediator's processMessageFromForeign function with the data:", data); + + const requestGasLimit = "2000000"; + const timelockPayload = await AMBProxy.interface.encodeFunctionData("requireToPassMessage", [homeMediatorAddress, + mediatorPayload, requestGasLimit]); + + const targets = [AMBProxyAddress]; + const values = [0]; + const callDatas = [timelockPayload]; + const description = "Change Manager in StakingVerifier on gnosis"; + + // Proposal details + console.log("targets:", targets); + console.log("values:", values); + console.log("call datas:", callDatas); + console.log("description:", description); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); From 35d60704205e898a5716aa73d05d49e8a46cf052 Mon Sep 17 00:00:00 2001 From: Aleksandr Kuperman Date: Wed, 18 Sep 2024 09:44:35 +0100 Subject: [PATCH 3/3] chore: linters --- .gitleaksignore | 2 ++ .../proposal_10_staking_verifier_change_limits_gnosis.js | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitleaksignore b/.gitleaksignore index 17bdb456..1894428c 100644 --- a/.gitleaksignore +++ b/.gitleaksignore @@ -372,3 +372,5 @@ f47ff3a0f41adec19b37c7541dfd5a9abf2afad3:scripts/deployment/l2/globals_optimisti f47ff3a0f41adec19b37c7541dfd5a9abf2afad3:scripts/deployment/l2/globals_optimistic_sepolia.json:generic-api-key:2 f47ff3a0f41adec19b37c7541dfd5a9abf2afad3:scripts/deployment/l2/globals_polygon_amoy.json:generic-api-key:2 f47ff3a0f41adec19b37c7541dfd5a9abf2afad3:scripts/deployment/l2/globals_polygon_mainnet.json:generic-api-key:2 +905aaeef69534fd72e5094fcbcae62f3d66c7703:scripts/deployment/l2/globals_arbitrum_sepolia.json:generic-api-key:1 +905aaeef69534fd72e5094fcbcae62f3d66c7703:scripts/deployment/l2/globals_arbitrum_sepolia.json:generic-api-key:2 diff --git a/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js b/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js index 9a3401c6..b3337637 100644 --- a/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js +++ b/scripts/proposals/proposal_10_staking_verifier_change_limits_gnosis.js @@ -49,7 +49,7 @@ async function main() { // Timelock contract across the bridge must change the manager address const rawPayload = stakingVerifier.interface.encodeFunctionData("changeStakingLimits", [parsedData.minStakingDepositLimit, parsedData.timeForEmissionsLimit, parsedData.numServicesLimit, - parsedData.apyLimit]); + parsedData.apyLimit]); // Pack the second part of data const target = stakingVerifierAddress; const value = 0;