Skip to content

Commit

Permalink
Merge branch 'main' into SMR-1677-FlowRate
Browse files Browse the repository at this point in the history
  • Loading branch information
proletesseract committed Nov 7, 2023
2 parents 9c9ecaa + 95ddd11 commit c5bef71
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 24 deletions.
12 changes: 9 additions & 3 deletions src/root/RootERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ contract RootERC20Bridge is
bytes32 public constant DEPOSIT_SIG = keccak256("DEPOSIT");
bytes32 public constant WITHDRAW_SIG = keccak256("WITHDRAW");
address public constant NATIVE_ETH = address(0xeee);
address public constant NATIVE_IMX = address(0xfff);

IRootERC20BridgeAdaptor public rootBridgeAdaptor;
/// @dev Used to verify source address in messages sent from child chain.
Expand Down Expand Up @@ -376,9 +377,14 @@ contract RootERC20Bridge is
function _withdraw(bytes memory data) internal virtual {
(address rootToken, address withdrawer, address receiver, uint256 amount) =
abi.decode(data, (address, address, address, uint256));
address childToken = rootTokenToChildToken[rootToken];
if (childToken == address(0)) {
revert NotMapped();
address childToken;
if (address(rootToken) == rootIMXToken) {
childToken = NATIVE_IMX;
} else {
childToken = rootTokenToChildToken[rootToken];
if (childToken == address(0)) {
revert NotMapped();
}
}
_executeTransfer(rootToken, childToken, withdrawer, receiver, amount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ contract ChildERC20BridgeWithdrawIMXIntegrationTest is
childBridge.withdrawIMX{value: withdrawFee + withdrawAmount}(withdrawAmount);
}

function test_WithdrawIMX_EmitsAxelarMessageEvent() public {
function test_WithdrawIMX_EmitsAxelarMessageSentEvent() public {
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;

bytes memory predictedPayload =
abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount);

vm.expectEmit(address(axelarAdaptor));
emit AxelarMessage(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload);
emit AxelarMessageSent(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload);

childBridge.withdrawIMX{value: withdrawFee + withdrawAmount}(withdrawAmount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,20 @@ contract ChildERC20BridgewithdrawIMXToIntegrationTest is
childBridge.withdrawIMXTo{value: withdrawFee + withdrawAmount}(receiver, withdrawAmount);
}

function test_withdrawIMXTo_EmitsAxelarMessageEvent() public {
function test_withdrawIMXTo_EmitsAxelarMessageSentEvent() public {
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;

bytes memory predictedPayload =
abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount);

vm.expectEmit(address(axelarAdaptor));
emit AxelarMessage(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload);
emit AxelarMessageSent(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload);

childBridge.withdrawIMXTo{value: withdrawFee + withdrawAmount}(address(this), withdrawAmount);
}

function test_withdrawIMXToWithDifferentAccount_EmitsAxelarMessageEvent() public {
function test_withdrawIMXToWithDifferentAccount_EmitsAxelarMessageSentEvent() public {
address receiver = address(0xabcd);
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;
Expand All @@ -185,7 +185,7 @@ contract ChildERC20BridgewithdrawIMXToIntegrationTest is
abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), receiver, withdrawAmount);

vm.expectEmit(address(axelarAdaptor));
emit AxelarMessage(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload);
emit AxelarMessageSent(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload);

childBridge.withdrawIMXTo{value: withdrawFee + withdrawAmount}(receiver, withdrawAmount);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ contract RootERC20BridgeWithdrawIntegrationTest is
address constant IMX_TOKEN_ADDRESS = address(0xccc);
address constant NATIVE_ETH = address(0xeee);
address constant WRAPPED_ETH = address(0xddd);
address public constant NATIVE_IMX = address(0xfff);
uint256 constant UNLIMITED_IMX_DEPOSIT_LIMIT = 0;

uint256 constant withdrawAmount = 0.5 ether;
Expand Down Expand Up @@ -59,6 +60,7 @@ contract RootERC20BridgeWithdrawIntegrationTest is
rootBridge.mapToken{value: 1}(token);
// And give the bridge some tokens
token.transfer(address(rootBridge), 100 ether);
imxToken.transfer(address(rootBridge), 100 ether);
}

function test_RevertsIf_WithdrawWithInvalidSourceChain() public {
Expand Down Expand Up @@ -119,6 +121,24 @@ contract RootERC20BridgeWithdrawIntegrationTest is
assertEq(bridgePostBal, bridgePreBal - withdrawAmount, "Incorrect bridge balance after withdraw");
}

function test_withdrawIMX_TransfersIMX() public {
bytes memory data = abi.encode(WITHDRAW_SIG, IMX_TOKEN_ADDRESS, address(this), address(this), withdrawAmount);

bytes32 commandId = bytes32("testCommandId");
string memory sourceAddress = rootBridge.childBridgeAdaptor();

uint256 thisPreBal = imxToken.balanceOf(address(this));
uint256 bridgePreBal = imxToken.balanceOf(address(rootBridge));

axelarAdaptor.execute(commandId, CHILD_CHAIN_NAME, sourceAddress, data);

uint256 thisPostBal = imxToken.balanceOf(address(this));
uint256 bridgePostBal = imxToken.balanceOf(address(rootBridge));

assertEq(thisPostBal, thisPreBal + withdrawAmount, "Incorrect user balance after withdraw");
assertEq(bridgePostBal, bridgePreBal - withdrawAmount, "Incorrect bridge balance after withdraw");
}

function test_withdraw_TransfersTokens_DifferentReceiver() public {
address receiver = address(987654321);
bytes memory data = abi.encode(WITHDRAW_SIG, address(token), address(this), receiver, withdrawAmount);
Expand All @@ -138,6 +158,25 @@ contract RootERC20BridgeWithdrawIntegrationTest is
assertEq(bridgePostBal, bridgePreBal - withdrawAmount, "Incorrect bridge balance after withdraw");
}

function test_withdrawIMX_TransfersIMX_DifferentReceiver() public {
address receiver = address(987654321);
bytes memory data = abi.encode(WITHDRAW_SIG, IMX_TOKEN_ADDRESS, address(this), receiver, withdrawAmount);

bytes32 commandId = bytes32("testCommandId");
string memory sourceAddress = rootBridge.childBridgeAdaptor();

uint256 receiverPreBal = imxToken.balanceOf(receiver);
uint256 bridgePreBal = imxToken.balanceOf(address(rootBridge));

axelarAdaptor.execute(commandId, CHILD_CHAIN_NAME, sourceAddress, data);

uint256 receiverPostBal = imxToken.balanceOf(receiver);
uint256 bridgePostBal = imxToken.balanceOf(address(rootBridge));

assertEq(receiverPostBal, receiverPreBal + withdrawAmount, "Incorrect user balance after withdraw");
assertEq(bridgePostBal, bridgePreBal - withdrawAmount, "Incorrect bridge balance after withdraw");
}

function test_withdraw_EmitsRootChainERC20WithdrawEvent() public {
bytes memory data = abi.encode(WITHDRAW_SIG, address(token), address(this), address(this), withdrawAmount);

Expand All @@ -155,6 +194,17 @@ contract RootERC20BridgeWithdrawIntegrationTest is
axelarAdaptor.execute(commandId, CHILD_CHAIN_NAME, sourceAddress, data);
}

function test_withdrawIMX_EmitsRootChainERC20WithdrawEvent() public {
bytes memory data = abi.encode(WITHDRAW_SIG, IMX_TOKEN_ADDRESS, address(this), address(this), withdrawAmount);

bytes32 commandId = bytes32("testCommandId");
string memory sourceAddress = rootBridge.childBridgeAdaptor();

vm.expectEmit();
emit RootChainERC20Withdraw(address(imxToken), NATIVE_IMX, address(this), address(this), withdrawAmount);
axelarAdaptor.execute(commandId, CHILD_CHAIN_NAME, sourceAddress, data);
}

function test_withdraw_EmitsRootChainERC20WithdrawEvent_DifferentReceiver() public {
address receiver = address(987654321);
bytes memory data = abi.encode(WITHDRAW_SIG, address(token), address(this), receiver, withdrawAmount);
Expand All @@ -168,4 +218,16 @@ contract RootERC20BridgeWithdrawIntegrationTest is
);
axelarAdaptor.execute(commandId, CHILD_CHAIN_NAME, sourceAddress, data);
}

function test_withdrawIMX_EmitsRootChainERC20WithdrawEvent_DifferentReceiver() public {
address receiver = address(987654321);
bytes memory data = abi.encode(WITHDRAW_SIG, IMX_TOKEN_ADDRESS, address(this), receiver, withdrawAmount);

bytes32 commandId = bytes32("testCommandId");
string memory sourceAddress = rootBridge.childBridgeAdaptor();

vm.expectEmit();
emit RootChainERC20Withdraw(address(imxToken), NATIVE_IMX, address(this), receiver, withdrawAmount);
axelarAdaptor.execute(commandId, CHILD_CHAIN_NAME, sourceAddress, data);
}
}
2 changes: 1 addition & 1 deletion test/unit/child/ChildAxelarBridgeAdaptor.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ contract ChildAxelarBridgeAdaptorUnitTest is Test, IChildAxelarBridgeAdaptorErro
axelarAdaptor.initialize(ROOT_CHAIN_NAME, address(mockChildERC20Bridge), address(mockChildAxelarGasService));
}

