diff --git a/.circleci/config.yml b/.circleci/config.yml index 5250db39416..5fe3bc2d42d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -160,7 +160,6 @@ commands: pip3 install -r requirements.txt python3 main.py "<>" - install-solc-compilers: description: "Install the solc compilers" parameters: @@ -245,33 +244,46 @@ commands: echo "Resolved TARGET_BRANCH=$TARGET_BRANCH" echo "export TARGET_BRANCH=$TARGET_BRANCH" >> "$BASH_ENV" - setup-dev-features: - description: "Set up dev feature environment variables from comma-separated list" + setup-features: + description: "Set up dev and system feature environment variables. Features are auto-classified based on system_features registry." parameters: - dev_features: - description: "Comma-separated list of dev features to enable" + features: + description: "Comma-separated list of features (can mix dev and system features, e.g., 'OPTIMISM_PORTAL_INTEROP,CUSTOM_GAS_TOKEN')" type: string default: "" + system_features: + description: "Registry of system features (others treated as dev features)" + type: string + default: "CUSTOM_GAS_TOKEN" steps: - run: - name: Set dev feature environment variables + name: Set feature environment variables command: | - # Set dev feature environment variables if provided - if [ -n "<>" ]; then - DEV_FEATURES_STRING="<>" + # Define which features are system features (registry) + SYSTEM_FEATURES="<>" + + if [ -n "<>" ]; then + FEATURES_STRING="<>" - # Check if this is just "main" (baseline with no dev features) - if [ "$(echo "$DEV_FEATURES_STRING" | tr '[:upper:]' '[:lower:]')" = "main" ]; then - echo "Running with baseline configuration (no dev features enabled)" + # Check if this is just "main" (baseline with no features) + if [ "$(echo "$FEATURES_STRING" | tr '[:upper:]' '[:lower:]')" = "main" ]; then + echo "Running with baseline configuration (no features enabled)" else - echo "Enabling dev features: <>" + echo "Processing features: <>" IFS=',' - for feature in $DEV_FEATURES_STRING; do + for feature in $FEATURES_STRING; do feature=$(echo "$feature" | xargs) # trim whitespace if [ -n "$feature" ] && [ "$(echo "$feature" | tr '[:upper:]' '[:lower:]')" != "main" ]; then - env_var="DEV_FEATURE__${feature}" - echo "Setting ${env_var}=true" - echo "export ${env_var}=true" >> $BASH_ENV + # Check if this feature is in the system features registry + if echo "$SYSTEM_FEATURES" | grep -qw "$feature"; then + env_var="SYS_FEATURE__${feature}" + echo "Setting ${env_var}=true (system feature)" + echo "export ${env_var}=true" >> $BASH_ENV + else + env_var="DEV_FEATURE__${feature}" + echo "Setting ${env_var}=true (dev feature)" + echo "export ${env_var}=true" >> $BASH_ENV + fi fi done unset IFS @@ -492,7 +504,7 @@ jobs: default: false steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - attach_workspace: at: . - check-changed: @@ -544,7 +556,7 @@ jobs: resource_class: xlarge steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: name: Check `RISCV.sol` bytecode working_directory: packages/contracts-bedrock @@ -594,7 +606,7 @@ jobs: default: ci steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - install-zstd - install-contracts-dependencies - run: @@ -692,7 +704,7 @@ jobs: docker_layer_caching: true # we rely on this for faster builds, and actively warm it up for builds with common stages steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: command: mkdir -p /tmp/docker_images - when: @@ -913,13 +925,13 @@ jobs: description: List of changed files to run tests on type: string default: contracts-bedrock - dev_features: - description: Comma-separated list of dev features to enable (e.g., "OPTIMISM_PORTAL_INTEROP,ANOTHER_FEATURE") + features: + description: Comma-separated list of features to enable (e.g., "OPTIMISM_PORTAL_INTEROP", "CUSTOM_GAS_TOKEN") type: string default: "" steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - install-zstd - run: name: Check if test list is empty @@ -949,8 +961,8 @@ jobs: working_directory: packages/contracts-bedrock - go-save-cache: namespace: packages/contracts-bedrock/scripts/go-ffi - - setup-dev-features: - dev_features: <> + - setup-features: + features: <> - run: name: Run tests command: | @@ -983,7 +995,7 @@ jobs: resource_class: 2xlarge steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - install-contracts-dependencies - install-zstd - run: @@ -1032,7 +1044,7 @@ jobs: resource_class: medium steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: name: Check Python version command: python3 --version @@ -1086,13 +1098,13 @@ jobs: description: Profile to use for testing type: string default: ci - dev_features: - description: Comma-separated list of dev features to enable (e.g., "OPTIMISM_PORTAL_INTEROP,ANOTHER_FEATURE") + features: + description: Comma-separated list of features to enable (e.g., "OPTIMISM_PORTAL_INTEROP", "CUSTOM_GAS_TOKEN") type: string default: "" steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - install-contracts-dependencies - install-zstd - attach_workspace: @@ -1123,8 +1135,8 @@ jobs: - restore_cache: name: Restore forked state key: forked-state-contracts-bedrock-tests-upgrade-{{ checksum "packages/contracts-bedrock/pinnedBlockNumber.txt" }} - - setup-dev-features: - dev_features: <> + - setup-features: + features: <> - run: name: Build go-ffi command: just build-go-ffi @@ -1178,8 +1190,8 @@ jobs: fork_base_rpc: description: Fork Base RPC type: string - dev_features: - description: Comma-separated list of dev features to enable (e.g., "OPTIMISM_PORTAL_INTEROP,ANOTHER_FEATURE") + features: + description: Comma-separated list of features to enable (e.g., "OPTIMISM_PORTAL_INTEROP", "CUSTOM_GAS_TOKEN") type: string default: "" docker: @@ -1214,8 +1226,8 @@ jobs: - restore_cache: name: Restore forked state key: forked-state-contracts-bedrock-tests-upgrade-<>-<>-{{ checksum "packages/contracts-bedrock/pinnedBlockNumber.txt" }} - - setup-dev-features: - dev_features: <> + - setup-features: + features: <> - run: name: Run tests command: just test-upgrade @@ -1353,7 +1365,7 @@ jobs: resource_class: xlarge steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - check-changed: patterns: "<>" - attach_workspace: @@ -1385,7 +1397,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - restore_cache: key: golangci-v1-{{ checksum ".golangci.yaml" }} - run: @@ -1434,7 +1446,7 @@ jobs: parallelism: <> steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - attach_workspace: at: . - restore_cache: @@ -1509,7 +1521,7 @@ jobs: resource_class: <> steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - attach_workspace: at: . - run: @@ -1573,7 +1585,7 @@ jobs: circleci_ip_ranges: true steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless # Restore cached Go modules - restore_cache: keys: @@ -1671,7 +1683,7 @@ jobs: resource_class: 2xlarge+ steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - attach_workspace: at: . # Restore cached Go modules @@ -1765,7 +1777,7 @@ jobs: parallelism: << pipeline.parameters.flake-shake-workers >> steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - restore_cache: keys: - go-mod-v1-{{ checksum "go.sum" }} @@ -1812,7 +1824,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - attach_workspace: at: . - run: @@ -1863,7 +1875,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: name: Lint/Vet/Build op-acceptance-tests/cmd working_directory: op-acceptance-tests @@ -1942,7 +1954,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: name: Install tools command: | @@ -1965,7 +1977,7 @@ jobs: resource_class: xlarge steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - restore_cache: name: Restore cannon prestate cache key: cannon-prestate-{{ checksum "./cannon/bin/cannon" }}-{{ checksum "op-program/bin/op-program-client.elf" }} @@ -1993,7 +2005,7 @@ jobs: - image: <> steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - setup_remote_docker - run: name: Build prestates @@ -2009,7 +2021,7 @@ jobs: docker_layer_caching: true # we rely on this for faster builds, and actively warm it up for builds with common stages steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - restore_cache: name: Restore kona cache key: kona-prestate-{{ checksum "./kona/justfile" }}-{{ checksum "./kona/version.json" }} @@ -2032,7 +2044,7 @@ jobs: - image: <> steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - restore_cache: name: Restore kona host cache key: kona-host-{{ checksum "./kona/justfile" }}-{{ checksum "./kona/version.json" }} @@ -2205,7 +2217,7 @@ jobs: resource_class: xlarge steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - setup_remote_docker - run: name: Run Analyzer @@ -2219,7 +2231,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: name: Verify Compatibility command: | @@ -2232,7 +2244,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - check-changed: patterns: op-node - run: @@ -2245,7 +2257,7 @@ jobs: resource_class: large steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - check-changed: patterns: op-service - run: @@ -2257,7 +2269,7 @@ jobs: - image: <> steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - run: command: just check-forge-version working_directory: op-deployer @@ -2361,7 +2373,7 @@ jobs: resource_class: medium steps: - utils/checkout-with-mise: - checkout-method: blobless + checkout-method: blobless - install-contracts-dependencies - run: name: Build contracts @@ -2552,51 +2564,51 @@ workflows: - circleci-repo-readonly-authenticated-github-token - contracts-bedrock-tests: # Heavily fuzz any fuzz tests within added or modified test files. - name: contracts-bedrock-tests-heavy-fuzz-modified <> + name: contracts-bedrock-tests-heavy-fuzz-modified <> test_list: git diff origin/develop...HEAD --name-only --diff-filter=AM -- './test/**/*.t.sol' | sed 's|packages/contracts-bedrock/||' test_timeout: 1h test_profile: ciheavy - dev_features: <> + features: <> matrix: parameters: - dev_features: &dev_features_matrix + features: &features_matrix - main - OPTIMISM_PORTAL_INTEROP - CANNON_KONA,DEPLOY_V2_DISPUTE_GAMES - - CUSTOM_GAS_TOKEN - OPCM_V2 + - CUSTOM_GAS_TOKEN context: - circleci-repo-readonly-authenticated-github-token - contracts-bedrock-tests: - name: contracts-bedrock-tests <> + name: contracts-bedrock-tests <> test_list: find test -name "*.t.sol" - dev_features: <> + features: <> matrix: parameters: - dev_features: *dev_features_matrix + features: *features_matrix context: - circleci-repo-readonly-authenticated-github-token check_changed_patterns: contracts-bedrock,op-node - contracts-bedrock-coverage: # Generate coverage reports. - name: contracts-bedrock-coverage <> + name: contracts-bedrock-coverage <> test_timeout: 1h test_profile: cicoverage - dev_features: <> + features: <> matrix: parameters: - dev_features: *dev_features_matrix + features: *features_matrix context: - circleci-repo-readonly-authenticated-github-token - contracts-bedrock-tests-upgrade: - name: contracts-bedrock-tests-upgrade op-mainnet <> + name: contracts-bedrock-tests-upgrade op-mainnet <> fork_op_chain: op fork_base_chain: mainnet fork_base_rpc: https://ci-mainnet-l1-archive.optimism.io - dev_features: <> + features: <> matrix: parameters: - dev_features: *dev_features_matrix + features: *features_matrix context: - circleci-repo-readonly-authenticated-github-token - contracts-bedrock-tests-upgrade: diff --git a/op-deployer/pkg/deployer/devfeatures.go b/op-deployer/pkg/deployer/devfeatures.go index 6a8867d43a2..fefd390e06b 100644 --- a/op-deployer/pkg/deployer/devfeatures.go +++ b/op-deployer/pkg/deployer/devfeatures.go @@ -17,9 +17,6 @@ var ( // DeployV2DisputeGamesDevFlag enables deployment of V2 dispute game contracts. DeployV2DisputeGamesDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100") - - // CustomGasTokenDevFlag enables the custom gas token. - CustomGasTokenDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000001000") ) // IsDevFeatureEnabled checks if a specific development feature is enabled in a feature bitmap. diff --git a/op-deployer/pkg/deployer/integration_test/apply_test.go b/op-deployer/pkg/deployer/integration_test/apply_test.go index bd5dc5c88af..b028b09f82e 100644 --- a/op-deployer/pkg/deployer/integration_test/apply_test.go +++ b/op-deployer/pkg/deployer/integration_test/apply_test.go @@ -321,10 +321,6 @@ func TestEndToEndApply(t *testing.T) { Symbol: "CGT", InitialLiquidity: (*hexutil.Big)(amount), } - // CGT config for OPCM - intent.GlobalDeployOverrides = map[string]interface{}{ - "devFeatureBitmap": deployer.CustomGasTokenDevFlag, - } require.NoError(t, deployer.ApplyPipeline(ctx, deployer.ApplyPipelineOpts{ DeploymentTarget: deployer.DeploymentTargetLive, diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 9e743b2fa4f..87c76b7855d 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -169,6 +169,11 @@ contract Deploy is Deployer { deploySuperchain(); } + // Override useCustomGasToken config if system feature flag is set + if (Config.sysFeatureCustomGasToken()) { + cfg.setUseCustomGasToken(true); + } + deployImplementations({ _isInterop: cfg.useInterop() }); // Deploy Current OPChain Contracts diff --git a/packages/contracts-bedrock/scripts/libraries/Config.sol b/packages/contracts-bedrock/scripts/libraries/Config.sol index 60653866f7c..4b5a2ed6339 100644 --- a/packages/contracts-bedrock/scripts/libraries/Config.sol +++ b/packages/contracts-bedrock/scripts/libraries/Config.sol @@ -286,13 +286,13 @@ library Config { return vm.envOr("DEV_FEATURE__DEPLOY_V2_DISPUTE_GAMES", false); } - /// @notice Returns true if the development feature custom gas token is enabled. - function devFeatureCustomGasToken() internal view returns (bool) { - return vm.envOr("DEV_FEATURE__CUSTOM_GAS_TOKEN", false); - } - /// @notice Returns true if the development feature opcm_v2 is enabled. function devFeatureOpcmV2() internal view returns (bool) { return vm.envOr("DEV_FEATURE__OPCM_V2", false); } + + /// @notice Returns true if the system feature custom_gas_token is enabled. + function sysFeatureCustomGasToken() internal view returns (bool) { + return vm.envOr("SYS_FEATURE__CUSTOM_GAS_TOKEN", false); + } } diff --git a/packages/contracts-bedrock/src/libraries/DevFeatures.sol b/packages/contracts-bedrock/src/libraries/DevFeatures.sol index 33a372c63b0..ed46b8c8d2b 100644 --- a/packages/contracts-bedrock/src/libraries/DevFeatures.sol +++ b/packages/contracts-bedrock/src/libraries/DevFeatures.sol @@ -22,10 +22,6 @@ library DevFeatures { bytes32 public constant DEPLOY_V2_DISPUTE_GAMES = bytes32(0x0000000000000000000000000000000000000000000000000000000000000100); - /// @notice The feature that enables the custom gas token. - bytes32 public constant CUSTOM_GAS_TOKEN = - bytes32(0x0000000000000000000000000000000000000000000000000000000000001000); - /// @notice The feature that enables the OPContractsManagerV2 contract. bytes32 public constant OPCM_V2 = bytes32(0x0000000000000000000000000000000000000000000000000000000000010000); diff --git a/packages/contracts-bedrock/test/L1/FeesDepositor.t.sol b/packages/contracts-bedrock/test/L1/FeesDepositor.t.sol index 43b28d21150..e329f243869 100644 --- a/packages/contracts-bedrock/test/L1/FeesDepositor.t.sol +++ b/packages/contracts-bedrock/test/L1/FeesDepositor.t.sol @@ -9,7 +9,6 @@ import { FeesDepositor } from "src/L1/FeesDepositor.sol"; import { IProxyAdminOwnedBase } from "interfaces/L1/IProxyAdminOwnedBase.sol"; import { Proxy } from "src/universal/Proxy.sol"; import { Features } from "src/libraries/Features.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; /// @title FeesDepositor_TestInit /// @notice Base test contract with initialization for `FeesDepositor` tests. @@ -98,7 +97,7 @@ contract FeesDepositor_Receive_Test is FeesDepositor_TestInit { } function testFuzz_receive_atOrAboveThreshold_succeeds(uint256 _sendAmount) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); // Handling the fork tests scenario case for the fork tests uint256 depositFeesRecipientBalanceBefore = depositFeesRecipient.balance; @@ -126,7 +125,7 @@ contract FeesDepositor_Receive_Test is FeesDepositor_TestInit { } function testFuzz_receive_multipleDeposits_succeeds(uint256 _firstAmount, uint256 _secondAmount) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); // Handling the fork tests scenario uint256 depositFeesRecipientBalanceBefore = depositFeesRecipient.balance; diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index e26b938a9c2..abec06bf78b 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -15,7 +15,6 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Features } from "src/libraries/Features.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; // Interfaces import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenger.sol"; @@ -333,7 +332,7 @@ contract L1StandardBridge_Paused_Test is CommonTest { contract L1StandardBridge_Receive_Test is CommonTest { /// @notice Tests receive bridges ETH successfully. function test_receive_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); uint256 portalBalanceBefore = address(optimismPortal2).balance; uint256 ethLockboxBalanceBefore = address(ethLockbox).balance; @@ -377,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 @@ -388,7 +401,7 @@ contract L1StandardBridge_DepositETH_Test is L1StandardBridge_TestInit { /// Only EOA can call depositETH. /// ETH ends up in the optimismPortal. function test_depositETH_fromEOA_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); _preBridgeETH({ isLegacy: true, value: 500 }); uint256 portalBalanceBefore = address(optimismPortal2).balance; uint256 ethLockboxBalanceBefore = address(ethLockbox).balance; @@ -404,7 +417,7 @@ contract L1StandardBridge_DepositETH_Test is L1StandardBridge_TestInit { /// @notice Tests that depositing ETH succeeds for an EOA using 7702 delegation. function test_depositETH_fromEOA7702_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); // Set alice to have 7702 code. vm.etch(alice, abi.encodePacked(hex"EF0100", address(0))); @@ -428,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 @@ -439,7 +478,7 @@ contract L1StandardBridge_DepositETHTo_Test is L1StandardBridge_TestInit { /// EOA or contract can call depositETHTo. /// ETH ends up in the optimismPortal. function test_depositETHTo_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); _preBridgeETHTo({ isLegacy: true, value: 600 }); uint256 portalBalanceBefore = address(optimismPortal2).balance; uint256 ethLockboxBalanceBefore = address(ethLockbox).balance; @@ -457,7 +496,7 @@ contract L1StandardBridge_DepositETHTo_Test is L1StandardBridge_TestInit { /// @param _to Random recipient address /// @param _amount Random ETH amount to deposit function testFuzz_depositETHTo_randomRecipient_succeeds(address _to, uint256 _amount) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); vm.assume(_to != address(0)); _amount = bound(_amount, 1, 10 ether); @@ -475,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 @@ -786,7 +842,7 @@ contract L1StandardBridge_Uncategorized_Test is L1StandardBridge_TestInit { /// Only EOA can call bridgeETH. /// ETH ends up in the optimismPortal. function test_bridgeETH_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); _preBridgeETH({ isLegacy: false, value: 500 }); uint256 portalBalanceBefore = address(optimismPortal2).balance; uint256 ethLockboxBalanceBefore = address(ethLockbox).balance; @@ -806,7 +862,7 @@ contract L1StandardBridge_Uncategorized_Test is L1StandardBridge_TestInit { /// Only EOA can call bridgeETHTo. /// ETH ends up in the optimismPortal. function test_bridgeETHTo_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); _preBridgeETHTo({ isLegacy: false, value: 600 }); uint256 portalBalanceBefore = address(optimismPortal2).balance; uint256 ethLockboxBalanceBefore = address(ethLockbox).balance; @@ -878,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/FeeSplitter.t.sol b/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol index 0ed14418f63..35edca9a278 100644 --- a/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol +++ b/packages/contracts-bedrock/test/L2/FeeSplitter.t.sol @@ -13,7 +13,6 @@ import { ReentrantMockFeeVault } from "test/mocks/ReentrantMockFeeVault.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; import { Types } from "src/libraries/Types.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; // Interfaces import { IFeeSplitter } from "interfaces/L2/IFeeSplitter.sol"; @@ -42,10 +41,6 @@ contract FeeSplitter_TestInit is CommonTest { /// @notice Test setup. function setUp() public virtual override { - // Resolve features and skip whole test suite if custom gas token is enabled - resolveFeaturesFromEnv(); - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); - // Enable revenue sharing before calling parent setUp super.enableRevenueShare(); super.setUp(); diff --git a/packages/contracts-bedrock/test/L2/FeeVault.t.sol b/packages/contracts-bedrock/test/L2/FeeVault.t.sol index fcdb1e464a9..aa8a572335b 100644 --- a/packages/contracts-bedrock/test/L2/FeeVault.t.sol +++ b/packages/contracts-bedrock/test/L2/FeeVault.t.sol @@ -8,12 +8,13 @@ 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"; import { Types } from "src/libraries/Types.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; /// @title FeeVault_Uncategorized_Test /// @notice Abstract test contract for fee feeVault testing. @@ -83,7 +84,7 @@ abstract contract FeeVault_Uncategorized_Test is CommonTest { /// @notice Tests that `withdraw` successfully initiates a withdrawal to L1. function test_withdraw_toL1_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); // Setup L1 withdrawal vm.prank(IProxyAdmin(Predeploys.PROXY_ADMIN).owner()); @@ -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/L1Block.t.sol b/packages/contracts-bedrock/test/L2/L1Block.t.sol index 444587bb120..5d36bb88631 100644 --- a/packages/contracts-bedrock/test/L2/L1Block.t.sol +++ b/packages/contracts-bedrock/test/L2/L1Block.t.sol @@ -9,7 +9,7 @@ import { stdStorage, StdStorage } from "forge-std/Test.sol"; import { Encoding } from "src/libraries/Encoding.sol"; import { Constants } from "src/libraries/Constants.sol"; import "src/libraries/L1BlockErrors.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; // Interfaces import { IL1BlockCGT } from "interfaces/L2/IL1BlockCGT.sol"; @@ -54,7 +54,7 @@ contract L1Block_GasPayingToken_Test is L1Block_TestInit { /// @notice Tests that the `gasPayingToken` function returns the correct token address and /// decimals. function test_gasPayingToken_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); (address token, uint8 decimals) = l1Block.gasPayingToken(); assertEq(token, Constants.ETHER); assertEq(uint256(decimals), uint256(18)); @@ -62,7 +62,7 @@ contract L1Block_GasPayingToken_Test is L1Block_TestInit { /// @notice Tests that the `gasPayingToken` function reverts when custom gas token is enabled. function test_gasPayingToken_customGasToken_reverts() external { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); vm.expectRevert("L1BlockCGT: deprecated"); l1Block.gasPayingToken(); } @@ -73,14 +73,14 @@ contract L1Block_GasPayingToken_Test is L1Block_TestInit { contract L1Block_GasPayingTokenName_Test is L1Block_TestInit { /// @notice Tests that the `gasPayingTokenName` function returns the correct token name. function test_gasPayingTokenName_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); assertEq("Ether", l1Block.gasPayingTokenName()); } /// @notice Tests that the `gasPayingTokenName` function returns the correct token name when custom gas token is /// enabled. function test_gasPayingTokenName_customGasToken_succeeds() external { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); assertEq(liquidityController.gasPayingTokenName(), l1Block.gasPayingTokenName()); } } @@ -90,14 +90,14 @@ contract L1Block_GasPayingTokenName_Test is L1Block_TestInit { contract L1Block_GasPayingTokenSymbol_Test is L1Block_TestInit { /// @notice Tests that the `gasPayingTokenSymbol` function returns the correct token symbol. function test_gasPayingTokenSymbol_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); assertEq("ETH", l1Block.gasPayingTokenSymbol()); } /// @notice Tests that the `gasPayingTokenSymbol` function returns the correct token symbol when custom gas token is /// enabled. function test_gasPayingTokenSymbol_customGasToken_succeeds() external { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); assertEq(liquidityController.gasPayingTokenSymbol(), l1Block.gasPayingTokenSymbol()); } } @@ -108,14 +108,14 @@ contract L1Block_IsCustomGasToken_Test is L1Block_TestInit { /// @notice Tests that the `isCustomGasToken` function returns false when no custom gas token /// is used. function test_isCustomGasToken_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); assertFalse(l1Block.isCustomGasToken()); } /// @notice Tests that the `isCustomGasToken` function returns true when custom gas token /// is used. function test_isCustomGasToken_customGasToken_succeeds() external { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); assertTrue(l1Block.isCustomGasToken()); } } @@ -467,7 +467,7 @@ contract L1Block_SetCustomGasToken_Test is L1Block_TestInit { function setUp() public override { super.setUp(); - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); l1BlockCGT = IL1BlockCGT(address(l1Block)); } diff --git a/packages/contracts-bedrock/test/L2/L1Withdrawer.t.sol b/packages/contracts-bedrock/test/L2/L1Withdrawer.t.sol index 277959e30be..865e7177f23 100644 --- a/packages/contracts-bedrock/test/L2/L1Withdrawer.t.sol +++ b/packages/contracts-bedrock/test/L2/L1Withdrawer.t.sol @@ -6,7 +6,6 @@ import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenge import { Predeploys } from "src/libraries/Predeploys.sol"; import { IL1Withdrawer } from "interfaces/L2/IL1Withdrawer.sol"; import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; /// @title L1Withdrawer_TestInit /// @notice Base test contract with initialization for `L1Withdrawer` tests. @@ -26,10 +25,6 @@ contract L1Withdrawer_TestInit is CommonTest { /// @notice Test setup. function setUp() public virtual override { - // Resolve features and skip whole test suite if custom gas token is enabled - resolveFeaturesFromEnv(); - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); - // Enable revenue sharing before calling parent setUp super.enableRevenueShare(); super.setUp(); diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol index 0f25b19caaa..a0f1c0aec8c 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol @@ -14,12 +14,13 @@ import { OptimismMintableERC20 } from "src/universal/OptimismMintableERC20.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Types } from "src/libraries/Types.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; // Interfaces 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 @@ -232,7 +233,7 @@ contract L2StandardBridge_Initialize_Test is L2StandardBridge_TestInit { contract L2StandardBridge_Receive_Test is L2StandardBridge_TestInit { /// @notice Tests that the bridge receives ETH and successfully initiates a withdrawal. function test_receive_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); assertEq(address(l2ToL1MessagePasser).balance, 0); uint256 nonce = l2CrossDomainMessenger.messageNonce(); @@ -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 @@ -325,7 +340,7 @@ contract L2StandardBridge_Withdraw_Test is L2StandardBridge_TestInit { /// @notice Tests that the legacy `withdraw` interface on the L2StandardBridge sucessfully /// initiates a withdrawal. function test_withdraw_ether_succeeds() external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); assertTrue(alice.balance >= 100); assertEq(Predeploys.L2_TO_L1_MESSAGE_PASSER.balance, 0); @@ -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 @@ -468,7 +495,7 @@ contract L2StandardBridge_Uncategorized_Test is L2StandardBridge_TestInit { /// @notice Tests that bridging ETH succeeds. function testFuzz_bridgeETH_succeeds(uint256 _value, uint32 _minGasLimit, bytes calldata _extraData) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); uint256 nonce = l2CrossDomainMessenger.messageNonce(); bytes memory message = abi.encodeCall(IStandardBridge.finalizeBridgeETH, (alice, alice, _value, _extraData)); @@ -502,7 +529,7 @@ contract L2StandardBridge_Uncategorized_Test is L2StandardBridge_TestInit { /// @notice Tests that bridging ETH to a different address succeeds. function testFuzz_bridgeETHTo_succeeds(uint256 _value, uint32 _minGasLimit, bytes calldata _extraData) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); uint256 nonce = l2CrossDomainMessenger.messageNonce(); vm.expectCall( @@ -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); + } } diff --git a/packages/contracts-bedrock/test/L2/L2ToL1MessagePasser.t.sol b/packages/contracts-bedrock/test/L2/L2ToL1MessagePasser.t.sol index c79f3af797e..e3ddd2497db 100644 --- a/packages/contracts-bedrock/test/L2/L2ToL1MessagePasser.t.sol +++ b/packages/contracts-bedrock/test/L2/L2ToL1MessagePasser.t.sol @@ -7,7 +7,7 @@ import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; import { SemverComp } from "src/libraries/SemverComp.sol"; // Interfaces @@ -27,7 +27,7 @@ contract L2ToL1MessagePasser_Version_Test is CommonTest { contract L2ToL1MessagePasser_Receive_Test is CommonTest { /// @notice Tests that receive() initiates withdrawal with default gas limit. function testFuzz_receive_initiatesWithdrawal_succeeds(uint256 _value) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); uint256 nonce = l2ToL1MessagePasser.messageNonce(); @@ -59,7 +59,7 @@ contract L2ToL1MessagePasser_Receive_Test is CommonTest { contract L2ToL1MessagePasser_Burn_Test is CommonTest { /// @notice Tests that `burn` succeeds and destroys the ETH held in the contract. function testFuzz_burn_succeeds(uint256 _value, address _target, uint256 _gasLimit, bytes memory _data) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); vm.deal(address(this), _value); l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data }); @@ -89,7 +89,7 @@ contract L2ToL1MessagePasser_InitiateWithdrawal_Test is CommonTest { ) external { - if (isDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN)) { + if (isSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN)) { _value = 0; } uint256 nonce = l2ToL1MessagePasser.messageNonce(); @@ -129,7 +129,7 @@ contract L2ToL1MessagePasser_InitiateWithdrawal_Test is CommonTest { ) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); bytes32 withdrawalHash = Hashing.hashWithdrawal( Types.WithdrawalTransaction({ nonce: l2ToL1MessagePasser.messageNonce(), @@ -161,7 +161,7 @@ contract L2ToL1MessagePasser_InitiateWithdrawal_Test is CommonTest { ) external { - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureEnabled(Features.CUSTOM_GAS_TOKEN); uint256 nonce = l2ToL1MessagePasser.messageNonce(); // Verify caller is an EOA (alice has no code) @@ -192,7 +192,7 @@ contract L2ToL1MessagePasser_InitiateWithdrawal_Test is CommonTest { ) external { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); // Set initial state _value = bound(_value, 1, type(uint256).max); vm.deal(_randomAddress, _value); diff --git a/packages/contracts-bedrock/test/L2/LiquidityController.t.sol b/packages/contracts-bedrock/test/L2/LiquidityController.t.sol index 45375ce66ca..82208200fcc 100644 --- a/packages/contracts-bedrock/test/L2/LiquidityController.t.sol +++ b/packages/contracts-bedrock/test/L2/LiquidityController.t.sol @@ -6,7 +6,8 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; // Libraries -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; +import { Predeploys } from "src/libraries/Predeploys.sol"; // Contracts import { LiquidityController } from "src/L2/LiquidityController.sol"; @@ -38,7 +39,7 @@ contract LiquidityController_TestInit is CommonTest { /// @notice Test setup. function setUp() public virtual override { super.setUp(); - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); } /// @notice Helper function to authorize a minter. @@ -215,6 +216,8 @@ contract LiquidityController_Mint_Test is LiquidityController_TestInit { contract LiquidityController_Burn_Test is LiquidityController_TestInit { /// @notice Tests that the burn function can be called by an authorized minter. function testFuzz_burn_fromAuthorizedMinter_succeeds(uint256 _amount, address _minter) public { + vm.assume(_minter != Predeploys.NATIVE_ASSET_LIQUIDITY); + _authorizeMinter(_minter); _amount = bound(_amount, 0, address(nativeAssetLiquidity).balance); diff --git a/packages/contracts-bedrock/test/L2/NativeAssetLiquidity.t.sol b/packages/contracts-bedrock/test/L2/NativeAssetLiquidity.t.sol index 2b5869b5565..db3a9c6eaca 100644 --- a/packages/contracts-bedrock/test/L2/NativeAssetLiquidity.t.sol +++ b/packages/contracts-bedrock/test/L2/NativeAssetLiquidity.t.sol @@ -5,7 +5,7 @@ pragma solidity 0.8.15; import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; import { NativeAssetLiquidity } from "src/L2/NativeAssetLiquidity.sol"; /// @title NativeAssetLiquidity_TestInit @@ -23,7 +23,7 @@ contract NativeAssetLiquidity_TestInit is CommonTest { /// @notice Test setup. function setUp() public virtual override { super.setUp(); - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); } } diff --git a/packages/contracts-bedrock/test/L2/RevenueSharingIntegration.t.sol b/packages/contracts-bedrock/test/L2/RevenueSharingIntegration.t.sol index 5484029d752..777b0ffa942 100644 --- a/packages/contracts-bedrock/test/L2/RevenueSharingIntegration.t.sol +++ b/packages/contracts-bedrock/test/L2/RevenueSharingIntegration.t.sol @@ -8,7 +8,6 @@ import { IFeeVault } from "interfaces/L2/IFeeVault.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { Types } from "src/libraries/Types.sol"; import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenger.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; /// @title RevenueSharingIntegration_Test /// @notice Integration tests for the complete revenue sharing system including @@ -26,10 +25,6 @@ contract RevenueSharingIntegration_Test is CommonTest { event FundsReceived(address indexed sender, uint256 amount, uint256 newBalance); function setUp() public override { - // Resolve features and skip whole test suite if custom gas token is enabled - resolveFeaturesFromEnv(); - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); - // Enable revenue sharing before calling parent setUp super.enableRevenueShare(); super.setUp(); diff --git a/packages/contracts-bedrock/test/L2/SuperchainRevSharesCalculator.t.sol b/packages/contracts-bedrock/test/L2/SuperchainRevSharesCalculator.t.sol index c801ae37308..9f08bdc33ac 100644 --- a/packages/contracts-bedrock/test/L2/SuperchainRevSharesCalculator.t.sol +++ b/packages/contracts-bedrock/test/L2/SuperchainRevSharesCalculator.t.sol @@ -8,9 +8,6 @@ import { CommonTest } from "test/setup/CommonTest.sol"; import { ISharesCalculator } from "interfaces/L2/ISharesCalculator.sol"; import { ISuperchainRevSharesCalculator } from "interfaces/L2/ISuperchainRevSharesCalculator.sol"; -// Libraries -import { DevFeatures } from "src/libraries/DevFeatures.sol"; - /// @notice Base setup contract for SuperchainRevSharesCalculator tests. contract SuperchainRevSharesCalculator_TestInit is CommonTest { uint256 internal constant BASIS_POINT_SCALE = 10_000; @@ -24,10 +21,6 @@ contract SuperchainRevSharesCalculator_TestInit is CommonTest { event RemainderRecipientUpdated(address indexed oldRemainderRecipient, address indexed newRemainderRecipient); function setUp() public virtual override { - // Resolve features and skip whole test suite if custom gas token is enabled - resolveFeaturesFromEnv(); - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); - // Enable revenue sharing before calling parent setUp super.enableRevenueShare(); super.setUp(); diff --git a/packages/contracts-bedrock/test/invariants/CustomGasToken.t.sol b/packages/contracts-bedrock/test/invariants/CustomGasToken.t.sol index fe96f009e30..764a3a0236c 100644 --- a/packages/contracts-bedrock/test/invariants/CustomGasToken.t.sol +++ b/packages/contracts-bedrock/test/invariants/CustomGasToken.t.sol @@ -8,7 +8,8 @@ import { CommonTest } from "test/setup/CommonTest.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; +import { SafeSend } from "src/universal/SafeSend.sol"; // Contracts import { ILiquidityController } from "interfaces/L2/ILiquidityController.sol"; @@ -103,7 +104,7 @@ contract NativeAssetLiquidity_Fundooor is StdUtils { _amount = bound(_amount, 0, address(this).balance); // action: fund _amount - vm.deal(address(nativeAssetLiquidity), _amount); + new SafeSend{ value: _amount }(payable(address(nativeAssetLiquidity))); // postcondition: nil here (in the invariant tests) // update ghost variables @@ -190,8 +191,8 @@ contract CustomGasToken_Invariants_Test is CommonTest { /// @notice Test setup. function setUp() public override { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); super.setUp(); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); randomActor = new RandomActor(); actor_funder = new NativeAssetLiquidity_Fundooor(vm); diff --git a/packages/contracts-bedrock/test/invariants/FeeSplit.t.sol b/packages/contracts-bedrock/test/invariants/FeeSplit.t.sol index 0ddacddd82b..f8d36eb6b19 100644 --- a/packages/contracts-bedrock/test/invariants/FeeSplit.t.sol +++ b/packages/contracts-bedrock/test/invariants/FeeSplit.t.sol @@ -10,7 +10,6 @@ import { Predeploys } from "src/libraries/Predeploys.sol"; import { IFeeSplitter } from "interfaces/L2/IFeeSplitter.sol"; import { IL1Withdrawer } from "interfaces/L2/IL1Withdrawer.sol"; import { ISuperchainRevSharesCalculator } from "interfaces/L2/ISuperchainRevSharesCalculator.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; /// @notice A struct to keep track of the state when a disburse call fails struct DisburseFailureState { @@ -215,10 +214,6 @@ contract FeeSplitter_Invariant is CommonTest { /// @notice Setup: enable the revenue share, deploy handlers and target them. function setUp() public override { - // Resolve features and skip whole test suite if custom gas token is enabled - resolveFeaturesFromEnv(); - skipIfDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN); - super.enableRevenueShare(); super.setUp(); diff --git a/packages/contracts-bedrock/test/libraries/Predeploys.t.sol b/packages/contracts-bedrock/test/libraries/Predeploys.t.sol index 590c10395cb..2a025cd5c09 100644 --- a/packages/contracts-bedrock/test/libraries/Predeploys.t.sol +++ b/packages/contracts-bedrock/test/libraries/Predeploys.t.sol @@ -9,7 +9,7 @@ import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { Predeploys } from "src/libraries/Predeploys.sol"; import { ForgeArtifacts } from "scripts/libraries/ForgeArtifacts.sol"; import { Fork } from "scripts/libraries/Config.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; +import { Features } from "src/libraries/Features.sol"; /// @title Predeploys_TestInit /// @notice Reusable test initialization for `Predeploys` tests. @@ -165,7 +165,7 @@ contract Predeploys_Uncategorized_Test is Predeploys_TestInit { /// @notice Tests that the predeploy addresses are set correctly. They have code /// and the proxied accounts have the correct admin. Using custom gas token. function test_predeploys_customGasToken_succeeds() external { - skipIfDevFeatureDisabled(DevFeatures.CUSTOM_GAS_TOKEN); + skipIfSysFeatureDisabled(Features.CUSTOM_GAS_TOKEN); _test_predeploys(Fork.ISTHMUS, false, true); } } diff --git a/packages/contracts-bedrock/test/setup/CommonTest.sol b/packages/contracts-bedrock/test/setup/CommonTest.sol index 0be3c9cb7ae..529534b7ceb 100644 --- a/packages/contracts-bedrock/test/setup/CommonTest.sol +++ b/packages/contracts-bedrock/test/setup/CommonTest.sol @@ -14,9 +14,9 @@ import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; // Contracts import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { DevFeatures } from "src/libraries/DevFeatures.sol"; // Libraries +import { Config } from "scripts/libraries/Config.sol"; import { console } from "forge-std/console.sol"; // Interfaces @@ -79,6 +79,12 @@ abstract contract CommonTest is Test, Setup, Events { deploy.cfg().setUseInterop(true); } if (useRevenueShareOverride) { + // Revenue share is not supported when custom gas token is enabled + if (Config.sysFeatureCustomGasToken()) { + vm.skip(true); + } + + console.log("CommonTest: enabling revenue share"); deploy.cfg().setUseRevenueShare(true); deploy.cfg().setChainFeesRecipient(chainFeesRecipient); deploy.cfg().setL1FeesDepositor(l1FeesDepositor); @@ -86,7 +92,7 @@ abstract contract CommonTest is Test, Setup, Events { if (useUpgradedFork) { deploy.cfg().setUseUpgradedFork(true); } - if (isDevFeatureEnabled(DevFeatures.CUSTOM_GAS_TOKEN)) { + if (Config.sysFeatureCustomGasToken()) { console.log("CommonTest: enabling custom gas token"); deploy.cfg().setUseCustomGasToken(true); deploy.cfg().setGasPayingTokenName("Custom Gas Token"); diff --git a/packages/contracts-bedrock/test/setup/FeatureFlags.sol b/packages/contracts-bedrock/test/setup/FeatureFlags.sol index 2f71edac4f7..10f2d20ffa6 100644 --- a/packages/contracts-bedrock/test/setup/FeatureFlags.sol +++ b/packages/contracts-bedrock/test/setup/FeatureFlags.sol @@ -44,10 +44,6 @@ abstract contract FeatureFlags { console.log("Setup: DEV_FEATURE__DEPLOY_V2_DISPUTE_GAMES is enabled"); devFeatureBitmap |= DevFeatures.DEPLOY_V2_DISPUTE_GAMES; } - if (Config.devFeatureCustomGasToken()) { - console.log("Setup: DEV_FEATURE__CUSTOM_GAS_TOKEN is enabled"); - devFeatureBitmap |= DevFeatures.CUSTOM_GAS_TOKEN; - } if (Config.devFeatureOpcmV2()) { // WARNING: OPCMv2 also automatically implies DEPLOY_V2_DISPUTE_GAMES and CANNON_KONA. console.log("Setup: DEV_FEATURE__OPCM_V2 is enabled");