From 4224bd6e2b40c6ca2088c982bfafd6be748ec152 Mon Sep 17 00:00:00 2001 From: wcgcyx Date: Tue, 7 Nov 2023 20:09:23 +1000 Subject: [PATCH] Update --- .../ChildAxelarBridgeWithdrawWIMX.t.sol | 148 ++++++++++++ .../ChildAxelarBridgeWithdrawWIMXTo.t.sol | 228 ++++++++++++++++++ test/utils.t.sol | 3 + 3 files changed, 379 insertions(+) create mode 100644 test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMX.t.sol create mode 100644 test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMXTo.t.sol diff --git a/test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMX.t.sol b/test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMX.t.sol new file mode 100644 index 00000000..0e0a44c2 --- /dev/null +++ b/test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMX.t.sol @@ -0,0 +1,148 @@ +// SPDX-License-Identifier: Apache 2.0 +pragma solidity ^0.8.19; + +import {Test, console2} from "forge-std/Test.sol"; +import {ERC20PresetMinterPauser} from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {MockAxelarGateway} from "../../../../src/test/root/MockAxelarGateway.sol"; +import {MockAxelarGasService} from "../../../../src/test/root/MockAxelarGasService.sol"; +import {ChildERC20Bridge, IChildERC20BridgeEvents} from "../../../../src/child/ChildERC20Bridge.sol"; +import { + ChildAxelarBridgeAdaptor, + IChildAxelarBridgeAdaptorEvents, + IChildAxelarBridgeAdaptorErrors +} from "../../../../src/child/ChildAxelarBridgeAdaptor.sol"; +import {Utils} from "../../../utils.t.sol"; +import {WETH} from "../../../../src/test/root/WETH.sol"; +import {WIMX} from "../../../../src/child/WIMX.sol"; +import {ChildERC20} from "../../../../src/child/ChildERC20.sol"; +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; + +contract ChildERC20BridgeWithdrawWIMXIntegrationTest is + Test, + IChildERC20BridgeEvents, + IChildAxelarBridgeAdaptorEvents, + IChildAxelarBridgeAdaptorErrors, + Utils +{ + address constant CHILD_BRIDGE = address(3); + address constant CHILD_BRIDGE_ADAPTOR = address(4); + string constant CHILD_CHAIN_NAME = "test"; + address constant ROOT_IMX_TOKEN = address(555555); + address constant NATIVE_ETH = address(0xeee); + address constant WRAPPED_ETH = address(0xddd); + address constant WRAPPED_IMX = address(0xabc); + + ChildERC20Bridge public childBridge; + ChildAxelarBridgeAdaptor public axelarAdaptor; + address public rootToken; + address public rootImxToken; + ChildERC20 public childTokenTemplate; + MockAxelarGasService public axelarGasService; + MockAxelarGateway public mockAxelarGateway; + WIMX public wIMXToken; + + function setUp() public { + (childBridge, axelarAdaptor, rootToken, rootImxToken, childTokenTemplate, axelarGasService, mockAxelarGateway) = + childIntegrationSetup(); + wIMXToken = WIMX(payable(WRAPPED_IMX)); + Address.sendValue(payable(wIMXToken), 100 ether); + } + + function test_WithdrawWIMX_CallsBridgeAdaptor() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + vm.expectCall( + address(axelarAdaptor), + withdrawFee, + abi.encodeWithSelector(axelarAdaptor.sendMessage.selector, predictedPayload, address(this)) + ); + + + childBridge.withdrawWIMX{value: withdrawFee}(withdrawAmount); + } + + function test_WithdrawWIMX_CallsAxelarGateway() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + vm.expectCall( + address(mockAxelarGateway), + 0, + abi.encodeWithSelector( + mockAxelarGateway.callContract.selector, + childBridge.rootChain(), + childBridge.rootERC20BridgeAdaptor(), + predictedPayload + ) + ); + + childBridge.withdrawWIMX{value: withdrawFee}(withdrawAmount); + } + + function test_WithdrawWIMX_CallsGasService() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + + vm.expectCall( + address(axelarGasService), + withdrawFee, + abi.encodeWithSelector( + axelarGasService.payNativeGasForContractCall.selector, + address(axelarAdaptor), + childBridge.rootChain(), + childBridge.rootERC20BridgeAdaptor(), + predictedPayload, + address(this) + ) + ); + + childBridge.withdrawWIMX{value: withdrawFee}(withdrawAmount); + } + + function test_WithdrawWIMX_EmitsAxelarMessageSentEvent() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + + vm.expectEmit(address(axelarAdaptor)); + emit AxelarMessageSent(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload); + + childBridge.withdrawWIMX{value: withdrawFee}(withdrawAmount); + } + + function test_WithdrawWIMX_ReducesBalance() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + uint256 preBal = address(this).balance; + uint256 preTokenBal = wIMXToken.balanceOf(address(this)); + uint256 preGasBal = address(axelarGasService).balance; + + wIMXToken.approve(address(childBridge), withdrawAmount); + childBridge.withdrawWIMX{value: withdrawFee}(withdrawAmount); + + uint256 postBal = address(this).balance; + uint256 postTokenBal = wIMXToken.balanceOf(address(this)); + uint256 postGasBal = address(axelarGasService).balance; + + assertEq(postBal, preBal - withdrawFee, "Balance not reduced"); + assertEq(postTokenBal, preTokenBal - withdrawAmount); + assertEq(postGasBal, preGasBal + withdrawFee, "Gas service not getting paid"); + } +} \ No newline at end of file diff --git a/test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMXTo.t.sol b/test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMXTo.t.sol new file mode 100644 index 00000000..d8110e41 --- /dev/null +++ b/test/integration/child/withdrawals/ChildAxelarBridgeWithdrawWIMXTo.t.sol @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: Apache 2.0 +pragma solidity ^0.8.19; + +import {Test, console2} from "forge-std/Test.sol"; +import {ERC20PresetMinterPauser} from "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; +import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; +import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; +import {MockAxelarGateway} from "../../../../src/test/root/MockAxelarGateway.sol"; +import {MockAxelarGasService} from "../../../../src/test/root/MockAxelarGasService.sol"; +import {ChildERC20Bridge, IChildERC20BridgeEvents} from "../../../../src/child/ChildERC20Bridge.sol"; +import { + ChildAxelarBridgeAdaptor, + IChildAxelarBridgeAdaptorEvents, + IChildAxelarBridgeAdaptorErrors +} from "../../../../src/child/ChildAxelarBridgeAdaptor.sol"; +import {Utils} from "../../../utils.t.sol"; +import {WETH} from "../../../../src/test/root/WETH.sol"; +import {WIMX} from "../../../../src/child/WIMX.sol"; +import {ChildERC20} from "../../../../src/child/ChildERC20.sol"; +import {Address} from "@openzeppelin/contracts/utils/Address.sol"; + +contract ChildERC20BridgeWithdrawWIMXToIntegrationTest is + Test, + IChildERC20BridgeEvents, + IChildAxelarBridgeAdaptorEvents, + IChildAxelarBridgeAdaptorErrors, + Utils +{ + address constant CHILD_BRIDGE = address(3); + address constant CHILD_BRIDGE_ADAPTOR = address(4); + string constant CHILD_CHAIN_NAME = "test"; + address constant ROOT_IMX_TOKEN = address(555555); + address constant NATIVE_ETH = address(0xeee); + address constant WRAPPED_ETH = address(0xddd); + address constant WRAPPED_IMX = address(0xabc); + + ChildERC20Bridge public childBridge; + ChildAxelarBridgeAdaptor public axelarAdaptor; + address public rootToken; + address public rootImxToken; + ChildERC20 public childTokenTemplate; + MockAxelarGasService public axelarGasService; + MockAxelarGateway public mockAxelarGateway; + WIMX public wIMXToken; + + function setUp() public { + (childBridge, axelarAdaptor, rootToken, rootImxToken, childTokenTemplate, axelarGasService, mockAxelarGateway) = + childIntegrationSetup(); + wIMXToken = WIMX(payable(WRAPPED_IMX)); + Address.sendValue(payable(wIMXToken), 100 ether); + } + + function test_WithdrawWIMXTo_CallsBridgeAdaptor() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + vm.expectCall( + address(axelarAdaptor), + withdrawFee, + abi.encodeWithSelector(axelarAdaptor.sendMessage.selector, predictedPayload, address(this)) + ); + + + childBridge.withdrawWIMXTo{value: withdrawFee}(address(this), withdrawAmount); + } + + function test_WithdrawWIMXToWithDifferentAccount_CallsBridgeAdaptor() public { + address receiver = address(0xabcd); + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), receiver, withdrawAmount); + vm.expectCall( + address(axelarAdaptor), + withdrawFee, + abi.encodeWithSelector(axelarAdaptor.sendMessage.selector, predictedPayload, address(this)) + ); + + + childBridge.withdrawWIMXTo{value: withdrawFee}(receiver, withdrawAmount); + } + + function test_WithdrawWIMXTo_CallsAxelarGateway() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + vm.expectCall( + address(mockAxelarGateway), + 0, + abi.encodeWithSelector( + mockAxelarGateway.callContract.selector, + childBridge.rootChain(), + childBridge.rootERC20BridgeAdaptor(), + predictedPayload + ) + ); + + childBridge.withdrawWIMXTo{value: withdrawFee}(address(this), withdrawAmount); + } + + function test_WithdrawWIMXToWithDifferentAccount_CallsAxelarGateway() public { + address receiver = address(0xabcd); + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), receiver, withdrawAmount); + vm.expectCall( + address(mockAxelarGateway), + 0, + abi.encodeWithSelector( + mockAxelarGateway.callContract.selector, + childBridge.rootChain(), + childBridge.rootERC20BridgeAdaptor(), + predictedPayload + ) + ); + + childBridge.withdrawWIMXTo{value: withdrawFee}(receiver, withdrawAmount); + } + + function test_WithdrawWIMXTo_CallsGasService() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + + vm.expectCall( + address(axelarGasService), + withdrawFee, + abi.encodeWithSelector( + axelarGasService.payNativeGasForContractCall.selector, + address(axelarAdaptor), + childBridge.rootChain(), + childBridge.rootERC20BridgeAdaptor(), + predictedPayload, + address(this) + ) + ); + + childBridge.withdrawWIMXTo{value: withdrawFee}(address(this), withdrawAmount); + } + + function test_WithdrawWIMXToWithDifferentAccount_CallsGasService() public { + address receiver = address(0xabcd); + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), receiver, withdrawAmount); + + vm.expectCall( + address(axelarGasService), + withdrawFee, + abi.encodeWithSelector( + axelarGasService.payNativeGasForContractCall.selector, + address(axelarAdaptor), + childBridge.rootChain(), + childBridge.rootERC20BridgeAdaptor(), + predictedPayload, + address(this) + ) + ); + + childBridge.withdrawWIMXTo{value: withdrawFee}(receiver, withdrawAmount); + } + + function test_WithdrawWIMXTo_EmitsAxelarMessageSentEvent() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), address(this), withdrawAmount); + + vm.expectEmit(address(axelarAdaptor)); + emit AxelarMessageSent(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload); + + childBridge.withdrawWIMXTo{value: withdrawFee}(address(this), withdrawAmount); + } + + function test_WithdrawWIMXToWithDifferentAccount_EmitsAxelarMessageSentEvent() public { + address receiver = address(0xabcd); + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + wIMXToken.approve(address(childBridge), withdrawAmount); + bytes memory predictedPayload = + abi.encode(WITHDRAW_SIG, ROOT_IMX_TOKEN, address(this), receiver, withdrawAmount); + + vm.expectEmit(address(axelarAdaptor)); + emit AxelarMessageSent(childBridge.rootChain(), childBridge.rootERC20BridgeAdaptor(), predictedPayload); + + childBridge.withdrawWIMXTo{value: withdrawFee}(receiver, withdrawAmount); + } + + function test_WithdrawWIMXTo_ReducesBalance() public { + uint256 withdrawFee = 300; + uint256 withdrawAmount = 7 ether; + + uint256 preBal = address(this).balance; + uint256 preTokenBal = wIMXToken.balanceOf(address(this)); + uint256 preGasBal = address(axelarGasService).balance; + + wIMXToken.approve(address(childBridge), withdrawAmount); + childBridge.withdrawWIMXTo{value: withdrawFee}(address(this), withdrawAmount); + + uint256 postBal = address(this).balance; + uint256 postTokenBal = wIMXToken.balanceOf(address(this)); + uint256 postGasBal = address(axelarGasService).balance; + + assertEq(postBal, preBal - withdrawFee, "Balance not reduced"); + assertEq(postTokenBal, preTokenBal - withdrawAmount); + assertEq(postGasBal, preGasBal + withdrawFee, "Gas service not getting paid"); + } +} \ No newline at end of file diff --git a/test/utils.t.sol b/test/utils.t.sol index 2eecfec9..c297cb41 100644 --- a/test/utils.t.sol +++ b/test/utils.t.sol @@ -11,6 +11,7 @@ import {ChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol"; import {ChildAxelarBridgeAdaptor} from "../src/child/ChildAxelarBridgeAdaptor.sol"; import {WETH} from "../src/test/root/WETH.sol"; import {IWETH} from "../src/interfaces/root/IWETH.sol"; +import {WIMX} from "../src/child/WIMX.sol"; import {IChildERC20, ChildERC20} from "../src/child/ChildERC20.sol"; import {RootAxelarBridgeAdaptor} from "../src/root/RootAxelarBridgeAdaptor.sol"; @@ -36,6 +37,8 @@ contract Utils is Test { rootToken = address(44444); address childWIMX = address(0xabc); + deployCodeTo("WIMX.sol", childWIMX); + axelarGasService = new MockAxelarGasService(); mockAxelarGateway = new MockAxelarGateway(); childTokenTemplate = new ChildERC20();