Skip to content

Commit

Permalink
test(RoninBridgeManager): add test cast vote for adding bridge operators
Browse files Browse the repository at this point in the history
  • Loading branch information
huyhuynh3103 committed Jan 19, 2024
1 parent 0de12b4 commit 381c48f
Show file tree
Hide file tree
Showing 8 changed files with 396 additions and 3 deletions.
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ src = 'src'
out = 'out'
optimizer = true
optimizer_runs = 200
ffi = true

libs = [
'lib',
Expand Down
12 changes: 9 additions & 3 deletions script/Migration.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { ISharedArgument } from "./interfaces/ISharedArgument.sol";
import { Network } from "./utils/Network.sol";
import { Utils } from "./utils/Utils.sol";
import { Contract } from "./utils/Contract.sol";

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 {
ISharedArgument public constant config = ISharedArgument(address(CONFIG));
Expand All @@ -33,16 +33,21 @@ contract Migration is BaseMigration, Utils {
uint256[] memory operatorPKs = new uint256[](num);
uint256[] memory governorPKs = new uint256[](num);
uint96[] memory voteWeights = new uint96[](num);

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));

address governanceAdmin = makeAddr("governance-admin");
address validatorSetContract = makeAddr("validator-set-contract");
Token.Standard[] memory standards = new Token.Standard[](1);
Expand All @@ -65,6 +70,7 @@ contract Migration is BaseMigration, Utils {

// test
param.test.proxyAdmin = makeAddr("proxy-admin");
param.test.roninChainId = 0;
param.test.operatorPKs = operatorPKs;
param.test.governorPKs = governorPKs;

Expand All @@ -89,7 +95,7 @@ contract Migration is BaseMigration, Utils {
// Ronin Bridge Manager
param.roninBridgeManager.num = 2;
param.roninBridgeManager.denom = 4;
param.roninBridgeManager.roninChainId = 0;
param.roninBridgeManager.roninChainId = param.test.roninChainId;
param.roninBridgeManager.expiryDuration = 60 * 60 * 24 * 14; // 14 days
param.roninBridgeManager.bridgeContract = loadContract(Contract.RoninGatewayV3.key());
param.roninBridgeManager.callbackRegisters = wrapAddress(loadContract(Contract.BridgeSlash.key()));
Expand Down Expand Up @@ -124,7 +130,7 @@ contract Migration is BaseMigration, Utils {

param.mainchainBridgeManager.num = 2;
param.mainchainBridgeManager.denom = 4;
param.mainchainBridgeManager.roninChainId = 0;
param.mainchainBridgeManager.roninChainId = param.test.roninChainId;
param.mainchainBridgeManager.bridgeContract = loadContract(Contract.MainchainGatewayV3.key());
param.mainchainBridgeManager.callbackRegisters = getEmptyAddressArray();
param.mainchainBridgeManager.bridgeOperators = operatorAddrs;
Expand Down
1 change: 1 addition & 0 deletions script/interfaces/ISharedArgument.sol
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ interface ISharedArgument is IGeneralConfig {

struct UnitTestParam {
address proxyAdmin;
uint256 roninChainId;
uint256[] operatorPKs;
uint256[] governorPKs;
}
Expand Down
173 changes: 173 additions & 0 deletions script/libraries/LibArray.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/**
* @title LibArray
* @dev A library for array-related utility functions in Solidity.
*/
library LibArray {
/**
* @dev Error indicating a length mismatch between two arrays.
*/
error LengthMismatch();

function toUint256s(uint8[] memory self) internal pure returns (uint256[] memory uint256s) {
assembly ("memory-safe") {
uint256s := self
}
}

function toUint8sUnsafe(uint256[] memory self) internal pure returns (uint8[] memory uint8s) {
assembly ("memory-safe") {
uint8s := self
}
}

function arange(uint256 length) internal pure returns (uint256[] memory data) {
data = new uint256[](length);
for (uint256 i; i < length; ++i) {
data[i] = i;
}
}

/**
* @dev Converts an array of uint256 to an array of bytes32.
* @param self The array of uint256.
* @return bytes32s The resulting array of bytes32.
*/
function toBytes32s(uint256[] memory self) internal pure returns (bytes32[] memory bytes32s) {
assembly ("memory-safe") {
bytes32s := self
}
}

function hash(uint256[] memory data) internal pure returns (bytes32 digest) {
assembly ("memory-safe") {
digest := keccak256(add(data, 0x20), mload(data))
}
}

/**
* @dev Calculates the sum of an array of uint256 values.
* @param data The array of uint256 values for which the sum is calculated.
* @return result The sum of the provided array of uint256 values.
*/
function sum(uint256[] memory data) internal pure returns (uint256 result) {
assembly ("memory-safe") {
// Load the length (first 32 bytes)
let len := mload(data)
let dataElementLocation := add(data, 0x20)

// Iterate until the bound is not met.
for { let end := add(dataElementLocation, mul(len, 0x20)) } lt(dataElementLocation, end) {
dataElementLocation := add(dataElementLocation, 0x20)
} { result := add(result, mload(dataElementLocation)) }
}
}

/**
* @dev Converts an array of bytes32 to an array of uint256.
* @param self The array of bytes32.
* @return uint256s The resulting array of uint256.
*/
function toUint256s(bytes32[] memory self) internal pure returns (uint256[] memory uint256s) {
assembly ("memory-safe") {
uint256s := self
}
}

/**
* @dev Converts an array of uint64 to an array of uint256.
* @param self The array of bytes32.
* @return uint256s The resulting array of uint256.
*/
function toUint256s(uint64[] memory self) internal pure returns (uint256[] memory uint256s) {
assembly ("memory-safe") {
uint256s := self
}
}

/**
* @dev Converts an array of address to an array of uint256.
* @param self The array of address.
* @return uint256s The resulting array of uint256.
*/
function toUint256s(address[] memory self) internal pure returns (uint256[] memory uint256s) {
assembly ("memory-safe") {
uint256s := self
}
}

/**
* @dev Sorts an array of uint256 values based on a corresponding array of values using the specified sorting mode.
* @param self The array to be sorted.
* @param values The corresponding array of values used for sorting.
* @notice This function modify `self` and `values`
* @return sorted The sorted array.
*/
function inlineSortByValue(uint256[] memory self, uint256[] memory values)
internal
pure
returns (uint256[] memory sorted)
{
return inlineQuickSortByValue(self, values);
}

/**
* @dev Sorts an array of uint256 based on a corresponding array of values.
* @param self The array to be sorted.
* @param values The corresponding array of values used for sorting.
* @notice This function modify `self` and `values`
* @return sorted The sorted array.
*/
function inlineQuickSortByValue(uint256[] memory self, uint256[] memory values)
internal
pure
returns (uint256[] memory sorted)
{
uint256 length = self.length;
if (length != values.length) revert LengthMismatch();
unchecked {
if (length > 1) inlineQuickSortByValue(self, values, 0, int256(length - 1));
}

assembly ("memory-safe") {
sorted := self
}
}

/**
* @dev Internal function to perform quicksort on an array of uint256 values based on a corresponding array of values.
* @param arr The array to be sorted.
* @param values The corresponding array of values used for sorting.
* @param left The left index of the subarray to be sorted.
* @param right The right index of the subarray to be sorted.
* @notice This function modify `arr` and `values`
*/
function inlineQuickSortByValue(uint256[] memory arr, uint256[] memory values, int256 left, int256 right)
private
pure
{
unchecked {
if (left == right) return;
int256 i = left;
int256 j = right;
uint256 pivot = values[uint256(left + right) >> 1];

while (i <= j) {
while (pivot > values[uint256(i)]) ++i;
while (pivot < values[uint256(j)]) --j;

if (i <= j) {
(arr[uint256(i)], arr[uint256(j)]) = (arr[uint256(j)], arr[uint256(i)]);
(values[uint256(i)], values[uint256(j)]) = (values[uint256(j)], values[uint256(i)]);
++i;
--j;
}
}

if (left < j) inlineQuickSortByValue(arr, values, left, j);
if (i < right) inlineQuickSortByValue(arr, values, i, right);
}
}
}
5 changes: 5 additions & 0 deletions script/utils/Utils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ contract Utils {
arr[0] = val;
}

function wrapBytes(bytes memory val) internal pure returns (bytes[] memory arr) {
arr = new bytes[](1);
arr[0] = val;
}

function wrapAddress(address val1, address val2, address val3) internal pure returns (address[] memory arr) {
arr = new address[](3);
arr[0] = val1;
Expand Down
6 changes: 6 additions & 0 deletions test/bridge/integration/BaseIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,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 { BridgeAdminInterface } from "test/helpers/BridgeAdminInterface.t.sol";

contract BaseIntegration_Test is Base_Test {
ISharedArgument.SharedParameter _param;

Expand All @@ -43,6 +45,8 @@ contract BaseIntegration_Test is Base_Test {
MockERC20 _slp;
MockERC20 _usdc;

BridgeAdminInterface _bridgeAdminInterface;

function setUp() public virtual {
_roninGatewayV3 = new RoninGatewayV3Deploy().run();
_bridgeTracking = new BridgeTrackingDeploy().run();
Expand All @@ -59,5 +63,7 @@ contract BaseIntegration_Test is Base_Test {
_usdc = new USDCDeploy().run();

_param = ISharedArgument(LibSharedAddress.CONFIG).sharedArguments();

_bridgeAdminInterface = new BridgeAdminInterface(_param.test.roninChainId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import { console2 as console } from "forge-std/console2.sol";
import { GlobalProposal } from "@ronin/contracts/libraries/GlobalProposal.sol";
import { Ballot } from "@ronin/contracts/libraries/Ballot.sol";
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 {
using LibSort for address[];

uint256 _nonce;
uint256 _proposalExpiryDuration;
uint256 _addingOperatorNum;
address[] _addingOperators;
address[] _addingGovernors;
uint96[] _voteWeights;

address[] _beforeRelayedOperators;
address[] _beforeRelayedGovernors;

Ballot.VoteType[] _supports;

function setUp() public virtual override {
super.setUp();

_nonce = 1;
_proposalExpiryDuration = 60;
_addingOperatorNum = 3;

_beforeRelayedOperators = _param.roninBridgeManager.bridgeOperators;
_beforeRelayedGovernors = _param.roninBridgeManager.governors;

_supports = new Ballot.VoteType[](_beforeRelayedOperators.length);
for (uint256 i; i < _beforeRelayedGovernors.length; i++) {
_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)));
}
}

function test_voteBridgeOperators() public {
GlobalProposal.GlobalProposalDetail memory globalProposal = _bridgeAdminInterface.createGlobalProposal({
expiryTimestamp: block.timestamp + _proposalExpiryDuration,
targetOption: GlobalProposal.TargetOption.BridgeManager,
value: 0,
calldata_: abi.encodeCall(IBridgeManager.addBridgeOperators, (_voteWeights, _addingOperators, _addingGovernors)),
gasAmount: 500_000,
nonce: _nonce
});

SignatureConsumer.Signature[] memory signatures =
_bridgeAdminInterface.generateSignaturesGlobal(globalProposal, _param.test.governorPKs);

vm.prank(_param.roninBridgeManager.governors[0]);
_roninBridgeManager.proposeGlobalProposalStructAndCastVotes(globalProposal, _supports, signatures);
}
}
Loading

0 comments on commit 381c48f

Please sign in to comment.