From 7e8dbaeae8f6e6e9e66fc5d66bed4f8887306e6b Mon Sep 17 00:00:00 2001 From: huyhuynh3103 Date: Thu, 25 Jan 2024 11:28:10 +0700 Subject: [PATCH] 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,