diff --git a/script/20240403-deploy-sepolia/changeGV-config.s.sol b/script/20240403-deploy-sepolia/changeGV-config.s.sol new file mode 100644 index 00000000..5d471b0c --- /dev/null +++ b/script/20240403-deploy-sepolia/changeGV-config.s.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { IBridgeManager } from "@ronin/contracts/interfaces/bridge/IBridgeManager.sol"; + +contract DeploySepolia__ChangeGV_Config { + function _removeInitOperator() internal pure returns (bytes memory) { + address[] memory bridgeOperator = new address[](1); + bridgeOperator[0] = 0xbA8E32D874948dF4Cbe72284De91CC4968293BCe; + + // function removeBridgeOperators( + // address[] calldata bridgeOperators + // ) + + return abi.encodeCall(IBridgeManager.removeBridgeOperators, (bridgeOperator)); + } + + function _addTestnetOperators() internal pure returns (bytes memory) { + uint96[] memory voteWeights = new uint96[](4); + address[] memory governors = new address[](4); // 0xd24D87DDc1917165435b306aAC68D99e0F49A3Fa,0xb033ba62EC622dC54D0ABFE0254e79692147CA26,0x087D08e3ba42e64E3948962dd1371F906D1278b9,0x52ec2e6BBcE45AfFF8955Da6410bb13812F4289F + address[] memory bridgeOperators = new address[](4); // 0x2e82D2b56f858f79DeeF11B160bFC4631873da2B,0xBcb61783dd2403FE8cC9B89B27B1A9Bb03d040Cb,0xB266Bf53Cf7EAc4E2065A404598DCB0E15E9462c,0xcc5Fc5B6c8595F56306Da736F6CD02eD9141C84A + + voteWeights[0] = 100; + voteWeights[1] = 100; + voteWeights[2] = 100; + voteWeights[3] = 100; + + governors[0] = 0xd24D87DDc1917165435b306aAC68D99e0F49A3Fa; + governors[1] = 0xb033ba62EC622dC54D0ABFE0254e79692147CA26; + governors[2] = 0x087D08e3ba42e64E3948962dd1371F906D1278b9; + governors[3] = 0x52ec2e6BBcE45AfFF8955Da6410bb13812F4289F; + + bridgeOperators[0] = 0x2e82D2b56f858f79DeeF11B160bFC4631873da2B; + bridgeOperators[1] = 0xBcb61783dd2403FE8cC9B89B27B1A9Bb03d040Cb; + bridgeOperators[2] = 0xB266Bf53Cf7EAc4E2065A404598DCB0E15E9462c; + bridgeOperators[3] = 0xcc5Fc5B6c8595F56306Da736F6CD02eD9141C84A; + + // function addBridgeOperators( + // uint96[] calldata voteWeights, + // address[] calldata governors, + // address[] calldata bridgeOperators + // ) + + return abi.encodeCall(IBridgeManager.addBridgeOperators, (voteWeights, governors, bridgeOperators)); + } +} diff --git a/script/20240403-deploy-sepolia/deploy-sepolia.s.sol b/script/20240403-deploy-sepolia/deploy-sepolia.s.sol index 7b02fa95..f20610fe 100644 --- a/script/20240403-deploy-sepolia/deploy-sepolia.s.sol +++ b/script/20240403-deploy-sepolia/deploy-sepolia.s.sol @@ -1,14 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import { BaseMigration } from "foundry-deployment-kit/BaseMigration.s.sol"; - import { ISharedArgument } from "@ronin/script/interfaces/ISharedArgument.sol"; import { LibSharedAddress } from "foundry-deployment-kit/libraries/LibSharedAddress.sol"; -import { MainchainGatewayV3 } from "@ronin/contracts/mainchain/MainchainGatewayV3.sol"; -import { PauseEnforcer } from "@ronin/contracts/ronin/gateway/PauseEnforcer.sol"; -import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import "@ronin/contracts/mainchain/MainchainGatewayV3.sol"; +import "@ronin/contracts/ronin/gateway/PauseEnforcer.sol"; +import "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; import { MockERC20 } from "@ronin/contracts/mocks/token/MockERC20.sol"; import { MockERC721 } from "@ronin/contracts/mocks/token/MockERC721.sol"; import { MockWrappedToken } from "@ronin/contracts/mocks/token/MockWrappedToken.sol"; @@ -27,8 +25,13 @@ import { MockERC721Deploy } from "@ronin/script/contracts/token/MockERC721Deploy import { GeneralConfig } from "../GeneralConfig.sol"; import { Network } from "../utils/Network.sol"; +import { BridgeMigration } from "../BridgeMigration.sol"; + +import "./changeGV-config.s.sol"; -contract DeploySepolia is BaseMigration { +import "forge-std/console2.sol"; + +contract DeploySepolia is BridgeMigration, DeploySepolia__ChangeGV_Config { ISharedArgument.SharedParameter _param; PauseEnforcer _mainchainPauseEnforcer; @@ -37,7 +40,6 @@ contract DeploySepolia is BaseMigration { MockWrappedToken _mainchainWeth; MockERC20 _mainchainAxs; - MockERC20 _mainchainSlp; MockERC20 _mainchainUsdc; MockERC721 _mainchainMockERC721; @@ -51,17 +53,14 @@ contract DeploySepolia is BaseMigration { return ""; } - function _getProxyAdmin() internal virtual override returns (address payable) { - return payable(0x55ba00EeB8D8d33Df1b1985459D310b9CAfB19f2); - } - function setUp() public override { super.setUp(); } - function run() public { - // function run() public onlyOn(Network.Sepolia.key()) { + function run() public onlyOn(Network.Sepolia.key()) { _deployContractsOnMainchain(); + _mainchainGatewayV3Initialize(); + _correctGVs(); } function _deployContractsOnMainchain() internal { @@ -71,13 +70,122 @@ contract DeploySepolia is BaseMigration { _mainchainWeth = new WETHDeploy().run(); _mainchainAxs = new AXSDeploy().run(); - _mainchainSlp = new SLPDeploy().run(); _mainchainUsdc = new USDCDeploy().run(); _mainchainMockERC721 = new MockERC721Deploy().run(); _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); _mainchainProposalUtils = new MainchainBridgeAdminUtils( - _param.test.governorPKs, _mainchainBridgeManager, _param.mainchainBridgeManager.governors[0] + 2021, _param.test.governorPKs, _mainchainBridgeManager, _param.mainchainBridgeManager.governors[0] ); } + + function _mainchainGatewayV3Initialize() internal { + (address[] memory mainchainTokens, address[] memory roninTokens) = _getMainchainAndRoninTokens(); + uint256 tokenNum = mainchainTokens.length; + uint256[] memory highTierThreshold = new uint256[](tokenNum); + uint256[] memory lockedThreshold = new uint256[](tokenNum); + uint256[] memory unlockFeePercentages = new uint256[](tokenNum); + uint256[] memory dailyWithdrawalLimits = new uint256[](tokenNum); + Token.Standard[] memory standards = new Token.Standard[](tokenNum); + + for (uint256 i; i < tokenNum; i++) { + bool isERC721 = i == mainchainTokens.length - 1; // last item is ERC721 + + highTierThreshold[i] = 10; + lockedThreshold[i] = 20; + unlockFeePercentages[i] = 100_000; + dailyWithdrawalLimits[i] = 12; + standards[i] = isERC721 ? Token.Standard.ERC721 : Token.Standard.ERC20; + } + + // Mainchain Gateway V3 + _param.mainchainGatewayV3.wrappedToken = address(_mainchainWeth); + _param.mainchainGatewayV3.addresses[0] = mainchainTokens; // (ERC20 + ERC721) + _param.mainchainGatewayV3.addresses[1] = roninTokens; // (ERC20 + ERC721) + _param.mainchainGatewayV3.addresses[2] = new address[](0); + _param.mainchainGatewayV3.thresholds[0] = highTierThreshold; + _param.mainchainGatewayV3.thresholds[1] = lockedThreshold; + _param.mainchainGatewayV3.thresholds[2] = unlockFeePercentages; + _param.mainchainGatewayV3.thresholds[3] = dailyWithdrawalLimits; + _param.mainchainGatewayV3.standards = standards; + + ISharedArgument.MainchainGatewayV3Param memory param = _param.mainchainGatewayV3; + + vm.broadcast(sender()); + _mainchainGatewayV3.initialize( + param.roleSetter, + IWETH(param.wrappedToken), + 2021, + param.numerator, + param.highTierVWNumerator, + param.denominator, + param.addresses, + param.thresholds, + param.standards + ); + + vm.broadcast(sender()); + _mainchainGatewayV3.initializeV2(address(_mainchainBridgeManager)); + } + + function _correctGVs() internal { + uint256 expiredTime = block.timestamp + 10 days; + address[] memory targets = new address[](2); + uint256[] memory values = new uint256[](2); + bytes[] memory calldatas = new bytes[](2); + uint256[] memory gasAmounts = new uint256[](2); + + targets[0] = address(_mainchainBridgeManager); + values[0] = 0; + calldatas[0] = _removeInitOperator(); + gasAmounts[0] = 1_000_000; + + targets[1] = address(_mainchainBridgeManager); + values[1] = 0; + calldatas[1] = _addTestnetOperators(); + gasAmounts[1] = 1_000_000; + + // ================ VERIFY AND EXECUTE PROPOSAL =============== + + // _verifyMainchainProposalGasAmount(targets, values, calldatas, gasAmounts); + + Proposal.ProposalDetail memory proposal = Proposal.ProposalDetail({ + nonce: _mainchainBridgeManager.round(0) + 1, + chainId: block.chainid, + expiryTimestamp: expiredTime, + targets: targets, + values: values, + calldatas: calldatas, + gasAmounts: gasAmounts + }); + + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](1); + supports_[0] = Ballot.VoteType.For; + + SignatureConsumer.Signature[] memory signatures = + _mainchainProposalUtils.generateSignatures(proposal, _param.test.governorPKs); + + vm.broadcast(_mainchainBridgeManager.getGovernors()[0]); + _mainchainBridgeManager.relayProposal(proposal, supports_, signatures); + } + + function _getMainchainAndRoninTokens() + internal + view + returns (address[] memory mainchainTokens, address[] memory roninTokens) + { + uint256 tokenNum = 5; + mainchainTokens = new address[](tokenNum); + roninTokens = new address[](tokenNum); + + mainchainTokens[0] = address(_mainchainWeth); + mainchainTokens[1] = address(_mainchainAxs); + mainchainTokens[2] = address(_mainchainUsdc); + mainchainTokens[3] = address(_mainchainMockERC721); + + roninTokens[0] = address(0x00); + roninTokens[1] = address(0x00); + roninTokens[2] = address(0x067FBFf8990c58Ab90BaE3c97241C5d736053F77); + roninTokens[3] = address(0x00); + } } diff --git a/script/Migration.s.sol b/script/Migration.s.sol index 019f7419..0b5b11f4 100644 --- a/script/Migration.s.sol +++ b/script/Migration.s.sol @@ -23,7 +23,54 @@ contract Migration is BaseMigrationV2, Utils { ISharedArgument.SharedParameter memory param; if (network() == Network.Sepolia.key()) { - // Undefined + // tokens + param.weth.name = "Wrapped WETH"; + param.weth.symbol = "WETH"; + param.axs.name = "Axie Infinity Shard"; + param.axs.symbol = "AXS"; + param.usdc.name = "USD Coin"; + param.usdc.symbol = "USDC"; + param.mockErc721.name = "Mock ERC721"; + param.mockErc721.symbol = "M_ERC721"; + + uint256 num = 1; + address[] memory operatorAddrs = new address[](num); + address[] memory governorAddrs = new address[](num); + uint256[] memory operatorPKs = new uint256[](num); + uint256[] memory governorPKs = new uint256[](num); + uint96[] memory voteWeights = new uint96[](num); + GlobalProposal.TargetOption[] memory options = new GlobalProposal.TargetOption[](0); + address[] memory targets = new address[](0); + + operatorAddrs[0] = 0xbA8E32D874948dF4Cbe72284De91CC4968293BCe; // One-time address, becomes useless after this migration + operatorPKs[0] = 0xd5df10f17539ff887f211a90bfede2dffb664b7442b4303ba93ac8f6a7d9fa9b; // One-time address, becomes useless after this migration + + governorAddrs[0] = 0x45E8f1aCFC89F45720cf11e807eD85B730C67C7e; // One-time address, becomes useless after this migration + governorPKs[0] = 0xc2b5a7cc553931272fc819150c4ea31d24ad06fdfa021c403b2ef5293bfe685b; // One-time address, becomes useless after this migration + voteWeights[0] = 100; + + param.test.operatorPKs = operatorPKs; + param.test.governorPKs = governorPKs; + + // Mainchain Gateway Pause Enforcer + param.mainchainPauseEnforcer.admin = makeAddr("pause-enforcer-admin"); + param.mainchainPauseEnforcer.sentries = wrapAddress(makeAddr("pause-enforcer-sentry")); + + // Mainchain Gateway V3 + param.mainchainGatewayV3.roninChainId = 2021; + param.mainchainGatewayV3.numerator = 1; + param.mainchainGatewayV3.highTierVWNumerator = 10; + param.mainchainGatewayV3.denominator = 10; + + // Mainchain Bridge Manager + param.mainchainBridgeManager.num = 2; + param.mainchainBridgeManager.denom = 4; + param.mainchainBridgeManager.roninChainId = 2021; + param.mainchainBridgeManager.bridgeOperators = operatorAddrs; + param.mainchainBridgeManager.governors = governorAddrs; + param.mainchainBridgeManager.voteWeights = voteWeights; + param.mainchainBridgeManager.targetOptions = options; + param.mainchainBridgeManager.targets = targets; } else if (network() == DefaultNetwork.RoninTestnet.key()) { // Undefined } else if (network() == DefaultNetwork.Local.key()) { @@ -116,7 +163,6 @@ contract Migration is BaseMigrationV2, Utils { // Mainchain Bridge Manager param.mainchainBridgeManager.num = 2; param.mainchainBridgeManager.denom = 4; - param.mainchainBridgeManager.roninChainId = 0; param.mainchainBridgeManager.roninChainId = block.chainid; param.mainchainBridgeManager.bridgeOperators = operatorAddrs; param.mainchainBridgeManager.governors = governorAddrs; diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 8dbabc08..482fe386 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -124,8 +124,9 @@ contract BaseIntegration_Test is Base_Test { _roninMockERC721 = new MockERC721Deploy().run(); _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); - _roninProposalUtils = - new RoninBridgeAdminUtils(_param.test.governorPKs, _roninBridgeManager, _param.roninBridgeManager.governors[0]); + _roninProposalUtils = new RoninBridgeAdminUtils( + block.chainid, _param.test.governorPKs, _roninBridgeManager, _param.roninBridgeManager.governors[0] + ); _validatorSet = new MockValidatorContract_OnlyTiming_ForHardhatTest(_param.test.numberOfBlocksInEpoch); } @@ -142,7 +143,7 @@ contract BaseIntegration_Test is Base_Test { _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); _mainchainProposalUtils = new MainchainBridgeAdminUtils( - _param.test.governorPKs, _mainchainBridgeManager, _param.mainchainBridgeManager.governors[0] + block.chainid, _param.test.governorPKs, _mainchainBridgeManager, _param.mainchainBridgeManager.governors[0] ); } diff --git a/test/helpers/MainchainBridgeAdminUtils.t.sol b/test/helpers/MainchainBridgeAdminUtils.t.sol index 55c534d0..1236f29b 100644 --- a/test/helpers/MainchainBridgeAdminUtils.t.sol +++ b/test/helpers/MainchainBridgeAdminUtils.t.sol @@ -8,7 +8,9 @@ contract MainchainBridgeAdminUtils is ProposalUtils { MainchainBridgeManager _contract; address _sender; - constructor(uint256[] memory signerPKs, MainchainBridgeManager contract_, address sender) ProposalUtils(signerPKs) { + constructor(uint256 roninChainId, uint256[] memory signerPKs, MainchainBridgeManager contract_, address sender) + ProposalUtils(roninChainId, signerPKs) + { _contract = contract_; _sender = sender; } diff --git a/test/helpers/ProposalUtils.t.sol b/test/helpers/ProposalUtils.t.sol index 4e06b0b5..c5f61e09 100644 --- a/test/helpers/ProposalUtils.t.sol +++ b/test/helpers/ProposalUtils.t.sol @@ -18,8 +18,15 @@ contract ProposalUtils is Utils, Test { uint256[] _signerPKs; bytes32 _domain; - constructor(uint256[] memory signerPKs) { - _domain = getBridgeManagerDomain(); + constructor(uint256 roninChainId, uint256[] memory signerPKs) { + _domain = keccak256( + abi.encode( + keccak256("EIP712Domain(string name,string version,bytes32 salt)"), + keccak256("BridgeAdmin"), // name hash + keccak256("2"), // version hash + keccak256(abi.encode("BRIDGE_ADMIN", roninChainId)) // salt + ) + );; for (uint256 i; i < signerPKs.length; i++) { _signerPKs.push(signerPKs[i]); @@ -117,14 +124,7 @@ contract ProposalUtils is Utils, Test { } function getBridgeManagerDomain() public view returns (bytes32) { - return keccak256( - abi.encode( - keccak256("EIP712Domain(string name,string version,bytes32 salt)"), - keccak256("BridgeAdmin"), // name hash - keccak256("2"), // version hash - keccak256(abi.encode("BRIDGE_ADMIN", block.chainid)) // salt - ) - ); + return _domain; } function generateSignaturesFor(bytes32 proposalHash, uint256[] memory signerPKs, Ballot.VoteType support) @@ -135,7 +135,7 @@ contract ProposalUtils is Utils, Test { sigs = new SignatureConsumer.Signature[](signerPKs.length); for (uint256 i; i < signerPKs.length; i++) { - bytes32 digest = _domain.toTypedDataHash(Ballot.hash(proposalHash, support)); + bytes32 digest = ECDSA.toTypedDataHash(_domain, Ballot.hash(proposalHash, support)); sigs[i] = _sign(signerPKs[i], digest); } } diff --git a/test/helpers/RoninBridgeAdminUtils.t.sol b/test/helpers/RoninBridgeAdminUtils.t.sol index 1b65257d..dabec5e8 100644 --- a/test/helpers/RoninBridgeAdminUtils.t.sol +++ b/test/helpers/RoninBridgeAdminUtils.t.sol @@ -8,7 +8,9 @@ contract RoninBridgeAdminUtils is ProposalUtils { RoninBridgeManager _contract; address _sender; - constructor(uint256[] memory signerPKs, RoninBridgeManager contract_, address sender) ProposalUtils(signerPKs) { + constructor(uint256 roninChainId, uint256[] memory signerPKs, RoninBridgeManager contract_, address sender) + ProposalUtils(roninChainId, signerPKs) + { _contract = contract_; _sender = sender; }