Skip to content

Commit

Permalink
Add root bridge unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
wcgcyx committed Nov 8, 2023
1 parent fc10c64 commit 737c9c3
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/root/RootERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,8 @@ contract RootERC20Bridge is
address childToken;
if (address(rootToken) == rootIMXToken) {
childToken = NATIVE_IMX;
} else if (address(rootToken) == NATIVE_ETH) {
childToken = childETHToken;
} else {
childToken = rootTokenToChildToken[rootToken];
if (childToken == address(0)) {
Expand Down
62 changes: 62 additions & 0 deletions test/unit/root/withdrawals/RootERC20BridgeWithdraw.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {MockAxelarGateway} from "../../../../src/test/root/MockAxelarGateway.sol
import {MockAxelarGasService} from "../../../../src/test/root/MockAxelarGasService.sol";
import {MockAdaptor} from "../../../../src/test/root/MockAdaptor.sol";
import {Utils} from "../../../utils.t.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";

contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootERC20BridgeErrors, Utils {
address constant CHILD_BRIDGE = address(3);
Expand All @@ -20,6 +21,7 @@ contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootE
address constant UnmappedToken = address(0xbbb);
address constant IMX_TOKEN = address(0xccc);
address constant WRAPPED_ETH = address(0xddd);
address public constant NATIVE_ETH = address(0xeee);
address public constant NATIVE_IMX = address(0xfff);
uint256 constant mapTokenFee = 300;
uint256 constant withdrawAmount = 0.5 ether;
Expand All @@ -32,6 +34,8 @@ contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootE
MockAxelarGateway public mockAxelarGateway;
MockAxelarGasService public axelarGasService;

receive() external payable {}

function setUp() public {
token = new ERC20PresetMinterPauser("Test", "TST");
token.mint(address(this), 100 ether);
Expand Down Expand Up @@ -144,6 +148,21 @@ contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootE
);
}

function test_onMessageReceive_TransfersETH() public {
// Give bridge some ETH
Address.sendValue(payable(rootBridge), 100 ether);

uint256 thisPreBal = address(this).balance;
uint256 bridgePreBal = address(rootBridge).balance;

bytes memory data = abi.encode(WITHDRAW_SIG, NATIVE_ETH, address(this), address(this), withdrawAmount);
vm.prank(address(mockAxelarAdaptor));
rootBridge.onMessageReceive(CHILD_CHAIN_NAME, CHILD_BRIDGE_ADAPTOR_STRING, data);

assertEq(address(this).balance, thisPreBal + withdrawAmount, "ETH not transferred to receiver");
assertEq(address(rootBridge).balance, bridgePreBal - withdrawAmount, "ETH not transferred from bridge");
}

function test_onMessageReceive_TransfersTokens_DifferentReceiver() public {
address receiver = address(123456);
// Need to first map the token.
Expand Down Expand Up @@ -184,6 +203,22 @@ contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootE
);
}

function test_onMessageReceive_TransfersETH_DifferentReceiver() public {
address receiver = address(123456);
// Give bridge some ETH
Address.sendValue(payable(rootBridge), 100 ether);

uint256 receiverPreBal = address(receiver).balance;
uint256 bridgePreBal = address(rootBridge).balance;

bytes memory data = abi.encode(WITHDRAW_SIG, NATIVE_ETH, address(this), receiver, withdrawAmount);
vm.prank(address(mockAxelarAdaptor));
rootBridge.onMessageReceive(CHILD_CHAIN_NAME, CHILD_BRIDGE_ADAPTOR_STRING, data);

assertEq(address(receiver).balance, receiverPreBal + withdrawAmount, "ETH not transferred to receiver");
assertEq(address(rootBridge).balance, bridgePreBal - withdrawAmount, "ETH not transferred from bridge");
}

function test_onMessageReceive_EmitsRootChainERC20WithdrawEvent() public {
// Need to first map the token.
rootBridge.mapToken(token);
Expand Down Expand Up @@ -214,6 +249,19 @@ contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootE
rootBridge.onMessageReceive(CHILD_CHAIN_NAME, CHILD_BRIDGE_ADAPTOR_STRING, data);
}

function test_onMessageReceive_EmitsRootChainERC20WithdrawEventForETH() public {
// Give bridge some ETH
Address.sendValue(payable(rootBridge), 100 ether);

bytes memory data = abi.encode(WITHDRAW_SIG, NATIVE_ETH, address(this), address(this), withdrawAmount);
vm.expectEmit();
emit RootChainERC20Withdraw(
NATIVE_ETH, address(rootBridge.childETHToken()), address(this), address(this), withdrawAmount
);
vm.prank(address(mockAxelarAdaptor));
rootBridge.onMessageReceive(CHILD_CHAIN_NAME, CHILD_BRIDGE_ADAPTOR_STRING, data);
}

function test_onMessageReceive_EmitsRootChainERC20WithdrawEvent_DifferentReceiver() public {
address receiver = address(123456);
// Need to first map the token.
Expand Down Expand Up @@ -241,4 +289,18 @@ contract RootERC20BridgeWithdrawUnitTest is Test, IRootERC20BridgeEvents, IRootE
vm.prank(address(mockAxelarAdaptor));
rootBridge.onMessageReceive(CHILD_CHAIN_NAME, CHILD_BRIDGE_ADAPTOR_STRING, data);
}

function test_onMessageReceive_EmitsRootChainERC20WithdrawEventForETH_DifferentReceiver() public {
address receiver = address(123456);
// Give bridge some ETH
Address.sendValue(payable(rootBridge), 100 ether);

bytes memory data = abi.encode(WITHDRAW_SIG, NATIVE_ETH, address(this), receiver, withdrawAmount);
vm.expectEmit();
emit RootChainERC20Withdraw(
NATIVE_ETH, address(rootBridge.childETHToken()), address(this), receiver, withdrawAmount
);
vm.prank(address(mockAxelarAdaptor));
rootBridge.onMessageReceive(CHILD_CHAIN_NAME, CHILD_BRIDGE_ADAPTOR_STRING, data);
}
}

0 comments on commit 737c9c3

Please sign in to comment.