diff --git a/script/20240308-maptoken-aperios/20240308-maptoken-aperios-mainchain.s.sol b/script/20240308-maptoken-aperios/20240308-maptoken-aperios-mainchain.s.sol index 57cf4462..b5fc25a7 100644 --- a/script/20240308-maptoken-aperios/20240308-maptoken-aperios-mainchain.s.sol +++ b/script/20240308-maptoken-aperios/20240308-maptoken-aperios-mainchain.s.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import "../factories/factory-maptoken-mainchain.s.sol"; +import "../factories/mainchain/factory-maptoken-mainchain-ethereum.s.sol"; import "./base-maptoken.s.sol"; -contract Migration__20240308_MapTokenAperiosMainchain is Base__MapToken, Factory__MapTokensMainchain { +contract Migration__20240308_MapTokenAperiosMainchain is Base__MapToken, Factory__MapTokensMainchain_Ethereum { function _initCaller() internal override(Base__MapToken, Factory__MapTokensMainchain) returns (address) { return Base__MapToken._initCaller(); } diff --git a/script/20240308-maptoken-aperios/20240308-maptoken-aperios-roninchain.s.sol b/script/20240308-maptoken-aperios/20240308-maptoken-aperios-roninchain.s.sol index ff54faad..212ee7f0 100644 --- a/script/20240308-maptoken-aperios/20240308-maptoken-aperios-roninchain.s.sol +++ b/script/20240308-maptoken-aperios/20240308-maptoken-aperios-roninchain.s.sol @@ -2,10 +2,10 @@ pragma solidity ^0.8.19; import { console2 } from "forge-std/console2.sol"; -import "../factories/factory-maptoken-roninchain.s.sol"; +import "../factories/roninchain/factory-maptoken-ronin-mainnet.s.sol"; import "./base-maptoken.s.sol"; -contract Migration__20240308_MapTokenAperiosRoninchain is Base__MapToken, Factory__MapTokensRoninchain { +contract Migration__20240308_MapTokenAperiosRoninchain is Base__MapToken, Factory__MapTokensRonin_Mainnet { function _initCaller() internal override(Base__MapToken, Factory__MapTokensRoninchain) returns (address) { return Base__MapToken._initCaller(); } diff --git a/script/20240308-maptoken-aperios/caller-configs.s.sol b/script/20240308-maptoken-aperios/caller-configs.s.sol index d1fad437..1e3428d5 100644 --- a/script/20240308-maptoken-aperios/caller-configs.s.sol +++ b/script/20240308-maptoken-aperios/caller-configs.s.sol @@ -2,5 +2,5 @@ pragma solidity ^0.8.19; contract Migration__Caller_Config { - address internal SM_GOVERNOR = 0xe880802580a1fbdeF67ACe39D1B21c5b2C74f059; // TODO: replace by address of the SV governor + address internal SM_GOVERNOR = 0xd24D87DDc1917165435b306aAC68D99e0F49A3Fa; // TODO: replace by address of the SV governor } diff --git a/script/20240626-maptoken-anima/20240626-maptoken-anima-mainchain.s.sol b/script/20240626-maptoken-anima/20240626-maptoken-anima-mainchain.s.sol new file mode 100644 index 00000000..4584161c --- /dev/null +++ b/script/20240626-maptoken-anima/20240626-maptoken-anima-mainchain.s.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "../factories/mainchain/factory-maptoken-mainchain-sepolia.s.sol"; +import "./base-maptoken.s.sol"; +import "@ronin/contracts/libraries/Ballot.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { MainchainBridgeAdminUtils } from "test/helpers/MainchainBridgeAdminUtils.t.sol"; +import { SignatureConsumer } from "@ronin/contracts/interfaces/consumers/SignatureConsumer.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; + +contract Migration__20242606_MapTokenAnimaMainchain is Base__MapToken, Factory__MapTokensMainchain_Sepolia { + MainchainBridgeAdminUtils _mainchainProposalUtils; + + function _initCaller() internal override(Base__MapToken, Factory__MapTokensMainchain) returns (address) { + return Base__MapToken._initCaller(); + } + + function _initTokenList() internal override(Base__MapToken, Factory__MapTokensMainchain) returns (uint256 totalToken, MapTokenInfo[] memory infos) { + return Base__MapToken._initTokenList(); + } + + function _initGovernors() internal override(Base__MapToken, Factory__MapTokensMainchain_Sepolia) returns (address[] memory) { + return Base__MapToken._initGovernors(); + } + + function _initGovernorPKs() internal override(Base__MapToken, Factory__MapTokensMainchain_Sepolia) returns (uint256[] memory) { + return Base__MapToken._initGovernorPKs(); + } + + function run() public override { + Factory__MapTokensMainchain_Sepolia.run(); + } +} diff --git a/script/20240626-maptoken-anima/20240626-maptoken-anima-ronin-testnet.s.sol b/script/20240626-maptoken-anima/20240626-maptoken-anima-ronin-testnet.s.sol new file mode 100644 index 00000000..3d6bf393 --- /dev/null +++ b/script/20240626-maptoken-anima/20240626-maptoken-anima-ronin-testnet.s.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 } from "forge-std/console2.sol"; +import "../factories/roninchain/factory-maptoken-ronin-testnet.s.sol"; +import "./base-maptoken.s.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; + +contract Migration__20242606_MapTokenAnimaRoninTestnet is Base__MapToken, Factory__MapTokensRonin_Testnet { + function _initCaller() internal override(Base__MapToken, Factory__MapTokensRoninchain) returns (address) { + return Base__MapToken._initCaller(); + } + + function _initTokenList() internal override(Base__MapToken, Factory__MapTokensRoninchain) returns (uint256 totalToken, MapTokenInfo[] memory infos) { + return Base__MapToken._initTokenList(); + } + + function _initGovernors() internal override(Base__MapToken, Factory__MapTokensRonin_Testnet) returns (address[] memory) { + return Base__MapToken._initGovernors(); + } + + function run() public override { + Factory__MapTokensRonin_Testnet.run(); + } +} diff --git a/script/20240626-maptoken-anima/base-maptoken.s.sol b/script/20240626-maptoken-anima/base-maptoken.s.sol new file mode 100644 index 00000000..aca143de --- /dev/null +++ b/script/20240626-maptoken-anima/base-maptoken.s.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "forge-std/console2.sol"; + +import "./caller-configs.s.sol"; +import "./maptoken-anima-configs.s.sol"; +import "./governors-configs.s.sol"; + +contract Base__MapToken is Migration__Caller_Config, Migration__MapToken_Anima_Config, Migration__Governors_Config { + function _initCaller() internal virtual returns (address) { + return SM_GOVERNOR; + } + + function _initGovernors() internal virtual returns (address[] memory) { + return governors; + } + + function _initGovernorPKs() internal virtual returns (uint256[] memory) { + return governorPks; + } + + function _initTokenList() internal virtual returns (uint256 totalToken, MapTokenInfo[] memory infos) { + totalToken = 1; + + infos = new MapTokenInfo[](totalToken); + infos[0] = _animaInfo; + } +} diff --git a/script/20240626-maptoken-anima/caller-configs.s.sol b/script/20240626-maptoken-anima/caller-configs.s.sol new file mode 100644 index 00000000..1e3428d5 --- /dev/null +++ b/script/20240626-maptoken-anima/caller-configs.s.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +contract Migration__Caller_Config { + address internal SM_GOVERNOR = 0xd24D87DDc1917165435b306aAC68D99e0F49A3Fa; // TODO: replace by address of the SV governor +} diff --git a/script/20240626-maptoken-anima/governors-configs.s.sol b/script/20240626-maptoken-anima/governors-configs.s.sol new file mode 100644 index 00000000..2e729f5a --- /dev/null +++ b/script/20240626-maptoken-anima/governors-configs.s.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +contract Migration__Governors_Config { + address[] internal governors = new address[](4); + uint256[] internal governorPks = new uint256[](4); + + constructor() { + // TODO: replace by address of the testnet governors + governors[3] = 0xd24D87DDc1917165435b306aAC68D99e0F49A3Fa; + governors[2] = 0xb033ba62EC622dC54D0ABFE0254e79692147CA26; + governors[0] = 0x087D08e3ba42e64E3948962dd1371F906D1278b9; + governors[1] = 0x52ec2e6BBcE45AfFF8955Da6410bb13812F4289F; + // TODO: replace by private key of the testnet governors + governorPks[3] = 0x0; + governorPks[2] = 0x0; + governorPks[0] = 0x0; + governorPks[1] = 0x0; + } +} diff --git a/script/20240626-maptoken-anima/maptoken-anima-configs.s.sol b/script/20240626-maptoken-anima/maptoken-anima-configs.s.sol new file mode 100644 index 00000000..b86ba82e --- /dev/null +++ b/script/20240626-maptoken-anima/maptoken-anima-configs.s.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { MapTokenInfo } from "../libraries/MapTokenInfo.sol"; +import { LibTokenInfo, TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol"; + +contract Migration__MapToken_Anima_Config { + MapTokenInfo _animaInfo; + + constructor() { + _animaInfo.roninToken = address(0x9F6a5cDc477e9f667d60424bFdb4E82089d9d72c); + _animaInfo.mainchainToken = address(0xEd52E203D2D44FAaEA0D9fB6A40220A63c743c80); + _animaInfo.standard = TokenStandard.ERC20; + _animaInfo.minThreshold = 100 ether; + _animaInfo.highTierThreshold = 20_000_000 ether; + _animaInfo.lockedThreshold = 100_000_000 ether; + _animaInfo.dailyWithdrawalLimit = 50_000_000 ether; + _animaInfo.unlockFeePercentages = 10; // 0.001%. Max percentage is 100_0000, so 10 is 0.001% (`10 / 1e6 = 0.001 * 100`) + } +} diff --git a/script/factories/factory-maptoken-mainchain.s.sol b/script/factories/factory-maptoken-mainchain.s.sol deleted file mode 100644 index fa0f4d7e..00000000 --- a/script/factories/factory-maptoken-mainchain.s.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import { console2 } from "forge-std/console2.sol"; -import { StdStyle } from "forge-std/StdStyle.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 { LibTokenInfo, TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol"; -import { Contract } from "../utils/Contract.sol"; -import { Migration } from "../Migration.s.sol"; -import { Network } from "../utils/Network.sol"; -import { Contract } from "../utils/Contract.sol"; -import { IGeneralConfigExtended } from "../interfaces/IGeneralConfigExtended.sol"; - -import { MapTokenInfo } from "../libraries/MapTokenInfo.sol"; -import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; - -abstract contract Factory__MapTokensMainchain is Migration { - using LibCompanionNetwork for *; - - RoninBridgeManager internal _roninBridgeManager; - address internal _mainchainGatewayV3; - address internal _mainchainBridgeManager; - address private _governor; - - function setUp() public override { - super.setUp(); - - _roninBridgeManager = RoninBridgeManager(config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); - _mainchainGatewayV3 = config.getAddress(network().companionNetwork(), Contract.MainchainGatewayV3.key()); - _mainchainBridgeManager = config.getAddress(network().companionNetwork(), Contract.MainchainBridgeManager.key()); - - _governor = _initCaller(); - } - - function _initCaller() internal virtual returns (address); - function _initTokenList() internal virtual returns (uint256 totalToken, MapTokenInfo[] memory infos); - - function run() public virtual { - (uint256 N, MapTokenInfo[] memory tokenInfos) = _initTokenList(); - - address[] memory mainchainTokens = new address[](N); - address[] memory roninTokens = new address[](N); - TokenStandard[] memory standards = new TokenStandard[](N); - uint256[][4] memory thresholds; - thresholds[0] = new uint256[](N); - thresholds[1] = new uint256[](N); - thresholds[2] = new uint256[](N); - thresholds[3] = new uint256[](N); - - uint256 expiredTime = block.timestamp + 14 days; - address[] memory targets = new address[](1); - uint256[] memory values = new uint256[](1); - bytes[] memory calldatas = new bytes[](1); - uint256[] memory gasAmounts = new uint256[](1); - - // ================ APERIOS AND YGG ERC-20 ====================== - - for (uint256 i; i < N; ++i) { - mainchainTokens[i] = tokenInfos[i].mainchainToken; - roninTokens[i] = tokenInfos[i].roninToken; - standards[i] = TokenStandard.ERC20; - thresholds[0][i] = tokenInfos[i].highTierThreshold; - thresholds[1][i] = tokenInfos[i].lockedThreshold; - thresholds[2][i] = tokenInfos[i].unlockFeePercentages; - thresholds[3][i] = tokenInfos[i].dailyWithdrawalLimit; - } - - // function mapTokensAndThresholds( - // address[] calldata _mainchainTokens, - // address[] calldata _roninTokens, - // TokenStandard[] 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); - - targets[0] = _mainchainGatewayV3; - values[0] = 0; - calldatas[0] = proxyData; - gasAmounts[0] = 1_000_000; - - // ================ VERIFY AND EXECUTE PROPOSAL =============== - - // _verifyMainchainProposalGasAmount(targets, values, calldatas, gasAmounts); - - uint256 chainId = network().companionChainId(); - - vm.broadcast(_governor); - _roninBridgeManager.propose(chainId, expiredTime, address(0), targets, values, calldatas, gasAmounts); - } -} diff --git a/script/factories/factory-maptoken-roninchain.s.sol b/script/factories/factory-maptoken-roninchain.s.sol deleted file mode 100644 index 6fb30cd8..00000000 --- a/script/factories/factory-maptoken-roninchain.s.sol +++ /dev/null @@ -1,116 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import { console2 } from "forge-std/console2.sol"; -import { StdStyle } from "forge-std/StdStyle.sol"; - -import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; -import { IRoninGatewayV3 } from "@ronin/contracts/interfaces/IRoninGatewayV3.sol"; -import { MinimumWithdrawal } from "@ronin/contracts/extensions/MinimumWithdrawal.sol"; -import { LibTokenInfo, TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol"; -import { Ballot } from "@ronin/contracts/libraries/Ballot.sol"; -import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol"; - -import { Contract } from "../utils/Contract.sol"; -import { Migration } from "../Migration.s.sol"; -import { Network } from "../utils/Network.sol"; -import { Contract } from "../utils/Contract.sol"; -import { IGeneralConfigExtended } from "../interfaces/IGeneralConfigExtended.sol"; - -import { MapTokenInfo } from "../libraries/MapTokenInfo.sol"; -import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; - -abstract contract Factory__MapTokensRoninchain is Migration { - using LibCompanionNetwork for *; - - RoninBridgeManager internal _roninBridgeManager; - address internal _roninGatewayV3; - address private _governor; - - function setUp() public override { - super.setUp(); - _roninBridgeManager = RoninBridgeManager(config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); - _roninGatewayV3 = config.getAddressFromCurrentNetwork(Contract.RoninGatewayV3.key()); - - _governor = _initCaller(); - _cheatWeightOperator(_governor); - } - - function _cheatWeightOperator(address gov) internal { - bytes32 $ = keccak256(abi.encode(gov, 0x88547008e60f5748911f2e59feb3093b7e4c2e87b2dd69d61f112fcc932de8e3)); - bytes32 opAndWeight = vm.load(address(_roninBridgeManager), $); - - uint256 totalWeight = _roninBridgeManager.getTotalWeight(); - bytes32 newOpAndWeight = bytes32((totalWeight << 160) + uint160(uint256(opAndWeight))); - vm.store(address(_roninBridgeManager), $, newOpAndWeight); - } - - function _initCaller() internal virtual returns (address); - function _initTokenList() internal virtual returns (uint256 totalToken, MapTokenInfo[] memory infos); - - function run() public virtual { - (uint256 N, MapTokenInfo[] memory tokenInfos) = _initTokenList(); - - address[] memory roninTokens = new address[](N); - address[] memory mainchainTokens = new address[](N); - uint256[] memory chainIds = new uint256[](N); - TokenStandard[] memory standards = new TokenStandard[](N); - - uint256 expiredTime = block.timestamp + 14 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); - - // ============= MAP TOKENS =========== - - for (uint256 i; i < N; ++i) { - roninTokens[i] = tokenInfos[i].roninToken; - mainchainTokens[i] = tokenInfos[i].mainchainToken; - chainIds[i] = network().companionChainId(); - standards[i] = TokenStandard.ERC20; - } - - // function mapTokens( - // address[] calldata _roninTokens, - // address[] calldata _mainchainTokens, - // uint256[] calldata chainIds, - // TokenStandard[] calldata _standards - // ) - bytes memory innerData = abi.encodeCall(IRoninGatewayV3.mapTokens, (roninTokens, mainchainTokens, chainIds, standards)); - bytes memory proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); - - targets[0] = _roninGatewayV3; - values[0] = 0; - calldatas[0] = proxyData; - gasAmounts[0] = 1_000_000; - - // ============= SET MIN THRESHOLD ============ - // function setMinimumThresholds( - // address[] calldata _tokens, - // uint256[] calldata _thresholds - // ); - address[] memory roninTokensToSetMinThreshold = new address[](N); - uint256[] memory minThresholds = new uint256[](N); - - for (uint256 i; i < N; ++i) { - roninTokensToSetMinThreshold[i] = tokenInfos[i].roninToken; - minThresholds[i] = tokenInfos[i].minThreshold; - } - - innerData = abi.encodeCall(MinimumWithdrawal.setMinimumThresholds, (roninTokensToSetMinThreshold, minThresholds)); - proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); - - targets[1] = _roninGatewayV3; - values[1] = 0; - calldatas[1] = proxyData; - gasAmounts[1] = 1_000_000; - - // ================ VERIFY AND EXECUTE PROPOSAL =============== - - // _verifyRoninProposalGasAmount(targets, values, calldatas, gasAmounts); - - vm.broadcast(_governor); - _roninBridgeManager.propose(block.chainid, expiredTime, address(0), targets, values, calldatas, gasAmounts); - } -} diff --git a/script/factories/mainchain/factory-maptoken-mainchain-ethereum.s.sol b/script/factories/mainchain/factory-maptoken-mainchain-ethereum.s.sol new file mode 100644 index 00000000..7238de33 --- /dev/null +++ b/script/factories/mainchain/factory-maptoken-mainchain-ethereum.s.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; +import { Network, TNetwork } from "../../utils/Network.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import "./factory-maptoken-mainchain.s.sol"; +import "../simulation/factory-maptoken-simulation-mainchain.s.sol"; + +abstract contract Factory__MapTokensMainchain_Ethereum is Factory__MapTokensMainchain { + using LibCompanionNetwork for *; + + function setUp() public override { + super.setUp(); + _roninBridgeManager = RoninBridgeManager(config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); + _mainchainGatewayV3 = config.getAddress(network().companionNetwork(), Contract.MainchainGatewayV3.key()); + _mainchainBridgeManager = config.getAddress(network().companionNetwork(), Contract.MainchainBridgeManager.key()); + } + + function run() public virtual override { + uint256 chainId = network().companionChainId(); + uint256 nonce = _roninBridgeManager.round(chainId) + 1; + Proposal.ProposalDetail memory proposal = _createAndVerifyProposalOnMainchain(chainId, nonce); + // Simulate relay proposal + new Factory__MapTokensSimulation_Mainchain().simulate(proposal); + _propose(proposal); + } +} diff --git a/script/factories/mainchain/factory-maptoken-mainchain-sepolia.s.sol b/script/factories/mainchain/factory-maptoken-mainchain-sepolia.s.sol new file mode 100644 index 00000000..63266612 --- /dev/null +++ b/script/factories/mainchain/factory-maptoken-mainchain-sepolia.s.sol @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { Network, TNetwork } from "../../utils/Network.sol"; +import { console2 as console } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import "./factory-maptoken-mainchain.s.sol"; +import "../simulation/factory-maptoken-simulation-mainchain.s.sol"; + +abstract contract Factory__MapTokensMainchain_Sepolia is Factory__MapTokensMainchain { + function setUp() public override { + super.setUp(); + _mainchainGatewayV3 = config.getAddressFromCurrentNetwork(Contract.MainchainGatewayV3.key()); + _mainchainBridgeManager = config.getAddressFromCurrentNetwork(Contract.MainchainBridgeManager.key()); + } + + function _initGovernorPKs() internal virtual returns (uint256[] memory); + function _initGovernors() internal virtual returns (address[] memory); + + function run() public virtual override { + address[] memory mGovernors; + uint256[] memory mGovernorsPk; + + mGovernors = _initGovernors(); + mGovernorsPk = _initGovernorPKs(); + + for (uint256 i; i < mGovernors.length; ++i) { + _governors.push(mGovernors[i]); + _governorPKs.push(mGovernorsPk[i]); + } + + uint256 chainId = block.chainid; + uint256 nonce = MainchainBridgeManager(_mainchainBridgeManager).round(chainId) + 1; + + Proposal.ProposalDetail memory proposal = _createAndVerifyProposalOnMainchain(chainId, nonce); + // Simulate relay proposal + new Factory__MapTokensSimulation_Mainchain().simulate(proposal); + _relayProposal(proposal); + } +} diff --git a/script/factories/mainchain/factory-maptoken-mainchain.s.sol b/script/factories/mainchain/factory-maptoken-mainchain.s.sol new file mode 100644 index 00000000..3bb2691e --- /dev/null +++ b/script/factories/mainchain/factory-maptoken-mainchain.s.sol @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "@ronin/contracts/libraries/Ballot.sol"; +import { console2 as console } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.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 { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { LibTokenInfo, TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { Migration } from "../../Migration.s.sol"; +import { Network, TNetwork } from "../../utils/Network.sol"; +import { IGeneralConfigExtended } from "../../interfaces/IGeneralConfigExtended.sol"; +import { SignatureConsumer } from "@ronin/contracts/interfaces/consumers/SignatureConsumer.sol"; +import { MapTokenInfo } from "../../libraries/MapTokenInfo.sol"; +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; +import { MainchainBridgeAdminUtils } from "test/helpers/MainchainBridgeAdminUtils.t.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { Network, TNetwork } from "../../utils/Network.sol"; +import { IBridgeManager } from "@ronin/contracts/interfaces/bridge/IBridgeManager.sol"; +import { DefaultNetwork } from "@fdk/utils/DefaultNetwork.sol"; + +abstract contract Factory__MapTokensMainchain is Migration { + using LibCompanionNetwork for *; + + RoninBridgeManager internal _roninBridgeManager; + address internal _mainchainGatewayV3; + address internal _mainchainBridgeManager; + address internal _specifiedCaller; + address[] internal _governors; + uint256[] internal _governorPKs; + + function setUp() public virtual override { + super.setUp(); + _specifiedCaller = _initCaller(); + } + + function run() public virtual; + function _initCaller() internal virtual returns (address); + function _initTokenList() internal virtual returns (uint256 totalToken, MapTokenInfo[] memory infos); + + function _propose(Proposal.ProposalDetail memory proposal) internal virtual { + vm.broadcast(_specifiedCaller); + _roninBridgeManager.propose( + proposal.chainId, proposal.expiryTimestamp, proposal.executor, proposal.targets, proposal.values, proposal.calldatas, proposal.gasAmounts + ); + } + + function _relayProposal(Proposal.ProposalDetail memory proposal) internal { + MainchainBridgeAdminUtils mainchainProposalUtils = + new MainchainBridgeAdminUtils(2021, _governorPKs, MainchainBridgeManager(_mainchainBridgeManager), _governors[0]); + + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](_governors.length); + require(_governors.length > 0 && _governors.length == _governorPKs.length, "Invalid governors information"); + + for (uint256 i; i < _governors.length; ++i) { + supports_[i] = Ballot.VoteType.For; + } + + SignatureConsumer.Signature[] memory signatures = mainchainProposalUtils.generateSignatures(proposal, _governorPKs); + + uint256 gasAmounts = 1_000_000; + for (uint256 i; i < proposal.gasAmounts.length; ++i) { + gasAmounts += proposal.gasAmounts[i]; + } + + vm.broadcast(_specifiedCaller); + MainchainBridgeManager(_mainchainBridgeManager).relayProposal{ gas: gasAmounts }(proposal, supports_, signatures); + } + + function _createAndVerifyProposalOnMainchain(uint256 chainId, uint256 nonce) internal returns (Proposal.ProposalDetail memory proposal) { + (uint256 N, MapTokenInfo[] memory tokenInfos) = _initTokenList(); + require(tokenInfos.length > 0, "Number of tokens required to map cannot be 0."); + + bytes memory innerData; + bytes memory proxyData; + + if (tokenInfos[0].standard == TokenStandard.ERC20) { + (address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards, uint256[][4] memory thresholds) = + _prepareMapTokensAndThresholds(N, tokenInfos); + + innerData = abi.encodeCall(IMainchainGatewayV3.mapTokensAndThresholds, (mainchainTokens, roninTokens, standards, thresholds)); + proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); + } else { + (address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards) = _prepareMapTokens(N, tokenInfos); + + innerData = abi.encodeCall(IMainchainGatewayV3.mapTokens, (mainchainTokens, roninTokens, standards)); + proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); + } + + uint256 expiredTime = block.timestamp + 14 days; + address[] memory targets = new address[](1); + uint256[] memory values = new uint256[](1); + bytes[] memory calldatas = new bytes[](1); + uint256[] memory gasAmounts = new uint256[](1); + + targets[0] = _mainchainGatewayV3; + values[0] = 0; + calldatas[0] = proxyData; + gasAmounts[0] = 1_000_000; + + if (network() == DefaultNetwork.RoninMainnet.key() || network() == DefaultNetwork.RoninMainnet.key()) { + // Verify gas amount for ronin targets. + (uint256 companionChainId, TNetwork companionNetwork) = network().companionNetworkData(); + address companionManager = config.getAddress(companionNetwork, Contract.MainchainBridgeManager.key()); + LibProposal.verifyMainchainProposalGasAmount(companionNetwork, companionManager, targets, values, calldatas, gasAmounts); + } else { + // Verify gas amount for mainchain targets. + LibProposal.verifyProposalGasAmount(address(_mainchainBridgeManager), targets, values, calldatas, gasAmounts); + } + + proposal = Proposal.ProposalDetail({ + nonce: nonce, + chainId: chainId, + expiryTimestamp: expiredTime, + executor: address(0), + targets: targets, + values: values, + calldatas: calldatas, + gasAmounts: gasAmounts + }); + } + + function _prepareMapTokensAndThresholds( + uint256 N, + MapTokenInfo[] memory tokenInfos + ) internal returns (address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards, uint256[][4] memory thresholds) { + // function mapTokensAndThresholds( + // address[] calldata _mainchainTokens, + // address[] calldata _roninTokens, + // TokenStandard.ERC20[] calldata _standards, + // uint256[][4] calldata _thresholds + // ) + + mainchainTokens = new address[](N); + roninTokens = new address[](N); + standards = new TokenStandard[](N); + + thresholds[0] = new uint256[](N); + thresholds[1] = new uint256[](N); + thresholds[2] = new uint256[](N); + thresholds[3] = new uint256[](N); + + for (uint256 i; i < N; ++i) { + mainchainTokens[i] = tokenInfos[i].mainchainToken; + roninTokens[i] = tokenInfos[i].roninToken; + standards[i] = tokenInfos[i].standard; + + thresholds[0][i] = tokenInfos[i].highTierThreshold; + thresholds[1][i] = tokenInfos[i].lockedThreshold; + thresholds[2][i] = tokenInfos[i].unlockFeePercentages; + thresholds[3][i] = tokenInfos[i].dailyWithdrawalLimit; + } + } + + function _prepareMapTokens( + uint256 N, + MapTokenInfo[] memory tokenInfos + ) internal returns (address[] memory mainchainTokens, address[] memory roninTokens, TokenStandard[] memory standards) { + // function mapTokens( + // address[] calldata _mainchainTokens, + // address[] calldata _roninTokens, + // TokenStandard[] calldata _standards + // ); + + mainchainTokens = new address[](N); + roninTokens = new address[](N); + standards = new TokenStandard[](N); + + for (uint256 i; i < N; ++i) { + mainchainTokens[i] = tokenInfos[i].mainchainToken; + roninTokens[i] = tokenInfos[i].roninToken; + standards[i] = tokenInfos[i].standard; + } + } +} diff --git a/script/factories/roninchain/factory-maptoken-ronin-mainnet.s.sol b/script/factories/roninchain/factory-maptoken-ronin-mainnet.s.sol new file mode 100644 index 00000000..bafcb28a --- /dev/null +++ b/script/factories/roninchain/factory-maptoken-ronin-mainnet.s.sol @@ -0,0 +1,22 @@ +pragma solidity ^0.8.19; + +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; +import { Network, TNetwork } from "../../utils/Network.sol"; +import { console2 } from "forge-std/console2.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import "./factory-maptoken-roninchain.s.sol"; +import "../simulation/factory-maptoken-simulation-roninchain.s.sol"; + +abstract contract Factory__MapTokensRonin_Mainnet is Factory__MapTokensRoninchain { + using LibCompanionNetwork for *; + + function run() public virtual override { + Proposal.ProposalDetail memory proposal = _createAndVerifyProposalOnRonin(); + // Simulate execute proposal + new Factory__MapTokensSimulation_Roninchain().simulate(proposal); + _propose(proposal); + } +} diff --git a/script/factories/roninchain/factory-maptoken-ronin-testnet.s.sol b/script/factories/roninchain/factory-maptoken-ronin-testnet.s.sol new file mode 100644 index 00000000..01e71143 --- /dev/null +++ b/script/factories/roninchain/factory-maptoken-ronin-testnet.s.sol @@ -0,0 +1,30 @@ +pragma solidity ^0.8.19; + +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; +import { Network, TNetwork } from "../../utils/Network.sol"; +import { console2 } from "forge-std/console2.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import "./factory-maptoken-roninchain.s.sol"; +import "../simulation/factory-maptoken-simulation-roninchain.s.sol"; + +abstract contract Factory__MapTokensRonin_Testnet is Factory__MapTokensRoninchain { + using LibCompanionNetwork for *; + + function _initGovernors() internal virtual returns (address[] memory); + + function run() public virtual override { + address[] memory mGovernors = _initGovernors(); + + for (uint256 i; i < mGovernors.length; ++i) { + _governors.push(mGovernors[i]); + } + + Proposal.ProposalDetail memory proposal = _createAndVerifyProposalOnRonin(); + // Simulate execute proposal + new Factory__MapTokensSimulation_Roninchain().simulate(proposal); + _proposeAndExecuteProposal(proposal); + } +} diff --git a/script/factories/roninchain/factory-maptoken-roninchain.s.sol b/script/factories/roninchain/factory-maptoken-roninchain.s.sol new file mode 100644 index 00000000..47766a5c --- /dev/null +++ b/script/factories/roninchain/factory-maptoken-roninchain.s.sol @@ -0,0 +1,188 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; + +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import { IRoninGatewayV3 } from "@ronin/contracts/interfaces/IRoninGatewayV3.sol"; +import { MinimumWithdrawal } from "@ronin/contracts/extensions/MinimumWithdrawal.sol"; +import { LibTokenInfo, TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol"; +import { Ballot } from "@ronin/contracts/libraries/Ballot.sol"; +import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { Migration } from "../../Migration.s.sol"; +import { Network } from "../../utils/Network.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { IGeneralConfigExtended } from "../../interfaces/IGeneralConfigExtended.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { MapTokenInfo } from "../../libraries/MapTokenInfo.sol"; +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; + +abstract contract Factory__MapTokensRoninchain is Migration { + using LibCompanionNetwork for *; + + RoninBridgeManager internal _roninBridgeManager; + address internal _roninGatewayV3; + address internal _specifiedCaller; + address[] internal _governors; + + function setUp() public virtual override { + super.setUp(); + _roninBridgeManager = RoninBridgeManager(config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); + _roninGatewayV3 = config.getAddressFromCurrentNetwork(Contract.RoninGatewayV3.key()); + _specifiedCaller = _initCaller(); + } + + function run() public virtual; + function _initCaller() internal virtual returns (address); + function _initTokenList() internal virtual returns (uint256 totalToken, MapTokenInfo[] memory infos); + + function _proposeAndExecuteProposal(Proposal.ProposalDetail memory proposal) internal { + proposal.executor = _specifiedCaller; + _propose(proposal); + _executeProposal(proposal); + } + + function _propose(Proposal.ProposalDetail memory proposal) internal { + vm.broadcast(_specifiedCaller); + _roninBridgeManager.propose( + proposal.chainId, proposal.expiryTimestamp, proposal.executor, proposal.targets, proposal.values, proposal.calldatas, proposal.gasAmounts + ); + } + + function _executeProposal(Proposal.ProposalDetail memory proposal) internal { + uint256 minVoteWeight = _roninBridgeManager.minimumVoteWeight(); + uint256 sumVoteWeight; + uint256 numberGovernorsNeedToVote; + + for (uint256 i; i < _governors.length; ++i) { + sumVoteWeight += _roninBridgeManager.getGovernorWeight(_governors[i]); + numberGovernorsNeedToVote++; + if (sumVoteWeight >= minVoteWeight) break; + } + require(sumVoteWeight > 0 && numberGovernorsNeedToVote > 0); + + for (uint256 i; i < numberGovernorsNeedToVote; ++i) { + vm.broadcast(_governors[i]); + _roninBridgeManager.castProposalVoteForCurrentNetwork(proposal, Ballot.VoteType.For); + } + + uint256 gasAmounts = 1_000_000; + for (uint256 i; i < proposal.gasAmounts.length; ++i) { + gasAmounts += proposal.gasAmounts[i]; + } + + vm.broadcast(_specifiedCaller); + _roninBridgeManager.execute{ gas: gasAmounts }(proposal); + } + + function _createAndVerifyProposalOnRonin() internal returns (Proposal.ProposalDetail memory proposal) { + (uint256 N, MapTokenInfo[] memory tokenInfos) = _initTokenList(); + + (address[] memory roninTokens, address[] memory mainchainTokens, uint256[] memory chainIds, TokenStandard[] memory standards) = _prepareMapTokens(); + + // Assume that all tokens have the same standard. + TokenStandard tokenStandard = standards[0]; + + address[] memory targets; + uint256[] memory values; + bytes[] memory calldatas; + uint256[] memory gasAmounts; + + targets = new address[](1); + values = new uint256[](1); + calldatas = new bytes[](1); + gasAmounts = new uint256[](1); + + bytes memory innerData = abi.encodeCall(IRoninGatewayV3.mapTokens, (roninTokens, mainchainTokens, chainIds, standards)); + bytes memory proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); + + uint256 expiredTime = block.timestamp + 14 days; + targets[0] = _roninGatewayV3; + values[0] = 0; + calldatas[0] = proxyData; + gasAmounts[0] = 1_000_000; + + if (tokenStandard == TokenStandard.ERC20) { + targets = new address[](2); + values = new uint256[](2); + calldatas = new bytes[](2); + gasAmounts = new uint256[](2); + + uint256 expiredTime = block.timestamp + 14 days; + targets[0] = _roninGatewayV3; + values[0] = 0; + calldatas[0] = proxyData; + gasAmounts[0] = 1_000_000; + + (address[] memory roninTokensToSetMinThreshold, uint256[] memory minThresholds) = _prepareSetMinThreshold(); + + innerData = abi.encodeCall(MinimumWithdrawal.setMinimumThresholds, (roninTokensToSetMinThreshold, minThresholds)); + proxyData = abi.encodeWithSignature("functionDelegateCall(bytes)", innerData); + + targets[1] = _roninGatewayV3; + values[1] = 0; + calldatas[1] = proxyData; + gasAmounts[1] = 1_000_000; + } + + LibProposal.verifyProposalGasAmount(address(_roninBridgeManager), targets, values, calldatas, gasAmounts); + + proposal = Proposal.ProposalDetail({ + nonce: RoninBridgeManager(_roninBridgeManager).round(block.chainid) + 1, + chainId: block.chainid, + expiryTimestamp: expiredTime, + executor: address(0), + targets: targets, + values: values, + calldatas: calldatas, + gasAmounts: gasAmounts + }); + } + + function _prepareMapTokens() + internal + returns (address[] memory roninTokens, address[] memory mainchainTokens, uint256[] memory chainIds, TokenStandard[] memory standards) + { + // function mapTokens( + // address[] calldata _roninTokens, + // address[] calldata _mainchainTokens, + // uint256[] calldata chainIds, + // TokenStandard[] calldata _standards + // ) + (uint256 N, MapTokenInfo[] memory tokenInfos) = _initTokenList(); + + roninTokens = new address[](N); + mainchainTokens = new address[](N); + chainIds = new uint256[](N); + standards = new TokenStandard[](N); + + // ============= MAP TOKENS =========== + + for (uint256 i; i < N; ++i) { + roninTokens[i] = tokenInfos[i].roninToken; + mainchainTokens[i] = tokenInfos[i].mainchainToken; + chainIds[i] = network().companionChainId(); + standards[i] = tokenInfos[i].standard; + } + } + + function _prepareSetMinThreshold() internal returns (address[] memory roninTokensToSetMinThreshold, uint256[] memory minThresholds) { + (uint256 N, MapTokenInfo[] memory tokenInfos) = _initTokenList(); + + // ============= SET MIN THRESHOLD ============ + // function setMinimumThresholds( + // address[] calldata _tokens, + // uint256[] calldata _thresholds + // ); + roninTokensToSetMinThreshold = new address[](N); + minThresholds = new uint256[](N); + + for (uint256 i; i < N; ++i) { + roninTokensToSetMinThreshold[i] = tokenInfos[i].roninToken; + minThresholds[i] = tokenInfos[i].minThreshold; + } + } +} diff --git a/script/factories/simulation/factory-maptoken-simulation-base.s.sol b/script/factories/simulation/factory-maptoken-simulation-base.s.sol new file mode 100644 index 00000000..f314fa1f --- /dev/null +++ b/script/factories/simulation/factory-maptoken-simulation-base.s.sol @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { Migration } from "../../Migration.s.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import "@ronin/contracts/libraries/Ballot.sol"; +import { IBridgeManager } from "@ronin/contracts/interfaces/bridge/IBridgeManager.sol"; +import { DefaultNetwork } from "@fdk/utils/DefaultNetwork.sol"; + +abstract contract Factory__MapTokensSimulation_Base is Migration { + modifier inSimulation() { + uint256 snapshot = vm.snapshot(); + _; + vm.revertTo(snapshot); + } + + function simulate() public virtual { + _setUp(); + } + + function _setUp() internal virtual; + + function _cheatWeightGovernor(IBridgeManager manager, address gov) internal virtual { + bytes32 governorsWeightSlot = bytes32(uint256(0xc648703095712c0419b6431ae642c061f0a105ac2d7c3d9604061ef4ebc38300) + uint256(2)); + bytes32 $ = keccak256(abi.encode(gov, governorsWeightSlot)); + + uint256 totalWeight = manager.getTotalWeight(); + bytes32 newGovWeight = bytes32(uint256(totalWeight)); + + vm.store(address(manager), $, newGovWeight); + assert(manager.getGovernorWeight(gov) == totalWeight); + } +} diff --git a/script/factories/simulation/factory-maptoken-simulation-mainchain.s.sol b/script/factories/simulation/factory-maptoken-simulation-mainchain.s.sol new file mode 100644 index 00000000..d402d27b --- /dev/null +++ b/script/factories/simulation/factory-maptoken-simulation-mainchain.s.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "@ronin/contracts/libraries/Ballot.sol"; +import { console2 } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import "@ronin/contracts/libraries/Ballot.sol"; +import { IBridgeManager } from "@ronin/contracts/interfaces/bridge/IBridgeManager.sol"; +import "./factory-maptoken-simulation-base.s.sol"; +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import { DefaultNetwork } from "@fdk/utils/DefaultNetwork.sol"; +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; +import { SignatureConsumer } from "@ronin/contracts/interfaces/consumers/SignatureConsumer.sol"; +import { LibProposal } from "script/shared/libraries/LibProposal.sol"; +import { Network, TNetwork } from "../../utils/Network.sol"; + +contract Factory__MapTokensSimulation_Mainchain is Factory__MapTokensSimulation_Base { + using LibCompanionNetwork for *; + + RoninBridgeManager internal _roninBridgeManager; + address internal _mainchainGatewayV3; + address internal _mainchainBridgeManager; + + function _setUp() internal override { + if (network() == DefaultNetwork.RoninMainnet.key() || network() == DefaultNetwork.RoninTestnet.key()) { + _roninBridgeManager = RoninBridgeManager(config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); + _mainchainGatewayV3 = config.getAddress(network().companionNetwork(), Contract.MainchainGatewayV3.key()); + _mainchainBridgeManager = config.getAddress(network().companionNetwork(), Contract.MainchainBridgeManager.key()); + } else { + _mainchainGatewayV3 = config.getAddressFromCurrentNetwork(Contract.MainchainGatewayV3.key()); + _mainchainBridgeManager = config.getAddressFromCurrentNetwork(Contract.MainchainBridgeManager.key()); + } + } + + function simulate(Proposal.ProposalDetail memory proposal) public inSimulation { + super.simulate(); + + Ballot.VoteType[] memory cheatingSupports = new Ballot.VoteType[](1); + uint256[] memory cheatingPks = new uint256[](1); + (address cheatingGov, uint256 cheatingGovPk) = makeAddrAndKey("Governor"); + + cheatingSupports[0] = Ballot.VoteType.For; + cheatingPks[0] = cheatingGovPk; + SignatureConsumer.Signature[] memory cheatingSignatures = LibProposal.generateSignatures(proposal, cheatingPks, Ballot.VoteType.For); + + uint256 gasAmounts = 1_000_000; + for (uint256 i; i < proposal.gasAmounts.length; ++i) { + gasAmounts += proposal.gasAmounts[i]; + } + + vm.startPrank(cheatingGov); + if (network() == DefaultNetwork.RoninMainnet.key() || network() == DefaultNetwork.RoninTestnet.key()) { + _cheatWeightGovernor(IBridgeManager(_roninBridgeManager), cheatingGov); + + _roninBridgeManager.propose( + proposal.chainId, proposal.expiryTimestamp, proposal.executor, proposal.targets, proposal.values, proposal.calldatas, proposal.gasAmounts + ); + _roninBridgeManager.castProposalBySignatures(proposal, cheatingSupports, cheatingSignatures); + + address mMainchainAdress = _mainchainBridgeManager; + TNetwork currentNetwork = network(); + config.createFork(network().companionNetwork()); + config.switchTo(network().companionNetwork()); + + // Handle wrong nonce on testnet + if (currentNetwork == DefaultNetwork.RoninTestnet.key()) { + uint256 roundSlot = uint256(0x0000000000000000000000000000000000000000000000000000000000000002); + bytes32 $ = keccak256(abi.encode(block.chainid, roundSlot)); + + bytes32 newNonce = bytes32(proposal.nonce - 1); + vm.store(address(mMainchainAdress), $, newNonce); + assertEq(MainchainBridgeManager(mMainchainAdress).round(block.chainid) + 1, proposal.nonce); + } + + _cheatWeightGovernor(IBridgeManager(mMainchainAdress), cheatingGov); + MainchainBridgeManager(mMainchainAdress).relayProposal{ gas: gasAmounts }(proposal, cheatingSupports, cheatingSignatures); + + config.switchTo(currentNetwork); + } else { + _cheatWeightGovernor(IBridgeManager(_mainchainBridgeManager), cheatingGov); + MainchainBridgeManager(_mainchainBridgeManager).relayProposal{ gas: gasAmounts }(proposal, cheatingSupports, cheatingSignatures); + } + vm.stopPrank(); + } +} diff --git a/script/factories/simulation/factory-maptoken-simulation-roninchain.s.sol b/script/factories/simulation/factory-maptoken-simulation-roninchain.s.sol new file mode 100644 index 00000000..28afc7dc --- /dev/null +++ b/script/factories/simulation/factory-maptoken-simulation-roninchain.s.sol @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { console2 } from "forge-std/console2.sol"; +import { StdStyle } from "forge-std/StdStyle.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; +import "@ronin/contracts/libraries/Ballot.sol"; +import { IBridgeManager } from "@ronin/contracts/interfaces/bridge/IBridgeManager.sol"; +import "./factory-maptoken-simulation-base.s.sol"; +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import { Contract } from "../../utils/Contract.sol"; +import { DefaultNetwork } from "@fdk/utils/DefaultNetwork.sol"; +import { LibCompanionNetwork } from "script/shared/libraries/LibCompanionNetwork.sol"; + +contract Factory__MapTokensSimulation_Roninchain is Factory__MapTokensSimulation_Base { + using LibCompanionNetwork for *; + + RoninBridgeManager internal _roninBridgeManager; + address internal _roninGatewayV3; + + function _setUp() internal override { + _roninBridgeManager = RoninBridgeManager(config.getAddressFromCurrentNetwork(Contract.RoninBridgeManager.key())); + _roninGatewayV3 = config.getAddressFromCurrentNetwork(Contract.RoninGatewayV3.key()); + } + + function simulate(Proposal.ProposalDetail memory proposal) public inSimulation { + super.simulate(); + + Ballot.VoteType cheatingSupport = Ballot.VoteType.For; + address cheatingGov = makeAddr("Governor"); + _cheatWeightGovernor(IBridgeManager(_roninBridgeManager), cheatingGov); + + vm.startPrank(cheatingGov); + _roninBridgeManager.propose( + proposal.chainId, proposal.expiryTimestamp, proposal.executor, proposal.targets, proposal.values, proposal.calldatas, proposal.gasAmounts + ); + _roninBridgeManager.castProposalVoteForCurrentNetwork(proposal, cheatingSupport); + vm.stopPrank(); + + if (proposal.executor != address(0)) { + vm.prank(proposal.executor); + _roninBridgeManager.execute(proposal); + } + } +} diff --git a/script/libraries/MapTokenInfo.sol b/script/libraries/MapTokenInfo.sol index fc7edbf6..3ca87af7 100644 --- a/script/libraries/MapTokenInfo.sol +++ b/script/libraries/MapTokenInfo.sol @@ -1,9 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import { LibTokenInfo, TokenStandard } from "@ronin/contracts/libraries/LibTokenInfo.sol"; + struct MapTokenInfo { address roninToken; address mainchainToken; + TokenStandard standard; + // This properties is used for ERC20 only. // Config on mainchain uint256 minThreshold; // Config on ronin chain