Skip to content

Commit

Permalink
test: adapt new impl
Browse files Browse the repository at this point in the history
  • Loading branch information
TuDo1403 committed Jan 2, 2025
1 parent aea2fcd commit b0e59a7
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 21 deletions.
4 changes: 2 additions & 2 deletions script/interfaces/IMainchainGatewayV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ interface IMainchainGatewayV3 {
event UnRestricted(address indexed by, bytes4 indexed fnSig);
event UnlockFeePercentagesUpdated(address[] tokens, uint256[] percentages);
event Unpaused(address account);
event WhitelistUpdated(address indexed by, address[] tokens, address[] recipients);
event WhitelistUpdated(address indexed by, address[] tokens, address[] recipients, uint64[] remoteChainSelectors);
event WithdrawalLocked(bytes32 receiptHash, Transfer.Receipt receipt);
event WithdrawalUnlocked(bytes32 receiptHash, Transfer.Receipt receipt);
event Withdrew(bytes32 receiptHash, Transfer.Receipt receipt);
Expand Down Expand Up @@ -169,7 +169,7 @@ interface IMainchainGatewayV3 {
Transfer.Receipt memory receipt
) external;
function unpause() external;
function whitelist(address[] memory tokens, address[] memory recipients) external;
function whitelist(address[] memory tokens, address[] memory recipients, uint64[] memory remoteChainSelectors) external;
function withdrawalHash(
uint256
) external view returns (bytes32);
Expand Down
4 changes: 2 additions & 2 deletions script/interfaces/IRoninGatewayV3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ interface IRoninGatewayV3 {
);
event UnRestricted(address indexed by, bytes4 indexed fnSig);
event Unpaused(address account);
event WhitelistUpdated(address indexed by, address[] tokens, address[] recipients);
event WhitelistUpdated(address indexed by, address[] tokens, address[] recipients, uint64[] remoteChainSelectors);
event WithdrawalRequested(bytes32 receiptHash, Transfer.Receipt);
event WithdrawalSignaturesRequested(bytes32 receiptHash, Transfer.Receipt);

Expand Down Expand Up @@ -147,7 +147,7 @@ interface IRoninGatewayV3 {
) external returns (bool[] memory _executedReceipts);
function unmapTokens(address[] memory roninTokens_, uint256[] memory chainIds_) external;
function unpause() external;
function whitelist(address[] memory tokens, address[] memory recipients) external;
function whitelist(address[] memory tokens, address[] memory recipients, uint64[] memory remoteChainSelectors) external;
function withdrawal(
uint256
) external view returns (uint256 id, Transfer.Kind kind, TokenOwner memory mainchain, TokenOwner memory ronin, TokenInfo memory info);
Expand Down
154 changes: 137 additions & 17 deletions test/bridge/integration/asset-migration/GatewayV3.AssetMigration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,21 @@ pragma solidity ^0.8.19;

import "../BaseIntegration.t.sol";
import { LibProxy } from "@fdk/libraries/LibProxy.sol";
import { MockCCIPPoolSingleLane } from "test/mocks/MockCCIPPoolSingleLane.sol";
import { MockCCIPPoolMultiLane } from "test/mocks/MockCCIPPoolMultiLane.sol";

contract GatewayV3_AssetMigration is BaseIntegration_Test {
address internal _pauseEnforcer;
address internal _migrator;

address[] internal _ronTokens;
address[] internal _ronRecipients;
uint64[] internal _ronRemoteChainSelectors;

address[] internal _ethTokens;
address[] internal _ethRecipients;
uint64[] internal _ethRemoteChainSelectors;

bytes32 internal constant _MIGRATOR_ROLE = keccak256("MIGRATOR_ROLE");

function setUp() public virtual override {
Expand All @@ -16,25 +26,114 @@ contract GatewayV3_AssetMigration is BaseIntegration_Test {
_pauseEnforcer = makeAddr("pause-enforcer");
_migrator = makeAddr("migrator");

(bool success,) = address(_roninGatewayV3).call(abi.encodeWithSignature("initializeV4(address,address)", _migrator, _pauseEnforcer));
_initialize();
}

function _initialize() internal {
(bool success,) = address(_roninGatewayV3).call(
abi.encodeWithSignature(
"initializeV4(address,address,address[],address[],uint64[])", _migrator, _pauseEnforcer, _ronTokens, _ronRecipients, _ronRemoteChainSelectors
)
);

require(success, "GatewayV3_AssetMigration: failed to initialize V4");

(success,) = address(_mainchainGatewayV3).call(abi.encodeWithSignature("initializeV5(address,address)", _migrator, _pauseEnforcer));
(success,) = address(_mainchainGatewayV3).call(
abi.encodeWithSignature(
"initializeV5(address,address,address[],address[],uint64[])", _migrator, _pauseEnforcer, _ethTokens, _ethRecipients, _ethRemoteChainSelectors
)
);

require(success, "GatewayV3_AssetMigration: failed to initialize V5");
}

function testConcrete_AutoWrap_If_Migrate_Native() external {
function testConcrete_RevertIf_Whitelisted_IsEOA() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_roninWeth);
whitelists[0] = makeAddr("alice");

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

uint256[] memory amounts = new uint256[](1);
amounts[0] = 1000 ether;

deal(address(_roninWeth), address(_roninGatewayV3), 1000 ether);

vm.expectRevert();
vm.prank(_migrator);
_roninGatewayV3.migrateERC20(tokens, amounts);
}

function testConcrete_RevertIf_Whitelist_NullRemoteChainSelectors_But_WhitelistedSpender_IsMultiLane() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_roninWeth);
whitelists[0] = address(new MockCCIPPoolMultiLane(address(_roninWeth)));

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

uint256[] memory amounts = new uint256[](1);
amounts[0] = 1000 ether;

deal(address(_roninWeth), address(_roninGatewayV3), 1000 ether);

vm.expectRevert();
vm.prank(_migrator);
_roninGatewayV3.migrateERC20(tokens, amounts);
}

