diff --git a/src/child/ChildERC20Bridge.sol b/src/child/ChildERC20Bridge.sol index a603ac2a..48562440 100644 --- a/src/child/ChildERC20Bridge.sol +++ b/src/child/ChildERC20Bridge.sol @@ -67,7 +67,13 @@ contract ChildERC20Bridge is /** * @notice Fallback function on recieving native IMX. */ - receive() external payable {} + receive() external payable { + // Revert if sender if not the wIMX token + // Or the wIMXToken is not set (contract not initialized) + if (msg.sender != wIMXToken || wIMXToken == address(0)) { + revert NonWrappedNativeTransfer(); + } + } /** * @notice Initialization function for ChildERC20Bridge. diff --git a/src/interfaces/child/IChildERC20Bridge.sol b/src/interfaces/child/IChildERC20Bridge.sol index 729c9ddf..c17e8c5c 100644 --- a/src/interfaces/child/IChildERC20Bridge.sol +++ b/src/interfaces/child/IChildERC20Bridge.sol @@ -158,4 +158,6 @@ interface IChildERC20BridgeErrors { error TransferWIMXFailed(); /// @notice Error when token balance invariant check fails. error BalanceInvariantCheckFailed(uint256 actualBalance, uint256 expectedBalance); + /// @notice Error when native transfer is sent to contract from non wrapped-token address. + error NonWrappedNativeTransfer(); } diff --git a/src/interfaces/root/IRootERC20Bridge.sol b/src/interfaces/root/IRootERC20Bridge.sol index 2f29a6fa..912cbddf 100644 --- a/src/interfaces/root/IRootERC20Bridge.sol +++ b/src/interfaces/root/IRootERC20Bridge.sol @@ -125,4 +125,6 @@ interface IRootERC20BridgeErrors { error ImxDepositLimitExceeded(); /// @notice Error when the IMX deposit limit is set below the amount of IMX already deposited error ImxDepositLimitTooLow(); + /// @notice Error when native transfer is sent to contract from non wrapped-token address. + error NonWrappedNativeTransfer(); } diff --git a/src/root/RootERC20Bridge.sol b/src/root/RootERC20Bridge.sol index 56fdd3c1..339e7f2b 100644 --- a/src/root/RootERC20Bridge.sol +++ b/src/root/RootERC20Bridge.sol @@ -168,7 +168,13 @@ contract RootERC20Bridge is /** * @dev method to receive the ETH back from the WETH contract when it is unwrapped */ - receive() external payable {} + receive() external payable { + // Revert if sender if not the wIMX token + // Or the wIMXToken is not set (contract not initialized) + if (msg.sender != rootWETHToken || rootWETHToken == address(0)) { + revert NonWrappedNativeTransfer(); + } + } /** * @inheritdoc IRootERC20Bridge diff --git a/test/unit/child/ChildERC20Bridge.t.sol b/test/unit/child/ChildERC20Bridge.t.sol index 5eeae329..91a2593d 100644 --- a/test/unit/child/ChildERC20Bridge.t.sol +++ b/test/unit/child/ChildERC20Bridge.t.sol @@ -62,6 +62,11 @@ contract ChildERC20BridgeUnitTest is Test, IChildERC20BridgeEvents, IChildERC20B assertFalse(address(childBridge.childETHToken()).code.length == 0, "childETHToken contract empty"); } + function test_RevertIfNativeTransferIsFromNonWIMX() public { + vm.expectRevert(NonWrappedNativeTransfer.selector); + payable(childBridge).transfer(1); + } + function test_RevertIfInitializeTwice() public { IChildERC20Bridge.InitializationRoles memory roles = IChildERC20Bridge.InitializationRoles({ defaultAdmin: address(this), diff --git a/test/unit/root/RootERC20Bridge.t.sol b/test/unit/root/RootERC20Bridge.t.sol index a2788f18..fd85608d 100644 --- a/test/unit/root/RootERC20Bridge.t.sol +++ b/test/unit/root/RootERC20Bridge.t.sol @@ -87,6 +87,11 @@ contract RootERC20BridgeUnitTest is Test, IRootERC20BridgeEvents, IRootERC20Brid assertEq(rootBridge.rootWETHToken(), WRAPPED_ETH, "rootWETHToken not set"); } + function test_RevertIfNativeTransferIsFromNonWETH() public { + vm.expectRevert(NonWrappedNativeTransfer.selector); + payable(rootBridge).transfer(1); + } + function test_RevertIfInitializeTwice() public { IRootERC20Bridge.InitializationRoles memory roles = IRootERC20Bridge.InitializationRoles({ defaultAdmin: address(this),