Skip to content

Commit

Permalink
Fix failing test
Browse files Browse the repository at this point in the history
  • Loading branch information
ermyas committed Oct 25, 2023
1 parent a3dcb0d commit ea4dcdc
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 49 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Compiler files
cache/
out/
.idea/

# Ignores development broadcast logs
!/broadcast
Expand All @@ -22,4 +23,4 @@ docs/
# Contract addresses
addresses.json

/node_modules
/node_modules
9 changes: 7 additions & 2 deletions script/InitializeRootContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";

contract InitializeRootContracts is Script {
function run() public {
RootERC20Bridge rootERC20Bridge = RootERC20Bridge(vm.envAddress("ROOT_ERC20_BRIDGE"));
RootERC20Bridge rootERC20Bridge = RootERC20Bridge(payable(vm.envAddress("ROOT_ERC20_BRIDGE")));
RootAxelarBridgeAdaptor rootBridgeAdaptor = RootAxelarBridgeAdaptor(vm.envAddress("ROOT_BRIDGE_ADAPTOR"));
address rootChainChildTokenTemplate = vm.envAddress("ROOTCHAIN_CHILD_TOKEN_TEMPLATE");
address childBridgeAdaptor = vm.envAddress("CHILD_BRIDGE_ADAPTOR");
Expand All @@ -31,7 +31,12 @@ contract InitializeRootContracts is Script {
vm.startBroadcast(rootPrivateKey);

rootERC20Bridge.initialize(
address(rootBridgeAdaptor), childERC20Bridge, childBridgeAdaptor, rootChainChildTokenTemplate, rootIMXToken, rootWETHToken
address(rootBridgeAdaptor),
childERC20Bridge,
childBridgeAdaptor,
rootChainChildTokenTemplate,
rootIMXToken,
rootWETHToken
);

rootBridgeAdaptor.setChildBridgeAdaptor();
Expand Down
6 changes: 1 addition & 5 deletions src/interfaces/root/IERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,7 @@ interface IERC20 {
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
Expand Down
31 changes: 15 additions & 16 deletions src/root/RootERC20Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import {IRootERC20BridgeEvents, IRootERC20BridgeErrors} from "../interfaces/root
import {IRootERC20BridgeAdaptor} from "../interfaces/root/IRootERC20BridgeAdaptor.sol";
import {IChildERC20} from "../interfaces/child/IChildERC20.sol";
import {IWETH} from "../interfaces/root/IWETH.sol";
import {console2} from "forge-std/Test.sol";

import "forge-std/console.sol";
/**
* @notice RootERC20Bridge is a bridge that allows ERC20 tokens to be transferred from the root chain to the child chain.
* @dev This contract is designed to be upgradeable.
Expand All @@ -23,6 +22,7 @@ import {console2} from "forge-std/Test.sol";
* @dev Because of this pattern, any checks or logic that is agnostic to the messaging protocol should be done in RootERC20Bridge.
* @dev Any checks or logic that is specific to the underlying messaging protocol should be done in the bridge adaptor.
*/

contract RootERC20Bridge is
Ownable2Step,
Initializable,
Expand Down Expand Up @@ -101,23 +101,25 @@ contract RootERC20Bridge is
}

function depositETH(uint256 amount) external payable {
//override removed?
_depositETH(msg.sender, amount);
}

function depositToETH(address receiver, uint256 amount) external payable {
//override removed?
_depositETH(receiver, amount);
}

function _depositUnwrappedETH(address receiver, uint256 amount) private {
_deposit(IERC20Metadata(NATIVE_ETH), receiver, amount, msg.value);
}

function _depositETH(address receiver, uint256 amount) private {
if (msg.value < amount) {
revert InsufficientValue();
}

uint256 expectedBalance = address(this).balance - (msg.value - amount);

_deposit(IERC20Metadata(NATIVE_ETH), receiver, amount);
_deposit(IERC20Metadata(NATIVE_ETH), receiver, amount, msg.value - amount);

// invariant check to ensure that the root native balance has increased by the amount deposited
if (address(this).balance != expectedBalance) {
Expand All @@ -143,28 +145,28 @@ contract RootERC20Bridge is
* @inheritdoc IRootERC20Bridge
*/
function deposit(IERC20Metadata rootToken, uint256 amount) external payable override {
_depositWETHorERC20(rootToken, msg.sender, amount);
_depositToken(rootToken, msg.sender, amount);
}

/**
* @inheritdoc IRootERC20Bridge
*/
function depositTo(IERC20Metadata rootToken, address receiver, uint256 amount) external payable override {
_depositWETHorERC20(rootToken, receiver, amount);
_depositToken(rootToken, receiver, amount);
}

function _depositWETHorERC20(IERC20Metadata rootToken, address receiver, uint256 amount) private {
function _depositToken(IERC20Metadata rootToken, address receiver, uint256 amount) private {
if (address(rootToken) == rootWETHToken) {
_unwrapWETH(amount);
_depositETH(receiver, amount);
_depositUnwrappedETH(receiver, amount);
} else {
_depositERC20(rootToken, receiver, amount);
}
}

function _depositERC20(IERC20Metadata rootToken, address receiver, uint256 amount) private {
uint256 expectedBalance = rootToken.balanceOf(address(this)) + amount;
_deposit(rootToken, receiver, amount);
_deposit(rootToken, receiver, amount, msg.value);
// invariant check to ensure that the root token balance has increased by the amount deposited
// slither-disable-next-line incorrect-equality
if (rootToken.balanceOf(address(this)) != expectedBalance) {
Expand Down Expand Up @@ -208,17 +210,15 @@ contract RootERC20Bridge is
return childToken;
}

function _deposit(IERC20Metadata rootToken, address receiver, uint256 amount) private {
function _deposit(IERC20Metadata rootToken, address receiver, uint256 amount, uint256 feeAmount) private {
if (receiver == address(0) || address(rootToken) == address(0)) {
revert ZeroAddress();
}

if (amount == 0) {
revert ZeroAmount();
}

address childToken;
uint256 feeAmount;

// The native token does not need to be mapped since it should have been mapped on initialization
// The native token also cannot be transferred since it was received in the payable function call
Expand All @@ -234,9 +234,6 @@ contract RootERC20Bridge is
}
// ERC20 must be transferred explicitly
rootToken.safeTransferFrom(msg.sender, address(this), amount);
feeAmount = msg.value;
} else {
feeAmount = msg.value - amount;
}

// Deposit sig, root token address, depositor, receiver, amount
Expand All @@ -260,4 +257,6 @@ contract RootERC20Bridge is
}
rootBridgeAdaptor = IRootERC20BridgeAdaptor(newRootBridgeAdaptor);
}

receive() external payable {}
}
5 changes: 2 additions & 3 deletions test/integration/root/RootERC20Bridge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,8 @@ contract RootERC20BridgeIntegrationTest is Test, IRootERC20BridgeEvents, IRootAx
uint256 tokenAmount = 300;
string memory childBridgeAdaptorString = Strings.toHexString(CHILD_BRIDGE_ADAPTOR);

(, bytes memory predictedPayload) = setupDeposit(
IMX_TOKEN_ADDRESS, rootBridge, mapTokenFee, depositFee, tokenAmount, false
);
(, bytes memory predictedPayload) =
setupDeposit(IMX_TOKEN_ADDRESS, rootBridge, mapTokenFee, depositFee, tokenAmount, false);

vm.expectEmit(address(axelarAdaptor));
emit MapTokenAxelarMessage(CHILD_CHAIN_NAME, childBridgeAdaptorString, predictedPayload);
Expand Down
42 changes: 22 additions & 20 deletions test/unit/root/RootERC20Bridge.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
mockAxelarAdaptor = new MockAdaptor();

// The specific ERC20 token template does not matter for these unit tests
rootBridge.initialize(address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, WRAPPED_ETH);
rootBridge.initialize(
address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, WRAPPED_ETH
);
}

/**
Expand All @@ -61,7 +63,9 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid

function test_RevertIfInitializeTwice() public {
vm.expectRevert("Initializable: contract is already initialized");
rootBridge.initialize(address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, WRAPPED_ETH);
rootBridge.initialize(
address(mockAxelarAdaptor), CHILD_BRIDGE, CHILD_BRIDGE_ADAPTOR, address(token), IMX_TOKEN, WRAPPED_ETH
);
}

function test_RevertIf_InitializeWithAZeroAddressRootAdapter() public {
Expand Down Expand Up @@ -208,8 +212,7 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid

function test_depositETHCallsSendMessage() public {
uint256 amount = 1000;
(, bytes memory predictedPayload) =
setupDeposit(NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, false);
(, bytes memory predictedPayload) = setupDeposit(NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, false);

vm.expectCall(
address(mockAxelarAdaptor),
Expand Down Expand Up @@ -244,9 +247,8 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
function test_depositToETHCallsSendMessage() public {
uint256 amount = 1000;
address receiver = address(12345);
(, bytes memory predictedPayload) = setupDepositTo(
NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, receiver, false
);
(, bytes memory predictedPayload) =
setupDepositTo(NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, receiver, false);
vm.expectCall(
address(mockAxelarAdaptor),
depositFee,
Expand All @@ -259,9 +261,7 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
function test_depositToETHEmitsNativeEthDepositEvent() public {
uint256 amount = 1000;
address receiver = address(12345);
setupDepositTo(
NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, receiver, false
);
setupDepositTo(NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, receiver, false);

vm.expectEmit();
emit NativeEthDeposit(NATIVE_ETH, rootBridge.childETHToken(), address(this), receiver, amount);
Expand All @@ -271,9 +271,7 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
function test_RevertIf_depositToETHInsufficientValue() public {
uint256 amount = 1000;
address receiver = address(12345);
setupDepositTo(
NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, receiver, false
);
setupDepositTo(NATIVE_ETH, rootBridge, mapTokenFee, depositFee, amount, receiver, false);

vm.expectRevert(InsufficientValue.selector);
rootBridge.depositToETH{value: (amount / 2) + depositFee}(receiver, amount);
Expand Down Expand Up @@ -318,21 +316,23 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
rootBridge.depositTo{value: depositFee}(token, receiver, amount);
}

/**
/**
* DEPOSIT WETH
*/

function test_depositWETHCallsSendMessage() public {
uint256 amount = 100;
(, bytes memory predictedPayload) = setupDeposit(WRAPPED_ETH, rootBridge, mapTokenFee, depositFee, amount, false);
(, bytes memory predictedPayload) =
setupDeposit(WRAPPED_ETH, rootBridge, mapTokenFee, depositFee, amount, false);

bytes memory pp = abi.encode(rootBridge.DEPOSIT_SIG(), NATIVE_ETH, address(this), address(this), amount);

vm.expectCall(
address(mockAxelarAdaptor),
depositFee,
abi.encodeWithSelector(mockAxelarAdaptor.sendMessage.selector, predictedPayload, address(this))
abi.encodeWithSelector(mockAxelarAdaptor.sendMessage.selector, pp, address(this))
);

rootBridge.deposit{value: depositFee}(ERC20PresetMinterPauser(WRAPPED_ETH), amount);
rootBridge.deposit{value: depositFee}(IERC20Metadata(WRAPPED_ETH), amount);
}

/**
Expand All @@ -341,7 +341,8 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid

function test_depositCallsSendMessage() public {
uint256 amount = 100;
(, bytes memory predictedPayload) = setupDeposit(address(token), rootBridge, mapTokenFee, depositFee, amount, true);
(, bytes memory predictedPayload) =
setupDeposit(address(token), rootBridge, mapTokenFee, depositFee, amount, true);

vm.expectCall(
address(mockAxelarAdaptor),
Expand Down Expand Up @@ -453,7 +454,8 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid
uint256 amount = 100;
address receiver = address(12345);

(address childToken,) = setupDepositTo(address(token), rootBridge, mapTokenFee, depositFee, amount, receiver, true);
(address childToken,) =
setupDepositTo(address(token), rootBridge, mapTokenFee, depositFee, amount, receiver, true);

vm.expectEmit();
emit ERC20Deposit(address(token), childToken, address(this), receiver, amount);
Expand Down
6 changes: 4 additions & 2 deletions test/utils.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ contract Utils is Test {
address(axelarGasService)
);

rootBridge.initialize(address(axelarAdaptor), childBridge, childBridgeAdaptor, address(token), imxTokenAddress, wethTokenAddress);
rootBridge.initialize(
address(axelarAdaptor), childBridge, childBridgeAdaptor, address(token), imxTokenAddress, wethTokenAddress
);
axelarAdaptor.setChildBridgeAdaptor();
}

Expand Down Expand Up @@ -96,7 +98,7 @@ contract Utils is Test {

if (token == address(0xeee)) {
vm.deal(to, tokenAmount + depositFee);
} else if(address(token) == address(0xddd)) {
} else if (address(token) == address(0xddd)) {
vm.deal(to, tokenAmount + depositFee);
IWETH(token).deposit{value: tokenAmount}();
IWETH(token).approve(address(rootBridge), tokenAmount);
Expand Down

0 comments on commit ea4dcdc

Please sign in to comment.