function testConcrete_RevertIf_Whitelist_RemoteChainSelectors_But_WhitelistedSpender_IsSingleLane() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_roninWeth);
whitelists[0] = address(new MockCCIPPoolSingleLane(address(_roninWeth)));
remoteChainSelectors[0] = uint64(uint256(keccak256("remote-chain-selector")));

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

uint256[] memory amounts = new uint256[](1);
amounts[0] = 1000 ether;

deal(address(_roninWeth), address(_roninGatewayV3), 1000 ether);

vm.expectRevert();
vm.prank(_migrator);
_roninGatewayV3.migrateERC20(tokens, amounts);
}

function testConcrete_AutoWrap_If_Migrate_Native_MultiLane() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_mainchainWeth);
whitelists[0] = makeAddr("whitelist");
whitelists[0] = address(new MockCCIPPoolMultiLane(address(_mainchainWeth)));
remoteChainSelectors[0] = uint64(uint256(keccak256("remote-chain-selector")));

address admin = LibProxy.getProxyAdmin(address(_mainchainGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_mainchainGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_mainchainGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

vm.deal(address(_mainchainGatewayV3), 1000 ether);

Expand All @@ -46,16 +145,19 @@ contract GatewayV3_AssetMigration is BaseIntegration_Test {
_mainchainGatewayV3.migrateERC20(new address[](1), amounts);
}

function testConcrete_CanMigrate_IfWhitelisted() external {
function testConcrete_CanMigrate_IfWhitelisted_SingleLane() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_roninWeth);
whitelists[0] = makeAddr("whitelist");
whitelists[0] = address(new MockCCIPPoolSingleLane(address(_roninWeth)));

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

deal(address(_roninWeth), address(_roninGatewayV3), 1000 ether);

Expand All @@ -69,13 +171,16 @@ contract GatewayV3_AssetMigration is BaseIntegration_Test {
function testConcrete_RevertIf_MigrateNative_RoninGatewayV3() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_roninWron);
whitelists[0] = makeAddr("whitelist");

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

uint256[] memory amounts = new uint256[](1);
tokens[0] = address(0x0);
Expand All @@ -95,26 +200,33 @@ contract GatewayV3_AssetMigration is BaseIntegration_Test {
function testConcrete_RevertIf_WhitelistNativeToken() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(0x0);
whitelists[0] = makeAddr("whitelist");

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
vm.expectRevert(IRoninGatewayV3.ErrWhitelistWrappedTokenInstead.selector);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);
}

function testConcrete_RevertIf_DeWhitelist() external {
function testConcrete_RevertIf_DeWhitelist_MultiLane() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = address(_roninWeth);
whitelists[0] = makeAddr("whitelist");
whitelists[0] = address(new MockCCIPPoolMultiLane(address(_roninWeth)));
remoteChainSelectors[0] = uint64(uint256(keccak256("remote-chain-selector")));

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

deal(address(_roninWeth), address(_roninGatewayV3), 1000 ether);

Expand All @@ -127,7 +239,9 @@ contract GatewayV3_AssetMigration is BaseIntegration_Test {
// De-whitelist
whitelists[0] = address(0x0);
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

vm.prank(_migrator);
vm.expectRevert(abi.encodeWithSelector(IRoninGatewayV3.ErrNotWhitelistedToken.selector, tokens[0]));
Expand All @@ -137,31 +251,37 @@ contract GatewayV3_AssetMigration is BaseIntegration_Test {
function testConcrete_Admin_Can_Whitelist() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = makeAddr("token");
whitelists[0] = makeAddr("whitelist");

address admin = LibProxy.getProxyAdmin(address(_roninGatewayV3));
vm.prank(admin);
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

assertEq(_roninGatewayV3.getWhitelistedAddresses(tokens)[0], whitelists[0], "GatewayV3_AssetMigration: invalid whitelist address");
}

function testConcrete_RevertIf_NotAdmin_Whitelist() external {
address[] memory tokens = new address[](1);
address[] memory whitelists = new address[](1);
uint64[] memory remoteChainSelectors = new uint64[](1);

tokens[0] = makeAddr("token");
whitelists[0] = makeAddr("whitelist");

address admin = _migrator;
vm.prank(admin);
vm.expectRevert();
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists)));
TransparentUpgradeableProxyV2(payable(address(_roninGatewayV3))).functionDelegateCall(
abi.encodeCall(IRoninGatewayV3.whitelist, (tokens, whitelists, remoteChainSelectors))
);

vm.prank(admin);
vm.expectRevert();
_roninGatewayV3.whitelist(tokens, whitelists);
_roninGatewayV3.whitelist(tokens, whitelists, remoteChainSelectors);
}
}
29 changes: 29 additions & 0 deletions test/mocks/MockCCIPPoolMultiLane.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.17 <0.9.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract MockCCIPPoolMultiLane {
using SafeERC20 for IERC20;

event LiquidityAdded(address indexed provider, uint256 indexed amount);

IERC20 public immutable i_token;

mapping(uint64 => uint256) public s_lockedTokensByChainSelector;

constructor(
address token
) {
i_token = IERC20(token);
}

function provideLiquidity(uint64 remoteChainSelector, uint256 amount) external {
s_lockedTokensByChainSelector[remoteChainSelector] += amount;

i_token.safeTransferFrom(msg.sender, address(this), amount);

emit LiquidityAdded(msg.sender, amount);
}
}
26 changes: 26 additions & 0 deletions test/mocks/MockCCIPPoolSingleLane.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.17 <0.9.0;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract MockCCIPPoolSingleLane {
using SafeERC20 for IERC20;

event LiquidityAdded(address indexed provider, uint256 indexed amount);

IERC20 public immutable i_token;

constructor(
address token
) {
i_token = IERC20(token);
}

function provideLiquidity(
uint256 amount
) external {
i_token.safeTransferFrom(msg.sender, address(this), amount);
emit LiquidityAdded(msg.sender, amount);
}
}

0 comments on commit b0e59a7

Please sign in to comment.