From 44f1f073f34c85e99deb914a3026639881cfccc5 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sun, 21 Jan 2024 15:57:03 +0700 Subject: [PATCH 01/18] test: migrate BridgeManager hardhat tests --- test/bridge/integration/BaseIntegration.t.sol | 1 + ...oteBridgeOperator.RoninBridgeManager.t.sol | 142 ++++++++++++++++-- 2 files changed, 132 insertions(+), 11 deletions(-) diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 665d1711..0d5a47fb 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -18,6 +18,7 @@ import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBrid import { MockERC20 } from "@ronin/contracts/mocks/token/MockERC20.sol"; import { MockWrappedToken } from "@ronin/contracts/mocks/token/MockWrappedToken.sol"; import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol"; +import { Proposal } from "@ronin/contracts/libraries/Proposal.sol"; import { Token } from "@ronin/contracts/libraries/Token.sol"; import { IWETH } from "@ronin/contracts/interfaces/IWETH.sol"; import { SignatureConsumer } from "@ronin/contracts/interfaces/consumers/SignatureConsumer.sol"; diff --git a/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol b/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol index ac06d9ed..4bc604b3 100644 --- a/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol +++ b/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol @@ -8,9 +8,14 @@ import { ContractType } from "@ronin/contracts/utils/ContractType.sol"; import { IBridgeManager } from "@ronin/contracts/interfaces/bridge/IBridgeManager.sol"; import { SignatureConsumer } from "@ronin/contracts/interfaces/consumers/SignatureConsumer.sol"; import { LibSort } from "solady/utils/LibSort.sol"; + import "../../BaseIntegration.t.sol"; contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { + event ProposalVoted(bytes32 indexed proposalHash, address indexed voter, Ballot.VoteType support, uint256 weight); + + error ErrInvalidProposalNonce(bytes4 sig); + using LibSort for address[]; uint256 _proposalExpiryDuration; @@ -22,11 +27,18 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { address[] _beforeRelayedOperators; address[] _beforeRelayedGovernors; + address[] _afterRelayedOperators; + address[] _afterRelayedGovernors; + Ballot.VoteType[] _supports; + GlobalProposal.GlobalProposalDetail _globalProposal; + SignatureConsumer.Signature[] _signatures; + + bytes32 _anyValue; + function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); _proposalExpiryDuration = 60; _addingOperatorNum = 3; @@ -39,27 +51,135 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { _supports[i] = Ballot.VoteType.For; } - for (uint256 i; i < _addingOperatorNum; i++) { - _addingOperators.push(makeAddr(string.concat("adding-operator", vm.toString(i)))); - _addingGovernors.push(makeAddr(string.concat("adding-governor", vm.toString(i)))); - _voteWeights.push(uint96(uint256(100))); - } + _generateAddingOperators(_addingOperatorNum); } - function test_voteBridgeOperators() public { - GlobalProposal.GlobalProposalDetail memory globalProposal = _roninProposalUtils.createGlobalProposal({ + function test_voteAddBridgeOperatorsProposal() public { + _config.switchTo(Network.RoninLocal.key()); + + _globalProposal = _roninProposalUtils.createGlobalProposal({ expiryTimestamp: block.timestamp + _proposalExpiryDuration, targetOption: GlobalProposal.TargetOption.BridgeManager, value: 0, - calldata_: abi.encodeCall(IBridgeManager.addBridgeOperators, (_voteWeights, _addingOperators, _addingGovernors)), + calldata_: abi.encodeCall(IBridgeManager.addBridgeOperators, (_voteWeights, _addingGovernors, _addingOperators)), gasAmount: 500_000, nonce: _roninNonce++ }); SignatureConsumer.Signature[] memory signatures = - _roninProposalUtils.generateSignaturesGlobal(globalProposal, _param.test.governorPKs); + _roninProposalUtils.generateSignaturesGlobal(_globalProposal, _param.test.governorPKs); + + for (uint256 i; i < signatures.length; i++) { + _signatures.push(signatures[i]); + } + + vm.expectEmit(false, true, true, true); + emit ProposalVoted(_anyValue, _param.roninBridgeManager.governors[0], Ballot.VoteType.For, 100); + + vm.prank(_param.roninBridgeManager.governors[0]); + _roninBridgeManager.proposeGlobalProposalStructAndCastVotes(_globalProposal, _supports, _signatures); + + assertEq( + _roninBridgeManager.globalProposalVoted(_globalProposal.nonce, _param.roninBridgeManager.governors[0]), true + ); + assertEq(_roninBridgeManager.getBridgeOperators(), _afterRelayedOperators); + } + + function test_relayAddBridgeOperator() public { + test_voteAddBridgeOperatorsProposal(); + + _config.switchTo(Network.EthLocal.key()); + + // before relay + assertEq(_mainchainBridgeManager.globalProposalRelayed(_globalProposal.nonce), false); + assertEq(_mainchainBridgeManager.getBridgeOperators(), _beforeRelayedOperators); + + vm.prank(_param.mainchainBridgeManager.governors[0]); + _mainchainBridgeManager.relayGlobalProposal(_globalProposal, _supports, _signatures); + + // after relay + assertEq(_mainchainBridgeManager.globalProposalRelayed(_globalProposal.nonce), true); + assertEq(_mainchainBridgeManager.getBridgeOperators(), _afterRelayedOperators); + } + + function test_RevertWhen_RelayAgain() public { + test_relayAddBridgeOperator(); + + vm.expectRevert( + abi.encodeWithSelector(ErrInvalidProposalNonce.selector, MainchainBridgeManager.relayGlobalProposal.selector) + ); + + vm.prank(_param.mainchainBridgeManager.governors[0]); + _mainchainBridgeManager.relayGlobalProposal(_globalProposal, _supports, _signatures); + } + + function test_voteForLargeNumberOfOperators(uint256 seed) public { + uint256 numAddingOperators = seed % 10 + 10; + _generateAddingOperators(numAddingOperators); + + _config.switchTo(Network.RoninLocal.key()); + + _globalProposal = _roninProposalUtils.createGlobalProposal({ + expiryTimestamp: block.timestamp + _proposalExpiryDuration, + targetOption: GlobalProposal.TargetOption.BridgeManager, + value: 0, + calldata_: abi.encodeCall(IBridgeManager.addBridgeOperators, (_voteWeights, _addingGovernors, _addingOperators)), + gasAmount: 200_000 * numAddingOperators, + nonce: _roninNonce++ + }); + + SignatureConsumer.Signature[] memory signatures = + _roninProposalUtils.generateSignaturesGlobal(_globalProposal, _param.test.governorPKs); + + for (uint256 i; i < signatures.length; i++) { + _signatures.push(signatures[i]); + } + + vm.expectEmit(false, true, true, true); + emit ProposalVoted(_anyValue, _param.roninBridgeManager.governors[0], Ballot.VoteType.For, 100); vm.prank(_param.roninBridgeManager.governors[0]); - _roninBridgeManager.proposeGlobalProposalStructAndCastVotes(globalProposal, _supports, signatures); + _roninBridgeManager.proposeGlobalProposalStructAndCastVotes(_globalProposal, _supports, _signatures); + + assertEq( + _roninBridgeManager.globalProposalVoted(_globalProposal.nonce, _param.roninBridgeManager.governors[0]), true + ); + assertEq(_roninBridgeManager.getBridgeOperators(), _afterRelayedOperators); + } + + function test_relayExpiredProposal() public { + test_voteAddBridgeOperatorsProposal(); + + _config.switchTo(Network.EthLocal.key()); + vm.warp(block.timestamp + _proposalExpiryDuration + 1); + + // before relay + assertEq(_mainchainBridgeManager.globalProposalRelayed(_globalProposal.nonce), false); + assertEq(_mainchainBridgeManager.getBridgeOperators(), _beforeRelayedOperators); + + vm.prank(_param.mainchainBridgeManager.governors[0]); + _mainchainBridgeManager.relayGlobalProposal(_globalProposal, _supports, _signatures); + + // after relay + assertEq(_mainchainBridgeManager.globalProposalRelayed(_globalProposal.nonce), true); + assertEq(_mainchainBridgeManager.getBridgeOperators(), _afterRelayedOperators); + } + + function _generateAddingOperators(uint256 num) internal { + delete _addingOperators; + delete _addingGovernors; + delete _voteWeights; + + _afterRelayedOperators = _beforeRelayedOperators; + _afterRelayedGovernors = _beforeRelayedGovernors; + + for (uint256 i; i < num; i++) { + _addingOperators.push(makeAddr(string.concat("adding-operator", vm.toString(i)))); + _addingGovernors.push(makeAddr(string.concat("adding-governor", vm.toString(i)))); + _voteWeights.push(uint96(uint256(100))); + + _afterRelayedOperators.push(_addingOperators[i]); + _afterRelayedGovernors.push(_addingGovernors[i]); + } } } From 5a30ecbd83742f591ed50e15dec64f0a7f3be69a Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 23 Jan 2024 09:36:50 +0700 Subject: [PATCH 02/18] test(RoninGatewayV3): test deposit vote --- script/BaseMigrationV2.sol | 47 +++++++ script/Migration.s.sol | 5 +- script/interfaces/ISharedArgument.sol | 1 + ...atorContract_OnlyTiming_ForHardhatTest.sol | 6 +- src/mocks/token/MockWrappedToken.sol | 7 ++ test/bridge/integration/BaseIntegration.t.sol | 48 +++++-- .../integration/bridge-tracking/.gitkeep | 0 .../depositVote.RoninGatewayV3.t.sol | 64 ++++++++++ test/helpers/ProposalUtils.t.sol | 26 +++- test/helpers/RoninBridgeAdminUtils.t.sol | 117 ++++++++++++++++++ 10 files changed, 303 insertions(+), 18 deletions(-) create mode 100644 script/BaseMigrationV2.sol create mode 100644 test/bridge/integration/bridge-tracking/.gitkeep create mode 100644 test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol create mode 100644 test/helpers/RoninBridgeAdminUtils.t.sol diff --git a/script/BaseMigrationV2.sol b/script/BaseMigrationV2.sol new file mode 100644 index 00000000..df622324 --- /dev/null +++ b/script/BaseMigrationV2.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.23; + +import "foundry-deployment-kit/BaseMigration.s.sol"; + +abstract contract BaseMigrationV2 is BaseMigration { + using StdStyle for *; + using LibString for bytes32; + using LibProxy for address payable; + + function _deployProxy(TContract contractType, bytes memory args) + internal + virtual + override + logFn(string.concat("_deployProxy ", TContract.unwrap(contractType).unpackOne())) + returns (address payable deployed) + { + string memory contractName = CONFIG.getContractName(contractType); + + address logic = _deployLogic(contractType); + string memory proxyAbsolutePath = "TransparentUpgradeableProxyV2.sol:TransparentUpgradeableProxyV2"; + uint256 proxyNonce; + address proxyAdmin = _getProxyAdmin(); + assertTrue(proxyAdmin != address(0x0), "BaseMigration: Null ProxyAdmin"); + + (deployed, proxyNonce) = _deployRaw(proxyAbsolutePath, abi.encode(logic, proxyAdmin, args)); + + // validate proxy admin + address actualProxyAdmin = deployed.getProxyAdmin(); + assertEq( + actualProxyAdmin, + proxyAdmin, + string.concat( + "BaseMigration: Invalid proxy admin\n", + "Actual: ", + vm.toString(actualProxyAdmin), + "\nExpected: ", + vm.toString(proxyAdmin) + ) + ); + + CONFIG.setAddress(network(), contractType, deployed); + ARTIFACT_FACTORY.generateArtifact( + sender(), deployed, proxyAbsolutePath, string.concat(contractName, "Proxy"), args, proxyNonce + ); + } +} diff --git a/script/Migration.s.sol b/script/Migration.s.sol index 0a53c03f..e02aba5a 100644 --- a/script/Migration.s.sol +++ b/script/Migration.s.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.23; -import { BaseMigration } from "foundry-deployment-kit/BaseMigration.s.sol"; +import { BaseMigrationV2 } from "./BaseMigrationV2.sol"; import { DefaultNetwork } from "foundry-deployment-kit/utils/DefaultNetwork.sol"; import { GeneralConfig } from "./GeneralConfig.sol"; import { ISharedArgument } from "./interfaces/ISharedArgument.sol"; @@ -12,7 +12,7 @@ import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol"; import { Token } from "@ronin/contracts/libraries/Token.sol"; import { LibArray } from "./libraries/LibArray.sol"; -contract Migration is BaseMigration, Utils { +contract Migration is BaseMigrationV2, Utils { ISharedArgument public constant config = ISharedArgument(address(CONFIG)); function _configByteCode() internal virtual override returns (bytes memory) { @@ -21,6 +21,7 @@ contract Migration is BaseMigration, Utils { function _sharedArguments() internal virtual override returns (bytes memory rawArgs) { ISharedArgument.SharedParameter memory param; + param.test.numberOfBlocksInEpoch = 600; param.test.proxyAdmin = makeAddr("proxy-admin"); param.test.dposGA = makeAddr("governance-admin"); param.test.mainchainChainId = Network.EthLocal.chainId(); diff --git a/script/interfaces/ISharedArgument.sol b/script/interfaces/ISharedArgument.sol index eb5508f6..a9224938 100644 --- a/script/interfaces/ISharedArgument.sol +++ b/script/interfaces/ISharedArgument.sol @@ -89,6 +89,7 @@ interface ISharedArgument is IGeneralConfig { struct UnitTestParam { address proxyAdmin; + uint256 numberOfBlocksInEpoch; address dposGA; uint256 mainchainChainId; uint256 roninChainId; diff --git a/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol b/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol index c73a2ab9..8b868cbf 100644 --- a/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol +++ b/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol @@ -46,7 +46,7 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { } function epochEndingAt(uint256 _block) public view returns (bool) { - for (uint _i = 0; _i < _epochs.length; _i++) { + for (uint256 _i = 0; _i < _epochs.length; _i++) { if (_block == _epochs[_i]) { return true; } @@ -77,6 +77,10 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { return _lastUpdatedPeriod; } + function setCurrentPeriod(uint256 period) external { + _lastUpdatedPeriod = period; + } + function currentPeriodStartAtBlock() public view returns (uint256) { return _currentPeriodStartAtBlock; } diff --git a/src/mocks/token/MockWrappedToken.sol b/src/mocks/token/MockWrappedToken.sol index 1cacf73c..8ad66878 100644 --- a/src/mocks/token/MockWrappedToken.sol +++ b/src/mocks/token/MockWrappedToken.sol @@ -42,6 +42,13 @@ contract MockWrappedToken { emit Withdrawal(msg.sender, wad); } + function mint(address account, uint256 amount) public { + require(account != address(0), "ERC20: mint to the zero address"); + + balanceOf[account] += amount; + emit Transfer(address(0), account, amount); + } + function totalSupply() public view returns (uint256) { return address(this).balance; } diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 0d5a47fb..7213cb03 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -26,6 +26,9 @@ import { Ballot } from "@ronin/contracts/libraries/Ballot.sol"; import { GlobalCoreGovernance } from "@ronin/contracts/extensions/sequential-governance/GlobalCoreGovernance.sol"; import { IHasContracts } from "@ronin/contracts/interfaces/collections/IHasContracts.sol"; import { ContractType } from "@ronin/contracts/utils/ContractType.sol"; +import { TransparentUpgradeableProxyV2 } from "@ronin/contracts/extensions/TransparentUpgradeableProxyV2.sol"; +import { MockValidatorContract_OnlyTiming_ForHardhatTest } from + "@ronin/contracts/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol"; import { RoninBridgeManagerDeploy } from "@ronin/script/contracts/RoninBridgeManagerDeploy.s.sol"; import { RoninGatewayV3Deploy } from "@ronin/script/contracts/RoninGatewayV3Deploy.s.sol"; @@ -41,7 +44,7 @@ import { SLPDeploy } from "@ronin/script/contracts/token/SLPDeploy.s.sol"; import { USDCDeploy } from "@ronin/script/contracts/token/USDCDeploy.s.sol"; import { ProposalUtils } from "test/helpers/ProposalUtils.t.sol"; -import { MockValidatorSet_ForFoundryTest } from "test/mocks/MockValidatorSet_ForFoundryTest.sol"; +import { RoninBridgeAdminUtils } from "test/helpers/RoninBridgeAdminUtils.t.sol"; contract BaseIntegration_Test is Base_Test { IGeneralConfig _config; @@ -67,9 +70,9 @@ contract BaseIntegration_Test is Base_Test { MockERC20 _mainchainSlp; MockERC20 _mainchainUsdc; - MockValidatorSet_ForFoundryTest _validatorSet; + MockValidatorContract_OnlyTiming_ForHardhatTest _validatorSet; - ProposalUtils _roninProposalUtils; + RoninBridgeAdminUtils _roninProposalUtils; ProposalUtils _mainchainProposalUtils; uint256 _roninNonce = 1; @@ -83,6 +86,9 @@ contract BaseIntegration_Test is Base_Test { _initializeRonin(); _initializeMainchain(); + + _changeAdminOnRonin(); + _changeAdminOnMainchain(); } function _deployContractsOnRonin() internal { @@ -101,10 +107,11 @@ contract BaseIntegration_Test is Base_Test { _roninSlp = new SLPDeploy().run(); _roninUsdc = new USDCDeploy().run(); - _validatorSet = new MockValidatorSet_ForFoundryTest(); - _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); - _roninProposalUtils = new ProposalUtils(_param.test.roninChainId); + _roninProposalUtils = new RoninBridgeAdminUtils( + _param.test.roninChainId, _param.test.governorPKs, _roninBridgeManager, _param.roninBridgeManager.governors[0] + ); + _validatorSet = new MockValidatorContract_OnlyTiming_ForHardhatTest(_param.test.numberOfBlocksInEpoch); } function _deployContractsOnMainchain() internal { @@ -121,7 +128,7 @@ contract BaseIntegration_Test is Base_Test { _mainchainUsdc = new USDCDeploy().run(); _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); - _mainchainProposalUtils = new ProposalUtils(_param.test.roninChainId); + _mainchainProposalUtils = new ProposalUtils(_param.test.roninChainId, _param.test.governorPKs); } function _initializeRonin() internal { @@ -159,8 +166,8 @@ contract BaseIntegration_Test is Base_Test { roninTokens[0] = address(_roninWeth); roninTokens[1] = address(_roninWron); roninTokens[2] = address(_roninAxs); - roninTokens[4] = address(_roninSlp); - roninTokens[3] = address(_roninUsdc); + roninTokens[3] = address(_roninSlp); + roninTokens[4] = address(_roninUsdc); } function _bridgeRewardInitialize() internal { @@ -194,10 +201,12 @@ contract BaseIntegration_Test is Base_Test { ISharedArgument.BridgeTrackingParam memory param = _param.bridgeTracking; _bridgeTracking.initialize(param.bridgeContract, param.validatorContract, param.startedAtBlock); - _bridgeTracking.initializeV2(); + // _bridgeTracking.initializeV2(); NOT INITIALIZE V2 _bridgeTracking.initializeV3( address(_roninBridgeManager), address(_bridgeSlash), address(_bridgeReward), _param.test.dposGA ); + vm.prank(_param.test.dposGA); + _bridgeTracking.initializeREP2(); } function _bridgeSlashInitialize() internal { @@ -417,6 +426,25 @@ contract BaseIntegration_Test is Base_Test { _mainchainGatewayV3.initializeV2(address(_mainchainBridgeManager)); } + function _changeAdminOnRonin() internal { + _config.switchTo(Network.RoninLocal.key()); + + vm.startPrank(_param.test.proxyAdmin); + TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).changeAdmin(address(_roninBridgeManager)); + TransparentUpgradeableProxyV2(payable(address(_bridgeReward))).changeAdmin(address(_roninBridgeManager)); + TransparentUpgradeableProxyV2(payable(address(_bridgeSlash))).changeAdmin(address(_roninBridgeManager)); + TransparentUpgradeableProxyV2(payable(address(_bridgeTracking))).changeAdmin(address(_roninBridgeManager)); + vm.stopPrank(); + } + + function _changeAdminOnMainchain() internal { + _config.switchTo(Network.EthLocal.key()); + + vm.startPrank(_param.test.proxyAdmin); + TransparentUpgradeableProxyV2(payable(address(_mainchainGatewayV3))).changeAdmin(address(_mainchainBridgeManager)); + vm.stopPrank(); + } + function _deployGeneralConfig() internal { vm.makePersistent(LibSharedAddress.CONFIG); vm.allowCheatcodes(LibSharedAddress.CONFIG); diff --git a/test/bridge/integration/bridge-tracking/.gitkeep b/test/bridge/integration/bridge-tracking/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol new file mode 100644 index 00000000..419e3cf9 --- /dev/null +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { Transfer } from "@ronin/contracts/libraries/Transfer.sol"; +import { Token } from "@ronin/contracts/libraries/Token.sol"; +import { ContractType } from "@ronin/contracts/utils/ContractType.sol"; +import { IsolatedGovernance } from "@ronin/contracts/libraries/IsolatedGovernance.sol"; +import { VoteStatusConsumer } from "@ronin/contracts/interfaces/consumers/VoteStatusConsumer.sol"; +import { MockRoninGatewayV3Extended } from "@ronin/contracts/mocks/ronin/MockRoninGatewayV3Extended.sol"; +import "../BaseIntegration.t.sol"; + +contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { + using Transfer for Transfer.Receipt; + + Transfer.Receipt[] _depositReceipts; + + function setUp() public virtual override { + super.setUp(); + _config.switchTo(Network.RoninLocal.key()); + + bytes memory calldata_ = + abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE_TRACKING, address(_bridgeTracking))); + _roninProposalUtils.functionDelegateCallGlobal( + GlobalProposal.TargetOption.GatewayContract, _roninNonce++, calldata_ + ); + + vm.etch(address(_roninGatewayV3), address(new MockRoninGatewayV3Extended()).code); + } + + function test_depositVote() public { + Transfer.Receipt memory receipt = Transfer.Receipt({ + id: 0, + kind: Transfer.Kind.Deposit, + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), + mainchain: Token.Owner({ + addr: makeAddr("requester"), + tokenAddr: address(_mainchainWeth), + chainId: _param.test.mainchainChainId + }), + info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) + }); + + _depositReceipts.push(receipt); + receipt.id = 1; + _depositReceipts.push(receipt); + + for (uint256 i; i < _param.roninBridgeManager.num - 1; i++) { + vm.prank(_param.roninBridgeManager.bridgeOperators[i]); + _roninGatewayV3.tryBulkDepositFor(_depositReceipts); + } + + for (uint256 i = 0; i < _depositReceipts.length; i++) { + (VoteStatusConsumer.VoteStatus status,,,) = + _roninGatewayV3.depositVote(_depositReceipts[i].mainchain.chainId, _depositReceipts[i].id); + + assertEq(uint256(uint8(status)), uint256(uint8(VoteStatusConsumer.VoteStatus.Pending))); + + uint256 totalWeight = MockRoninGatewayV3Extended(payable(address(_roninGatewayV3))).getDepositVoteWeight( + _depositReceipts[i].mainchain.chainId, i, Transfer.hash(_depositReceipts[i]) + ); + assertEq(totalWeight, (_param.roninBridgeManager.num - 1) * 100); + } + } +} diff --git a/test/helpers/ProposalUtils.t.sol b/test/helpers/ProposalUtils.t.sol index 8e4be079..d5667a2d 100644 --- a/test/helpers/ProposalUtils.t.sol +++ b/test/helpers/ProposalUtils.t.sol @@ -16,11 +16,16 @@ contract ProposalUtils is Utils, Test { using Proposal for Proposal.ProposalDetail; uint256 _roninChainId; + uint256[] _signerPKs; bytes32 _domain; - constructor(uint256 roninChainId) { + constructor(uint256 roninChainId, uint256[] memory signerPKs) { _roninChainId = roninChainId; _domain = getBridgeManagerDomain(roninChainId); + + for (uint256 i; i < signerPKs.length; i++) { + _signerPKs.push(signerPKs[i]); + } } function createProposal( @@ -80,6 +85,14 @@ contract ProposalUtils is Utils, Test { return generateSignatures(proposal, signerPKs, Ballot.VoteType.For); } + function generateSignatures(Proposal.ProposalDetail memory proposal) + public + view + returns (SignatureConsumer.Signature[] memory sigs) + { + return generateSignatures(proposal, _signerPKs, Ballot.VoteType.For); + } + function generateSignaturesGlobal( GlobalProposal.GlobalProposalDetail memory proposal, uint256[] memory signerPKs, @@ -97,10 +110,13 @@ contract ProposalUtils is Utils, Test { return generateSignaturesGlobal(proposal, signerPKs, Ballot.VoteType.For); } - function defaultExpiryTimestamp() public view returns (uint256) { } - - function functionDelegateCallGlobal() public view { } - function upgradeGlobal() public view { } + function generateSignaturesGlobal(GlobalProposal.GlobalProposalDetail memory proposal) + public + view + returns (SignatureConsumer.Signature[] memory sigs) + { + return generateSignaturesGlobal(proposal, _signerPKs, Ballot.VoteType.For); + } function getBridgeManagerDomain(uint256 roninChainId) public pure returns (bytes32) { return keccak256( diff --git a/test/helpers/RoninBridgeAdminUtils.t.sol b/test/helpers/RoninBridgeAdminUtils.t.sol new file mode 100644 index 00000000..742dda9b --- /dev/null +++ b/test/helpers/RoninBridgeAdminUtils.t.sol @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { RoninBridgeManager } from "@ronin/contracts/ronin/gateway/RoninBridgeManager.sol"; +import "./ProposalUtils.t.sol"; + +contract RoninBridgeAdminUtils is ProposalUtils { + RoninBridgeManager _contract; + address _sender; + + constructor(uint256 roninChainId, uint256[] memory signerPKs, RoninBridgeManager contract_, address sender) + ProposalUtils(roninChainId, signerPKs) + { + _contract = contract_; + _sender = sender; + } + + function defaultExpiryTimestamp() public view returns (uint256) { + return block.timestamp + 10; + } + + function functionDelegateCall(address to, uint256 nonce, bytes memory data) public { + Proposal.ProposalDetail memory proposal = this.createProposal({ + expiryTimestamp: this.defaultExpiryTimestamp(), + target: to, + value: 0, + calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), + gasAmount: 2_000_000, + nonce: nonce + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignatures(proposal); + uint256 length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.proposeProposalStructAndCastVotes(proposal, supports_, signatures); + } + + function functionDelegateCallGlobal(GlobalProposal.TargetOption target, uint256 nonce, bytes memory data) public { + GlobalProposal.GlobalProposalDetail memory proposal = this.createGlobalProposal({ + expiryTimestamp: this.defaultExpiryTimestamp(), + targetOption: target, + value: 0, + calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), + gasAmount: 2_000_000, + nonce: nonce + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); + uint256 length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.proposeGlobalProposalStructAndCastVotes(proposal, supports_, signatures); + } + + function functionDelegateCallsGlobal( + GlobalProposal.TargetOption[] memory targetOptions, + uint256 nonce, + bytes[] memory datas + ) public { + uint256 length = targetOptions.length; + if (length != datas.length || length == 0) revert("Invalid length"); + + bytes[] memory calldatas = new bytes[](length); + uint256[] memory values = new uint256[](length); + uint256[] memory gasAmounts = new uint256[](length); + for (uint256 i; i < length; i++) { + calldatas[i] = abi.encodeWithSignature("functionDelegateCall(bytes)", datas[i]); + values[i] = 0; + gasAmounts[i] = 2_000_000; + } + + GlobalProposal.GlobalProposalDetail memory proposal = GlobalProposal.GlobalProposalDetail({ + nonce: nonce, + expiryTimestamp: this.defaultExpiryTimestamp(), + targetOptions: targetOptions, + values: values, + calldatas: calldatas, + gasAmounts: gasAmounts + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); + length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.proposeGlobalProposalStructAndCastVotes(proposal, supports_, signatures); + } + + function upgradeGlobal(GlobalProposal.TargetOption targetOption, uint256 nonce, bytes memory data) public { + GlobalProposal.GlobalProposalDetail memory proposal = this.createGlobalProposal({ + expiryTimestamp: this.defaultExpiryTimestamp(), + targetOption: targetOption, + value: 0, + calldata_: abi.encodeWithSignature("upgradeTo(bytes)", data), + gasAmount: 2_000_000, + nonce: nonce + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); + uint256 length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.proposeGlobalProposalStructAndCastVotes(proposal, supports_, signatures); + } +} From 763a1ffad7b3876acf9f3522daa50b066b5b0637 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 23 Jan 2024 09:37:09 +0700 Subject: [PATCH 03/18] chore: storage layout --- logs/contract-code-sizes.log | 4 ++-- logs/storage/BaseMigrationV2.sol:BaseMigrationV2.log | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 logs/storage/BaseMigrationV2.sol:BaseMigrationV2.log diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index 81d81e1d..84a5dc26 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -44,9 +44,9 @@ | MockRoninBridgeManager | 24.601 | -0.025 | | MockRoninGatewayV3Extended | 20.048 | 4.528 | | MockTUint256Slot | 2.73 | 21.846 | -| MockValidatorContract_OnlyTiming_ForHardhatTest | 1.115 | 23.461 | +| MockValidatorContract_OnlyTiming_ForHardhatTest | 1.158 | 23.418 | | MockValidatorSet_ForFoundryTest | 0.172 | 24.404 | -| MockWrappedToken | 1.978 | 22.598 | +| MockWrappedToken | 2.225 | 22.351 | | PRBMathUtils | 0.063 | 24.513 | | PauseEnforcer | 4.548 | 20.028 | | Proposal | 0.166 | 24.41 | diff --git a/logs/storage/BaseMigrationV2.sol:BaseMigrationV2.log b/logs/storage/BaseMigrationV2.sol:BaseMigrationV2.log new file mode 100644 index 00000000..3f9c1ed2 --- /dev/null +++ b/logs/storage/BaseMigrationV2.sol:BaseMigrationV2.log @@ -0,0 +1,12 @@ +script/BaseMigrationV2.sol:BaseMigrationV2:stdstore (storage_slot: 0) (offset: 0) (type: struct StdStorage) (numberOfBytes: 224) +script/BaseMigrationV2.sol:BaseMigrationV2:stdChainsInitialized (storage_slot: 7) (offset: 0) (type: bool) (numberOfBytes: 1) +script/BaseMigrationV2.sol:BaseMigrationV2:chains (storage_slot: 8) (offset: 0) (type: mapping(string => struct StdChains.Chain)) (numberOfBytes: 32) +script/BaseMigrationV2.sol:BaseMigrationV2:defaultRpcUrls (storage_slot: 9) (offset: 0) (type: mapping(string => string)) (numberOfBytes: 32) +script/BaseMigrationV2.sol:BaseMigrationV2:idToAlias (storage_slot: 10) (offset: 0) (type: mapping(uint256 => string)) (numberOfBytes: 32) +script/BaseMigrationV2.sol:BaseMigrationV2:fallbackToDefaultRpcUrls (storage_slot: 11) (offset: 0) (type: bool) (numberOfBytes: 1) +script/BaseMigrationV2.sol:BaseMigrationV2:gasMeteringOff (storage_slot: 11) (offset: 1) (type: bool) (numberOfBytes: 1) +script/BaseMigrationV2.sol:BaseMigrationV2:IS_SCRIPT (storage_slot: 11) (offset: 2) (type: bool) (numberOfBytes: 1) +script/BaseMigrationV2.sol:BaseMigrationV2:IS_TEST (storage_slot: 11) (offset: 3) (type: bool) (numberOfBytes: 1) +script/BaseMigrationV2.sol:BaseMigrationV2:_failed (storage_slot: 11) (offset: 4) (type: bool) (numberOfBytes: 1) +script/BaseMigrationV2.sol:BaseMigrationV2:_overriddenArgs (storage_slot: 12) (offset: 0) (type: bytes) (numberOfBytes: 32) +script/BaseMigrationV2.sol:BaseMigrationV2:_deployScript (storage_slot: 13) (offset: 0) (type: mapping(TContract => contract IMigrationScript)) (numberOfBytes: 32) \ No newline at end of file From c7170b29a5c8ab8de03e8a7e0e8297e4402eb99e Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Tue, 23 Jan 2024 11:03:08 +0700 Subject: [PATCH 04/18] test(RoninGatewayV3): add more test --- .../depositVote.RoninGatewayV3.t.sol | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index 419e3cf9..ad14ddcb 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -13,6 +13,7 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { using Transfer for Transfer.Receipt; Transfer.Receipt[] _depositReceipts; + uint256 _numOperatorsForVoteExecuted; function setUp() public virtual override { super.setUp(); @@ -25,9 +26,7 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { ); vm.etch(address(_roninGatewayV3), address(new MockRoninGatewayV3Extended()).code); - } - function test_depositVote() public { Transfer.Receipt memory receipt = Transfer.Receipt({ id: 0, kind: Transfer.Kind.Deposit, @@ -44,7 +43,13 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { receipt.id = 1; _depositReceipts.push(receipt); - for (uint256 i; i < _param.roninBridgeManager.num - 1; i++) { + _numOperatorsForVoteExecuted = + _param.roninBridgeManager.bridgeOperators.length * _param.roninBridgeManager.num / _param.roninBridgeManager.denom; + } + + // @dev Should be able to bulk deposits using bridge operator accounts + function test_tryBulkDepositFor_NotExecuted() public { + for (uint256 i; i < _numOperatorsForVoteExecuted - 1; i++) { vm.prank(_param.roninBridgeManager.bridgeOperators[i]); _roninGatewayV3.tryBulkDepositFor(_depositReceipts); } @@ -58,7 +63,27 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { uint256 totalWeight = MockRoninGatewayV3Extended(payable(address(_roninGatewayV3))).getDepositVoteWeight( _depositReceipts[i].mainchain.chainId, i, Transfer.hash(_depositReceipts[i]) ); - assertEq(totalWeight, (_param.roninBridgeManager.num - 1) * 100); + assertEq(totalWeight, (_numOperatorsForVoteExecuted - 1) * 100); + } + } + + // Should be able to continue to vote on the votes, the later vote is not counted but is tracked + function test_tryBulkDepositFor_Executed() public { + test_tryBulkDepositFor_NotExecuted(); + + vm.prank(_param.roninBridgeManager.bridgeOperators[_numOperatorsForVoteExecuted - 1]); + _roninGatewayV3.tryBulkDepositFor(_depositReceipts); + + for (uint256 i = 0; i < _depositReceipts.length; i++) { + (VoteStatusConsumer.VoteStatus status,,,) = + _roninGatewayV3.depositVote(_depositReceipts[i].mainchain.chainId, _depositReceipts[i].id); + + assertEq(uint256(uint8(status)), uint256(uint8(VoteStatusConsumer.VoteStatus.Executed))); + + uint256 totalWeight = MockRoninGatewayV3Extended(payable(address(_roninGatewayV3))).getDepositVoteWeight( + _depositReceipts[i].mainchain.chainId, i, Transfer.hash(_depositReceipts[i]) + ); + assertEq(totalWeight, (_numOperatorsForVoteExecuted) * 100); } } } From 7e8dbaeae8f6e6e9e66fc5d66bed4f8887306e6b Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Thu, 25 Jan 2024 11:28:10 +0700 Subject: [PATCH 05/18] test: hardhat test of bridge tracking --- ...IsApprovedInLastEpoch.BridgeTracking.t.sol | 209 ++++++++++++++++++ ...otApprovedInLastEpoch.BridgeTracking.t.sol | 139 ++++++++++++ .../depositVote.RoninGatewayV3.t.sol | 4 +- test/helpers/RoninBridgeAdminUtils.t.sol | 16 +- 4 files changed, 355 insertions(+), 13 deletions(-) create mode 100644 test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol create mode 100644 test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol diff --git a/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol b/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol new file mode 100644 index 00000000..f1d03985 --- /dev/null +++ b/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { IBridgeTracking } from "@ronin/contracts/interfaces/bridge/IBridgeTracking.sol"; +import { MockGatewayForTracking } from "@ronin/contracts/mocks/MockGatewayForTracking.sol"; +import "../BaseIntegration.t.sol"; + +// Epoch e-1 test: Vote is approved in the last epoch of period +contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegration_Test { + MockGatewayForTracking _mockRoninGatewayV3; + + uint256 _period; + uint256 _receiptId; + IBridgeTracking.VoteKind _receiptKind; + address[] _operators; + + function setUp() public virtual override { + super.setUp(); + _config.switchTo(Network.RoninLocal.key()); + vm.coinbase(makeAddr("coin-base-addr")); + + // upgrade ronin gateway v3 + _mockRoninGatewayV3 = new MockGatewayForTracking(address(_bridgeTracking)); + + bytes memory calldata_ = + abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE, address(_mockRoninGatewayV3))); + _roninProposalUtils.functionDelegateCall(address(_bridgeTracking), calldata_); + + vm.deal(address(_bridgeReward), 10 ether); + + _setTimestampToPeriodEnding(); + _wrapUpEpochAndMine(); + + _period = _validatorSet.currentPeriod(); + _receiptId = 1; + _receiptKind = IBridgeTracking.VoteKind.Withdrawal; + + _operators.push(_param.roninBridgeManager.bridgeOperators[0]); + _operators.push(_param.roninBridgeManager.bridgeOperators[1]); + } + + // Epoch e-1: Vote & Approve & Vote > Should not record when not approved yet. Vote in last epoch (e-1). + function test_epochE1_notRecordVoteAndBallot_receiptWithoutApproval() public { + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, _operators); + + assertEq(_bridgeTracking.totalVote(_period), 0); + assertEq(_bridgeTracking.totalBallot(_period), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); + } + + // Epoch e-1: Vote & Approve & Vote > Should not record when approve. Approve in last epoch (e-1). + function test_epochE2_notRecordVoteAndBallot_approveInLastEpoch() public { + test_epochE1_notRecordVoteAndBallot_receiptWithoutApproval(); + + _mockRoninGatewayV3.sendApprovedVote(_receiptKind, _receiptId); + + assertEq(_bridgeTracking.totalVote(_period), 0); + assertEq(_bridgeTracking.totalBallot(_period), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); + } + + // Epoch e-1: Vote & Approve & Vote > Should not record even after approved. Vote in last epoch (e-1). + function test_epochE1_notRecordVoteAndBallot_voteInLastEpoch() public { + test_epochE2_notRecordVoteAndBallot_approveInLastEpoch(); + + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[2])); + + assertEq(_bridgeTracking.totalVote(_period), 0); + assertEq(_bridgeTracking.totalBallot(_period), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), 0); + } + + // Epoch e: vote > Should not record for current period metric when wrapping up period. Query in next epoch (e), for current period (p-1): return 0. + function test_epochE_notRecordForCurrentPeriod_WhenWrappingUpPeriod() public { + test_epochE1_notRecordVoteAndBallot_voteInLastEpoch(); + + _setTimestampToPeriodEnding(); + _wrapUpEpochAndMine(); + + uint256 lastPeriod = _period; + uint256 newPeriod = _validatorSet.currentPeriod(); + _period = newPeriod; + assertTrue(newPeriod != lastPeriod); + + assertEq(_bridgeTracking.totalVote(lastPeriod), 0); + assertEq(_bridgeTracking.totalBallot(lastPeriod), 0); + assertEq(_bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[1]), 0); + assertEq(_bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[2]), 0); + } + + // Epoch e: vote > Should record for the buffer metric when wrapping up period. Query in next epoch (e), for next period (p): return >0 (buffer). + function test_epochE_recordBufferMetricForNewPeriod_WhenWrappingUpPeriod() public { + test_epochE_notRecordForCurrentPeriod_WhenWrappingUpPeriod(); + + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 3); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + } + + // Epoch e: vote > Should record new ballot for the buffer metric + function test_epochE_recordNewBallotForBufferMetric() public { + test_epochE_recordBufferMetricForNewPeriod_WhenWrappingUpPeriod(); + + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[3])); + + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 4); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[3]), expectedTotalVotes); + + _wrapUpEpochAndMine(); + + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 4); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[3]), expectedTotalVotes); + } + + // Epoch 2e-1: vote > Should record new ballot for the buffer metric + function test_epoch2E_1_recordNewBallotForBufferMetric() public { + test_epochE_recordNewBallotForBufferMetric(); + + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[4])); + + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 5); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[3]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[4]), expectedTotalVotes); + + _setTimestampToPeriodEnding(); + _wrapUpEpochAndMine(); + + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 5); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[3]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[4]), expectedTotalVotes); + } + + // Epoch 3e: vote > Should not record new ballot. And the period metric is finalized as in epoch 2e-1. + function test_epoch3E_notRecordNewBallot_periodMetricIsFinalizedAsInEpoch2E_1() public { + test_epoch2E_1_recordNewBallotForBufferMetric(); + + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[5])); + + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 5); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[3]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[4]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[5]), 0); + } + + // Epoch 3e: vote > Should the metric of the new period get reset. + function test_epoch3E_metricOfNewPeriodGetReset() public { + test_epoch3E_notRecordNewBallot_periodMetricIsFinalizedAsInEpoch2E_1(); + + _setTimestampToPeriodEnding(); + _wrapUpEpochAndMine(); + + uint256 lastPeriod = _period; + uint256 newPeriod = _validatorSet.currentPeriod(); + _period = newPeriod; + assertTrue(newPeriod != lastPeriod); + + assertEq(_bridgeTracking.totalVote(newPeriod), 0); + assertEq(_bridgeTracking.totalBallot(newPeriod), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[1]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[2]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[3]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[4]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[5]), 0); + } + + function _wrapUpEpochAndMine() internal { + _validatorSet.endEpoch(); + vm.prank(block.coinbase); + _validatorSet.wrapUpEpoch(); + // mine a dummy block + vm.roll(block.number + 1); + } + + function _setTimestampToPeriodEnding() internal { + vm.warp(((block.timestamp / 86400) + 1) * 86400); + } +} diff --git a/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol b/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol new file mode 100644 index 00000000..431f82db --- /dev/null +++ b/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { IBridgeTracking } from "@ronin/contracts/interfaces/bridge/IBridgeTracking.sol"; +import { MockGatewayForTracking } from "@ronin/contracts/mocks/MockGatewayForTracking.sol"; +import "../BaseIntegration.t.sol"; + +// Epoch e-2 test: Vote is approved NOT in the last epoch +contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegration_Test { + MockGatewayForTracking _mockRoninGatewayV3; + + uint256 _period; + uint256 _receiptId; + IBridgeTracking.VoteKind _receiptKind; + address[] _operators; + + function setUp() public virtual override { + super.setUp(); + _config.switchTo(Network.RoninLocal.key()); + vm.coinbase(makeAddr("coin-base-addr")); + + // upgrade ronin gateway v3 + _mockRoninGatewayV3 = new MockGatewayForTracking(address(_bridgeTracking)); + + bytes memory calldata_ = + abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE, address(_mockRoninGatewayV3))); + _roninProposalUtils.functionDelegateCall(address(_bridgeTracking), calldata_); + + vm.deal(address(_bridgeReward), 10 ether); + + _setTimestampToPeriodEnding(); + _wrapUpEpochAndMine(); + + _period = _validatorSet.currentPeriod(); + _receiptId = 0; + _receiptKind = IBridgeTracking.VoteKind.Deposit; + + _operators.push(_param.roninBridgeManager.bridgeOperators[0]); + _operators.push(_param.roninBridgeManager.bridgeOperators[1]); + } + + // Epoch e-2: Vote & Approve & Vote. > Should not record the receipts which is not approved yet + function test_epochE2_notRecordVoteAndBallot_receiptWithoutApproval() public { + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, _operators); + + assertEq(_bridgeTracking.totalVote(_period), 0); + assertEq(_bridgeTracking.totalBallot(_period), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); + } + + // Epoch e-2: Vote & Approve & Vote. > Should be able to approve the receipts and not record the approved receipts once the epoch is not yet wrapped up + function test_epochE2_recordVoteAndBallot_receiptIsApproved() public { + test_epochE2_notRecordVoteAndBallot_receiptWithoutApproval(); + + _mockRoninGatewayV3.sendApprovedVote(_receiptKind, _receiptId); + assertEq(_bridgeTracking.totalVote(_period), 0); + assertEq(_bridgeTracking.totalBallot(_period), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); + } + + // Epoch e-1: Continue voting for the vote of e-2 > Should be able to record the approved votes/ballots when the epoch is wrapped up + function test_epochE1_continueVotingForVoteOfE2() public { + test_epochE2_recordVoteAndBallot_receiptIsApproved(); + + _wrapUpEpochAndMine(); + + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 2); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + } + + // Epoch e-1: Continue voting for the vote of e-2 > Should be able to record the approved votes/ballots when the epoch is wrapped up + function test_epochE1_recordForWhoVoteLately_onceRequestIsApproved() public { + test_epochE1_continueVotingForVoteOfE2(); + + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[2])); + + _wrapUpEpochAndMine(); + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 3); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes); + } + + // Epoch e (first epoch of new period): Continue voting for vote in e-2 > Should not record in the next period + function test_epochE_continueVotingForVoteInE2_notRecordInNextPeriod() public { + test_epochE1_recordForWhoVoteLately_onceRequestIsApproved(); + + _setTimestampToPeriodEnding(); + _wrapUpEpochAndMine(); + + uint256 lastPeriod = _period; + uint256 newPeriod = _validatorSet.currentPeriod(); + assertTrue(newPeriod != lastPeriod); + + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[3])); + + uint256 expectedTotalVotes = 1; + assertEq(_bridgeTracking.totalVote(lastPeriod), expectedTotalVotes); + assertEq(_bridgeTracking.totalBallot(lastPeriod), expectedTotalVotes * 3); + assertEq( + _bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[0]), expectedTotalVotes + ); + assertEq( + _bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[1]), expectedTotalVotes + ); + assertEq( + _bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[2]), expectedTotalVotes + ); + assertEq(_bridgeTracking.totalBallotOf(lastPeriod, _param.roninBridgeManager.bridgeOperators[3]), 0); + + _period = newPeriod; + + assertEq(_bridgeTracking.totalVote(newPeriod), 0); + assertEq(_bridgeTracking.totalBallot(newPeriod), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[0]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[1]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[2]), 0); + assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[3]), 0); + } + + function _wrapUpEpochAndMine() internal { + _validatorSet.endEpoch(); + vm.prank(block.coinbase); + _validatorSet.wrapUpEpoch(); + // mine a dummy block + vm.roll(block.number + 1); + } + + function _setTimestampToPeriodEnding() internal { + vm.warp(((block.timestamp / 86400) + 1) * 86400); + } +} diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index ad14ddcb..782bcd3e 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -21,9 +21,7 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { bytes memory calldata_ = abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE_TRACKING, address(_bridgeTracking))); - _roninProposalUtils.functionDelegateCallGlobal( - GlobalProposal.TargetOption.GatewayContract, _roninNonce++, calldata_ - ); + _roninProposalUtils.functionDelegateCallGlobal(GlobalProposal.TargetOption.GatewayContract, calldata_); vm.etch(address(_roninGatewayV3), address(new MockRoninGatewayV3Extended()).code); diff --git a/test/helpers/RoninBridgeAdminUtils.t.sol b/test/helpers/RoninBridgeAdminUtils.t.sol index 742dda9b..180d88fe 100644 --- a/test/helpers/RoninBridgeAdminUtils.t.sol +++ b/test/helpers/RoninBridgeAdminUtils.t.sol @@ -19,14 +19,14 @@ contract RoninBridgeAdminUtils is ProposalUtils { return block.timestamp + 10; } - function functionDelegateCall(address to, uint256 nonce, bytes memory data) public { + function functionDelegateCall(address to, bytes memory data) public { Proposal.ProposalDetail memory proposal = this.createProposal({ expiryTimestamp: this.defaultExpiryTimestamp(), target: to, value: 0, calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), gasAmount: 2_000_000, - nonce: nonce + nonce: _contract.round(_roninChainId) + 1 }); SignatureConsumer.Signature[] memory signatures = this.generateSignatures(proposal); @@ -39,14 +39,14 @@ contract RoninBridgeAdminUtils is ProposalUtils { _contract.proposeProposalStructAndCastVotes(proposal, supports_, signatures); } - function functionDelegateCallGlobal(GlobalProposal.TargetOption target, uint256 nonce, bytes memory data) public { + function functionDelegateCallGlobal(GlobalProposal.TargetOption target, bytes memory data) public { GlobalProposal.GlobalProposalDetail memory proposal = this.createGlobalProposal({ expiryTimestamp: this.defaultExpiryTimestamp(), targetOption: target, value: 0, calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), gasAmount: 2_000_000, - nonce: nonce + nonce: _contract.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); @@ -59,11 +59,7 @@ contract RoninBridgeAdminUtils is ProposalUtils { _contract.proposeGlobalProposalStructAndCastVotes(proposal, supports_, signatures); } - function functionDelegateCallsGlobal( - GlobalProposal.TargetOption[] memory targetOptions, - uint256 nonce, - bytes[] memory datas - ) public { + function functionDelegateCallsGlobal(GlobalProposal.TargetOption[] memory targetOptions, bytes[] memory datas) public { uint256 length = targetOptions.length; if (length != datas.length || length == 0) revert("Invalid length"); @@ -77,7 +73,7 @@ contract RoninBridgeAdminUtils is ProposalUtils { } GlobalProposal.GlobalProposalDetail memory proposal = GlobalProposal.GlobalProposalDetail({ - nonce: nonce, + nonce: _contract.round(0) + 1, expiryTimestamp: this.defaultExpiryTimestamp(), targetOptions: targetOptions, values: values, From d34969d1d1376fcc510617f39dab0f6e5d27cfe4 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Thu, 25 Jan 2024 13:54:54 +0700 Subject: [PATCH 06/18] feat: set-up pause enforcer --- .github/workflows/test.yml | 4 +- script/GeneralConfig.sol | 3 + script/Migration.s.sol | 97 +++++++++++-------- .../contracts/MainchainGatewayV3Deploy.s.sol | 1 - .../MainchainPauseEnforcerDeploy.s.sol | 13 +++ .../contracts/RoninPauseEnforcerDeploy.s.sol | 13 +++ script/interfaces/ISharedArgument.sol | 11 +++ script/utils/Contract.sol | 5 + test/bridge/integration/BaseIntegration.t.sol | 63 ++++++++++++ 9 files changed, 164 insertions(+), 46 deletions(-) create mode 100644 script/contracts/MainchainPauseEnforcerDeploy.s.sol create mode 100644 script/contracts/RoninPauseEnforcerDeploy.s.sol diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1b97da34..307a127f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: - name: Run Forge tests run: | - anvil --chain-id 2024 --port 8546 & - anvil --chain-id 2 --port 8547 & + anvil --chain-id 2024 --port 8546 --block-time 1 & + anvil --chain-id 2 --port 8547 --block-time 1 & forge test -vvv id: test diff --git a/script/GeneralConfig.sol b/script/GeneralConfig.sol index ccf4b9a8..57895eb2 100644 --- a/script/GeneralConfig.sol +++ b/script/GeneralConfig.sol @@ -71,6 +71,9 @@ contract GeneralConfig is BaseGeneralConfig, Utils { _contractNameMap[Contract.AXS.key()] = "MockERC20"; _contractNameMap[Contract.SLP.key()] = "MockERC20"; _contractNameMap[Contract.USDC.key()] = "MockERC20"; + + _contractNameMap[Contract.RoninPauseEnforcer.key()] = "PauseEnforcer"; + _contractNameMap[Contract.MainchainPauseEnforcer.key()] = "PauseEnforcer"; } function _mapContractName(Contract contractEnum) internal { diff --git a/script/Migration.s.sol b/script/Migration.s.sol index e02aba5a..10697dbc 100644 --- a/script/Migration.s.sol +++ b/script/Migration.s.sol @@ -21,55 +21,57 @@ contract Migration is BaseMigrationV2, Utils { function _sharedArguments() internal virtual override returns (bytes memory rawArgs) { ISharedArgument.SharedParameter memory param; - param.test.numberOfBlocksInEpoch = 600; - param.test.proxyAdmin = makeAddr("proxy-admin"); - param.test.dposGA = makeAddr("governance-admin"); - param.test.mainchainChainId = Network.EthLocal.chainId(); - param.test.roninChainId = Network.RoninLocal.chainId(); - - // tokens - param.weth.name = "Wrapped WETH"; - param.weth.symbol = "WETH"; - param.wron.name = "Wrapped RON"; - param.wron.symbol = "WRON"; - param.axs.name = "Axie Infinity Shard"; - param.axs.symbol = "AXS"; - param.slp.name = "Smooth Love Potion"; - param.slp.symbol = "SLP"; - param.usdc.name = "USD Coin"; - param.usdc.symbol = "USDC"; - - uint256 num = 6; - 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); - - for (uint256 i; i < num; i++) { - (address addrOperator, uint256 pkOperator) = makeAddrAndKey(string.concat("operator-", vm.toString(i + 1))); - (address addrGovernor, uint256 pkGovernor) = makeAddrAndKey(string.concat("governor-", vm.toString(i + 1))); - - operatorAddrs[i] = addrOperator; - governorAddrs[i] = addrGovernor; - operatorPKs[i] = pkOperator; - governorPKs[i] = pkGovernor; - voteWeights[i] = 100; - } - - LibArray.inlineSortByValue(operatorPKs, LibArray.toUint256s(operatorAddrs)); - LibArray.inlineSortByValue(governorPKs, LibArray.toUint256s(governorAddrs)); - - param.test.operatorPKs = operatorPKs; - param.test.governorPKs = governorPKs; if (network() == Network.Goerli.key()) { // Undefined } else if (network() == DefaultNetwork.RoninTestnet.key()) { // Undefined } else if (network() == Network.RoninLocal.key() || network() == Network.EthLocal.key()) { + // test + param.test.numberOfBlocksInEpoch = 600; + param.test.proxyAdmin = makeAddr("proxy-admin"); + param.test.dposGA = makeAddr("governance-admin"); + param.test.mainchainChainId = Network.EthLocal.chainId(); + param.test.roninChainId = Network.RoninLocal.chainId(); + + // tokens + param.weth.name = "Wrapped WETH"; + param.weth.symbol = "WETH"; + param.wron.name = "Wrapped RON"; + param.wron.symbol = "WRON"; + param.axs.name = "Axie Infinity Shard"; + param.axs.symbol = "AXS"; + param.slp.name = "Smooth Love Potion"; + param.slp.symbol = "SLP"; + param.usdc.name = "USD Coin"; + param.usdc.symbol = "USDC"; + + uint256 num = 6; + 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); + + for (uint256 i; i < num; i++) { + (address addrOperator, uint256 pkOperator) = makeAddrAndKey(string.concat("operator-", vm.toString(i + 1))); + (address addrGovernor, uint256 pkGovernor) = makeAddrAndKey(string.concat("governor-", vm.toString(i + 1))); + + operatorAddrs[i] = addrOperator; + governorAddrs[i] = addrGovernor; + operatorPKs[i] = pkOperator; + governorPKs[i] = pkGovernor; + voteWeights[i] = 100; + } + + LibArray.inlineSortByValue(operatorPKs, LibArray.toUint256s(operatorAddrs)); + LibArray.inlineSortByValue(governorPKs, LibArray.toUint256s(governorAddrs)); + + param.test.operatorPKs = operatorPKs; + param.test.governorPKs = governorPKs; + // Bridge rewards param.bridgeReward.dposGA = param.test.dposGA; param.bridgeReward.rewardPerPeriod = 5_000; @@ -79,6 +81,10 @@ contract Migration is BaseMigrationV2, Utils { // Bridge Tracking + // Ronin Gateway Pause Enforcer + param.roninPauseEnforcer.admin = makeAddr("pause-enforcer-admin"); + param.roninPauseEnforcer.sentries = wrapAddress(makeAddr("pause-enforcer-sentry")); + // Ronin Gateway V3 param.roninGatewayV3.numerator = 3; param.roninGatewayV3.denominator = 6; @@ -96,6 +102,11 @@ contract Migration is BaseMigrationV2, Utils { param.roninBridgeManager.voteWeights = voteWeights; param.roninBridgeManager.targetOptions = options; param.roninBridgeManager.targets = targets; + + // 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 = param.test.roninChainId; param.mainchainGatewayV3.numerator = 1; diff --git a/script/contracts/MainchainGatewayV3Deploy.s.sol b/script/contracts/MainchainGatewayV3Deploy.s.sol index bb4c2e07..d7255e4c 100644 --- a/script/contracts/MainchainGatewayV3Deploy.s.sol +++ b/script/contracts/MainchainGatewayV3Deploy.s.sol @@ -2,7 +2,6 @@ pragma solidity ^0.8.19; import { MainchainGatewayV3 } from "@ronin/contracts/mainchain/MainchainGatewayV3.sol"; -import { IWETH } from "src/interfaces/IWETH.sol"; import { Contract } from "../utils/Contract.sol"; import { ISharedArgument } from "../interfaces/ISharedArgument.sol"; import { Migration } from "../Migration.s.sol"; diff --git a/script/contracts/MainchainPauseEnforcerDeploy.s.sol b/script/contracts/MainchainPauseEnforcerDeploy.s.sol new file mode 100644 index 00000000..8cb42caf --- /dev/null +++ b/script/contracts/MainchainPauseEnforcerDeploy.s.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { PauseEnforcer } from "@ronin/contracts/ronin/gateway/PauseEnforcer.sol"; +import { Contract } from "../utils/Contract.sol"; +import { ISharedArgument } from "../interfaces/ISharedArgument.sol"; +import { Migration } from "../Migration.s.sol"; + +contract MainchainPauseEnforcerDeploy is Migration { + function run() public virtual returns (PauseEnforcer) { + return PauseEnforcer(_deployProxy(Contract.MainchainPauseEnforcer.key(), EMPTY_ARGS)); + } +} diff --git a/script/contracts/RoninPauseEnforcerDeploy.s.sol b/script/contracts/RoninPauseEnforcerDeploy.s.sol new file mode 100644 index 00000000..252fc84d --- /dev/null +++ b/script/contracts/RoninPauseEnforcerDeploy.s.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { PauseEnforcer } from "@ronin/contracts/ronin/gateway/PauseEnforcer.sol"; +import { Contract } from "../utils/Contract.sol"; +import { ISharedArgument } from "../interfaces/ISharedArgument.sol"; +import { Migration } from "../Migration.s.sol"; + +contract RoninPauseEnforcerDeploy is Migration { + function run() public virtual returns (PauseEnforcer) { + return PauseEnforcer(_deployProxy(Contract.RoninPauseEnforcer.key(), EMPTY_ARGS)); + } +} diff --git a/script/interfaces/ISharedArgument.sol b/script/interfaces/ISharedArgument.sol index a9224938..ef5b215c 100644 --- a/script/interfaces/ISharedArgument.sol +++ b/script/interfaces/ISharedArgument.sol @@ -77,6 +77,12 @@ interface ISharedArgument is IGeneralConfig { uint256 rewardPerPeriod; } + struct PauseEnforcerParam { + address target; + address admin; + address[] sentries; + } + struct MockWrappedTokenParam { string name; string symbol; @@ -98,13 +104,18 @@ interface ISharedArgument is IGeneralConfig { } struct SharedParameter { + // mainchain BridgeManagerParam mainchainBridgeManager; MainchainGatewayV3Param mainchainGatewayV3; + PauseEnforcerParam mainchainPauseEnforcer; + // ronin BridgeManagerParam roninBridgeManager; RoninGatewayV3Param roninGatewayV3; + PauseEnforcerParam roninPauseEnforcer; BridgeSlashParam bridgeSlash; BridgeTrackingParam bridgeTracking; BridgeRewardParam bridgeReward; + // tokens MockWrappedTokenParam weth; MockWrappedTokenParam wron; MockERC20Param axs; diff --git a/script/utils/Contract.sol b/script/utils/Contract.sol index bd20e691..9578abc9 100644 --- a/script/utils/Contract.sol +++ b/script/utils/Contract.sol @@ -12,8 +12,10 @@ enum Contract { BridgeTracking, BridgeSlash, BridgeReward, + RoninPauseEnforcer, RoninGatewayV3, RoninBridgeManager, + MainchainPauseEnforcer, MainchainGatewayV3, MainchainBridgeManager } @@ -34,8 +36,11 @@ function name(Contract contractEnum) pure returns (string memory) { if (contractEnum == Contract.BridgeTracking) return "BridgeTracking"; if (contractEnum == Contract.BridgeSlash) return "BridgeSlash"; if (contractEnum == Contract.BridgeReward) return "BridgeReward"; + if (contractEnum == Contract.RoninPauseEnforcer) return "PauseEnforcer"; if (contractEnum == Contract.RoninGatewayV3) return "RoninGatewayV3"; if (contractEnum == Contract.RoninBridgeManager) return "RoninBridgeManager"; + + if (contractEnum == Contract.MainchainPauseEnforcer) return "PauseEnforcer"; if (contractEnum == Contract.MainchainGatewayV3) return "MainchainGatewayV3"; if (contractEnum == Contract.MainchainBridgeManager) return "MainchainBridgeManager"; diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 7213cb03..5635e9d8 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -29,14 +29,20 @@ import { ContractType } from "@ronin/contracts/utils/ContractType.sol"; import { TransparentUpgradeableProxyV2 } from "@ronin/contracts/extensions/TransparentUpgradeableProxyV2.sol"; import { MockValidatorContract_OnlyTiming_ForHardhatTest } from "@ronin/contracts/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol"; +import { PauseEnforcer } from "@ronin/contracts/ronin/gateway/PauseEnforcer.sol"; +import { IPauseTarget } from "@ronin/contracts/interfaces/IPauseTarget.sol"; +import { GatewayV3 } from "@ronin/contracts/extensions/GatewayV3.sol"; import { RoninBridgeManagerDeploy } from "@ronin/script/contracts/RoninBridgeManagerDeploy.s.sol"; import { RoninGatewayV3Deploy } from "@ronin/script/contracts/RoninGatewayV3Deploy.s.sol"; import { BridgeTrackingDeploy } from "@ronin/script/contracts/BridgeTrackingDeploy.s.sol"; import { BridgeSlashDeploy } from "@ronin/script/contracts/BridgeSlashDeploy.s.sol"; import { BridgeRewardDeploy } from "@ronin/script/contracts/BridgeRewardDeploy.s.sol"; +import { RoninPauseEnforcerDeploy } from "@ronin/script/contracts/RoninPauseEnforcerDeploy.s.sol"; + import { MainchainGatewayV3Deploy } from "@ronin/script/contracts/MainchainGatewayV3Deploy.s.sol"; import { MainchainBridgeManagerDeploy } from "@ronin/script/contracts/MainchainBridgeManagerDeploy.s.sol"; +import { MainchainPauseEnforcerDeploy } from "@ronin/script/contracts/MainchainPauseEnforcerDeploy.s.sol"; import { WETHDeploy } from "@ronin/script/contracts/token/WETHDeploy.s.sol"; import { WRONDeploy } from "@ronin/script/contracts/token/WRONDeploy.s.sol"; import { AXSDeploy } from "@ronin/script/contracts/token/AXSDeploy.s.sol"; @@ -50,11 +56,14 @@ contract BaseIntegration_Test is Base_Test { IGeneralConfig _config; ISharedArgument.SharedParameter _param; + PauseEnforcer _roninPauseEnforcer; RoninBridgeManager _roninBridgeManager; RoninGatewayV3 _roninGatewayV3; BridgeTracking _bridgeTracking; BridgeSlash _bridgeSlash; BridgeReward _bridgeReward; + + PauseEnforcer _mainchainPauseEnforcer; MainchainGatewayV3 _mainchainGatewayV3; MainchainBridgeManager _mainchainBridgeManager; @@ -89,6 +98,9 @@ contract BaseIntegration_Test is Base_Test { _changeAdminOnRonin(); _changeAdminOnMainchain(); + + _configEmergencyPauserForRoninGateway(); + _configEmergencyPauserForMainchainGateway(); } function _deployContractsOnRonin() internal { @@ -99,6 +111,7 @@ contract BaseIntegration_Test is Base_Test { _bridgeTracking = new BridgeTrackingDeploy().run(); _bridgeSlash = new BridgeSlashDeploy().run(); _bridgeReward = new BridgeRewardDeploy().run(); + _roninPauseEnforcer = new RoninPauseEnforcerDeploy().run(); _roninBridgeManager = new RoninBridgeManagerDeploy().run(); _roninWeth = new WETHDeploy().run(); @@ -118,6 +131,7 @@ contract BaseIntegration_Test is Base_Test { _config.createFork(Network.EthLocal.key()); _config.switchTo(Network.EthLocal.key()); + _mainchainPauseEnforcer = new MainchainPauseEnforcerDeploy().run(); _mainchainGatewayV3 = new MainchainGatewayV3Deploy().run(); _mainchainBridgeManager = new MainchainBridgeManagerDeploy().run(); @@ -137,6 +151,7 @@ contract BaseIntegration_Test is Base_Test { _bridgeRewardInitialize(); _bridgeTrackingInitialize(); _bridgeSlashInitialize(); + _roninPauseEnforcerInitialize(); _roninGatewayV3Initialize(); _constructForRoninBridgeManager(); } @@ -144,6 +159,7 @@ contract BaseIntegration_Test is Base_Test { function _initializeMainchain() internal { _config.switchTo(Network.EthLocal.key()); + _mainchainPauseEnforcerInitialize(); _constructForMainchainBridgeManager(); _mainchainGatewayV3Initialize(); } @@ -225,6 +241,14 @@ contract BaseIntegration_Test is Base_Test { _bridgeSlash.initializeREP2(); } + function _roninPauseEnforcerInitialize() internal { + _param.roninPauseEnforcer.target = address(_roninGatewayV3); + + ISharedArgument.PauseEnforcerParam memory param = _param.roninPauseEnforcer; + + _roninPauseEnforcer.initialize(IPauseTarget(param.target), param.admin, param.sentries); + } + function _roninGatewayV3Initialize() internal { (address[] memory mainchainTokens, address[] memory roninTokens) = _getMainchainAndRoninTokens(); uint256 tokenNum = mainchainTokens.length; @@ -426,6 +450,14 @@ contract BaseIntegration_Test is Base_Test { _mainchainGatewayV3.initializeV2(address(_mainchainBridgeManager)); } + function _mainchainPauseEnforcerInitialize() internal { + _param.mainchainPauseEnforcer.target = address(_mainchainGatewayV3); + + ISharedArgument.PauseEnforcerParam memory param = _param.mainchainPauseEnforcer; + + _mainchainPauseEnforcer.initialize(IPauseTarget(param.target), param.admin, param.sentries); + } + function _changeAdminOnRonin() internal { _config.switchTo(Network.RoninLocal.key()); @@ -445,6 +477,37 @@ contract BaseIntegration_Test is Base_Test { vm.stopPrank(); } + function _configEmergencyPauserForRoninGateway() internal { + _config.switchTo(Network.RoninLocal.key()); + + bytes memory calldata_ = abi.encodeCall(GatewayV3.setEmergencyPauser, (address(_roninPauseEnforcer))); + _roninProposalUtils.functionDelegateCall(address(_roninGatewayV3), calldata_); + } + + function _configEmergencyPauserForMainchainGateway() internal { + _config.switchTo(Network.EthLocal.key()); + + bytes memory calldata_ = abi.encodeCall(GatewayV3.setEmergencyPauser, (address(_mainchainPauseEnforcer))); + Proposal.ProposalDetail memory proposal = _mainchainProposalUtils.createProposal({ + expiryTimestamp: block.timestamp + 1 minutes, + target: address(_mainchainGatewayV3), + value: 0, + calldata_: calldata_, + gasAmount: 1_000_000, + nonce: _mainchainBridgeManager.round(_param.test.mainchainChainId) + 1 + }); + + SignatureConsumer.Signature[] memory signatures = _mainchainProposalUtils.generateSignatures(proposal); + + Ballot.VoteType[] memory voteTypes = new Ballot.VoteType[](signatures.length); + for (uint256 i; i < signatures.length; i++) { + voteTypes[i] = Ballot.VoteType.For; + } + + vm.prank(_param.mainchainBridgeManager.governors[0]); + _mainchainBridgeManager.relayProposal(proposal, voteTypes, signatures); + } + function _deployGeneralConfig() internal { vm.makePersistent(LibSharedAddress.CONFIG); vm.allowCheatcodes(LibSharedAddress.CONFIG); From 5817a367af89536c2d8df6d32ae2a44f1c899b24 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Thu, 25 Jan 2024 20:25:44 +0700 Subject: [PATCH 07/18] test: try deposit 100 txs --- .github/workflows/test.yml | 4 +- script/Migration.s.sol | 2 +- ...atorContract_OnlyTiming_ForHardhatTest.sol | 57 ++++++++++-------- test/bridge/integration/BaseIntegration.t.sol | 24 +++++++- ...IsApprovedInLastEpoch.BridgeTracking.t.sol | 26 +++------ ...otApprovedInLastEpoch.BridgeTracking.t.sol | 12 ---- .../depositVote.RoninGatewayV3.t.sol | 58 +++++++++++++++++++ 7 files changed, 124 insertions(+), 59 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 307a127f..5e2b4e56 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: - name: Run Forge tests run: | - anvil --chain-id 2024 --port 8546 --block-time 1 & - anvil --chain-id 2 --port 8547 --block-time 1 & + anvil --chain-id 2024 --port 8546 --block-time 3 & + anvil --chain-id 2 --port 8547 --block-time 3 & forge test -vvv id: test diff --git a/script/Migration.s.sol b/script/Migration.s.sol index 10697dbc..6fd4ff13 100644 --- a/script/Migration.s.sol +++ b/script/Migration.s.sol @@ -28,7 +28,7 @@ contract Migration is BaseMigrationV2, Utils { // Undefined } else if (network() == Network.RoninLocal.key() || network() == Network.EthLocal.key()) { // test - param.test.numberOfBlocksInEpoch = 600; + param.test.numberOfBlocksInEpoch = 200; param.test.proxyAdmin = makeAddr("proxy-admin"); param.test.dposGA = makeAddr("governance-admin"); param.test.mainchainChainId = Network.EthLocal.chainId(); diff --git a/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol b/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol index 8b868cbf..09382fe4 100644 --- a/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol +++ b/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol @@ -2,6 +2,8 @@ pragma solidity ^0.8.0; contract MockValidatorContract_OnlyTiming_ForHardhatTest { + event WrappedUpEpoch(uint256 newPeriod, uint256 newEpoch, bool periodEnding); + uint256 public constant PERIOD_DURATION = 1 days; /// @dev The number of blocks in a epoch uint256 internal _numberOfBlocksInEpoch; @@ -11,14 +13,15 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { uint256 internal _lastUpdatedPeriod; /// @dev The starting block of the last updated period uint256 internal _currentPeriodStartAtBlock; - uint256[] internal _epochs; + /// @dev Mapping from epoch index => period index + mapping(uint256 => uint256) internal _periodOf; constructor(uint256 __numberOfBlocksInEpoch) { _numberOfBlocksInEpoch = __numberOfBlocksInEpoch; - _epochs.push(0); } function wrapUpEpoch() external payable { + require(epochEndingAt(block.number), "Tach"); uint256 _newPeriod = _computePeriod(block.timestamp); bool _periodEnding = _isPeriodEnding(_newPeriod); @@ -31,39 +34,45 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { _periodOf[_nextEpoch] = _newPeriod; _lastUpdatedPeriod = _newPeriod; + emit WrappedUpEpoch(_newPeriod, _nextEpoch, _periodEnding); } - function endEpoch() external { - _epochs.push(block.number); - } + // function endEpoch() external { + // // _epochs.push(block.number); + // uint nextEpoch = epochOf(block.number) + 1; + // uint startBlockOfNextEpoch = nextEpoch * _numberOfBlocksInEpoch; + // uint currPeriod = _computePeriod(block.timestamp); + // for (uint i = block.number; i < startBlockOfNextEpoch; i++) { - function epochOf(uint256 _block) public view returns (uint256 _epoch) { - for (uint256 _i = _epochs.length; _i > 0; _i--) { - if (_block > _epochs[_i - 1]) { - return _i; - } - } - } + // } + // } + + // function epochOf(uint256 _block) public view returns (uint256 _epoch) { + // for (uint256 _i = _epochs.length; _i > 0; _i--) { + // if (_block > _epochs[_i - 1]) { + // return _i; + // } + // } + // } function epochEndingAt(uint256 _block) public view returns (bool) { - for (uint256 _i = 0; _i < _epochs.length; _i++) { - if (_block == _epochs[_i]) { - return true; - } - } - return false; + // for (uint256 _i = 0; _i < _epochs.length; _i++) { + // if (_block == _epochs[_i]) { + // return true; + // } + // } + // return false; + + return (_block + 1) % _numberOfBlocksInEpoch == 0; } - /// @dev Mapping from epoch index => period index - mapping(uint256 => uint256) internal _periodOf; - function getLastUpdatedBlock() external view returns (uint256) { return _lastUpdatedBlock; } - // function epochOf(uint256 _block) public view virtual returns (uint256) { - // return _block / _numberOfBlocksInEpoch + 1; - // } + function epochOf(uint256 _block) public view virtual returns (uint256) { + return _block / _numberOfBlocksInEpoch + 1; + } function tryGetPeriodOfEpoch(uint256 _epoch) external view returns (bool _filled, uint256 _periodNumber) { return (_epoch <= epochOf(block.number) || _periodOf[_epoch] > 0, _periodOf[_epoch]); diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 5635e9d8..f9390ed5 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import { console2 as console } from "forge-std/console2.sol"; import { Base_Test } from "../../Base.t.sol"; import { LibSharedAddress } from "foundry-deployment-kit/libraries/LibSharedAddress.sol"; import { ISharedArgument } from "@ronin/script/interfaces/ISharedArgument.sol"; @@ -148,6 +149,8 @@ contract BaseIntegration_Test is Base_Test { function _initializeRonin() internal { _config.switchTo(Network.RoninLocal.key()); + _validatorSet.setCurrentPeriod(block.timestamp / 1 days); + _bridgeRewardInitialize(); _bridgeTrackingInitialize(); _bridgeSlashInitialize(); @@ -204,7 +207,6 @@ contract BaseIntegration_Test is Base_Test { param.rewardPerPeriod ); - _validatorSet.setCurrentPeriod(10); vm.prank(_param.test.dposGA); _bridgeReward.initializeREP2(); } @@ -514,4 +516,24 @@ contract BaseIntegration_Test is Base_Test { deployCodeTo("GeneralConfig.sol", type(GeneralConfig).creationCode, LibSharedAddress.CONFIG); _config = IGeneralConfig(LibSharedAddress.CONFIG); } + + function _wrapUpEpochAndMine() internal { + _wrapUpEpoch(); + // mine a dummy block + vm.roll(block.number + 1); + } + + function _wrapUpEpoch() internal { + uint256 multiplier = _validatorSet.numberOfBlocksInEpoch(); + console.log(block.number); + + vm.roll((block.number / multiplier + 1) * (multiplier) - 1); + + vm.prank(block.coinbase); + _validatorSet.wrapUpEpoch(); + } + + function _setTimestampToPeriodEnding() internal { + vm.warp(((block.timestamp / 1 days) + 1) * 1 days); + } } diff --git a/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol b/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol index f1d03985..3cdb172f 100644 --- a/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol +++ b/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol @@ -19,6 +19,11 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio _config.switchTo(Network.RoninLocal.key()); vm.coinbase(makeAddr("coin-base-addr")); + _operators.push(_param.roninBridgeManager.bridgeOperators[0]); + _operators.push(_param.roninBridgeManager.bridgeOperators[1]); + _receiptId = 1; + _receiptKind = IBridgeTracking.VoteKind.Withdrawal; + // upgrade ronin gateway v3 _mockRoninGatewayV3 = new MockGatewayForTracking(address(_bridgeTracking)); @@ -32,11 +37,6 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio _wrapUpEpochAndMine(); _period = _validatorSet.currentPeriod(); - _receiptId = 1; - _receiptKind = IBridgeTracking.VoteKind.Withdrawal; - - _operators.push(_param.roninBridgeManager.bridgeOperators[0]); - _operators.push(_param.roninBridgeManager.bridgeOperators[1]); } // Epoch e-1: Vote & Approve & Vote > Should not record when not approved yet. Vote in last epoch (e-1). @@ -78,13 +78,13 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio function test_epochE_notRecordForCurrentPeriod_WhenWrappingUpPeriod() public { test_epochE1_notRecordVoteAndBallot_voteInLastEpoch(); + uint256 lastPeriod = _period; _setTimestampToPeriodEnding(); _wrapUpEpochAndMine(); - uint256 lastPeriod = _period; uint256 newPeriod = _validatorSet.currentPeriod(); _period = newPeriod; - assertTrue(newPeriod != lastPeriod); + assertEq(newPeriod, lastPeriod + 1); assertEq(_bridgeTracking.totalVote(lastPeriod), 0); assertEq(_bridgeTracking.totalBallot(lastPeriod), 0); @@ -194,16 +194,4 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[4]), 0); assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[5]), 0); } - - function _wrapUpEpochAndMine() internal { - _validatorSet.endEpoch(); - vm.prank(block.coinbase); - _validatorSet.wrapUpEpoch(); - // mine a dummy block - vm.roll(block.number + 1); - } - - function _setTimestampToPeriodEnding() internal { - vm.warp(((block.timestamp / 86400) + 1) * 86400); - } } diff --git a/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol b/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol index 431f82db..1f3f2c03 100644 --- a/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol +++ b/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol @@ -124,16 +124,4 @@ contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegra assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[2]), 0); assertEq(_bridgeTracking.totalBallotOf(newPeriod, _param.roninBridgeManager.bridgeOperators[3]), 0); } - - function _wrapUpEpochAndMine() internal { - _validatorSet.endEpoch(); - vm.prank(block.coinbase); - _validatorSet.wrapUpEpoch(); - // mine a dummy block - vm.roll(block.number + 1); - } - - function _setTimestampToPeriodEnding() internal { - vm.warp(((block.timestamp / 86400) + 1) * 86400); - } } diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index 782bcd3e..6e121e32 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; +import { console2 as console } from "forge-std/console2.sol"; import { Transfer } from "@ronin/contracts/libraries/Transfer.sol"; import { Token } from "@ronin/contracts/libraries/Token.sol"; import { ContractType } from "@ronin/contracts/utils/ContractType.sol"; @@ -14,6 +15,8 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { Transfer.Receipt[] _depositReceipts; uint256 _numOperatorsForVoteExecuted; + Transfer.Receipt[] first50Receipts; + Transfer.Receipt[] second50Receipts; function setUp() public virtual override { super.setUp(); @@ -84,4 +87,59 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { assertEq(totalWeight, (_numOperatorsForVoteExecuted) * 100); } } + + function test_bulkDeposit_100Txs() public { + _wrapUpEpochAndMine(); + _wrapUpEpochAndMine(); + _setTimestampToPeriodEnding(); + + vm.deal(address(_bridgeReward), 10 ether); + address newBridgeOperator = makeAddr("new-bridge-operator"); + Transfer.Receipt memory sampleReceipt = Transfer.Receipt({ + id: 0, + kind: Transfer.Kind.Deposit, + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), + mainchain: Token.Owner({ + addr: makeAddr("requester"), + tokenAddr: address(_mainchainWeth), + chainId: _param.test.mainchainChainId + }), + info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) + }); + + uint256 id = 1; + for (uint256 i; i < 50; i++) { + first50Receipts.push(sampleReceipt); + second50Receipts.push(sampleReceipt); + first50Receipts[i].id = id; + second50Receipts[i].id = id + 50; + + id++; + } + + for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { + vm.prank(_param.roninBridgeManager.bridgeOperators[i]); + _roninGatewayV3.tryBulkDepositFor(first50Receipts); + } + + vm.prank(_param.roninBridgeManager.governors[0]); + _roninBridgeManager.updateBridgeOperator(newBridgeOperator); + _param.roninBridgeManager.bridgeOperators[0] = newBridgeOperator; + + for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { + vm.prank(_param.roninBridgeManager.bridgeOperators[i]); + _roninGatewayV3.tryBulkDepositFor(second50Receipts); + } + + _wrapUpEpochAndMine(); + _wrapUpEpochAndMine(); + _setTimestampToPeriodEnding(); + + sampleReceipt.id = 101; + + for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { + vm.prank(_param.roninBridgeManager.bridgeOperators[i]); + _roninGatewayV3.depositFor(sampleReceipt); + } + } } From d6a6b4795170776a029d81247928420ca08e5ff1 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Fri, 26 Jan 2024 10:15:46 +0700 Subject: [PATCH 08/18] chore: storage layout --- logs/contract-code-sizes.log | 2 +- ...est.sol:MockValidatorContract_OnlyTiming_ForHardhatTest.log | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index 84a5dc26..a3a076f8 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -44,7 +44,7 @@ | MockRoninBridgeManager | 24.601 | -0.025 | | MockRoninGatewayV3Extended | 20.048 | 4.528 | | MockTUint256Slot | 2.73 | 21.846 | -| MockValidatorContract_OnlyTiming_ForHardhatTest | 1.158 | 23.418 | +| MockValidatorContract_OnlyTiming_ForHardhatTest | 1.063 | 23.513 | | MockValidatorSet_ForFoundryTest | 0.172 | 24.404 | | MockWrappedToken | 2.225 | 22.351 | | PRBMathUtils | 0.063 | 24.513 | diff --git a/logs/storage/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest.log b/logs/storage/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest.log index 4bcfa7f5..1ae53479 100644 --- a/logs/storage/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest.log +++ b/logs/storage/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest.log @@ -2,5 +2,4 @@ src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidato src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest:_lastUpdatedBlock (storage_slot: 1) (offset: 0) (type: uint256) (numberOfBytes: 32) src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest:_lastUpdatedPeriod (storage_slot: 2) (offset: 0) (type: uint256) (numberOfBytes: 32) src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest:_currentPeriodStartAtBlock (storage_slot: 3) (offset: 0) (type: uint256) (numberOfBytes: 32) -src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest:_epochs (storage_slot: 4) (offset: 0) (type: uint256[]) (numberOfBytes: 32) -src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest:_periodOf (storage_slot: 5) (offset: 0) (type: mapping(uint256 => uint256)) (numberOfBytes: 32) \ No newline at end of file +src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol:MockValidatorContract_OnlyTiming_ForHardhatTest:_periodOf (storage_slot: 4) (offset: 0) (type: mapping(uint256 => uint256)) (numberOfBytes: 32) \ No newline at end of file From 79984fcea3a0442efa199f50725b5b5f57e6ef81 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 27 Jan 2024 18:40:54 +0700 Subject: [PATCH 09/18] test: revamp mock validator set --- ...atorContract_OnlyTiming_ForHardhatTest.sol | 10 +++++-- test/bridge/integration/BaseIntegration.t.sol | 30 +++++++++++++++++-- .../depositVote.RoninGatewayV3.t.sol | 5 ++-- 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol b/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol index 09382fe4..6c3d439e 100644 --- a/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol +++ b/src/mocks/ronin/MockValidatorContract_OnlyTiming_ForHardhatTest.sol @@ -3,6 +3,7 @@ pragma solidity ^0.8.0; contract MockValidatorContract_OnlyTiming_ForHardhatTest { event WrappedUpEpoch(uint256 newPeriod, uint256 newEpoch, bool periodEnding); + event CurrentPeriodUpdated(uint256 previousPeriod, uint256 currentPeriod); uint256 public constant PERIOD_DURATION = 1 days; /// @dev The number of blocks in a epoch @@ -21,7 +22,6 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { } function wrapUpEpoch() external payable { - require(epochEndingAt(block.number), "Tach"); uint256 _newPeriod = _computePeriod(block.timestamp); bool _periodEnding = _isPeriodEnding(_newPeriod); @@ -33,7 +33,9 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { } _periodOf[_nextEpoch] = _newPeriod; - _lastUpdatedPeriod = _newPeriod; + + setCurrentPeriod(_newPeriod); + emit WrappedUpEpoch(_newPeriod, _nextEpoch, _periodEnding); } @@ -86,7 +88,9 @@ contract MockValidatorContract_OnlyTiming_ForHardhatTest { return _lastUpdatedPeriod; } - function setCurrentPeriod(uint256 period) external { + function setCurrentPeriod(uint256 period) public { + emit CurrentPeriodUpdated(_lastUpdatedPeriod, period); + _lastUpdatedPeriod = period; } diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index f9390ed5..b9ba4536 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -33,6 +33,7 @@ import { MockValidatorContract_OnlyTiming_ForHardhatTest } from import { PauseEnforcer } from "@ronin/contracts/ronin/gateway/PauseEnforcer.sol"; import { IPauseTarget } from "@ronin/contracts/interfaces/IPauseTarget.sol"; import { GatewayV3 } from "@ronin/contracts/extensions/GatewayV3.sol"; +import { IBridgeManagerCallbackRegister } from "@ronin/contracts/interfaces/bridge/IBridgeManagerCallbackRegister.sol"; import { RoninBridgeManagerDeploy } from "@ronin/script/contracts/RoninBridgeManagerDeploy.s.sol"; import { RoninGatewayV3Deploy } from "@ronin/script/contracts/RoninGatewayV3Deploy.s.sol"; @@ -149,7 +150,7 @@ contract BaseIntegration_Test is Base_Test { function _initializeRonin() internal { _config.switchTo(Network.RoninLocal.key()); - _validatorSet.setCurrentPeriod(block.timestamp / 1 days); + _validatorSet.setCurrentPeriod(block.timestamp / _validatorSet.PERIOD_DURATION() - 2); _bridgeRewardInitialize(); _bridgeTrackingInitialize(); @@ -350,6 +351,26 @@ contract BaseIntegration_Test is Base_Test { vm.prank(_param.roninBridgeManager.governors[0]); _roninBridgeManager.proposeGlobalProposalStructAndCastVotes(globalProposal, supports_, signatures); } + + { + // set callback register + bytes memory calldata_ = + abi.encodeCall(IBridgeManagerCallbackRegister.registerCallbacks, (param.callbackRegisters)); + GlobalProposal.GlobalProposalDetail memory globalProposal = _roninProposalUtils.createGlobalProposal({ + expiryTimestamp: block.timestamp + 10, + targetOption: GlobalProposal.TargetOption.BridgeManager, + value: 0, + calldata_: calldata_, + gasAmount: 500_000, + nonce: _roninNonce++ + }); + + SignatureConsumer.Signature[] memory signatures = + _roninProposalUtils.generateSignaturesGlobal(globalProposal, _param.test.governorPKs); + + vm.prank(_param.roninBridgeManager.governors[0]); + _roninBridgeManager.proposeGlobalProposalStructAndCastVotes(globalProposal, supports_, signatures); + } } function _constructForMainchainBridgeManager() internal { @@ -525,12 +546,15 @@ contract BaseIntegration_Test is Base_Test { function _wrapUpEpoch() internal { uint256 multiplier = _validatorSet.numberOfBlocksInEpoch(); - console.log(block.number); + console.log("Before roll block.number: ", block.number); - vm.roll((block.number / multiplier + 1) * (multiplier) - 1); + vm.roll((block.number / multiplier + 1) * multiplier - 1); + console.log("After roll block.number: ", block.number); vm.prank(block.coinbase); + console.log("Before wrap up", _validatorSet.currentPeriod()); _validatorSet.wrapUpEpoch(); + console.log("After wrap up", _validatorSet.currentPeriod()); } function _setTimestampToPeriodEnding() internal { diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index 6e121e32..907554ba 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -89,9 +89,9 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { } function test_bulkDeposit_100Txs() public { + _setTimestampToPeriodEnding(); _wrapUpEpochAndMine(); _wrapUpEpochAndMine(); - _setTimestampToPeriodEnding(); vm.deal(address(_bridgeReward), 10 ether); address newBridgeOperator = makeAddr("new-bridge-operator"); @@ -124,6 +124,7 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { vm.prank(_param.roninBridgeManager.governors[0]); _roninBridgeManager.updateBridgeOperator(newBridgeOperator); + _param.roninBridgeManager.bridgeOperators[0] = newBridgeOperator; for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { @@ -131,9 +132,9 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { _roninGatewayV3.tryBulkDepositFor(second50Receipts); } + _setTimestampToPeriodEnding(); _wrapUpEpochAndMine(); _wrapUpEpochAndMine(); - _setTimestampToPeriodEnding(); sampleReceipt.id = 101; From 30b4d1be17ac6c8afe2db7608935e70d750a0d65 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 27 Jan 2024 18:42:37 +0700 Subject: [PATCH 10/18] chore: contract sizes --- logs/contract-code-sizes.log | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index a3a076f8..4c5b215a 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -44,7 +44,7 @@ | MockRoninBridgeManager | 24.601 | -0.025 | | MockRoninGatewayV3Extended | 20.048 | 4.528 | | MockTUint256Slot | 2.73 | 21.846 | -| MockValidatorContract_OnlyTiming_ForHardhatTest | 1.063 | 23.513 | +| MockValidatorContract_OnlyTiming_ForHardhatTest | 1.06 | 23.516 | | MockValidatorSet_ForFoundryTest | 0.172 | 24.404 | | MockWrappedToken | 2.225 | 22.351 | | PRBMathUtils | 0.063 | 24.513 | From 1ad9cff1aee7d93c5c810cca8bd2642991ebec10 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 27 Jan 2024 19:06:44 +0700 Subject: [PATCH 11/18] test: fix nonce --- test/bridge/integration/BaseIntegration.t.sol | 33 ++++++++++++++----- ...oteBridgeOperator.RoninBridgeManager.t.sol | 6 ++-- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index b9ba4536..9737356e 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -86,9 +86,6 @@ contract BaseIntegration_Test is Base_Test { RoninBridgeAdminUtils _roninProposalUtils; ProposalUtils _mainchainProposalUtils; - uint256 _roninNonce = 1; - uint256 _mainchainNonce = 1; - function setUp() public virtual { _deployGeneralConfig(); @@ -325,7 +322,7 @@ contract BaseIntegration_Test is Base_Test { value: 0, calldata_: abi.encodeCall(GlobalCoreGovernance.updateManyTargetOption, (param.targetOptions, param.targets)), gasAmount: 500_000, - nonce: _roninNonce++ + nonce: _roninBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = @@ -342,7 +339,7 @@ contract BaseIntegration_Test is Base_Test { value: 0, calldata_: abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE, param.bridgeContract)), gasAmount: 500_000, - nonce: _roninNonce++ + nonce: _roninBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = @@ -362,7 +359,7 @@ contract BaseIntegration_Test is Base_Test { value: 0, calldata_: calldata_, gasAmount: 500_000, - nonce: _roninNonce++ + nonce: _roninBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = @@ -400,7 +397,7 @@ contract BaseIntegration_Test is Base_Test { value: 0, calldata_: abi.encodeCall(GlobalCoreGovernance.updateManyTargetOption, (param.targetOptions, param.targets)), gasAmount: 500_000, - nonce: _mainchainNonce++ + nonce: _mainchainBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = @@ -417,7 +414,27 @@ contract BaseIntegration_Test is Base_Test { value: 0, calldata_: abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE, param.bridgeContract)), gasAmount: 500_000, - nonce: _mainchainNonce++ + nonce: _mainchainBridgeManager.round(0) + 1 + }); + + SignatureConsumer.Signature[] memory signatures = + _mainchainProposalUtils.generateSignaturesGlobal(globalProposal, _param.test.governorPKs); + + vm.prank(_param.roninBridgeManager.governors[0]); + _mainchainBridgeManager.relayGlobalProposal(globalProposal, supports_, signatures); + } + + { + // set callback register + bytes memory calldata_ = + abi.encodeCall(IBridgeManagerCallbackRegister.registerCallbacks, (param.callbackRegisters)); + GlobalProposal.GlobalProposalDetail memory globalProposal = _mainchainProposalUtils.createGlobalProposal({ + expiryTimestamp: block.timestamp + 10, + targetOption: GlobalProposal.TargetOption.BridgeManager, + value: 0, + calldata_: calldata_, + gasAmount: 500_000, + nonce: _mainchainBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = diff --git a/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol b/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol index 4bc604b3..0b831b4c 100644 --- a/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol +++ b/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol @@ -62,8 +62,8 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { targetOption: GlobalProposal.TargetOption.BridgeManager, value: 0, calldata_: abi.encodeCall(IBridgeManager.addBridgeOperators, (_voteWeights, _addingGovernors, _addingOperators)), - gasAmount: 500_000, - nonce: _roninNonce++ + gasAmount: 1_000_000, + nonce: _roninBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = @@ -125,7 +125,7 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { value: 0, calldata_: abi.encodeCall(IBridgeManager.addBridgeOperators, (_voteWeights, _addingGovernors, _addingOperators)), gasAmount: 200_000 * numAddingOperators, - nonce: _roninNonce++ + nonce: _roninBridgeManager.round(0) + 1 }); SignatureConsumer.Signature[] memory signatures = From 8a37936730849383ad004f8ebbe22382c091b95e Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 27 Jan 2024 19:43:18 +0700 Subject: [PATCH 12/18] test(PauseEnforcer): test configurations --- .../set-config/setConfig.PauseEnforcer.t.sol | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol diff --git a/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol new file mode 100644 index 00000000..e9bde218 --- /dev/null +++ b/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol"; +import { ContractType } from "@ronin/contracts/utils/ContractType.sol"; +import "../../BaseIntegration.t.sol"; + +contract SetConfig_PauseEnforcer_Test is BaseIntegration_Test { + function setUp() public virtual override { + super.setUp(); + _config.switchTo(Network.RoninLocal.key()); + } + + function test_configPauseEnforcerContract() public { + address pauseEnforcer = _roninGatewayV3.emergencyPauser(); + assertEq(pauseEnforcer, address(_roninPauseEnforcer)); + } + + function test_configBridgeContract() public { + address bridgeContract = address(_roninPauseEnforcer.target()); + + assertEq(bridgeContract, address(_roninGatewayV3)); + } + + function test_sentryEnforcerRole() public { + bool isSentryRole = + _roninPauseEnforcer.hasRole(_roninPauseEnforcer.SENTRY_ROLE(), _param.roninPauseEnforcer.sentries[0]); + + assertEq(isSentryRole, true); + } +} From 85635da922f4ec71d033070048947c78ecc765be Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sun, 28 Jan 2024 13:02:41 +0700 Subject: [PATCH 13/18] test(PauseEnforcer): done test --- test/bridge/integration/BaseIntegration.t.sol | 40 +++---- .../accessControl.PauseEnforcer.t.sol | 31 +++++ .../emergencyAction.PauseEnforcer.t.sol | 88 ++++++++++++++ .../set-config/normalPause.GatewayV3.t.sol | 61 ++++++++++ .../depositVote.RoninGatewayV3.t.sol | 4 - test/helpers/MainchainBridgeAdminUtils.t.sol | 113 ++++++++++++++++++ test/helpers/ProposalUtils.t.sol | 2 +- 7 files changed, 314 insertions(+), 25 deletions(-) create mode 100644 test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol create mode 100644 test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol create mode 100644 test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol create mode 100644 test/helpers/MainchainBridgeAdminUtils.t.sol diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 9737356e..47b1495d 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -51,8 +51,8 @@ import { AXSDeploy } from "@ronin/script/contracts/token/AXSDeploy.s.sol"; import { SLPDeploy } from "@ronin/script/contracts/token/SLPDeploy.s.sol"; import { USDCDeploy } from "@ronin/script/contracts/token/USDCDeploy.s.sol"; -import { ProposalUtils } from "test/helpers/ProposalUtils.t.sol"; import { RoninBridgeAdminUtils } from "test/helpers/RoninBridgeAdminUtils.t.sol"; +import { MainchainBridgeAdminUtils } from "test/helpers/MainchainBridgeAdminUtils.t.sol"; contract BaseIntegration_Test is Base_Test { IGeneralConfig _config; @@ -84,7 +84,7 @@ contract BaseIntegration_Test is Base_Test { MockValidatorContract_OnlyTiming_ForHardhatTest _validatorSet; RoninBridgeAdminUtils _roninProposalUtils; - ProposalUtils _mainchainProposalUtils; + MainchainBridgeAdminUtils _mainchainProposalUtils; function setUp() public virtual { _deployGeneralConfig(); @@ -100,6 +100,8 @@ contract BaseIntegration_Test is Base_Test { _configEmergencyPauserForRoninGateway(); _configEmergencyPauserForMainchainGateway(); + + _configBridgeTrackingForRoninGateway(); } function _deployContractsOnRonin() internal { @@ -141,7 +143,12 @@ contract BaseIntegration_Test is Base_Test { _mainchainUsdc = new USDCDeploy().run(); _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); - _mainchainProposalUtils = new ProposalUtils(_param.test.roninChainId, _param.test.governorPKs); + _mainchainProposalUtils = new MainchainBridgeAdminUtils( + _param.test.roninChainId, + _param.test.governorPKs, + _mainchainBridgeManager, + _param.mainchainBridgeManager.governors[0] + ); } function _initializeRonin() internal { @@ -528,24 +535,17 @@ contract BaseIntegration_Test is Base_Test { _config.switchTo(Network.EthLocal.key()); bytes memory calldata_ = abi.encodeCall(GatewayV3.setEmergencyPauser, (address(_mainchainPauseEnforcer))); - Proposal.ProposalDetail memory proposal = _mainchainProposalUtils.createProposal({ - expiryTimestamp: block.timestamp + 1 minutes, - target: address(_mainchainGatewayV3), - value: 0, - calldata_: calldata_, - gasAmount: 1_000_000, - nonce: _mainchainBridgeManager.round(_param.test.mainchainChainId) + 1 - }); - - SignatureConsumer.Signature[] memory signatures = _mainchainProposalUtils.generateSignatures(proposal); - - Ballot.VoteType[] memory voteTypes = new Ballot.VoteType[](signatures.length); - for (uint256 i; i < signatures.length; i++) { - voteTypes[i] = Ballot.VoteType.For; - } + _mainchainProposalUtils.functionDelegateCall(address(_mainchainGatewayV3), calldata_); + } - vm.prank(_param.mainchainBridgeManager.governors[0]); - _mainchainBridgeManager.relayProposal(proposal, voteTypes, signatures); + function _configBridgeTrackingForRoninGateway() internal { + _config.switchTo(Network.RoninLocal.key()); + + bytes memory calldata_ = + abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE_TRACKING, address(_bridgeTracking))); + _roninProposalUtils.functionDelegateCall(address(_roninGatewayV3), calldata_); + + _config.switchTo(Network.EthLocal.key()); } function _deployGeneralConfig() internal { diff --git a/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol new file mode 100644 index 00000000..250529ba --- /dev/null +++ b/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "../../BaseIntegration.t.sol"; + +contract AccessControl_PauseEnforcer_Test is BaseIntegration_Test { + function setUp() public virtual override { + super.setUp(); + _config.switchTo(Network.RoninLocal.key()); + } + + function test_changeAdmin_OfPauseEnforcer() public { + address newEnforcerAdmin = makeAddr("new-enforcer-admin"); + + vm.prank(_param.roninPauseEnforcer.admin); + _roninPauseEnforcer.grantRole(0x0, newEnforcerAdmin); + + assertEq(_roninPauseEnforcer.hasRole(0x0, newEnforcerAdmin), true); + } + + function test_renounceAdminRole_PreviousAdmin() public { + test_changeAdmin_OfPauseEnforcer(); + + assertEq(_roninPauseEnforcer.hasRole(0x0, _param.roninPauseEnforcer.admin), true); + + vm.prank(_param.roninPauseEnforcer.admin); + _roninPauseEnforcer.renounceRole(0x0, _param.roninPauseEnforcer.admin); + + assertEq(_roninPauseEnforcer.hasRole(0x0, _param.roninPauseEnforcer.admin), false); + } +} diff --git a/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol new file mode 100644 index 00000000..04126e76 --- /dev/null +++ b/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { Transfer } from "@ronin/contracts/libraries/Transfer.sol"; +import { GatewayV3 } from "@ronin/contracts/extensions/GatewayV3.sol"; +import "../../BaseIntegration.t.sol"; + +contract EmergencyAction_PauseEnforcer_Test is BaseIntegration_Test { + error ErrTargetIsNotOnPaused(); + + function setUp() public virtual override { + super.setUp(); + } + + // Should be able to emergency pause + function test_EmergencyPause_RoninGatewayV3() public { + _config.switchTo(Network.RoninLocal.key()); + vm.prank(_param.roninPauseEnforcer.sentries[0]); + _roninPauseEnforcer.triggerPause(); + + assertEq(_roninPauseEnforcer.emergency(), true); + assertEq(_roninGatewayV3.paused(), true); + } + + // Should the gateway cannot interacted when on pause + function test_RevertWhen_InteractWithGateway_AfterPause() public { + test_EmergencyPause_RoninGatewayV3(); + Transfer.Receipt memory receipt = Transfer.Receipt({ + id: 0, + kind: Transfer.Kind.Deposit, + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), + mainchain: Token.Owner({ + addr: makeAddr("requester"), + tokenAddr: address(_mainchainWeth), + chainId: _param.test.mainchainChainId + }), + info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) + }); + + vm.expectRevert("Pausable: paused"); + + _roninGatewayV3.depositFor(receipt); + } + + // Should not be able to emergency pause for a second time + function test_RevertWhen_PauseAgain() public { + test_EmergencyPause_RoninGatewayV3(); + + vm.expectRevert(ErrTargetIsNotOnPaused.selector); + + vm.prank(_param.roninPauseEnforcer.sentries[0]); + _roninPauseEnforcer.triggerPause(); + } + + // Should be able to emergency unpause + function test_EmergencyUnpause_RoninGatewayV3() public { + test_EmergencyPause_RoninGatewayV3(); + + vm.prank(_param.roninPauseEnforcer.sentries[0]); + _roninPauseEnforcer.triggerUnpause(); + + assertEq(_roninPauseEnforcer.emergency(), false); + assertEq(_roninGatewayV3.paused(), false); + } + + // Should the gateway can be interacted after unpause + function test_InteractWithGateway_AfterUnpause() public { + test_EmergencyUnpause_RoninGatewayV3(); + Transfer.Receipt memory receipt = Transfer.Receipt({ + id: 0, + kind: Transfer.Kind.Deposit, + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), + mainchain: Token.Owner({ + addr: makeAddr("requester"), + tokenAddr: address(_mainchainWeth), + chainId: _param.test.mainchainChainId + }), + info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) + }); + + uint256 numOperatorsForVoteExecuted = + _param.roninBridgeManager.bridgeOperators.length * _param.roninBridgeManager.num / _param.roninBridgeManager.denom; + for (uint256 i; i < numOperatorsForVoteExecuted; i++) { + vm.prank(_param.roninBridgeManager.bridgeOperators[i]); + _roninGatewayV3.depositFor(receipt); + } + } +} diff --git a/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol b/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol new file mode 100644 index 00000000..77a3cb9a --- /dev/null +++ b/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { Transfer } from "@ronin/contracts/libraries/Transfer.sol"; +import { GatewayV3 } from "@ronin/contracts/extensions/GatewayV3.sol"; +import "../../BaseIntegration.t.sol"; + +contract NormalPause_GatewayV3_Test is BaseIntegration_Test { + error ErrNotOnEmergencyPause(); + error ErrTargetIsNotOnPaused(); + + function setUp() public virtual override { + super.setUp(); + _config.switchTo(Network.RoninLocal.key()); + } + + // Should gateway admin can pause the gateway through voting + function test_GovernanceAdmin_PauseGateway_ThroughoutVoting() public { + bytes memory calldata_ = abi.encodeCall(GatewayV3.pause, ()); + _roninProposalUtils.functionDelegateCall(address(_roninGatewayV3), calldata_); + + assertEq(_roninPauseEnforcer.emergency(), false); + assertEq(_roninGatewayV3.paused(), true); + } + + // Should not be able to emergency unpause + function test_RevertWhen_EmergencyUnpause() public { + test_GovernanceAdmin_PauseGateway_ThroughoutVoting(); + + vm.expectRevert(ErrNotOnEmergencyPause.selector); + + vm.prank(_param.roninPauseEnforcer.sentries[0]); + _roninPauseEnforcer.triggerUnpause(); + } + + // Should not be able to override by emergency pause and emergency unpause + function test_RevertWhen_OverrideByEmergencyPauseOrUnPause() public { + test_GovernanceAdmin_PauseGateway_ThroughoutVoting(); + + vm.expectRevert(ErrTargetIsNotOnPaused.selector); + + vm.prank(_param.roninPauseEnforcer.sentries[0]); + _roninPauseEnforcer.triggerPause(); + + vm.expectRevert(ErrNotOnEmergencyPause.selector); + + vm.prank(_param.roninPauseEnforcer.sentries[0]); + _roninPauseEnforcer.triggerUnpause(); + } + + // Should gateway admin can unpause the gateway through voting + function test_GovernanceAdmin_UnPauseGateway_ThroughoutVoting() public { + test_GovernanceAdmin_PauseGateway_ThroughoutVoting(); + + bytes memory calldata_ = abi.encodeCall(GatewayV3.unpause, ()); + _roninProposalUtils.functionDelegateCall(address(_roninGatewayV3), calldata_); + + assertEq(_roninPauseEnforcer.emergency(), false); + assertEq(_roninGatewayV3.paused(), false); + } +} diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index 907554ba..b6da50d5 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -22,10 +22,6 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { super.setUp(); _config.switchTo(Network.RoninLocal.key()); - bytes memory calldata_ = - abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE_TRACKING, address(_bridgeTracking))); - _roninProposalUtils.functionDelegateCallGlobal(GlobalProposal.TargetOption.GatewayContract, calldata_); - vm.etch(address(_roninGatewayV3), address(new MockRoninGatewayV3Extended()).code); Transfer.Receipt memory receipt = Transfer.Receipt({ diff --git a/test/helpers/MainchainBridgeAdminUtils.t.sol b/test/helpers/MainchainBridgeAdminUtils.t.sol new file mode 100644 index 00000000..1d02105a --- /dev/null +++ b/test/helpers/MainchainBridgeAdminUtils.t.sol @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import { MainchainBridgeManager } from "@ronin/contracts/mainchain/MainchainBridgeManager.sol"; +import "./ProposalUtils.t.sol"; + +contract MainchainBridgeAdminUtils is ProposalUtils { + MainchainBridgeManager _contract; + address _sender; + + constructor(uint256 roninChainId, uint256[] memory signerPKs, MainchainBridgeManager contract_, address sender) + ProposalUtils(roninChainId, signerPKs) + { + _contract = contract_; + _sender = sender; + } + + function defaultExpiryTimestamp() public view returns (uint256) { + return block.timestamp + 10; + } + + function functionDelegateCall(address to, bytes memory data) public { + Proposal.ProposalDetail memory proposal = this.createProposal({ + expiryTimestamp: this.defaultExpiryTimestamp(), + target: to, + value: 0, + calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), + gasAmount: 2_000_000, + nonce: _contract.round(_roninChainId) + 1 + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignatures(proposal); + uint256 length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.relayProposal(proposal, supports_, signatures); + } + + function functionDelegateCallGlobal(GlobalProposal.TargetOption target, bytes memory data) public { + GlobalProposal.GlobalProposalDetail memory proposal = this.createGlobalProposal({ + expiryTimestamp: this.defaultExpiryTimestamp(), + targetOption: target, + value: 0, + calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), + gasAmount: 2_000_000, + nonce: _contract.round(0) + 1 + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); + uint256 length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.relayGlobalProposal(proposal, supports_, signatures); + } + + function functionDelegateCallsGlobal(GlobalProposal.TargetOption[] memory targetOptions, bytes[] memory datas) public { + uint256 length = targetOptions.length; + if (length != datas.length || length == 0) revert("Invalid length"); + + bytes[] memory calldatas = new bytes[](length); + uint256[] memory values = new uint256[](length); + uint256[] memory gasAmounts = new uint256[](length); + for (uint256 i; i < length; i++) { + calldatas[i] = abi.encodeWithSignature("functionDelegateCall(bytes)", datas[i]); + values[i] = 0; + gasAmounts[i] = 2_000_000; + } + + GlobalProposal.GlobalProposalDetail memory proposal = GlobalProposal.GlobalProposalDetail({ + nonce: _contract.round(0) + 1, + expiryTimestamp: this.defaultExpiryTimestamp(), + targetOptions: targetOptions, + values: values, + calldatas: calldatas, + gasAmounts: gasAmounts + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); + length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.relayGlobalProposal(proposal, supports_, signatures); + } + + function upgradeGlobal(GlobalProposal.TargetOption targetOption, uint256 nonce, bytes memory data) public { + GlobalProposal.GlobalProposalDetail memory proposal = this.createGlobalProposal({ + expiryTimestamp: this.defaultExpiryTimestamp(), + targetOption: targetOption, + value: 0, + calldata_: abi.encodeWithSignature("upgradeTo(bytes)", data), + gasAmount: 2_000_000, + nonce: nonce + }); + + SignatureConsumer.Signature[] memory signatures = this.generateSignaturesGlobal(proposal); + uint256 length = signatures.length; + Ballot.VoteType[] memory supports_ = new Ballot.VoteType[](length); + for (uint256 i; i < length; i++) { + supports_[i] = Ballot.VoteType.For; + } + vm.prank(_sender); + _contract.relayGlobalProposal(proposal, supports_, signatures); + } +} diff --git a/test/helpers/ProposalUtils.t.sol b/test/helpers/ProposalUtils.t.sol index d5667a2d..ef504c8b 100644 --- a/test/helpers/ProposalUtils.t.sol +++ b/test/helpers/ProposalUtils.t.sol @@ -38,7 +38,7 @@ contract ProposalUtils is Utils, Test { ) public view returns (Proposal.ProposalDetail memory proposal) { proposal = Proposal.ProposalDetail({ nonce: nonce, - chainId: _roninChainId, + chainId: block.chainid, expiryTimestamp: expiryTimestamp, targets: wrapAddress(target), values: wrapUint(value), From f86178223a61b54ae707a8f369f761e585245628 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Mon, 29 Jan 2024 10:01:05 +0700 Subject: [PATCH 14/18] chore: contract-code-sizes --- logs/contract-code-sizes.log | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index 4c5b215a..ced47400 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -51,7 +51,7 @@ | PauseEnforcer | 4.548 | 20.028 | | Proposal | 0.166 | 24.41 | | ProxyAdmin | 1.684 | 22.892 | -| RoninBridgeManager | 24.601 | -0.025 | +| RoninBridgeManager | 24.72 | -0.144 | | RoninGatewayV3 | 19.765 | 4.811 | | StdStyle | 0.086 | 24.49 | | StorageSlot | 0.086 | 24.49 | From 94e848234f83a90fa74162450ee218da9b2e7ac4 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Fri, 2 Feb 2024 11:37:52 +0700 Subject: [PATCH 15/18] chore: remove update operator test --- test/bridge/integration/BaseIntegration.t.sol | 5 -- .../integration/bridge-tracking/.gitkeep | 0 .../depositVote.RoninGatewayV3.t.sol | 58 ------------------- 3 files changed, 63 deletions(-) delete mode 100644 test/bridge/integration/bridge-tracking/.gitkeep diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 47b1495d..0e6f875e 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -563,15 +563,10 @@ contract BaseIntegration_Test is Base_Test { function _wrapUpEpoch() internal { uint256 multiplier = _validatorSet.numberOfBlocksInEpoch(); - console.log("Before roll block.number: ", block.number); - vm.roll((block.number / multiplier + 1) * multiplier - 1); - console.log("After roll block.number: ", block.number); vm.prank(block.coinbase); - console.log("Before wrap up", _validatorSet.currentPeriod()); _validatorSet.wrapUpEpoch(); - console.log("After wrap up", _validatorSet.currentPeriod()); } function _setTimestampToPeriodEnding() internal { diff --git a/test/bridge/integration/bridge-tracking/.gitkeep b/test/bridge/integration/bridge-tracking/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index b6da50d5..f0e13164 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -15,8 +15,6 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { Transfer.Receipt[] _depositReceipts; uint256 _numOperatorsForVoteExecuted; - Transfer.Receipt[] first50Receipts; - Transfer.Receipt[] second50Receipts; function setUp() public virtual override { super.setUp(); @@ -83,60 +81,4 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { assertEq(totalWeight, (_numOperatorsForVoteExecuted) * 100); } } - - function test_bulkDeposit_100Txs() public { - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); - _wrapUpEpochAndMine(); - - vm.deal(address(_bridgeReward), 10 ether); - address newBridgeOperator = makeAddr("new-bridge-operator"); - Transfer.Receipt memory sampleReceipt = Transfer.Receipt({ - id: 0, - kind: Transfer.Kind.Deposit, - ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), - mainchain: Token.Owner({ - addr: makeAddr("requester"), - tokenAddr: address(_mainchainWeth), - chainId: _param.test.mainchainChainId - }), - info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) - }); - - uint256 id = 1; - for (uint256 i; i < 50; i++) { - first50Receipts.push(sampleReceipt); - second50Receipts.push(sampleReceipt); - first50Receipts[i].id = id; - second50Receipts[i].id = id + 50; - - id++; - } - - for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { - vm.prank(_param.roninBridgeManager.bridgeOperators[i]); - _roninGatewayV3.tryBulkDepositFor(first50Receipts); - } - - vm.prank(_param.roninBridgeManager.governors[0]); - _roninBridgeManager.updateBridgeOperator(newBridgeOperator); - - _param.roninBridgeManager.bridgeOperators[0] = newBridgeOperator; - - for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { - vm.prank(_param.roninBridgeManager.bridgeOperators[i]); - _roninGatewayV3.tryBulkDepositFor(second50Receipts); - } - - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); - _wrapUpEpochAndMine(); - - sampleReceipt.id = 101; - - for (uint256 i; i < _numOperatorsForVoteExecuted; i++) { - vm.prank(_param.roninBridgeManager.bridgeOperators[i]); - _roninGatewayV3.depositFor(sampleReceipt); - } - } } From a6f390ab7ea9284ab0a258371810c599d9ed9c08 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Fri, 2 Feb 2024 11:41:49 +0700 Subject: [PATCH 16/18] fix: add contract-code-sizes --- logs/contract-code-sizes.log | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index ced47400..4c5b215a 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -51,7 +51,7 @@ | PauseEnforcer | 4.548 | 20.028 | | Proposal | 0.166 | 24.41 | | ProxyAdmin | 1.684 | 22.892 | -| RoninBridgeManager | 24.72 | -0.144 | +| RoninBridgeManager | 24.601 | -0.025 | | RoninGatewayV3 | 19.765 | 4.811 | | StdStyle | 0.086 | 24.49 | | StorageSlot | 0.086 | 24.49 | From 5877a8644e3e7b9ba09e63efd77e860de20b0a43 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Fri, 2 Feb 2024 17:18:06 +0700 Subject: [PATCH 17/18] test: remove 2 local chains --- .github/workflows/test.yml | 2 - foundry.toml | 3 - script/GeneralConfig.sol | 22 +------ script/Migration.s.sol | 15 ++--- script/interfaces/ISharedArgument.sol | 2 - script/utils/Network.sol | 16 +---- test/bridge/integration/BaseIntegration.t.sol | 65 ++++++++----------- ...oteBridgeOperator.RoninBridgeManager.t.sol | 7 -- .../setConfig.MainchainManager.t.sol | 1 - .../setConfig.RoninBridgeManager.t.sol | 1 - ...IsApprovedInLastEpoch.BridgeTracking.t.sol | 42 ++++++------ ...otApprovedInLastEpoch.BridgeTracking.t.sol | 12 ++-- .../submitWithdrawal.MainchainGatewayV3.t.sol | 5 +- .../accessControl.PauseEnforcer.t.sol | 1 - .../emergencyAction.PauseEnforcer.t.sol | 17 ++--- .../set-config/normalPause.GatewayV3.t.sol | 1 - .../set-config/setConfig.PauseEnforcer.t.sol | 1 - .../depositVote.RoninGatewayV3.t.sol | 9 +-- test/helpers/MainchainBridgeAdminUtils.t.sol | 6 +- test/helpers/ProposalUtils.t.sol | 10 ++- test/helpers/RoninBridgeAdminUtils.t.sol | 6 +- 21 files changed, 79 insertions(+), 165 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e2b4e56..ad49e528 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -42,7 +42,5 @@ jobs: - name: Run Forge tests run: | - anvil --chain-id 2024 --port 8546 --block-time 3 & - anvil --chain-id 2 --port 8547 --block-time 3 & forge test -vvv id: test diff --git a/foundry.toml b/foundry.toml index e20e1029..f72d3fc2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -52,6 +52,3 @@ ethereum = "https://eth.llamarpc.com" goerli = "https://ethereum-goerli.publicnode.com" ronin-mainnet = "https://api-partner.roninchain.com/rpc" ronin-testnet = "https://saigon-archive.roninchain.com/rpc" - -ronin-local = "http://localhost:8546" -ethereum-local = "http://localhost:8547" diff --git a/script/GeneralConfig.sol b/script/GeneralConfig.sol index 57895eb2..0d85a792 100644 --- a/script/GeneralConfig.sol +++ b/script/GeneralConfig.sol @@ -36,24 +36,6 @@ contract GeneralConfig is BaseGeneralConfig, Utils { Network.RoninDevnet.envLabel(), Network.RoninDevnet.explorer() ); - - setNetworkInfo( - Network.RoninLocal.chainId(), - Network.RoninLocal.key(), - Network.RoninLocal.chainAlias(), - Network.RoninLocal.deploymentDir(), - Network.RoninLocal.envLabel(), - Network.RoninLocal.explorer() - ); - - setNetworkInfo( - Network.EthLocal.chainId(), - Network.EthLocal.key(), - Network.EthLocal.chainAlias(), - Network.EthLocal.deploymentDir(), - Network.EthLocal.envLabel(), - Network.EthLocal.explorer() - ); } function _setUpContracts() internal virtual override { @@ -82,8 +64,8 @@ contract GeneralConfig is BaseGeneralConfig, Utils { function getSender() public view virtual override returns (address payable sender) { sender = _option.trezor ? payable(_trezorSender) : payable(_envSender); - bool isLocalNetwork = getCurrentNetwork() == DefaultNetwork.Local.key() - || getCurrentNetwork() == Network.RoninLocal.key() || getCurrentNetwork() == Network.EthLocal.key(); + bool isLocalNetwork = getCurrentNetwork() == DefaultNetwork.Local.key(); + if (sender == address(0x0) && isLocalNetwork) sender = payable(DEFAULT_SENDER); require(sender != address(0x0), "GeneralConfig: Sender is address(0x0)"); } diff --git a/script/Migration.s.sol b/script/Migration.s.sol index 6fd4ff13..c77df0a1 100644 --- a/script/Migration.s.sol +++ b/script/Migration.s.sol @@ -26,13 +26,11 @@ contract Migration is BaseMigrationV2, Utils { // Undefined } else if (network() == DefaultNetwork.RoninTestnet.key()) { // Undefined - } else if (network() == Network.RoninLocal.key() || network() == Network.EthLocal.key()) { + } else if (network() == DefaultNetwork.Local.key()) { // test param.test.numberOfBlocksInEpoch = 200; param.test.proxyAdmin = makeAddr("proxy-admin"); param.test.dposGA = makeAddr("governance-admin"); - param.test.mainchainChainId = Network.EthLocal.chainId(); - param.test.roninChainId = Network.RoninLocal.chainId(); // tokens param.weth.name = "Wrapped WETH"; @@ -95,7 +93,7 @@ contract Migration is BaseMigrationV2, Utils { param.roninBridgeManager.num = 2; param.roninBridgeManager.denom = 4; param.roninBridgeManager.roninChainId = 0; - param.roninBridgeManager.roninChainId = param.test.roninChainId; + param.roninBridgeManager.roninChainId = block.chainid; param.roninBridgeManager.expiryDuration = 60 * 60 * 24 * 14; // 14 days param.roninBridgeManager.bridgeOperators = operatorAddrs; param.roninBridgeManager.governors = governorAddrs; @@ -108,7 +106,7 @@ contract Migration is BaseMigrationV2, Utils { param.mainchainPauseEnforcer.sentries = wrapAddress(makeAddr("pause-enforcer-sentry")); // Mainchain Gateway V3 - param.mainchainGatewayV3.roninChainId = param.test.roninChainId; + param.mainchainGatewayV3.roninChainId = block.chainid; param.mainchainGatewayV3.numerator = 1; param.mainchainGatewayV3.highTierVWNumerator = 10; param.mainchainGatewayV3.denominator = 10; @@ -117,14 +115,12 @@ contract Migration is BaseMigrationV2, Utils { param.mainchainBridgeManager.num = 2; param.mainchainBridgeManager.denom = 4; param.mainchainBridgeManager.roninChainId = 0; - param.mainchainBridgeManager.roninChainId = param.test.roninChainId; + param.mainchainBridgeManager.roninChainId = block.chainid; param.mainchainBridgeManager.bridgeOperators = operatorAddrs; param.mainchainBridgeManager.governors = governorAddrs; param.mainchainBridgeManager.voteWeights = voteWeights; param.mainchainBridgeManager.targetOptions = options; param.mainchainBridgeManager.targets = targets; - } else if (network() == DefaultNetwork.Local.key()) { - // Undefined } else { revert("Migration: Network Unknown Shared Parameters Unimplemented!"); } @@ -133,8 +129,7 @@ contract Migration is BaseMigrationV2, Utils { } function _getProxyAdmin() internal virtual override returns (address payable) { - bool isLocalNetwork = network() == DefaultNetwork.Local.key() || network() == Network.RoninLocal.key() - || network() == Network.EthLocal.key(); + bool isLocalNetwork = network() == DefaultNetwork.Local.key(); return isLocalNetwork ? payable(config.sharedArguments().test.proxyAdmin) : super._getProxyAdmin(); } } diff --git a/script/interfaces/ISharedArgument.sol b/script/interfaces/ISharedArgument.sol index ef5b215c..6ae10e68 100644 --- a/script/interfaces/ISharedArgument.sol +++ b/script/interfaces/ISharedArgument.sol @@ -97,8 +97,6 @@ interface ISharedArgument is IGeneralConfig { address proxyAdmin; uint256 numberOfBlocksInEpoch; address dposGA; - uint256 mainchainChainId; - uint256 roninChainId; uint256[] operatorPKs; uint256[] governorPKs; } diff --git a/script/utils/Network.sol b/script/utils/Network.sol index b98bd445..9eda031a 100644 --- a/script/utils/Network.sol +++ b/script/utils/Network.sol @@ -6,9 +6,7 @@ import { LibString, TNetwork } from "foundry-deployment-kit/types/Types.sol"; enum Network { Goerli, EthMainnet, - RoninDevnet, - RoninLocal, - EthLocal + RoninDevnet } using { key, name, chainId, chainAlias, envLabel, deploymentDir, explorer } for Network global; @@ -17,8 +15,6 @@ function chainId(Network network) pure returns (uint256) { if (network == Network.Goerli) return 5; if (network == Network.EthMainnet) return 1; if (network == Network.RoninDevnet) return 2022; - if (network == Network.RoninLocal) return 2024; - if (network == Network.EthLocal) return 2; revert("Network: Unknown chain id"); } @@ -36,8 +32,6 @@ function name(Network network) pure returns (string memory) { if (network == Network.Goerli) return "Goerli"; if (network == Network.RoninDevnet) return "RoninDevnet"; if (network == Network.EthMainnet) return "EthMainnet"; - if (network == Network.RoninLocal) return "RoninLocal"; - if (network == Network.EthLocal) return "EthLocal"; revert("Network: Unknown network name"); } @@ -46,8 +40,6 @@ function deploymentDir(Network network) pure returns (string memory) { if (network == Network.Goerli) return "goerli/"; if (network == Network.EthMainnet) return "ethereum/"; if (network == Network.RoninDevnet) return "ronin-devnet/"; - if (network == Network.RoninLocal) return ""; - if (network == Network.EthLocal) return ""; revert("Network: Unknown network deployment directory"); } @@ -56,8 +48,7 @@ function envLabel(Network network) pure returns (string memory) { if (network == Network.Goerli) return "TESTNET_PK"; if (network == Network.RoninDevnet) return "DEVNET_PK"; if (network == Network.EthMainnet) return "MAINNET_PK"; - if (network == Network.RoninLocal) return "DEVNET_PK"; - if (network == Network.EthLocal) return "DEVNET_PK"; + revert("Network: Unknown private key env label"); } @@ -65,7 +56,6 @@ function chainAlias(Network network) pure returns (string memory) { if (network == Network.Goerli) return "goerli"; if (network == Network.EthMainnet) return "ethereum"; if (network == Network.RoninDevnet) return "ronin-devnet"; - if (network == Network.RoninLocal) return "ronin-local"; - if (network == Network.EthLocal) return "ethereum-local"; + revert("Network: Unknown network alias"); } diff --git a/test/bridge/integration/BaseIntegration.t.sol b/test/bridge/integration/BaseIntegration.t.sol index 0e6f875e..535bf093 100644 --- a/test/bridge/integration/BaseIntegration.t.sol +++ b/test/bridge/integration/BaseIntegration.t.sol @@ -105,9 +105,6 @@ contract BaseIntegration_Test is Base_Test { } function _deployContractsOnRonin() internal { - _config.createFork(Network.RoninLocal.key()); - _config.switchTo(Network.RoninLocal.key()); - _roninGatewayV3 = new RoninGatewayV3Deploy().run(); _bridgeTracking = new BridgeTrackingDeploy().run(); _bridgeSlash = new BridgeSlashDeploy().run(); @@ -122,16 +119,12 @@ contract BaseIntegration_Test is Base_Test { _roninUsdc = new USDCDeploy().run(); _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); - _roninProposalUtils = new RoninBridgeAdminUtils( - _param.test.roninChainId, _param.test.governorPKs, _roninBridgeManager, _param.roninBridgeManager.governors[0] - ); + _roninProposalUtils = + new RoninBridgeAdminUtils(_param.test.governorPKs, _roninBridgeManager, _param.roninBridgeManager.governors[0]); _validatorSet = new MockValidatorContract_OnlyTiming_ForHardhatTest(_param.test.numberOfBlocksInEpoch); } function _deployContractsOnMainchain() internal { - _config.createFork(Network.EthLocal.key()); - _config.switchTo(Network.EthLocal.key()); - _mainchainPauseEnforcer = new MainchainPauseEnforcerDeploy().run(); _mainchainGatewayV3 = new MainchainGatewayV3Deploy().run(); _mainchainBridgeManager = new MainchainBridgeManagerDeploy().run(); @@ -144,29 +137,24 @@ contract BaseIntegration_Test is Base_Test { _param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments(); _mainchainProposalUtils = new MainchainBridgeAdminUtils( - _param.test.roninChainId, - _param.test.governorPKs, - _mainchainBridgeManager, - _param.mainchainBridgeManager.governors[0] + _param.test.governorPKs, _mainchainBridgeManager, _param.mainchainBridgeManager.governors[0] ); } function _initializeRonin() internal { - _config.switchTo(Network.RoninLocal.key()); - - _validatorSet.setCurrentPeriod(block.timestamp / _validatorSet.PERIOD_DURATION() - 2); - + _moveToEndPeriodAndWrapUpEpoch(); + _moveToEndPeriodAndWrapUpEpoch(); _bridgeRewardInitialize(); + _bridgeTrackingInitialize(); _bridgeSlashInitialize(); + _roninPauseEnforcerInitialize(); _roninGatewayV3Initialize(); _constructForRoninBridgeManager(); } function _initializeMainchain() internal { - _config.switchTo(Network.EthLocal.key()); - _mainchainPauseEnforcerInitialize(); _constructForMainchainBridgeManager(); _mainchainGatewayV3Initialize(); @@ -264,7 +252,7 @@ contract BaseIntegration_Test is Base_Test { Token.Standard[] memory standards = new Token.Standard[](tokenNum); for (uint256 i; i < tokenNum; i++) { minimumThreshold[i] = 0; - chainIds[i] = _param.test.mainchainChainId; + chainIds[i] = block.chainid; standards[i] = Token.Standard.ERC20; } @@ -485,7 +473,7 @@ contract BaseIntegration_Test is Base_Test { _mainchainGatewayV3.initialize( param.roleSetter, IWETH(param.wrappedToken), - param.roninChainId, + block.chainid, param.numerator, param.highTierVWNumerator, param.denominator, @@ -506,8 +494,6 @@ contract BaseIntegration_Test is Base_Test { } function _changeAdminOnRonin() internal { - _config.switchTo(Network.RoninLocal.key()); - vm.startPrank(_param.test.proxyAdmin); TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).changeAdmin(address(_roninBridgeManager)); TransparentUpgradeableProxyV2(payable(address(_bridgeReward))).changeAdmin(address(_roninBridgeManager)); @@ -517,35 +503,25 @@ contract BaseIntegration_Test is Base_Test { } function _changeAdminOnMainchain() internal { - _config.switchTo(Network.EthLocal.key()); - vm.startPrank(_param.test.proxyAdmin); TransparentUpgradeableProxyV2(payable(address(_mainchainGatewayV3))).changeAdmin(address(_mainchainBridgeManager)); vm.stopPrank(); } function _configEmergencyPauserForRoninGateway() internal { - _config.switchTo(Network.RoninLocal.key()); - bytes memory calldata_ = abi.encodeCall(GatewayV3.setEmergencyPauser, (address(_roninPauseEnforcer))); _roninProposalUtils.functionDelegateCall(address(_roninGatewayV3), calldata_); } function _configEmergencyPauserForMainchainGateway() internal { - _config.switchTo(Network.EthLocal.key()); - bytes memory calldata_ = abi.encodeCall(GatewayV3.setEmergencyPauser, (address(_mainchainPauseEnforcer))); _mainchainProposalUtils.functionDelegateCall(address(_mainchainGatewayV3), calldata_); } function _configBridgeTrackingForRoninGateway() internal { - _config.switchTo(Network.RoninLocal.key()); - bytes memory calldata_ = abi.encodeCall(IHasContracts.setContract, (ContractType.BRIDGE_TRACKING, address(_bridgeTracking))); _roninProposalUtils.functionDelegateCall(address(_roninGatewayV3), calldata_); - - _config.switchTo(Network.EthLocal.key()); } function _deployGeneralConfig() internal { @@ -561,15 +537,26 @@ contract BaseIntegration_Test is Base_Test { vm.roll(block.number + 1); } - function _wrapUpEpoch() internal { - uint256 multiplier = _validatorSet.numberOfBlocksInEpoch(); - vm.roll((block.number / multiplier + 1) * multiplier - 1); + function _moveToEndPeriodAndWrapUpEpoch() internal { + _fastForwardToNextDay(); + _wrapUpEpoch(); + } - vm.prank(block.coinbase); + function _wrapUpEpoch() internal { _validatorSet.wrapUpEpoch(); + vm.roll(block.number + _validatorSet.numberOfBlocksInEpoch()); } - function _setTimestampToPeriodEnding() internal { - vm.warp(((block.timestamp / 1 days) + 1) * 1 days); + function _fastForwardToNextDay() internal { + uint256 numberOfBlocksInEpoch = _validatorSet.numberOfBlocksInEpoch(); + + uint256 epochEndingBlockNumber = block.number + (numberOfBlocksInEpoch - 1) - (block.number % numberOfBlocksInEpoch); + uint256 nextDayTimestamp = block.timestamp + 1 days; + + // fast forward to next day + vm.warp(nextDayTimestamp); + vm.roll(epochEndingBlockNumber); } + + function test_setUpIntegration() public { } } diff --git a/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol b/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol index 0b831b4c..63d56e58 100644 --- a/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol +++ b/test/bridge/integration/bridge-manager/propose-and-cast-vote/voteBridgeOperator.RoninBridgeManager.t.sol @@ -55,8 +55,6 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { } function test_voteAddBridgeOperatorsProposal() public { - _config.switchTo(Network.RoninLocal.key()); - _globalProposal = _roninProposalUtils.createGlobalProposal({ expiryTimestamp: block.timestamp + _proposalExpiryDuration, targetOption: GlobalProposal.TargetOption.BridgeManager, @@ -88,8 +86,6 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { function test_relayAddBridgeOperator() public { test_voteAddBridgeOperatorsProposal(); - _config.switchTo(Network.EthLocal.key()); - // before relay assertEq(_mainchainBridgeManager.globalProposalRelayed(_globalProposal.nonce), false); assertEq(_mainchainBridgeManager.getBridgeOperators(), _beforeRelayedOperators); @@ -117,8 +113,6 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { uint256 numAddingOperators = seed % 10 + 10; _generateAddingOperators(numAddingOperators); - _config.switchTo(Network.RoninLocal.key()); - _globalProposal = _roninProposalUtils.createGlobalProposal({ expiryTimestamp: block.timestamp + _proposalExpiryDuration, targetOption: GlobalProposal.TargetOption.BridgeManager, @@ -150,7 +144,6 @@ contract VoteBridgeOperator_RoninBridgeManager_Test is BaseIntegration_Test { function test_relayExpiredProposal() public { test_voteAddBridgeOperatorsProposal(); - _config.switchTo(Network.EthLocal.key()); vm.warp(block.timestamp + _proposalExpiryDuration + 1); // before relay diff --git a/test/bridge/integration/bridge-manager/set-config/setConfig.MainchainManager.t.sol b/test/bridge/integration/bridge-manager/set-config/setConfig.MainchainManager.t.sol index 311aefff..358c4810 100644 --- a/test/bridge/integration/bridge-manager/set-config/setConfig.MainchainManager.t.sol +++ b/test/bridge/integration/bridge-manager/set-config/setConfig.MainchainManager.t.sol @@ -8,7 +8,6 @@ import "../../BaseIntegration.t.sol"; contract SetConfig_MainchainManager_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.EthLocal.key()); } function test_configBridgeContractCorrectly() external { diff --git a/test/bridge/integration/bridge-manager/set-config/setConfig.RoninBridgeManager.t.sol b/test/bridge/integration/bridge-manager/set-config/setConfig.RoninBridgeManager.t.sol index 887ca08d..d27aa9d4 100644 --- a/test/bridge/integration/bridge-manager/set-config/setConfig.RoninBridgeManager.t.sol +++ b/test/bridge/integration/bridge-manager/set-config/setConfig.RoninBridgeManager.t.sol @@ -8,7 +8,6 @@ import "../../BaseIntegration.t.sol"; contract SetConfig_RoninBridgeManager_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); } function test_configBridgeContractCorrectly() external { diff --git a/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol b/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol index 3cdb172f..c4997634 100644 --- a/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol +++ b/test/bridge/integration/bridge-tracking/EpochE1_VoteIsApprovedInLastEpoch.BridgeTracking.t.sol @@ -5,6 +5,9 @@ import { IBridgeTracking } from "@ronin/contracts/interfaces/bridge/IBridgeTrack import { MockGatewayForTracking } from "@ronin/contracts/mocks/MockGatewayForTracking.sol"; import "../BaseIntegration.t.sol"; +import { EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test } from + "./EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol"; + // Epoch e-1 test: Vote is approved in the last epoch of period contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegration_Test { MockGatewayForTracking _mockRoninGatewayV3; @@ -16,7 +19,7 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); + vm.coinbase(makeAddr("coin-base-addr")); _operators.push(_param.roninBridgeManager.bridgeOperators[0]); @@ -33,14 +36,16 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio vm.deal(address(_bridgeReward), 10 ether); - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); - + _moveToEndPeriodAndWrapUpEpoch(); _period = _validatorSet.currentPeriod(); } // Epoch e-1: Vote & Approve & Vote > Should not record when not approved yet. Vote in last epoch (e-1). - function test_epochE1_notRecordVoteAndBallot_receiptWithoutApproval() public { + function test_epochEMinus1_notRecordVoteAndBallot_receiptWithoutApproval() public { + _wrapUpEpoch(); + _wrapUpEpoch(); + _wrapUpEpoch(); + _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, _operators); assertEq(_bridgeTracking.totalVote(_period), 0); @@ -50,8 +55,8 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio } // Epoch e-1: Vote & Approve & Vote > Should not record when approve. Approve in last epoch (e-1). - function test_epochE2_notRecordVoteAndBallot_approveInLastEpoch() public { - test_epochE1_notRecordVoteAndBallot_receiptWithoutApproval(); + function test_epochEMinus1_notRecordVoteAndBallot_approveInLastEpoch() public { + test_epochEMinus1_notRecordVoteAndBallot_receiptWithoutApproval(); _mockRoninGatewayV3.sendApprovedVote(_receiptKind, _receiptId); @@ -62,8 +67,8 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio } // Epoch e-1: Vote & Approve & Vote > Should not record even after approved. Vote in last epoch (e-1). - function test_epochE1_notRecordVoteAndBallot_voteInLastEpoch() public { - test_epochE2_notRecordVoteAndBallot_approveInLastEpoch(); + function test_epochEMinus1_notRecordVoteAndBallot_voteInLastEpoch() public { + test_epochEMinus1_notRecordVoteAndBallot_approveInLastEpoch(); _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[2])); @@ -76,11 +81,10 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio // Epoch e: vote > Should not record for current period metric when wrapping up period. Query in next epoch (e), for current period (p-1): return 0. function test_epochE_notRecordForCurrentPeriod_WhenWrappingUpPeriod() public { - test_epochE1_notRecordVoteAndBallot_voteInLastEpoch(); + test_epochEMinus1_notRecordVoteAndBallot_voteInLastEpoch(); uint256 lastPeriod = _period; - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); + _moveToEndPeriodAndWrapUpEpoch(); uint256 newPeriod = _validatorSet.currentPeriod(); _period = newPeriod; @@ -130,7 +134,7 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio } // Epoch 2e-1: vote > Should record new ballot for the buffer metric - function test_epoch2E_1_recordNewBallotForBufferMetric() public { + function test_epoch2EMinus1_recordNewBallotForBufferMetric() public { test_epochE_recordNewBallotForBufferMetric(); _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[4])); @@ -144,8 +148,7 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[3]), expectedTotalVotes); assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[4]), expectedTotalVotes); - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); + _moveToEndPeriodAndWrapUpEpoch(); assertEq(_bridgeTracking.totalVote(_period), expectedTotalVotes); assertEq(_bridgeTracking.totalBallot(_period), expectedTotalVotes * 5); @@ -157,8 +160,8 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio } // Epoch 3e: vote > Should not record new ballot. And the period metric is finalized as in epoch 2e-1. - function test_epoch3E_notRecordNewBallot_periodMetricIsFinalizedAsInEpoch2E_1() public { - test_epoch2E_1_recordNewBallotForBufferMetric(); + function test_epoch3E_notRecordNewBallot_periodMetricIsFinalizedAsInepoch2EMinus1() public { + test_epoch2EMinus1_recordNewBallotForBufferMetric(); _mockRoninGatewayV3.sendBallot(_receiptKind, _receiptId, wrapAddress(_param.roninBridgeManager.bridgeOperators[5])); @@ -175,10 +178,9 @@ contract EpochE1_VoteIsApprovedInLastEpoch_BridgeTracking_Test is BaseIntegratio // Epoch 3e: vote > Should the metric of the new period get reset. function test_epoch3E_metricOfNewPeriodGetReset() public { - test_epoch3E_notRecordNewBallot_periodMetricIsFinalizedAsInEpoch2E_1(); + test_epoch3E_notRecordNewBallot_periodMetricIsFinalizedAsInepoch2EMinus1(); - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); + _moveToEndPeriodAndWrapUpEpoch(); uint256 lastPeriod = _period; uint256 newPeriod = _validatorSet.currentPeriod(); diff --git a/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol b/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol index 1f3f2c03..5f487d0d 100644 --- a/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol +++ b/test/bridge/integration/bridge-tracking/EpochE2_VoteIsNotApprovedInLastEpoch.BridgeTracking.t.sol @@ -16,7 +16,7 @@ contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegra function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); + vm.coinbase(makeAddr("coin-base-addr")); // upgrade ronin gateway v3 @@ -28,8 +28,7 @@ contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegra vm.deal(address(_bridgeReward), 10 ether); - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); + // _moveToEndPeriodAndWrapUpEpoch(); _period = _validatorSet.currentPeriod(); _receiptId = 0; @@ -49,7 +48,7 @@ contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegra assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); } - // Epoch e-2: Vote & Approve & Vote. > Should be able to approve the receipts and not record the approved receipts once the epoch is not yet wrapped up + // Epoch e-2: Vote & Approve & Vote. > Should be able to approve the receipts and Should not record the approved receipts once the epoch is not yet wrapped up function test_epochE2_recordVoteAndBallot_receiptIsApproved() public { test_epochE2_notRecordVoteAndBallot_receiptWithoutApproval(); @@ -60,7 +59,7 @@ contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegra assertEq(_bridgeTracking.totalBallotOf(_period, _param.roninBridgeManager.bridgeOperators[1]), 0); } - // Epoch e-1: Continue voting for the vote of e-2 > Should be able to record the approved votes/ballots when the epoch is wrapped up + // Epoch e-1: Continue voting for the vote of e-2 > Should be able to record the approved votes/ballots when the epoch is wrapped up (value from buffer metric) function test_epochE1_continueVotingForVoteOfE2() public { test_epochE2_recordVoteAndBallot_receiptIsApproved(); @@ -92,8 +91,7 @@ contract EpochE2_VoteIsNotApprovedInLastEpoch_BridgeTracking_Test is BaseIntegra function test_epochE_continueVotingForVoteInE2_notRecordInNextPeriod() public { test_epochE1_recordForWhoVoteLately_onceRequestIsApproved(); - _setTimestampToPeriodEnding(); - _wrapUpEpochAndMine(); + _moveToEndPeriodAndWrapUpEpoch(); uint256 lastPeriod = _period; uint256 newPeriod = _validatorSet.currentPeriod(); diff --git a/test/bridge/integration/mainchain-gateway/submit-withdrawal/submitWithdrawal.MainchainGatewayV3.t.sol b/test/bridge/integration/mainchain-gateway/submit-withdrawal/submitWithdrawal.MainchainGatewayV3.t.sol index ea51c8b9..eb60743e 100644 --- a/test/bridge/integration/mainchain-gateway/submit-withdrawal/submitWithdrawal.MainchainGatewayV3.t.sol +++ b/test/bridge/integration/mainchain-gateway/submit-withdrawal/submitWithdrawal.MainchainGatewayV3.t.sol @@ -16,7 +16,6 @@ contract SubmitWithdrawal_MainchainGatewayV3_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.EthLocal.key()); _domainSeparator = _mainchainGatewayV3.DOMAIN_SEPARATOR(); @@ -24,10 +23,10 @@ contract SubmitWithdrawal_MainchainGatewayV3_Test is BaseIntegration_Test { _withdrawalReceipt.kind = Transfer.Kind.Withdrawal; _withdrawalReceipt.ronin.addr = makeAddr("requester"); _withdrawalReceipt.ronin.tokenAddr = address(_roninWeth); - _withdrawalReceipt.ronin.chainId = _param.test.roninChainId; + _withdrawalReceipt.ronin.chainId = block.chainid; _withdrawalReceipt.mainchain.addr = makeAddr("recipient"); _withdrawalReceipt.mainchain.tokenAddr = address(_mainchainWeth); - _withdrawalReceipt.mainchain.chainId = _param.test.mainchainChainId; + _withdrawalReceipt.mainchain.chainId = block.chainid; _withdrawalReceipt.info.erc = Token.Standard.ERC20; _withdrawalReceipt.info.id = 0; _withdrawalReceipt.info.quantity = 0; diff --git a/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol index 250529ba..a4b950cd 100644 --- a/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol +++ b/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol @@ -6,7 +6,6 @@ import "../../BaseIntegration.t.sol"; contract AccessControl_PauseEnforcer_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); } function test_changeAdmin_OfPauseEnforcer() public { diff --git a/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol index 04126e76..d078ce95 100644 --- a/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol +++ b/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol @@ -14,7 +14,6 @@ contract EmergencyAction_PauseEnforcer_Test is BaseIntegration_Test { // Should be able to emergency pause function test_EmergencyPause_RoninGatewayV3() public { - _config.switchTo(Network.RoninLocal.key()); vm.prank(_param.roninPauseEnforcer.sentries[0]); _roninPauseEnforcer.triggerPause(); @@ -28,12 +27,8 @@ contract EmergencyAction_PauseEnforcer_Test is BaseIntegration_Test { Transfer.Receipt memory receipt = Transfer.Receipt({ id: 0, kind: Transfer.Kind.Deposit, - ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), - mainchain: Token.Owner({ - addr: makeAddr("requester"), - tokenAddr: address(_mainchainWeth), - chainId: _param.test.mainchainChainId - }), + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: block.chainid }), + mainchain: Token.Owner({ addr: makeAddr("requester"), tokenAddr: address(_mainchainWeth), chainId: block.chainid }), info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) }); @@ -69,12 +64,8 @@ contract EmergencyAction_PauseEnforcer_Test is BaseIntegration_Test { Transfer.Receipt memory receipt = Transfer.Receipt({ id: 0, kind: Transfer.Kind.Deposit, - ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), - mainchain: Token.Owner({ - addr: makeAddr("requester"), - tokenAddr: address(_mainchainWeth), - chainId: _param.test.mainchainChainId - }), + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: block.chainid }), + mainchain: Token.Owner({ addr: makeAddr("requester"), tokenAddr: address(_mainchainWeth), chainId: block.chainid }), info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) }); diff --git a/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol b/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol index 77a3cb9a..cd9c1b1b 100644 --- a/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol +++ b/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol @@ -11,7 +11,6 @@ contract NormalPause_GatewayV3_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); } // Should gateway admin can pause the gateway through voting diff --git a/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol index e9bde218..60e7dd9c 100644 --- a/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol +++ b/test/bridge/integration/pause-enforcer/set-config/setConfig.PauseEnforcer.t.sol @@ -8,7 +8,6 @@ import "../../BaseIntegration.t.sol"; contract SetConfig_PauseEnforcer_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); } function test_configPauseEnforcerContract() public { diff --git a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol index f0e13164..055a1050 100644 --- a/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol +++ b/test/bridge/integration/ronin-gateway/depositVote.RoninGatewayV3.t.sol @@ -18,19 +18,14 @@ contract DepositVote_RoninGatewayV3_Test is BaseIntegration_Test { function setUp() public virtual override { super.setUp(); - _config.switchTo(Network.RoninLocal.key()); vm.etch(address(_roninGatewayV3), address(new MockRoninGatewayV3Extended()).code); Transfer.Receipt memory receipt = Transfer.Receipt({ id: 0, kind: Transfer.Kind.Deposit, - ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: _param.test.roninChainId }), - mainchain: Token.Owner({ - addr: makeAddr("requester"), - tokenAddr: address(_mainchainWeth), - chainId: _param.test.mainchainChainId - }), + ronin: Token.Owner({ addr: makeAddr("recipient"), tokenAddr: address(_roninWeth), chainId: block.chainid }), + mainchain: Token.Owner({ addr: makeAddr("requester"), tokenAddr: address(_mainchainWeth), chainId: block.chainid }), info: Token.Info({ erc: Token.Standard.ERC20, id: 0, quantity: 100 }) }); diff --git a/test/helpers/MainchainBridgeAdminUtils.t.sol b/test/helpers/MainchainBridgeAdminUtils.t.sol index 1d02105a..55c534d0 100644 --- a/test/helpers/MainchainBridgeAdminUtils.t.sol +++ b/test/helpers/MainchainBridgeAdminUtils.t.sol @@ -8,9 +8,7 @@ contract MainchainBridgeAdminUtils is ProposalUtils { MainchainBridgeManager _contract; address _sender; - constructor(uint256 roninChainId, uint256[] memory signerPKs, MainchainBridgeManager contract_, address sender) - ProposalUtils(roninChainId, signerPKs) - { + constructor(uint256[] memory signerPKs, MainchainBridgeManager contract_, address sender) ProposalUtils(signerPKs) { _contract = contract_; _sender = sender; } @@ -26,7 +24,7 @@ contract MainchainBridgeAdminUtils is ProposalUtils { value: 0, calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), gasAmount: 2_000_000, - nonce: _contract.round(_roninChainId) + 1 + nonce: _contract.round(block.chainid) + 1 }); SignatureConsumer.Signature[] memory signatures = this.generateSignatures(proposal); diff --git a/test/helpers/ProposalUtils.t.sol b/test/helpers/ProposalUtils.t.sol index ef504c8b..4e06b0b5 100644 --- a/test/helpers/ProposalUtils.t.sol +++ b/test/helpers/ProposalUtils.t.sol @@ -15,13 +15,11 @@ contract ProposalUtils is Utils, Test { using GlobalProposal for GlobalProposal.GlobalProposalDetail; using Proposal for Proposal.ProposalDetail; - uint256 _roninChainId; uint256[] _signerPKs; bytes32 _domain; - constructor(uint256 roninChainId, uint256[] memory signerPKs) { - _roninChainId = roninChainId; - _domain = getBridgeManagerDomain(roninChainId); + constructor(uint256[] memory signerPKs) { + _domain = getBridgeManagerDomain(); for (uint256 i; i < signerPKs.length; i++) { _signerPKs.push(signerPKs[i]); @@ -118,13 +116,13 @@ contract ProposalUtils is Utils, Test { return generateSignaturesGlobal(proposal, _signerPKs, Ballot.VoteType.For); } - function getBridgeManagerDomain(uint256 roninChainId) public pure returns (bytes32) { + 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", roninChainId)) // salt + keccak256(abi.encode("BRIDGE_ADMIN", block.chainid)) // salt ) ); } diff --git a/test/helpers/RoninBridgeAdminUtils.t.sol b/test/helpers/RoninBridgeAdminUtils.t.sol index 180d88fe..1b65257d 100644 --- a/test/helpers/RoninBridgeAdminUtils.t.sol +++ b/test/helpers/RoninBridgeAdminUtils.t.sol @@ -8,9 +8,7 @@ contract RoninBridgeAdminUtils is ProposalUtils { RoninBridgeManager _contract; address _sender; - constructor(uint256 roninChainId, uint256[] memory signerPKs, RoninBridgeManager contract_, address sender) - ProposalUtils(roninChainId, signerPKs) - { + constructor(uint256[] memory signerPKs, RoninBridgeManager contract_, address sender) ProposalUtils(signerPKs) { _contract = contract_; _sender = sender; } @@ -26,7 +24,7 @@ contract RoninBridgeAdminUtils is ProposalUtils { value: 0, calldata_: abi.encodeWithSignature("functionDelegateCall(bytes)", data), gasAmount: 2_000_000, - nonce: _contract.round(_roninChainId) + 1 + nonce: _contract.round(block.chainid) + 1 }); SignatureConsumer.Signature[] memory signatures = this.generateSignatures(proposal); From 1350f80601438e82785ee5e44a4743cd6f54be75 Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Sat, 3 Feb 2024 01:07:08 +0700 Subject: [PATCH 18/18] chore: refactor pause enforcer test --- logs/contract-code-sizes.log | 2 +- .../{set-config => }/accessControl.PauseEnforcer.t.sol | 2 +- .../{set-config => }/emergencyAction.PauseEnforcer.t.sol | 2 +- .../pause-enforcer/{set-config => }/normalPause.GatewayV3.t.sol | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename test/bridge/integration/pause-enforcer/{set-config => }/accessControl.PauseEnforcer.t.sol (95%) rename test/bridge/integration/pause-enforcer/{set-config => }/emergencyAction.PauseEnforcer.t.sol (98%) rename test/bridge/integration/pause-enforcer/{set-config => }/normalPause.GatewayV3.t.sol (98%) diff --git a/logs/contract-code-sizes.log b/logs/contract-code-sizes.log index 4c5b215a..d4d56b11 100644 --- a/logs/contract-code-sizes.log +++ b/logs/contract-code-sizes.log @@ -15,7 +15,7 @@ | ERC20PresetMinterPauser | 6.368 | 18.208 | | EnumerableSet | 0.086 | 24.49 | | ErrorHandler | 0.086 | 24.49 | -| GeneralConfig | 20.616 | 3.96 | +| GeneralConfig | 20.136 | 4.44 | | GeneralConfigExtended | 20.35 | 4.226 | | GlobalProposal | 0.166 | 24.41 | | HasBridgeDeprecated | 0.063 | 24.513 | diff --git a/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/accessControl.PauseEnforcer.t.sol similarity index 95% rename from test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol rename to test/bridge/integration/pause-enforcer/accessControl.PauseEnforcer.t.sol index a4b950cd..ec307524 100644 --- a/test/bridge/integration/pause-enforcer/set-config/accessControl.PauseEnforcer.t.sol +++ b/test/bridge/integration/pause-enforcer/accessControl.PauseEnforcer.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -import "../../BaseIntegration.t.sol"; +import "../BaseIntegration.t.sol"; contract AccessControl_PauseEnforcer_Test is BaseIntegration_Test { function setUp() public virtual override { diff --git a/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol b/test/bridge/integration/pause-enforcer/emergencyAction.PauseEnforcer.t.sol similarity index 98% rename from test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol rename to test/bridge/integration/pause-enforcer/emergencyAction.PauseEnforcer.t.sol index d078ce95..d161dc78 100644 --- a/test/bridge/integration/pause-enforcer/set-config/emergencyAction.PauseEnforcer.t.sol +++ b/test/bridge/integration/pause-enforcer/emergencyAction.PauseEnforcer.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import { Transfer } from "@ronin/contracts/libraries/Transfer.sol"; import { GatewayV3 } from "@ronin/contracts/extensions/GatewayV3.sol"; -import "../../BaseIntegration.t.sol"; +import "../BaseIntegration.t.sol"; contract EmergencyAction_PauseEnforcer_Test is BaseIntegration_Test { error ErrTargetIsNotOnPaused(); diff --git a/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol b/test/bridge/integration/pause-enforcer/normalPause.GatewayV3.t.sol similarity index 98% rename from test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol rename to test/bridge/integration/pause-enforcer/normalPause.GatewayV3.t.sol index cd9c1b1b..2f4d7192 100644 --- a/test/bridge/integration/pause-enforcer/set-config/normalPause.GatewayV3.t.sol +++ b/test/bridge/integration/pause-enforcer/normalPause.GatewayV3.t.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.19; import { Transfer } from "@ronin/contracts/libraries/Transfer.sol"; import { GatewayV3 } from "@ronin/contracts/extensions/GatewayV3.sol"; -import "../../BaseIntegration.t.sol"; +import "../BaseIntegration.t.sol"; contract NormalPause_GatewayV3_Test is BaseIntegration_Test { error ErrNotOnEmergencyPause();