function test_Constructor_SetsValues() public {
function test_Initialize() public {
assertEq(address(axelarAdaptor.childBridge()), address(mockChildERC20Bridge), "childBridge not set");
assertEq(address(axelarAdaptor.gateway()), address(mockChildAxelarGateway), "gateway not set");
assertEq(axelarAdaptor.rootChain(), ROOT_CHAIN_NAME, "rootChain not set");
Expand Down
4 changes: 2 additions & 2 deletions test/unit/child/withdrawals/ChildERC20BridgeWithdrawTo.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ contract ChildERC20BridgeWithdrawToUnitTest is Test, IChildERC20BridgeEvents, IC
childBridge.withdrawTo{value: withdrawFee}(IChildERC20(address(childToken)), address(this), withdrawAmount);
}

function test_withdraw_ReducesBalance() public {
function test_withdrawTo_ReducesBalance() public {
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;

Expand All @@ -147,7 +147,7 @@ contract ChildERC20BridgeWithdrawToUnitTest is Test, IChildERC20BridgeEvents, IC
assertEq(postBal, preBal - withdrawAmount);
}

function test_withdraw_ReducesTotalSupply() public {
function test_withdrawTo_ReducesTotalSupply() public {
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {ChildERC20} from "../../../../src/child/ChildERC20.sol";
import {MockAdaptor} from "../../../../src/test/root/MockAdaptor.sol";
import {Utils} from "../../../utils.t.sol";

contract ChildERC20BridgewithdrawIMXToUnitTest is Test, IChildERC20BridgeEvents, IChildERC20BridgeErrors, Utils {
contract ChildERC20BridgeWithdrawIMXToUnitTest is Test, IChildERC20BridgeEvents, IChildERC20BridgeErrors, Utils {
address constant ROOT_BRIDGE = address(3);
string public ROOT_BRIDGE_ADAPTOR = Strings.toHexString(address(4));
string constant ROOT_CHAIN_NAME = "test";
Expand Down Expand Up @@ -105,7 +105,7 @@ contract ChildERC20BridgewithdrawIMXToUnitTest is Test, IChildERC20BridgeEvents,
childBridge.withdrawIMXTo{value: withdrawFee + withdrawAmount}(receiver, withdrawAmount);
}

function test_WithdrawIMX_ReducesBalance() public {
function test_WithdrawIMXTo_ReducesBalance() public {
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;

Expand All @@ -117,7 +117,7 @@ contract ChildERC20BridgewithdrawIMXToUnitTest is Test, IChildERC20BridgeEvents,
assertEq(postBal, preBal - withdrawAmount - withdrawFee, "Balance not reduced");
}

function test_WithdrawIMX_PaysFee() public {
function test_WithdrawIMXTo_PaysFee() public {
uint256 withdrawFee = 300;
uint256 withdrawAmount = 7 ether;

Expand Down
6 changes: 3 additions & 3 deletions test/unit/root/RootAxelarBridgeAdaptor.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,20 @@ contract RootAxelarBridgeAdaptorTest is Test, IRootAxelarBridgeAdaptorEvents, IR
vm.deal(address(stubRootBridge), 99999999999);
}

function test_Constructor() public {
function test_Initialize() public {
assertEq(address(axelarAdaptor.rootBridge()), address(stubRootBridge), "rootBridge not set");
assertEq(axelarAdaptor.childChain(), CHILD_CHAIN_NAME, "childChain not set");
assertEq(address(axelarAdaptor.gateway()), address(mockAxelarGateway), "axelarGateway not set");
assertEq(address(axelarAdaptor.gasService()), address(axelarGasService), "axelarGasService not set");
}

function test_RevertWhen_InitializerGivenZeroAddress() public {
function test_RevertWhen_InitializeGivenZeroAddress() public {
RootAxelarBridgeAdaptor newAdaptor = new RootAxelarBridgeAdaptor(address(mockAxelarGateway));
vm.expectRevert(ZeroAddresses.selector);
newAdaptor.initialize(address(0), CHILD_CHAIN_NAME, address(axelarGasService));
}

function test_RevertWhen_ConstructorGivenEmptyChildChainName() public {
function test_RevertWhen_InitializeGivenEmptyChildChainName() public {
RootAxelarBridgeAdaptor newAdaptor = new RootAxelarBridgeAdaptor(address(mockAxelarGateway));
vm.expectRevert(InvalidChildChain.selector);
newAdaptor.initialize(address(this), "", address(axelarGasService));
Expand Down
Loading

0 comments on commit c5bef71

Please sign in to comment.