diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index a876ef795f7..abec06bf78b 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -376,6 +376,20 @@ contract L1StandardBridge_Receive_Test is CommonTest { (bool revertsAsExpected,) = address(l1StandardBridge).call{ value: 100 }(hex""); assertTrue(revertsAsExpected, "expectRevert: call did not revert"); } + + /// @notice Tests that receive reverts when custom gas token is enabled and value is sent. + function testFuzz_receive_withCustomGasToken_reverts(uint256 _value) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IOptimismPortal2.OptimismPortal_NotAllowedOnCGTMode.selector); + + (bool revertsAsExpected,) = address(l1StandardBridge).call{ value: _value }(hex""); + assertTrue(revertsAsExpected, "expectRevert: call did not revert"); + } } /// @title L1StandardBridge_DepositETH_Test @@ -427,6 +441,32 @@ contract L1StandardBridge_DepositETH_Test is L1StandardBridge_TestInit { vm.prank(alice); l1StandardBridge.depositETH{ value: 1 }(300, hex""); } + + /// @notice Tests that depositETH reverts when custom gas token is enabled and value is sent. + function testFuzz_depositETH_withCustomGasToken_reverts(uint256 _value, uint32 _minGasLimit) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IOptimismPortal2.OptimismPortal_NotAllowedOnCGTMode.selector); + l1StandardBridge.depositETH{ value: _value }(_minGasLimit, hex"dead"); + } + + /// @notice Tests that depositETH reverts when custom gas token is enabled for EOA with 7702 delegation. + function testFuzz_depositETH_fromEOA7702WithCustomGasToken_reverts(uint256 _value, uint32 _minGasLimit) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + _value = bound(_value, 1, type(uint128).max); + + // Set alice to have 7702 code. + vm.etch(alice, abi.encodePacked(hex"EF0100", address(0))); + + vm.deal(alice, _value); + vm.prank(alice, alice); + vm.expectRevert(IOptimismPortal2.OptimismPortal_NotAllowedOnCGTMode.selector); + l1StandardBridge.depositETH{ value: _value }(_minGasLimit, hex"dead"); + } } /// @title L1StandardBridge_DepositETHTo_Test @@ -474,6 +514,23 @@ contract L1StandardBridge_DepositETHTo_Test is L1StandardBridge_TestInit { assertEq(address(optimismPortal2).balance, portalBalanceBefore + _amount); } } + + /// @notice Tests that depositETHTo reverts when custom gas token is enabled and value is sent. + function testFuzz_depositETHTo_withCustomGasToken_reverts( + address _to, + uint256 _value, + uint32 _minGasLimit + ) + external + { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + vm.assume(_to != address(0)); + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + vm.prank(alice); + vm.expectRevert(IOptimismPortal2.OptimismPortal_NotAllowedOnCGTMode.selector); + l1StandardBridge.depositETHTo{ value: _value }(_to, _minGasLimit, hex"dead"); + } } /// @title L1StandardBridge_DepositERC20_Test @@ -877,4 +934,35 @@ contract L1StandardBridge_Uncategorized_Test is L1StandardBridge_TestInit { vm.expectRevert("StandardBridge: cannot send to messenger"); l1StandardBridge.finalizeBridgeETH{ value: 100 }(alice, messenger, 100, hex""); } + + /// @notice Tests that bridgeETH reverts when custom gas token is enabled and value is sent. + function testFuzz_bridgeETH_withCustomGasToken_reverts(uint256 _value, uint32 _minGasLimit) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IOptimismPortal2.OptimismPortal_NotAllowedOnCGTMode.selector); + l1StandardBridge.bridgeETH{ value: _value }(_minGasLimit, hex"dead"); + } + + /// @notice Tests that bridgeETHTo reverts when custom gas token is enabled and value is sent. + function testFuzz_bridgeETHTo_withCustomGasToken_reverts( + address _to, + uint256 _value, + uint32 _minGasLimit + ) + external + { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + vm.assume(_to != address(0)); + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice); + vm.expectRevert(IOptimismPortal2.OptimismPortal_NotAllowedOnCGTMode.selector); + l1StandardBridge.bridgeETHTo{ value: _value }(_to, _minGasLimit, hex"dead"); + } } diff --git a/packages/contracts-bedrock/test/L2/FeeVault.t.sol b/packages/contracts-bedrock/test/L2/FeeVault.t.sol index 56898a5a356..aa8a572335b 100644 --- a/packages/contracts-bedrock/test/L2/FeeVault.t.sol +++ b/packages/contracts-bedrock/test/L2/FeeVault.t.sol @@ -8,6 +8,7 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { IProxyAdmin } from "interfaces/universal/IProxyAdmin.sol"; import { IFeeVault } from "interfaces/L2/IFeeVault.sol"; import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; +import { IL2ToL1MessagePasserCGT } from "interfaces/L2/IL2ToL1MessagePasserCGT.sol"; // Libraries import { Hashing } from "src/libraries/Hashing.sol"; @@ -145,6 +146,31 @@ abstract contract FeeVault_Uncategorized_Test is CommonTest { assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, amount); } + /// @notice Tests that withdraw to L1 reverts when custom gas token is enabled and value is sent. + function testFuzz_withdraw_toL1WithCustomGasToken_reverts(uint256 _amount) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + // Setup L1 withdrawal + vm.prank(IProxyAdmin(Predeploys.PROXY_ADMIN).owner()); + feeVault.setWithdrawalNetwork(Types.WithdrawalNetwork.L1); + + // Set recipient + vm.prank(IProxyAdmin(Predeploys.PROXY_ADMIN).owner()); + feeVault.setRecipient(recipient); + + // Set minimum withdrawal amount + vm.prank(IProxyAdmin(Predeploys.PROXY_ADMIN).owner()); + feeVault.setMinWithdrawalAmount(minWithdrawalAmount); + + // Set the balance to be greater than the minimum withdrawal amount + _amount = bound(_amount, feeVault.minWithdrawalAmount() + 1, type(uint128).max); + vm.deal(address(feeVault), _amount); + + // Withdrawal should revert due to CGT mode + vm.expectRevert(IL2ToL1MessagePasserCGT.L2ToL1MessagePasserCGT_NotAllowedOnCGTMode.selector); + feeVault.withdraw(); + } + /// @notice Tests that `withdraw` successfully initiates a withdrawal to L2. function test_withdraw_toL2_succeeds() public { _setupL2Withdrawal(); diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol index 8df5b33b4fa..a0f1c0aec8c 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol @@ -20,6 +20,7 @@ import { Features } from "src/libraries/Features.sol"; import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenger.sol"; import { IStandardBridge } from "interfaces/universal/IStandardBridge.sol"; import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; +import { IL2ToL1MessagePasserCGT } from "interfaces/L2/IL2ToL1MessagePasserCGT.sol"; import { IL2StandardBridge } from "interfaces/L2/IL2StandardBridge.sol"; /// @title L2StandardBridge_TestInit @@ -299,6 +300,20 @@ contract L2StandardBridge_Receive_Test is L2StandardBridge_TestInit { assertEq(success, true); assertEq(address(l2ToL1MessagePasser).balance, 100); } + + /// @notice Tests that receive reverts when custom gas token is enabled and value is sent. + function testFuzz_receive_withCustomGasToken_reverts(uint256 _value) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IL2ToL1MessagePasserCGT.L2ToL1MessagePasserCGT_NotAllowedOnCGTMode.selector); + + (bool revertsAsExpected,) = address(l2StandardBridge).call{ value: _value }(hex""); + assertTrue(revertsAsExpected, "expectRevert: call did not revert"); + } } /// @title L2StandardBridge_Withdraw_Test @@ -376,6 +391,18 @@ contract L2StandardBridge_Withdraw_Test is L2StandardBridge_TestInit { vm.expectRevert("StandardBridge: function can only be called from an EOA"); l2StandardBridge.withdraw(address(L2Token), 100, 1000, hex""); } + + /// @notice Tests that withdraw reverts when custom gas token is enabled and value is sent. + function testFuzz_withdraw_withCustomGasToken_reverts(uint256 _value, uint32 _minGasLimit) external { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IL2ToL1MessagePasserCGT.L2ToL1MessagePasserCGT_NotAllowedOnCGTMode.selector); + l2StandardBridge.withdraw{ value: _value }(Predeploys.LEGACY_ERC20_ETH, _value, _minGasLimit, hex""); + } } /// @title L2StandardBridge_WithdrawTo_Test @@ -595,4 +622,42 @@ contract L2StandardBridge_Uncategorized_Test is L2StandardBridge_TestInit { vm.expectRevert("StandardBridge: wrong remote token for Optimism Mintable ERC20 local token"); l2StandardBridge.finalizeBridgeERC20(localToken, remoteToken, alice, alice, 100, hex""); } + + /// @notice Tests that bridgeETH reverts when custom gas token is enabled and value is sent. + function testFuzz_bridgeETH_withCustomGasToken_reverts( + uint256 _value, + uint32 _minGasLimit, + bytes calldata _extraData + ) + external + { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IL2ToL1MessagePasserCGT.L2ToL1MessagePasserCGT_NotAllowedOnCGTMode.selector); + l2StandardBridge.bridgeETH{ value: _value }(_minGasLimit, _extraData); + } + + /// @notice Tests that bridgeETHTo reverts when custom gas token is enabled and value is sent. + function testFuzz_bridgeETHTo_withCustomGasToken_reverts( + address _to, + uint256 _value, + uint32 _minGasLimit, + bytes calldata _extraData + ) + external + { + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); + + vm.assume(_to != address(0)); + _value = bound(_value, 1, type(uint128).max); + vm.deal(alice, _value); + + vm.prank(alice, alice); + vm.expectRevert(IL2ToL1MessagePasserCGT.L2ToL1MessagePasserCGT_NotAllowedOnCGTMode.selector); + l2StandardBridge.bridgeETHTo{ value: _value }(_to, _minGasLimit, _extraData); + } }