From 0a24fd62a9e7061035c714f65d0573e46e07c685 Mon Sep 17 00:00:00 2001 From: wcgcyx Date: Tue, 21 Nov 2023 19:54:31 +1000 Subject: [PATCH] Switch to root bridge with rate control --- scripts/bootstrap/.env.example | 8 ++++++ scripts/bootstrap/4_root_deployment.js | 2 +- scripts/bootstrap/8_root_initialisation.js | 32 ++++++++++++++++++++-- scripts/bootstrap/README.md | 9 ++++++ scripts/e2e/e2e.js | 2 +- scripts/localdev/.env.local | 8 ++++++ scripts/localdev/rootchain_setup.js | 11 ++++++++ 7 files changed, 67 insertions(+), 5 deletions(-) diff --git a/scripts/bootstrap/.env.example b/scripts/bootstrap/.env.example index 09ceb82d..759f6e28 100644 --- a/scripts/bootstrap/.env.example +++ b/scripts/bootstrap/.env.example @@ -19,6 +19,8 @@ CHILD_DEPLOYER_FUND= ROOT_DEPLOYER_ADDR= ## The private key for the deployer on root chain or "ledger" if using hardware wallet. ROOT_DEPLOYER_SECRET= +## The private key for rate admin or "ledger" if using hardware wallet. +ROOT_BRIDGE_RATE_ADMIN_SECRET= ## The IMX token address on root chain. ROOT_IMX_ADDR= ## The Wrapped ETH token address on the root chain. @@ -69,6 +71,12 @@ ROOT_ADAPTOR_BRIDGE_MANAGER= ROOT_ADAPTOR_GAS_SERVICE_MANAGER= ## The address to be assigned with TARGET_MANAGER_ROLE in root adaptor. ROOT_ADAPTOR_TARGET_MANAGER= +## The capacity of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_CAPACITY= +## The refill rate of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_REFILL_RATE= +## The large threshold of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_LARGE_THRESHOLD= # Set prior to 2_deployment_validation.js CHILD_GATEWAY_ADDRESS= diff --git a/scripts/bootstrap/4_root_deployment.js b/scripts/bootstrap/4_root_deployment.js index 53ca8a05..40677a23 100644 --- a/scripts/bootstrap/4_root_deployment.js +++ b/scripts/bootstrap/4_root_deployment.js @@ -50,7 +50,7 @@ async function run() { console.log("Deployed to ROOT_PROXY_ADMIN: ", proxyAdmin.address); // Deploy root bridge impl - let rootBridgeImplObj = JSON.parse(fs.readFileSync('../../out/RootERC20Bridge.sol/RootERC20Bridge.json', 'utf8')); + let rootBridgeImplObj = JSON.parse(fs.readFileSync('../../out/RootERC20BridgeFlowRate.sol/RootERC20BridgeFlowRate.json', 'utf8')); console.log("Deploy root bridge impl..."); let rootBridgeImpl = await helper.deployRootContract(rootBridgeImplObj, adminWallet); await helper.waitForReceipt(rootBridgeImpl.deployTransaction.hash, rootProvider); diff --git a/scripts/bootstrap/8_root_initialisation.js b/scripts/bootstrap/8_root_initialisation.js index b74c0f2c..50edd81c 100644 --- a/scripts/bootstrap/8_root_initialisation.js +++ b/scripts/bootstrap/8_root_initialisation.js @@ -12,6 +12,7 @@ async function run() { let rootRPCURL = helper.requireEnv("ROOT_RPC_URL"); let rootChainID = helper.requireEnv("ROOT_CHAIN_ID"); let rootDeployerSecret = helper.requireEnv("ROOT_DEPLOYER_SECRET"); + let rootRateAdminSecret = helper.requireEnv("ROOT_BRIDGE_RATE_ADMIN_SECRET"); let rootBridgeDefaultAdmin = helper.requireEnv("ROOT_BRIDGE_DEFAULT_ADMIN"); let rootBridgePauser = helper.requireEnv("ROOT_BRIDGE_PAUSER"); let rootBridgeUnpauser = helper.requireEnv("ROOT_BRIDGE_UNPAUSER"); @@ -25,6 +26,9 @@ async function run() { let rootIMXAddr = helper.requireEnv("ROOT_IMX_ADDR"); let rootWETHAddr = helper.requireEnv("ROOT_WETH_ADDR"); let imxDepositLimit = helper.requireEnv("IMX_DEPOSIT_LIMIT"); + let rateLimitIMXCap = helper.requireEnv("RATE_LIMIT_IMX_CAPACITY"); + let rateLimitIMXRefill = helper.requireEnv("RATE_LIMIT_IMX_REFILL_RATE"); + let rateLimitIMXLargeThreshold = helper.requireEnv("RATE_LIMIT_IMX_LARGE_THRESHOLD"); // Read from contract file. let data = fs.readFileSync(".child.bridge.contracts.json", 'utf-8'); @@ -48,15 +52,26 @@ async function run() { let adminAddr = await adminWallet.getAddress(); console.log("Deployer address is: ", adminAddr); + // Get rate admin address + let rateAdminWallet; + if (rootRateAdminSecret == "ledger") { + rateAdminWallet = new LedgerSigner(rateAdminWallet); + } else { + rateAdminWallet = new ethers.Wallet(rootRateAdminSecret, rootProvider); + } + let rateAdminAddr = await rateAdminWallet.getAddress(); + console.log("Rate admin address is: ", rateAdminAddr); + + // Execute console.log("Initialise root contracts in..."); await helper.waitForConfirmation(); // Initialise root bridge - let rootBridgeObj = JSON.parse(fs.readFileSync('../../out/RootERC20Bridge.sol/RootERC20Bridge.json', 'utf8')); + let rootBridgeObj = JSON.parse(fs.readFileSync('../../out/RootERC20BridgeFlowRate.sol/RootERC20BridgeFlowRate.json', 'utf8')); console.log("Initialise root bridge..."); let rootBridge = new ethers.Contract(rootBridgeAddr, rootBridgeObj.abi, rootProvider); - let resp = await rootBridge.connect(adminWallet).initialize( + let resp = await rootBridge.connect(adminWallet)["initialize((address,address,address,address,address),address,address,string,address,address,address,string,uint256,address)"]( { defaultAdmin: rootBridgeDefaultAdmin, pauser: rootBridgePauser, @@ -71,7 +86,18 @@ async function run() { rootIMXAddr, rootWETHAddr, childChainName, - ethers.utils.parseEther(imxDepositLimit)); + ethers.utils.parseEther(imxDepositLimit), + rateAdminAddr); + await helper.waitForReceipt(resp.hash, rootProvider); + + // Configure rate + // IMX + resp = await rootBridge.connect(rateAdminWallet).setRateControlThreshold( + rootIMXAddr, + ethers.utils.parseEther(rateLimitIMXCap), + ethers.utils.parseEther(rateLimitIMXRefill), + ethers.utils.parseEther(rateLimitIMXLargeThreshold) + ); await helper.waitForReceipt(resp.hash, rootProvider); // Initialise root adaptor diff --git a/scripts/bootstrap/README.md b/scripts/bootstrap/README.md index 6f0ba79d..125d5e7d 100644 --- a/scripts/bootstrap/README.md +++ b/scripts/bootstrap/README.md @@ -7,6 +7,7 @@ 4. Coordinate with security to obtain the addresses for different roles. 5. Fund deployer with `ETH` and `IMX` on root chain. (As a rule of thumb, _0.1 ETH and 1100 IMX_ (TBD)). 6. Fund a test account with `ETH` and `IMX` on root chain. (As a rule of thumb, _0.1 ETH and 50 IMX_ (TBD)). +7. Fund a rate admin account with `ETH` on root chain. (As a rule of thumb, _0.1 ETH_ (TBD)). ## Bootstrapping @@ -43,6 +44,8 @@ CHILD_DEPLOYER_FUND= ROOT_DEPLOYER_ADDR= ## The private key for the deployer on root chain or "ledger" if using hardware wallet. ROOT_DEPLOYER_SECRET= +## The private key for rate admin or "ledger" if using hardware wallet. +ROOT_BRIDGE_RATE_ADMIN_SECRET= ## The IMX token address on root chain. ROOT_IMX_ADDR= ## The Wrapped ETH token address on the root chain. @@ -93,6 +96,12 @@ ROOT_ADAPTOR_BRIDGE_MANAGER= ROOT_ADAPTOR_GAS_SERVICE_MANAGER= ## The address to be assigned with TARGET_MANAGER_ROLE in root adaptor. ROOT_ADAPTOR_TARGET_MANAGER= +## The capacity of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_CAPACITY= +## The refill rate of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_REFILL_RATE= +## The large threshold of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_LARGE_THRESHOLD= ``` 3. Fund deployer ``` diff --git a/scripts/e2e/e2e.js b/scripts/e2e/e2e.js index 7452e632..c17a33fa 100644 --- a/scripts/e2e/e2e.js +++ b/scripts/e2e/e2e.js @@ -47,7 +47,7 @@ describe("Bridge e2e test", () => { rootTestWallet = new ethers.Wallet(testAccountKey, rootProvider); childTestWallet = new ethers.Wallet(testAccountKey, childProvider); - let rootBridgeObj = JSON.parse(fs.readFileSync('../../out/RootERC20Bridge.sol/RootERC20Bridge.json', 'utf8')); + let rootBridgeObj = JSON.parse(fs.readFileSync('../../out/RootERC20BridgeFlowRate.sol/RootERC20BridgeFlowRate.json', 'utf8')); rootBridge = new ethers.Contract(rootBridgeAddr, rootBridgeObj.abi, rootProvider); let WETHObj = JSON.parse(fs.readFileSync('../../out/WETH.sol/WETH.json', 'utf8')) diff --git a/scripts/localdev/.env.local b/scripts/localdev/.env.local index 98383f87..87c203a9 100644 --- a/scripts/localdev/.env.local +++ b/scripts/localdev/.env.local @@ -19,6 +19,8 @@ CHILD_DEPLOYER_FUND=500 ROOT_DEPLOYER_ADDR=0x70997970C51812dc3A010C7d01b50e0d17dc79C8 ## The private key for the deployer on root chain or "ledger" if using hardware wallet. ROOT_DEPLOYER_SECRET=59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d +## The private key for rate admin or "ledger" if using hardware wallet. +ROOT_BRIDGE_RATE_ADMIN_SECRET=8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba ## The IMX token address on root chain. ROOT_IMX_ADDR=0x73511669fd4dE447feD18BB79bAFeAC93aB7F31f ## The Wrapped ETH token address on the root chain. @@ -69,6 +71,12 @@ ROOT_ADAPTOR_BRIDGE_MANAGER=0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc ROOT_ADAPTOR_GAS_SERVICE_MANAGER=0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc ## The address to be assigned with TARGET_MANAGER_ROLE in root adaptor. ROOT_ADAPTOR_TARGET_MANAGER=0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc +## The capacity of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_CAPACITY=15516 +## The refill rate of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_REFILL_RATE=4.31 +## The large threshold of the rate limit policy of IMX token, unit is in 10^18. +RATE_LIMIT_IMX_LARGE_THRESHOLD=7758 # Set prior to 2_deployment_validation.js CHILD_GATEWAY_ADDRESS=0xcf27F781841484d5CF7e155b44954D7224caF1dD diff --git a/scripts/localdev/rootchain_setup.js b/scripts/localdev/rootchain_setup.js index 4f68ad1c..cc7e5b35 100644 --- a/scripts/localdev/rootchain_setup.js +++ b/scripts/localdev/rootchain_setup.js @@ -12,6 +12,7 @@ async function main() { let rootDeployerKey = helper.requireEnv("ROOT_DEPLOYER_SECRET"); let axelarDeployerKey = helper.requireEnv("AXELAR_ROOT_EOA_SECRET"); let rootTestKey = helper.requireEnv("TEST_ACCOUNT_SECRET"); + let rootRateAdminKey = helper.requireEnv("ROOT_BRIDGE_RATE_ADMIN_SECRET"); // Get root provider. let rootProvider = new ethers.providers.JsonRpcProvider(rootRPCURL, Number(rootChainID)); @@ -24,6 +25,9 @@ async function main() { // Get test wwallet on the root chain. let testWallet = new ethers.Wallet(rootTestKey, rootProvider); + + // Get rate admin wallet on the root chain. + let rateAdminWallet = new ethers.Wallet(rootRateAdminKey, rootProvider); // Get root admin eoa wallet. let admin = new ethers.Wallet(rootAdminKey, rootProvider); @@ -81,6 +85,13 @@ async function main() { }) await helper.waitForReceipt(resp.hash, rootProvider); + // Transfer 0.1 ETH to rate admin + resp = await admin.sendTransaction({ + to: rateAdminWallet.address, + value: ethers.utils.parseEther("10.0"), + }) + await helper.waitForReceipt(resp.hash, rootProvider); + console.log("Root deployer now has " + ethers.utils.formatEther(await IMX.balanceOf(rootDeployer.address)) + " IMX."); console.log("Root deployer now has " + ethers.utils.formatEther(await rootProvider.getBalance(rootDeployer.address)) + " ETH."); console.log("Root axelar now has " + ethers.utils.formatEther(await rootProvider.getBalance(axelarDeployer.address)) + " ETH.");