From de5f5d306031cf3f2168e5a68998d40da7be3320 Mon Sep 17 00:00:00 2001 From: Bui Quang Minh Date: Fri, 15 Dec 2023 17:30:11 +0700 Subject: [PATCH 1/6] forge install: foundry-deployment-kit 288efb2f25dffab999351a6849082f0b27dfb984 --- .gitmodules | 3 +++ lib/foundry-deployment-kit | 1 + 2 files changed, 4 insertions(+) create mode 160000 lib/foundry-deployment-kit diff --git a/.gitmodules b/.gitmodules index 5274dcbda..8deb9b9ed 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,3 +15,6 @@ [submodule "lib/openzeppelin-contracts"] path = lib/openzeppelin-contracts url = https://github.com/openzeppelin/openzeppelin-contracts +[submodule "lib/foundry-deployment-kit"] + path = lib/foundry-deployment-kit + url = https://github.com/axieinfinity/foundry-deployment-kit diff --git a/lib/foundry-deployment-kit b/lib/foundry-deployment-kit new file mode 160000 index 000000000..288efb2f2 --- /dev/null +++ b/lib/foundry-deployment-kit @@ -0,0 +1 @@ +Subproject commit 288efb2f25dffab999351a6849082f0b27dfb984 From 2d2cca474a3905724bcb94a64c061e7974c8bb5c Mon Sep 17 00:00:00 2001 From: Bui Quang Minh Date: Tue, 19 Dec 2023 13:05:37 +0700 Subject: [PATCH 2/6] chore: add scripts to map AGG token --- remappings.txt | 3 +- .../20231218-maptoken-mainchain.s.sol | 98 +++++++++++++++++++ .../20231218-maptoken-roninchain.s.sol | 75 ++++++++++++++ script/BridgeMigration.sol | 46 +++++++++ script/GeneralConfigExtended.sol | 53 ++++++++++ script/IGeneralConfigExtended.sol | 17 ++++ script/utils/Contract.sol | 31 ++++++ script/utils/Network.sol | 50 ++++++++++ 8 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 script/20231218-maptoken/20231218-maptoken-mainchain.s.sol create mode 100644 script/20231218-maptoken/20231218-maptoken-roninchain.s.sol create mode 100644 script/BridgeMigration.sol create mode 100644 script/GeneralConfigExtended.sol create mode 100644 script/IGeneralConfigExtended.sol create mode 100644 script/utils/Contract.sol create mode 100644 script/utils/Network.sol diff --git a/remappings.txt b/remappings.txt index f56bd7f74..c1cb927bf 100644 --- a/remappings.txt +++ b/remappings.txt @@ -6,4 +6,5 @@ hardhat/=node_modules/hardhat/ @ronin/test/=test/ @prb/test/=lib/prb-test/src/ @prb/math/=lib/prb-math/ -solady/=lib/solady/src/ \ No newline at end of file +solady/=lib/solady/src/ +foundry-deployment-kit/=lib/foundry-deployment-kit/script/ diff --git a/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol b/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol new file mode 100644 index 000000000..4db7f687f --- /dev/null +++ b/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { BaseMigration } from "foundry-deployment-kit/BaseMigration.s.sol"; +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import { IMainchainGatewayV3 } from "@ronin/contracts/interfaces/IMainchainGatewayV3.sol"; +import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol"; +import { Token } from "@ronin/contracts/libraries/Token.sol"; +import { Contract } from "../utils/Contract.sol"; +import { BridgeMigration } from "../BridgeMigration.sol"; +import { Network } from "../utils/Network.sol"; +import { Contract } from "../utils/Contract.sol"; +import { IGeneralConfigExtended } from "../IGeneralConfigExtended.sol"; + +contract Migration__20231215_MapTokenMainchain is BridgeMigration { + RoninBridgeManager internal _roninBridgeManager; + IGeneralConfigExtended internal constant _config = IGeneralConfigExtended(address(CONFIG)); + address constant _aggRoninToken = address(0x294311a8C37F0744F99EB152c419D4D3D6FEC1C7); + address constant _aggMainchainToken = address(0xFB0489e9753B045DdB35e39c6B0Cc02EC6b99AC5); + address internal _mainchainGatewayV3; + + uint256 constant _highTierThreshold = 0; + uint256 constant _lockedThreshold = 0; + uint256 constant _unlockFeePercentages = 0; + uint256 constant _dailyWithdrawalLimit = 0; + + function setUp() public override { + super.setUp(); + + _roninBridgeManager = RoninBridgeManager(_config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); + _mainchainGatewayV3 = _config.getAddress( + _config.getCompanionNetwork(_config.getNetworkByChainId(block.chainid)).key(), + Contract.MainchainGatewayV3.key() + ); + } + + function run() public { + address[] memory mainchainTokens = new address[](1); + mainchainTokens[0] = _aggMainchainToken; + address[] memory roninTokens = new address[](1); + roninTokens[0] = _aggRoninToken; + Token.Standard[] memory standards = new Token.Standard[](1); + standards[0] = Token.Standard.ERC20; + uint256[][4] memory thresholds; + // highTierThreshold + thresholds[0] = new uint256[](1); + thresholds[0][0] = _highTierThreshold; + // lockedThreshold + thresholds[1] = new uint256[](1); + thresholds[1][0] = _lockedThreshold; + // unlockFeePercentages + thresholds[2] = new uint256[](1); + thresholds[2][0] = _unlockFeePercentages; + // dailyWithdrawalLimit + thresholds[3] = new uint256[](1); + thresholds[3][0] = _dailyWithdrawalLimit; + + // function mapTokensAndThresholds( + // address[] calldata _mainchainTokens, + // address[] calldata _roninTokens, + // Token.Standard[] calldata _standards, + // uint256[][4] calldata _thresholds + // ) + + bytes memory innerData = abi.encodeCall(IMainchainGatewayV3.mapTokensAndThresholds, ( + mainchainTokens, + roninTokens, + standards, + thresholds + )); + bytes memory proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); + + uint256 expiredTime = block.timestamp + 10 days; + address[] memory targets = new address[](1); + targets[0] = _mainchainGatewayV3; + uint256[] memory values = new uint256[](1); + values[0] = 0; + bytes[] memory calldatas = new bytes[](1); + calldatas[0] = proxyData; + uint256[] memory gasAmounts = new uint256[](1); + gasAmounts[0] = 1_000_000; + + _verifyProposalGasAmount(_roninBridgeManager, targets, values, calldatas, gasAmounts); + + uint256 chainId = _config.getCompanionNetwork(_config.getNetworkByChainId(block.chainid)).chainId(); + vm.broadcast(sender()); + _roninBridgeManager.propose( + chainId, + expiredTime, + targets, + values, + calldatas, + gasAmounts + ); + } +} diff --git a/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol b/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol new file mode 100644 index 000000000..ba14ee810 --- /dev/null +++ b/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { BaseMigration } from "foundry-deployment-kit/BaseMigration.s.sol"; +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import { IRoninGatewayV3 } from "@ronin/contracts/interfaces/IRoninGatewayV3.sol"; +import { Token } from "@ronin/contracts/libraries/Token.sol"; +import { Contract } from "../utils/Contract.sol"; +import { BridgeMigration } from "../BridgeMigration.sol"; +import { Network } from "../utils/Network.sol"; +import { Contract } from "../utils/Contract.sol"; +import { IGeneralConfigExtended } from "../IGeneralConfigExtended.sol"; + +contract Migration__20231215_MapTokenRoninchain is BridgeMigration { + RoninBridgeManager internal _roninBridgeManager; + IGeneralConfigExtended internal constant _config = IGeneralConfigExtended(address(CONFIG)); + address constant _aggRoninToken = address(0x294311a8C37F0744F99EB152c419D4D3D6FEC1C7); + address constant _aggMainchainToken = address(0xFB0489e9753B045DdB35e39c6B0Cc02EC6b99AC5); + address internal _roninGatewayV3; + + function setUp() public override { + super.setUp(); + _roninBridgeManager = RoninBridgeManager(_config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); + _roninGatewayV3 = _config.getAddressFromCurrentNetwork(Contract.RoninGatewayV3.key()); + } + + function run() public { + address[] memory roninTokens = new address[](1); + roninTokens[0] = _aggRoninToken; + address[] memory mainchainTokens = new address[](1); + mainchainTokens[0] = _aggMainchainToken; + uint256[] memory chainIds = new uint256[](1); + chainIds[0] = _config.getCompanionNetwork(_config.getNetworkByChainId(block.chainid)).chainId(); + Token.Standard[] memory standards = new Token.Standard[](1); + standards[0] = Token.Standard.ERC20; + + // function mapTokens( + // address[] calldata _roninTokens, + // address[] calldata _mainchainTokens, + // uint256[] calldata chainIds, + // Token.Standard[] calldata _standards + // ) + bytes memory innerData = abi.encodeCall(IRoninGatewayV3.mapTokens, ( + roninTokens, + mainchainTokens, + chainIds, + standards + )); + bytes memory proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); + + uint256 expiredTime = block.timestamp + 10 days; + address[] memory targets = new address[](1); + targets[0] = _roninGatewayV3; + uint256[] memory values = new uint256[](1); + values[0] = 0; + bytes[] memory calldatas = new bytes[](1); + calldatas[0] = proxyData; + uint256[] memory gasAmounts = new uint256[](1); + gasAmounts[0] = 1_000_000; + + _verifyProposalGasAmount(_roninBridgeManager, targets, values, calldatas, gasAmounts); + + vm.broadcast(sender()); + _roninBridgeManager.propose( + block.chainid, + expiredTime, + targets, + values, + calldatas, + gasAmounts + ); + } +} diff --git a/script/BridgeMigration.sol b/script/BridgeMigration.sol new file mode 100644 index 000000000..84299b64d --- /dev/null +++ b/script/BridgeMigration.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { BaseMigration } from "foundry-deployment-kit/BaseMigration.s.sol"; +import { GeneralConfigExtended } from "./GeneralConfigExtended.sol"; +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import { ErrorHandler } from "@ronin/contracts/libraries/ErrorHandler.sol"; + +contract BridgeMigration is BaseMigration { + using ErrorHandler for bool; + + error ErrProposalOutOfGas(bytes4 sig, uint256 expectedGas); + + function _configByteCode() internal virtual override returns (bytes memory) { + return abi.encodePacked(type(GeneralConfigExtended).creationCode); + } + + function _sharedArguments() internal virtual override returns (bytes memory rawArgs) { + return ""; + } + + function _verifyProposalGasAmount( + RoninBridgeManager _bridgeManager, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + uint256[] memory gasAmounts + ) internal { + uint256 snapshotId = vm.snapshot(); + + vm.startPrank(address(_bridgeManager)); + for (uint256 i; i < targets.length; i++) { + vm.deal(address(_bridgeManager), values[i]); + uint256 gasUsed = gasleft(); + (bool success, bytes memory returnOrRevertData) = targets[i].call{value: values[i]}(calldatas[i]); + gasUsed = gasUsed - gasleft(); + success.handleRevert(bytes4(calldatas[i]), returnOrRevertData); + + if (gasUsed > gasAmounts[i]) { + revert ErrProposalOutOfGas(bytes4(calldatas[i]), gasUsed); + } + } + vm.stopPrank(); + vm.revertTo(snapshotId); + } +} diff --git a/script/GeneralConfigExtended.sol b/script/GeneralConfigExtended.sol new file mode 100644 index 000000000..1d2f5ccb9 --- /dev/null +++ b/script/GeneralConfigExtended.sol @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 as console } from "forge-std/console2.sol"; +import { TContract } from "foundry-deployment-kit/types/Types.sol"; +import { BaseGeneralConfig } from "foundry-deployment-kit/BaseGeneralConfig.sol"; +import { TNetwork } from "foundry-deployment-kit/types/Types.sol"; +import { DefaultNetwork } from "foundry-deployment-kit/utils/DefaultNetwork.sol"; +import { Network } from "./utils/Network.sol"; +import { Contract } from "./utils/Contract.sol"; + +contract GeneralConfigExtended is BaseGeneralConfig { + constructor() BaseGeneralConfig("", "deployments/") { } + + function _setUpNetworks() internal virtual override { + setNetworkInfo( + Network.Goerli.chainId(), + Network.Goerli.key(), + Network.Goerli.chainAlias(), + Network.Goerli.deploymentDir(), + Network.Goerli.envLabel(), + Network.Goerli.explorer() + ); + setNetworkInfo( + Network.EthMainnet.chainId(), + Network.EthMainnet.key(), + Network.EthMainnet.chainAlias(), + Network.EthMainnet.deploymentDir(), + Network.EthMainnet.envLabel(), + Network.EthMainnet.explorer() + ); + } + + function _setUpContracts() internal virtual override { + _mapContractname(Contract.BridgeReward); + _mapContractname(Contract.BridgeSlash); + _mapContractname(Contract.BridgeTracking); + _mapContractname(Contract.RoninBridgeManager); + _mapContractname(Contract.RoninGatewayV3); + _mapContractname(Contract.MainchainBridgeManager); + _mapContractname(Contract.MainchainGatewayV3); + } + + function _mapContractname(Contract contractEnum) internal { + _contractNameMap[contractEnum.key()] = contractEnum.name(); + } + + function getCompanionNetwork(TNetwork network) external pure returns (Network) { + if (network == DefaultNetwork.RoninTestnet.key()) return Network.Goerli; + if (network == DefaultNetwork.RoninMainnet.key()) return Network.EthMainnet; + revert("Network: Unknown companion network"); + } +} diff --git a/script/IGeneralConfigExtended.sol b/script/IGeneralConfigExtended.sol new file mode 100644 index 000000000..78a02582a --- /dev/null +++ b/script/IGeneralConfigExtended.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { IGeneralConfig } from "foundry-deployment-kit/interfaces/IGeneralConfig.sol"; +import { TNetwork } from "foundry-deployment-kit/types/Types.sol"; +import { Network } from "./utils/Network.sol"; + +interface IGeneralConfigExtended is IGeneralConfig { + /** + * @dev Returns the companion mainchain network of a roninchain network + * + * Input: roninchain network + * Output: companion mainchain network of roninchain + * + */ + function getCompanionNetwork(TNetwork network) external pure returns (Network); +} diff --git a/script/utils/Contract.sol b/script/utils/Contract.sol new file mode 100644 index 000000000..3403c5b2f --- /dev/null +++ b/script/utils/Contract.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { LibString, TContract } from "foundry-deployment-kit/types/Types.sol"; + +enum Contract { + BridgeReward, + BridgeSlash, + BridgeTracking, + RoninBridgeManager, + RoninGatewayV3, + MainchainBridgeManager, + MainchainGatewayV3 +} + +using { key, name } for Contract global; + +function key(Contract contractEnum) pure returns (TContract) { + return TContract.wrap(LibString.packOne(name(contractEnum))); +} + +function name(Contract contractEnum) pure returns (string memory) { + if (contractEnum == Contract.BridgeReward) return "BridgeReward"; + if (contractEnum == Contract.BridgeSlash) return "BridgeSlash"; + if (contractEnum == Contract.BridgeTracking) return "BridgeTracking"; + if (contractEnum == Contract.RoninBridgeManager) return "RoninBridgeManager"; + if (contractEnum == Contract.RoninGatewayV3) return "RoninGatewayV3"; + if (contractEnum == Contract.MainchainBridgeManager) return "MainchainBridgeManager"; + if (contractEnum == Contract.MainchainGatewayV3) return "MainchainGatewayV3"; + revert("Contract: Unknown contract"); +} diff --git a/script/utils/Network.sol b/script/utils/Network.sol new file mode 100644 index 000000000..6c312a97a --- /dev/null +++ b/script/utils/Network.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { LibString, TNetwork } from "foundry-deployment-kit/types/Types.sol"; + +enum Network { + Goerli, + EthMainnet +} + +using { key, name, chainId, chainAlias, envLabel, deploymentDir, explorer } for Network global; + +function chainId(Network network) pure returns (uint256) { + if (network == Network.Goerli) return 5; + if (network == Network.EthMainnet) return 1; + revert("Network: Unknown chain id"); +} + +function key(Network network) pure returns (TNetwork) { + return TNetwork.wrap(LibString.packOne(name(network))); +} + +function explorer(Network network) pure returns (string memory link) { + if (network == Network.Goerli) return "https://goerli.etherscan.io/"; + if (network == Network.EthMainnet) return "https://etherscan.io/"; +} + +function name(Network network) pure returns (string memory) { + if (network == Network.Goerli) return "Goerli"; + if (network == Network.EthMainnet) return "EthMainnet"; + revert("Network: Unknown network name"); +} + +function deploymentDir(Network network) pure returns (string memory) { + if (network == Network.Goerli) return "goerli/"; + if (network == Network.EthMainnet) return "ethereum/"; + revert("Network: Unknown network deployment directory"); +} + +function envLabel(Network network) pure returns (string memory) { + if (network == Network.Goerli) return "TESTNET_PK"; + if (network == Network.EthMainnet) return "MAINNET_PK"; + revert("Network: Unknown private key env label"); +} + +function chainAlias(Network network) pure returns (string memory) { + if (network == Network.Goerli) return "goerli"; + if (network == Network.EthMainnet) return "ethereum"; + revert("Network: Unknown network alias"); +} From 5446c7b4cd3d78d2eedd312a63424d5a7358bd07 Mon Sep 17 00:00:00 2001 From: Bui Quang Minh Date: Wed, 20 Dec 2023 21:45:21 +0700 Subject: [PATCH 3/6] chore: add AGG token thresholds --- .../20231218-maptoken-mainchain.s.sol | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol b/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol index 4db7f687f..e90749bba 100644 --- a/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol +++ b/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol @@ -21,10 +21,12 @@ contract Migration__20231215_MapTokenMainchain is BridgeMigration { address constant _aggMainchainToken = address(0xFB0489e9753B045DdB35e39c6B0Cc02EC6b99AC5); address internal _mainchainGatewayV3; - uint256 constant _highTierThreshold = 0; - uint256 constant _lockedThreshold = 0; - uint256 constant _unlockFeePercentages = 0; - uint256 constant _dailyWithdrawalLimit = 0; + // The decimal of AGG token is 18 + uint256 constant _highTierThreshold = 200_000_000 ether; + uint256 constant _lockedThreshold = 800_000_000 ether; + // The MAX_PERCENTAGE is 1_000_000 + uint256 constant _unlockFeePercentages = 10; + uint256 constant _dailyWithdrawalLimit = 500_000_000 ether; function setUp() public override { super.setUp(); From 5ec9f4817ca0b6171e91858faf8d81e9f729fafd Mon Sep 17 00:00:00 2001 From: nxqbao Date: Thu, 21 Dec 2023 13:12:15 +0700 Subject: [PATCH 4/6] chore: fix validate gas on mainchain --- .../20231218-maptoken-mainchain.s.sol | 4 +- .../20231218-maptoken-roninchain.s.sol | 3 +- script/BridgeMigration.sol | 49 ++++++++++++++++--- 3 files changed, 46 insertions(+), 10 deletions(-) diff --git a/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol b/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol index e90749bba..7c14fb132 100644 --- a/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol +++ b/script/20231218-maptoken/20231218-maptoken-mainchain.s.sol @@ -16,7 +16,6 @@ import { IGeneralConfigExtended } from "../IGeneralConfigExtended.sol"; contract Migration__20231215_MapTokenMainchain is BridgeMigration { RoninBridgeManager internal _roninBridgeManager; - IGeneralConfigExtended internal constant _config = IGeneralConfigExtended(address(CONFIG)); address constant _aggRoninToken = address(0x294311a8C37F0744F99EB152c419D4D3D6FEC1C7); address constant _aggMainchainToken = address(0xFB0489e9753B045DdB35e39c6B0Cc02EC6b99AC5); address internal _mainchainGatewayV3; @@ -84,9 +83,10 @@ contract Migration__20231215_MapTokenMainchain is BridgeMigration { uint256[] memory gasAmounts = new uint256[](1); gasAmounts[0] = 1_000_000; - _verifyProposalGasAmount(_roninBridgeManager, targets, values, calldatas, gasAmounts); + _verifyMainchainProposalGasAmount(targets, values, calldatas, gasAmounts); uint256 chainId = _config.getCompanionNetwork(_config.getNetworkByChainId(block.chainid)).chainId(); + vm.broadcast(sender()); _roninBridgeManager.propose( chainId, diff --git a/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol b/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol index ba14ee810..a7bc37af9 100644 --- a/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol +++ b/script/20231218-maptoken/20231218-maptoken-roninchain.s.sol @@ -15,7 +15,6 @@ import { IGeneralConfigExtended } from "../IGeneralConfigExtended.sol"; contract Migration__20231215_MapTokenRoninchain is BridgeMigration { RoninBridgeManager internal _roninBridgeManager; - IGeneralConfigExtended internal constant _config = IGeneralConfigExtended(address(CONFIG)); address constant _aggRoninToken = address(0x294311a8C37F0744F99EB152c419D4D3D6FEC1C7); address constant _aggMainchainToken = address(0xFB0489e9753B045DdB35e39c6B0Cc02EC6b99AC5); address internal _roninGatewayV3; @@ -60,7 +59,7 @@ contract Migration__20231215_MapTokenRoninchain is BridgeMigration { uint256[] memory gasAmounts = new uint256[](1); gasAmounts[0] = 1_000_000; - _verifyProposalGasAmount(_roninBridgeManager, targets, values, calldatas, gasAmounts); + _verifyRoninProposalGasAmount(targets, values, calldatas, gasAmounts); vm.broadcast(sender()); _roninBridgeManager.propose( diff --git a/script/BridgeMigration.sol b/script/BridgeMigration.sol index 84299b64d..2f8662ba1 100644 --- a/script/BridgeMigration.sol +++ b/script/BridgeMigration.sol @@ -1,16 +1,23 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import { console2 } from "forge-std/console2.sol"; import { BaseMigration } from "foundry-deployment-kit/BaseMigration.s.sol"; import { GeneralConfigExtended } from "./GeneralConfigExtended.sol"; import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; import { ErrorHandler } from "@ronin/contracts/libraries/ErrorHandler.sol"; +import { IGeneralConfigExtended } from "./IGeneralConfigExtended.sol"; +import { Network } from "./utils/Network.sol"; +import { Contract } from "./utils/Contract.sol"; +import { DefaultNetwork } from "foundry-deployment-kit/utils/DefaultNetwork.sol"; contract BridgeMigration is BaseMigration { using ErrorHandler for bool; error ErrProposalOutOfGas(bytes4 sig, uint256 expectedGas); + IGeneralConfigExtended internal constant _config = IGeneralConfigExtended(address(CONFIG)); + function _configByteCode() internal virtual override returns (bytes memory) { return abi.encodePacked(type(GeneralConfigExtended).creationCode); } @@ -19,28 +26,58 @@ contract BridgeMigration is BaseMigration { return ""; } - function _verifyProposalGasAmount( - RoninBridgeManager _bridgeManager, + function _verifyRoninProposalGasAmount( + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + uint256[] memory gasAmounts + ) internal { + address roninBridgeManager = _config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key()); + uint256 snapshotId = vm.snapshot(); + vm.startPrank(address(roninBridgeManager)); + _verifyProposalGasAmount(roninBridgeManager, targets, values, calldatas, gasAmounts); + vm.stopPrank(); + vm.revertTo(snapshotId); + } + + function _verifyMainchainProposalGasAmount( address[] memory targets, uint256[] memory values, bytes[] memory calldatas, uint256[] memory gasAmounts ) internal { + _config.createFork(Network.EthMainnet.key()); + _config.switchTo(Network.EthMainnet.key()); + + address mainchainBridgeManager = _config.getAddressFromCurrentNetwork(Contract.MainchainBridgeManager.key()); uint256 snapshotId = vm.snapshot(); - vm.startPrank(address(_bridgeManager)); + vm.startPrank(address(mainchainBridgeManager)); + _verifyProposalGasAmount(mainchainBridgeManager, targets, values, calldatas, gasAmounts); + vm.stopPrank(); + vm.revertTo(snapshotId); + + _config.switchTo(DefaultNetwork.RoninMainnet.key()); + } + + function _verifyProposalGasAmount( + address bridgeManager, + address[] memory targets, + uint256[] memory values, + bytes[] memory calldatas, + uint256[] memory gasAmounts + ) private { for (uint256 i; i < targets.length; i++) { - vm.deal(address(_bridgeManager), values[i]); + vm.deal(address(bridgeManager), values[i]); uint256 gasUsed = gasleft(); (bool success, bytes memory returnOrRevertData) = targets[i].call{value: values[i]}(calldatas[i]); gasUsed = gasUsed - gasleft(); success.handleRevert(bytes4(calldatas[i]), returnOrRevertData); + console2.log("Call", i, ": gasUsed", gasUsed); if (gasUsed > gasAmounts[i]) { revert ErrProposalOutOfGas(bytes4(calldatas[i]), gasUsed); } } - vm.stopPrank(); - vm.revertTo(snapshotId); } } From f64d89ac15127324401b971e732ebb0a615d65e1 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 21 Dec 2023 13:42:17 +0700 Subject: [PATCH 5/6] forge install: foundry-deployment-kit e17e2699290d58f6474087c4ecbe50ea38c2c19e --- lib/foundry-deployment-kit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/foundry-deployment-kit b/lib/foundry-deployment-kit index 288efb2f2..e17e26992 160000 --- a/lib/foundry-deployment-kit +++ b/lib/foundry-deployment-kit @@ -1 +1 @@ -Subproject commit 288efb2f25dffab999351a6849082f0b27dfb984 +Subproject commit e17e2699290d58f6474087c4ecbe50ea38c2c19e From 982ab614e440c98de1b0f1916e79b53f2d0cf332 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 21 Dec 2023 14:14:34 +0700 Subject: [PATCH 6/6] feat: add run.sh --- run.sh | 1 + 1 file changed, 1 insertion(+) create mode 100755 run.sh diff --git a/run.sh b/run.sh new file mode 100755 index 000000000..931b150b7 --- /dev/null +++ b/run.sh @@ -0,0 +1 @@ +source lib/foundry-deployment-kit/run.sh \ No newline at end of file