From 47ca103641be76d1bc590df33fba0c0672f9735e Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 10 Jan 2025 14:24:21 +0100 Subject: [PATCH 01/15] remove CGT code --- .../interfaces/L1/IL1CrossDomainMessenger.sol | 1 - .../interfaces/L1/IL1StandardBridge.sol | 1 - .../interfaces/L1/IOptimismPortal2.sol | 15 - .../interfaces/L1/IOptimismPortalInterop.sol | 15 - .../interfaces/L1/ISystemConfig.sol | 7 - .../interfaces/L1/ISystemConfigInterop.sol | 6 - .../scripts/deploy/Deploy.s.sol | 3 +- .../scripts/deploy/DeployOPChain.s.sol | 2 - .../contracts-bedrock/snapshots/.gas-snapshot | 14 +- .../snapshots/abi/L1CrossDomainMessenger.json | 13 - .../snapshots/abi/L1StandardBridge.json | 13 - .../snapshots/abi/OptimismPortal2.json | 99 --- .../snapshots/abi/OptimismPortalInterop.json | 99 --- .../snapshots/abi/SystemConfig.json | 67 -- .../snapshots/abi/SystemConfigInterop.json | 82 +- .../snapshots/semver-lock.json | 28 +- .../src/L1/L1CrossDomainMessenger.sol | 11 +- .../src/L1/L1StandardBridge.sol | 11 +- .../src/L1/OPContractsManager.sol | 3 +- .../src/L1/OptimismPortal2.sol | 165 +--- .../src/L1/OptimismPortalInterop.sol | 4 +- .../contracts-bedrock/src/L1/SystemConfig.sol | 64 +- .../src/L1/SystemConfigInterop.sol | 38 - .../test/L1/L1CrossDomainMessenger.t.sol | 141 ---- .../test/L1/L1StandardBridge.t.sol | 146 ---- .../test/L1/OptimismPortal2.t.sol | 735 ------------------ .../test/L1/SystemConfig.t.sol | 206 +---- .../test/L1/SystemConfigInterop.t.sol | 141 ---- .../test/L2/L2CrossDomainMessenger.t.sol | 101 --- .../test/L2/L2StandardBridge.t.sol | 136 ---- .../test/invariants/SystemConfig.t.sol | 3 +- .../test/vendor/Initializable.t.sol | 7 +- 32 files changed, 61 insertions(+), 2316 deletions(-) diff --git a/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol b/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol index 578a975d32fa0..4047c57d56131 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol @@ -16,7 +16,6 @@ interface IL1CrossDomainMessenger is ICrossDomainMessenger { external; function portal() external view returns (IOptimismPortal); function superchainConfig() external view returns (ISuperchainConfig); - function systemConfig() external view returns (ISystemConfig); function version() external view returns (string memory); function __constructor__() external; diff --git a/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol b/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol index 847ea76b44d2e..abafca5457273 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol @@ -70,7 +70,6 @@ interface IL1StandardBridge is IStandardBridge { external; function l2TokenBridge() external view returns (address); function superchainConfig() external view returns (ISuperchainConfig); - function systemConfig() external view returns (ISystemConfig); function version() external view returns (string memory); function __constructor__() external; diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol index 436a467ce2916..e1223d7d0f75a 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol @@ -9,7 +9,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; interface IOptimismPortal2 { - error CustomGasTokenNotSupported(); error AlreadyFinalized(); error BadTarget(); error Blacklisted(); @@ -24,13 +23,10 @@ interface IOptimismPortal2 { error InvalidMerkleProof(); error InvalidProof(); error LargeCalldata(); - error NoValue(); error NonReentrant(); - error OnlyCustomGasToken(); error OutOfGas(); error ProposalNotValidated(); error SmallGasLimit(); - error TransferFailed(); error Unauthorized(); error UnexpectedList(); error UnexpectedString(); @@ -46,18 +42,8 @@ interface IOptimismPortal2 { receive() external payable; - function balance() external view returns (uint256); function blacklistDisputeGame(IDisputeGame _disputeGame) external; function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; - function depositERC20Transaction( - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) - external; function depositTransaction( address _to, uint256 _value, @@ -109,7 +95,6 @@ interface IOptimismPortal2 { returns (IDisputeGame disputeGameProxy, uint64 timestamp); // nosemgrep function respectedGameType() external view returns (GameType); function respectedGameTypeUpdatedAt() external view returns (uint64); - function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; function setRespectedGameType(GameType _gameType) external; function superchainConfig() external view returns (ISuperchainConfig); function systemConfig() external view returns (ISystemConfig); diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol index 3de6e5eea4754..1b8037ffc3563 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol @@ -10,7 +10,6 @@ import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; interface IOptimismPortalInterop { - error CustomGasTokenNotSupported(); error AlreadyFinalized(); error BadTarget(); error Blacklisted(); @@ -25,13 +24,10 @@ interface IOptimismPortalInterop { error InvalidMerkleProof(); error InvalidProof(); error LargeCalldata(); - error NoValue(); error NonReentrant(); - error OnlyCustomGasToken(); error OutOfGas(); error ProposalNotValidated(); error SmallGasLimit(); - error TransferFailed(); error Unauthorized(); error UnexpectedList(); error UnexpectedString(); @@ -47,18 +43,8 @@ interface IOptimismPortalInterop { receive() external payable; - function balance() external view returns (uint256); function blacklistDisputeGame(IDisputeGame _disputeGame) external; function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; - function depositERC20Transaction( - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) - external; function depositTransaction( address _to, uint256 _value, @@ -111,7 +97,6 @@ interface IOptimismPortalInterop { function respectedGameType() external view returns (GameType); function respectedGameTypeUpdatedAt() external view returns (uint64); function setConfig(ConfigType _type, bytes memory _value) external; - function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external; function setRespectedGameType(GameType _gameType) external; function superchainConfig() external view returns (ISuperchainConfig); function systemConfig() external view returns (ISystemConfig); diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol index 7ed0138ec5bd3..d8c4a6a19e61f 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISystemConfig.sol @@ -5,8 +5,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; /// @notice This interface corresponds to the Custom Gas Token version of the SystemConfig contract. interface ISystemConfig { - error CustomGasTokenNotSupported(); - enum UpdateType { BATCHER, FEE_SCALARS, @@ -22,7 +20,6 @@ interface ISystemConfig { address disputeGameFactory; address optimismPortal; address optimismMintableERC20Factory; - address gasPayingToken; } event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); @@ -47,9 +44,6 @@ interface ISystemConfig { function gasLimit() external view returns (uint64); function eip1559Denominator() external view returns (uint32); function eip1559Elasticity() external view returns (uint32); - function gasPayingToken() external view returns (address addr_, uint8 decimals_); - function gasPayingTokenName() external view returns (string memory name_); - function gasPayingTokenSymbol() external view returns (string memory symbol_); function initialize( address _owner, uint32 _basefeeScalar, @@ -62,7 +56,6 @@ interface ISystemConfig { Addresses memory _addresses ) external; - function isCustomGasToken() external view returns (bool); function l1CrossDomainMessenger() external view returns (address addr_); function l1ERC721Bridge() external view returns (address addr_); function l1StandardBridge() external view returns (address addr_); diff --git a/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol b/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol index 59950cc353608..c9b63db2b1df0 100644 --- a/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/ISystemConfigInterop.sol @@ -5,8 +5,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; interface ISystemConfigInterop { - error CustomGasTokenNotSupported(); - event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); event Initialized(uint8 version); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -29,10 +27,6 @@ interface ISystemConfigInterop { function gasLimit() external view returns (uint64); function eip1559Denominator() external view returns (uint32); function eip1559Elasticity() external view returns (uint32); - function gasPayingToken() external view returns (address addr_, uint8 decimals_); - function gasPayingTokenName() external view returns (string memory name_); - function gasPayingTokenSymbol() external view returns (string memory symbol_); - function isCustomGasToken() external view returns (bool); function l1CrossDomainMessenger() external view returns (address addr_); function l1ERC721Bridge() external view returns (address addr_); function l1StandardBridge() external view returns (address addr_); diff --git a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol index 5c194a45843e3..03f6e326dc881 100644 --- a/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/Deploy.s.sol @@ -523,8 +523,7 @@ contract Deploy is Deployer { l1StandardBridge: artifacts.mustGetAddress("L1StandardBridgeProxy"), disputeGameFactory: artifacts.mustGetAddress("DisputeGameFactoryProxy"), optimismPortal: artifacts.mustGetAddress("OptimismPortalProxy"), - optimismMintableERC20Factory: artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy"), - gasPayingToken: customGasTokenAddress + optimismMintableERC20Factory: artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy") }) ) ) diff --git a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol index 1bae1e6eefaf4..633fa5bedfd7b 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol @@ -563,8 +563,6 @@ contract DeployOPChain is Script { systemConfig.optimismMintableERC20Factory() == address(_doo.optimismMintableERC20FactoryProxy()), "SYSCON-210" ); - (address gasPayingToken,) = systemConfig.gasPayingToken(); - require(gasPayingToken == Constants.ETHER, "SYSCON-220"); } function assertValidL1CrossDomainMessenger(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal { diff --git a/packages/contracts-bedrock/snapshots/.gas-snapshot b/packages/contracts-bedrock/snapshots/.gas-snapshot index f4258caa9d69b..66c6653d40960 100644 --- a/packages/contracts-bedrock/snapshots/.gas-snapshot +++ b/packages/contracts-bedrock/snapshots/.gas-snapshot @@ -4,10 +4,10 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5144) GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531) GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369264) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967493) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564413) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076606) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467092) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512819) -GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72667) \ No newline at end of file +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 356541) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954770) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 551668) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4063689) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450376) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3496103) +GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 59849) \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json index 85747ae92c3e3..62e328c3f532e 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json +++ b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json @@ -345,19 +345,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "systemConfig", - "outputs": [ - { - "internalType": "contract ISystemConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json index 45480499fe9f4..5483d5bcef38e 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json @@ -502,19 +502,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "systemConfig", - "outputs": [ - { - "internalType": "contract ISystemConfig", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json index 99f31298fe631..00c7a4061e35a 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json @@ -19,19 +19,6 @@ "stateMutability": "payable", "type": "receive" }, - { - "inputs": [], - "name": "balance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -63,44 +50,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_mint", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "_isCreation", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "depositERC20Transaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -602,34 +551,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint8", - "name": "_decimals", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_name", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_symbol", - "type": "bytes32" - } - ], - "name": "setGasPayingToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -846,11 +767,6 @@ "name": "ContentLengthMismatch", "type": "error" }, - { - "inputs": [], - "name": "CustomGasTokenNotSupported", - "type": "error" - }, { "inputs": [], "name": "EmptyItem", @@ -896,21 +812,11 @@ "name": "LargeCalldata", "type": "error" }, - { - "inputs": [], - "name": "NoValue", - "type": "error" - }, { "inputs": [], "name": "NonReentrant", "type": "error" }, - { - "inputs": [], - "name": "OnlyCustomGasToken", - "type": "error" - }, { "inputs": [], "name": "OutOfGas", @@ -926,11 +832,6 @@ "name": "SmallGasLimit", "type": "error" }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, { "inputs": [], "name": "Unauthorized", diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json index 1509831f4f184..2ded911c4d591 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json @@ -19,19 +19,6 @@ "stateMutability": "payable", "type": "receive" }, - { - "inputs": [], - "name": "balance", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -63,44 +50,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "_to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "_mint", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "_value", - "type": "uint256" - }, - { - "internalType": "uint64", - "name": "_gasLimit", - "type": "uint64" - }, - { - "internalType": "bool", - "name": "_isCreation", - "type": "bool" - }, - { - "internalType": "bytes", - "name": "_data", - "type": "bytes" - } - ], - "name": "depositERC20Transaction", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -620,34 +569,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "uint8", - "name": "_decimals", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "_name", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "_symbol", - "type": "bytes32" - } - ], - "name": "setGasPayingToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -864,11 +785,6 @@ "name": "ContentLengthMismatch", "type": "error" }, - { - "inputs": [], - "name": "CustomGasTokenNotSupported", - "type": "error" - }, { "inputs": [], "name": "EmptyItem", @@ -914,21 +830,11 @@ "name": "LargeCalldata", "type": "error" }, - { - "inputs": [], - "name": "NoValue", - "type": "error" - }, { "inputs": [], "name": "NonReentrant", "type": "error" }, - { - "inputs": [], - "name": "OnlyCustomGasToken", - "type": "error" - }, { "inputs": [], "name": "OutOfGas", @@ -944,11 +850,6 @@ "name": "SmallGasLimit", "type": "error" }, - { - "inputs": [], - "name": "TransferFailed", - "type": "error" - }, { "inputs": [], "name": "Unauthorized", diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json index eaa8cb1ecbfde..9cf9533fc7348 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfig.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfig.json @@ -238,50 +238,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "gasPayingToken", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenName", - "outputs": [ - { - "internalType": "string", - "name": "name_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "symbol_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -387,11 +343,6 @@ "internalType": "address", "name": "optimismMintableERC20Factory", "type": "address" - }, - { - "internalType": "address", - "name": "gasPayingToken", - "type": "address" } ], "internalType": "struct SystemConfig.Addresses", @@ -404,19 +355,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "isCustomGasToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "l1CrossDomainMessenger", @@ -800,10 +738,5 @@ ], "name": "OwnershipTransferred", "type": "event" - }, - { - "inputs": [], - "name": "CustomGasTokenNotSupported", - "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json index c7dae3c2b8e4e..1657176ad563d 100644 --- a/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/SystemConfigInterop.json @@ -259,50 +259,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "gasPayingToken", - "outputs": [ - { - "internalType": "address", - "name": "addr_", - "type": "address" - }, - { - "internalType": "uint8", - "name": "decimals_", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenName", - "outputs": [ - { - "internalType": "string", - "name": "name_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "gasPayingTokenSymbol", - "outputs": [ - { - "internalType": "string", - "name": "symbol_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -408,21 +364,11 @@ "internalType": "address", "name": "optimismMintableERC20Factory", "type": "address" - }, - { - "internalType": "address", - "name": "gasPayingToken", - "type": "address" } ], "internalType": "struct SystemConfig.Addresses", "name": "_addresses", "type": "tuple" - }, - { - "internalType": "address", - "name": "_dependencyManager", - "type": "address" } ], "name": "initialize", @@ -535,16 +481,16 @@ "internalType": "address", "name": "optimismMintableERC20Factory", "type": "address" - }, - { - "internalType": "address", - "name": "gasPayingToken", - "type": "address" } ], "internalType": "struct SystemConfig.Addresses", "name": "_addresses", "type": "tuple" + }, + { + "internalType": "address", + "name": "_dependencyManager", + "type": "address" } ], "name": "initialize", @@ -552,19 +498,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "isCustomGasToken", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "l1CrossDomainMessenger", @@ -961,10 +894,5 @@ ], "name": "OwnershipTransferred", "type": "event" - }, - { - "inputs": [], - "name": "CustomGasTokenNotSupported", - "type": "error" } ] \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index e2a4f24ecb235..66144ad6c9965 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -4,28 +4,28 @@ "sourceCodeHash": "0xae49c741c8cd546981ab59b85b88e9fc1055c4fae085e7078d601b42464f86e6" }, "src/L1/L1CrossDomainMessenger.sol": { - "initCodeHash": "0x192b98a93759f2044ee1ea56270cd203d4f16210c06be388f29b8c1114b9329d", - "sourceCodeHash": "0xfa18fb2e6ac73a143303b07735239a383ae84bd0d0042cceb8253f4784e07afb" + "initCodeHash": "0xd1d16d47e0a769931585952fc12824a8cfd029cd7d658da7e025c06b85386460", + "sourceCodeHash": "0xa4ab39a89f34ef556c6e3e1864808de3361220b3dd25e7d1b47ef4bd6763642f" }, "src/L1/L1ERC721Bridge.sol": { "initCodeHash": "0x280488bce8b4fb364740c59de14c423851902088f384e077bccc79b9df48528a", "sourceCodeHash": "0xe12b9e6c4e4ac2e2c9a03f07c7689f6bf2231922536072812cf1f37a5a276e73" }, "src/L1/L1StandardBridge.sol": { - "initCodeHash": "0x7d7030359826f64714ef0c2a5198901812fb0a99e949f23fe54ccf87a0df2e67", - "sourceCodeHash": "0xa91b445bdc666a02ba18e3b91ba94b6d54bbe65da714002fc734814201319d57" + "initCodeHash": "0xfcf1bf7b7009f24f0336ae6e3905497cfb52bfe4767ad63176b710330db8e7cb", + "sourceCodeHash": "0x00e9b0495b83e34a10ab532ec2a35d55c5fa79e144f2c5a7f6d3299588c8f533" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0x4b413cbe79bd10d41d8f3e9f0408e773dd49ced823d457b9f9aa92f446828105", - "sourceCodeHash": "0xe5179a20ae40d4e4773c52df98bac67e73e04044bec9e8750073b4e2f14fe81b" + "initCodeHash": "0x7ce1bca09a7ecc97846bb8625d2eb94d79a46dd86e5a0621687f5c07d2c43fe8", + "sourceCodeHash": "0x1fa87a9891a94fc89ed378a7514c22c2ee9c365af141b4f821a21ce5761939db" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac", - "sourceCodeHash": "0xe67f0c01c9c9ba67d279304f9db84eebeb2e93d9f2728fea95c7a194f0ae338a" + "initCodeHash": "0x023c91cd71cb0b7d4763483a3cc955f6f39c29a91846a91042576743fff8bd19", + "sourceCodeHash": "0x6624394b7c273411f4e8e3b65899e3928160897cfbcc06c0943d571a78bf538f" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x917b3b31a149b5aab96539208f4810d207875f6f2563a45c50ed13a7940066c0", - "sourceCodeHash": "0xae2fbe02c0f8685692babeed0252ae8a624dc6d3bfb082fc3807d7b84869004b" + "initCodeHash": "0x45af565db1fc8b32357e91f2490558cd650478416f84005375cfae55393eaab5", + "sourceCodeHash": "0xcbd298a6a8bdb5afc8ee18796a3a506104e43ac9532e5e4c56885128f2c234f2" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0x0000ec89712d8b4609873f1ba76afffd4205bf9110818995c90134dbec12e91e", @@ -36,12 +36,12 @@ "sourceCodeHash": "0xafa784ea78818a382ff3a61e2d84be58c7978110c06b9273db68c0213ead02d3" }, "src/L1/SystemConfig.sol": { - "initCodeHash": "0xbb18eef17cdc1d0d307b0241e818820063e3ce3c7021ea3bb3a85ff6e79659e1", - "sourceCodeHash": "0x5d6a9ef41fed54479f742345368e693ec1fcabdb60118081c03fe9da3a5d27ed" + "initCodeHash": "0xf0bfbb889687af7d4e006f40b269bbd9e4d967cdd9c1f29900017ff11b1f5095", + "sourceCodeHash": "0x6a503695a4378634b10d8ba7b31e5be1b48c5db81e1108c7ab93b55917ca786f" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x0d61e2a95122417e9bf074a8fc0bce6f2b03268985d09580a83099dc9016c72d", - "sourceCodeHash": "0x673ec83b89680b44945af89229b286f26df07a5938d497df5def47872d331cf3" + "initCodeHash": "0x8784fa8262f3490e2838007de0dd3d2b15c06bb8b79e0a65601d193ba8e692f5", + "sourceCodeHash": "0xd521302c9dd02f0136b036b1cb88ed4f467b48b64251617cf3eb3581a47db294" }, "src/L2/BaseFeeVault.sol": { "initCodeHash": "0xc403d4c555d8e69a2699e01d192ae7327136701fa02da10a6d75a584b3c364c9", diff --git a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol index 60d69de403bb0..aa80e6be9ab2b 100644 --- a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol @@ -6,6 +6,7 @@ import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; @@ -27,11 +28,11 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { IOptimismPortal public portal; /// @notice Address of the SystemConfig contract. - ISystemConfig public systemConfig; + ISystemConfig internal systemConfig; /// @notice Semantic version. - /// @custom:semver 2.4.1-beta.5 - string public constant version = "2.4.1-beta.5"; + /// @custom:semver 2.4.1-beta.6 + string public constant version = "2.4.1-beta.6"; /// @notice Constructs the L1CrossDomainMessenger contract. constructor() { @@ -57,8 +58,8 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { } /// @inheritdoc CrossDomainMessenger - function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = systemConfig.gasPayingToken(); + function gasPayingToken() internal pure override returns (address addr_, uint8 decimals_) { + return (Constants.ETHER, 18); } /// @notice Getter function for the OptimismPortal contract on this chain. diff --git a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol index a9299ce9aa83b..38aec179a7023 100644 --- a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol @@ -6,6 +6,7 @@ import { StandardBridge } from "src/universal/StandardBridge.sol"; // Libraries import { Predeploys } from "src/libraries/Predeploys.sol"; +import { Constants } from "src/libraries/Constants.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; @@ -75,14 +76,14 @@ contract L1StandardBridge is StandardBridge, ISemver { ); /// @notice Semantic version. - /// @custom:semver 2.2.1-beta.5 - string public constant version = "2.2.1-beta.5"; + /// @custom:semver 2.2.1-beta.6 + string public constant version = "2.2.1-beta.6"; /// @notice Address of the SuperchainConfig contract. ISuperchainConfig public superchainConfig; /// @notice Address of the SystemConfig contract. - ISystemConfig public systemConfig; + ISystemConfig internal systemConfig; /// @notice Constructs the L1StandardBridge contract. constructor() StandardBridge() { @@ -119,8 +120,8 @@ contract L1StandardBridge is StandardBridge, ISemver { } /// @inheritdoc StandardBridge - function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = systemConfig.gasPayingToken(); + function gasPayingToken() internal pure override returns (address addr_, uint8 decimals_) { + return (Constants.ETHER, 18); } /// @custom:legacy diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index d09a63aa18e1c..0132e3bb0fd96 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -588,8 +588,7 @@ contract OPContractsManager is ISemver { l1StandardBridge: address(_output.l1StandardBridgeProxy), disputeGameFactory: address(_output.disputeGameFactoryProxy), optimismPortal: address(_output.optimismPortalProxy), - optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy) }); assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger); diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index 7447a4a3592fe..ceaa08c2cbb59 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -12,7 +12,6 @@ import { Constants } from "src/libraries/Constants.sol"; import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { SecureMerkleTrie } from "src/libraries/trie/SecureMerkleTrie.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { BadTarget, @@ -44,10 +43,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; -import { IL1Block } from "interfaces/L2/IL1Block.sol"; - -/// @notice This is temporary. Error thrown when a chain uses a custom gas token. -error CustomGasTokenNotSupported(); /// @custom:proxied true /// @title OptimismPortal2 @@ -232,19 +227,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { __ResourceMetering_init(); } - /// @notice Getter for the balance of the contract. - function balance() public view returns (uint256) { - (address token,) = gasPayingToken(); - if (token == Constants.ETHER) { - return address(this).balance; - } else { - // Temporary revert till we support custom gas tokens - if (true) revert CustomGasTokenNotSupported(); - - return _balance; - } - } - /// @notice Getter function for the address of the guardian. /// Public getter is legacy and will be removed in the future. Use `SuperchainConfig.guardian()` instead. /// @return Address of the guardian. @@ -294,11 +276,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // Intentionally empty. } - /// @notice Returns the gas paying token and its decimals. - function gasPayingToken() internal view returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = systemConfig.gasPayingToken(); - } - /// @notice Getter for the resource config. /// Used internally by the ResourceMetering contract. /// The SystemConfig is the source of truth for the resource config. @@ -418,52 +395,15 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { l2Sender = _tx.sender; bool success; - (address token,) = gasPayingToken(); - if (token == Constants.ETHER) { - // Trigger the call to the target contract. We use a custom low level method - // SafeCall.callWithMinGas to ensure two key properties - // 1. Target contracts cannot force this call to run out of gas by returning a very large - // amount of data (and this is OK because we don't care about the returndata here). - // 2. The amount of gas provided to the execution context of the target is at least the - // gas limit specified by the user. If there is not enough gas in the current context - // to accomplish this, `callWithMinGas` will revert. - success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data); - } else { - // Temporary revert till we support custom gas tokens - if (true) revert CustomGasTokenNotSupported(); - - // Cannot call the token contract directly from the portal. This would allow an attacker - // to call approve from a withdrawal and drain the balance of the portal. - if (_tx.target == token) revert BadTarget(); - - // Only transfer value when a non zero value is specified. This saves gas in the case of - // using the standard bridge or arbitrary message passing. - if (_tx.value != 0) { - // Update the contracts internal accounting of the amount of native asset in L2. - _balance -= _tx.value; - - // Read the balance of the target contract before the transfer so the consistency - // of the transfer can be checked afterwards. - uint256 startBalance = IERC20(token).balanceOf(address(this)); - - // Transfer the ERC20 balance to the target, accounting for non standard ERC20 - // implementations that may not return a boolean. This reverts if the low level - // call is not successful. - IERC20(token).safeTransfer({ to: _tx.target, value: _tx.value }); - - // The balance must be transferred exactly. - if (IERC20(token).balanceOf(address(this)) != startBalance - _tx.value) { - revert TransferFailed(); - } - } - - // Make a call to the target contract only if there is calldata. - if (_tx.data.length != 0) { - success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, 0, _tx.data); - } else { - success = true; - } - } + + // Trigger the call to the target contract. We use a custom low level method + // SafeCall.callWithMinGas to ensure two key properties + // 1. Target contracts cannot force this call to run out of gas by returning a very large + // amount of data (and this is OK because we don't care about the returndata here). + // 2. The amount of gas provided to the execution context of the target is at least the + // gas limit specified by the user. If there is not enough gas in the current context + // to accomplish this, `callWithMinGas` will revert. + success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data); // Reset the l2Sender back to the default value. l2Sender = Constants.DEFAULT_L2_SENDER; @@ -480,58 +420,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { } } - /// @notice Entrypoint to depositing an ERC20 token as a custom gas token. - /// This function depends on a well formed ERC20 token. There are only - /// so many checks that can be done on chain for this so it is assumed - /// that chain operators will deploy chains with well formed ERC20 tokens. - /// @param _to Target address on L2. - /// @param _mint Units of ERC20 token to deposit into L2. - /// @param _value Units of ERC20 token to send on L2 to the recipient. - /// @param _gasLimit Amount of L2 gas to purchase by burning gas on L1. - /// @param _isCreation Whether or not the transaction is a contract creation. - /// @param _data Data to trigger the recipient with. - function depositERC20Transaction( - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) - public - metered(_gasLimit) - { - // Temporary revert till we support custom gas tokens - if (true) revert CustomGasTokenNotSupported(); - - // Can only be called if an ERC20 token is used for gas paying on L2 - (address token,) = gasPayingToken(); - if (token == Constants.ETHER) revert OnlyCustomGasToken(); - - // Gives overflow protection for L2 account balances. - _balance += _mint; - - // Get the balance of the portal before the transfer. - uint256 startBalance = IERC20(token).balanceOf(address(this)); - - // Take ownership of the token. It is assumed that the user has given the portal an approval. - IERC20(token).safeTransferFrom({ from: msg.sender, to: address(this), value: _mint }); - - // Double check that the portal now has the exact amount of token. - if (IERC20(token).balanceOf(address(this)) != startBalance + _mint) { - revert TransferFailed(); - } - - _depositTransaction({ - _to: _to, - _mint: _mint, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data - }); - } - /// @notice Accepts deposits of ETH and data, and emits a TransactionDeposited event for use in /// deriving deposit transactions. Note that if a deposit is made by a contract, its /// address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider @@ -552,13 +440,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { payable metered(_gasLimit) { - (address token,) = gasPayingToken(); - - // Temporary revert till we support custom gas tokens - if (token != Constants.ETHER) revert CustomGasTokenNotSupported(); - - if (token != Constants.ETHER && msg.value != 0) revert NoValue(); - _depositTransaction({ _to: _to, _mint: msg.value, @@ -616,34 +497,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData); } - /// @notice Sets the gas paying token for the L2 system. This token is used as the - /// L2 native asset. Only the SystemConfig contract can call this function. - function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external { - // Temporary revert till we support custom gas tokens - if (true) revert CustomGasTokenNotSupported(); - - if (msg.sender != address(systemConfig)) revert Unauthorized(); - - // Set L2 deposit gas as used without paying burning gas. Ensures that deposits cannot use too much L2 gas. - // This value must be large enough to cover the cost of calling `L1Block.setGasPayingToken`. - useGas(SYSTEM_DEPOSIT_GAS_LIMIT); - - // Emit the special deposit transaction directly that sets the gas paying - // token in the L1Block predeploy contract. - emit TransactionDeposited( - Constants.DEPOSITOR_ACCOUNT, - Predeploys.L1_BLOCK_ATTRIBUTES, - DEPOSIT_VERSION, - abi.encodePacked( - uint256(0), // mint - uint256(0), // value - uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit - false, // isCreation, - abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) - ) - ); - } - /// @notice Blacklists a dispute game. Should only be used in the event that a dispute game resolves incorrectly. /// @param _disputeGame Dispute game to blacklist. function blacklistDisputeGame(IDisputeGame _disputeGame) external { diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 811c7136191eb..466efab8da0ac 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -25,9 +25,9 @@ contract OptimismPortalInterop is OptimismPortal2 { OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds) { } - /// @custom:semver +interop-beta.7 + /// @custom:semver +interop-beta.8 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.7"); + return string.concat(super.version(), "+interop-beta.8"); } /// @notice Sets static configuration options for the L2 system. diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index 8a9279bd92294..9ac633e06aaf2 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -3,27 +3,20 @@ pragma solidity 0.8.15; // Contracts import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; // Libraries import { Storage } from "src/libraries/Storage.sol"; -import { Constants } from "src/libraries/Constants.sol"; -import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol"; // Interfaces import { ISemver } from "interfaces/universal/ISemver.sol"; -import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; -/// @dev This is temporary. Error thrown when a chain uses a custom gas token. -error CustomGasTokenNotSupported(); - /// @custom:proxied true /// @title SystemConfig /// @notice The SystemConfig contract is used to manage configuration of an Optimism network. /// All configuration is stored on L1 and picked up by L2 as part of the derviation of /// the L2 chain. -contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { +contract SystemConfig is OwnableUpgradeable, ISemver { /// @notice Enum representing different types of updates. /// @custom:value BATCHER Represents an update to the batcher hash. /// @custom:value FEE_SCALARS Represents an update to l1 data fee scalars. @@ -48,7 +41,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { address disputeGameFactory; address optimismPortal; address optimismMintableERC20Factory; - address gasPayingToken; } /// @notice Version identifier, used for upgrades. @@ -140,9 +132,9 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); /// @notice Semantic version. - /// @custom:semver 2.3.0-beta.10 + /// @custom:semver 2.3.0-beta.11 function version() public pure virtual returns (string memory) { - return "2.3.0-beta.10"; + return "2.3.0-beta.11"; } /// @notice Constructs the SystemConfig contract. @@ -197,7 +189,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { Storage.setAddress(OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT, _addresses.optimismMintableERC20Factory); _setStartBlock(); - _setGasPayingToken(_addresses.gasPayingToken); _setResourceConfig(_config); } @@ -268,55 +259,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { startBlock_ = Storage.getUint(START_BLOCK_SLOT); } - /// @notice Getter for the gas paying asset address. - function gasPayingToken() public view returns (address addr_, uint8 decimals_) { - (addr_, decimals_) = GasPayingToken.getToken(); - } - - /// @notice Getter for custom gas token paying networks. Returns true if the - /// network uses a custom gas token. - function isCustomGasToken() public view returns (bool) { - (address token,) = gasPayingToken(); - return token != Constants.ETHER; - } - - /// @notice Getter for the gas paying token name. - function gasPayingTokenName() external view returns (string memory name_) { - name_ = GasPayingToken.getName(); - } - - /// @notice Getter for the gas paying token symbol. - function gasPayingTokenSymbol() external view returns (string memory symbol_) { - symbol_ = GasPayingToken.getSymbol(); - } - - /// @notice Internal setter for the gas paying token address, includes validation. - /// The token must not already be set and must be non zero and not the ether address - /// to set the token address. This prevents the token address from being changed - /// and makes it explicitly opt-in to use custom gas token. - /// @param _token Address of the gas paying token. - function _setGasPayingToken(address _token) internal virtual { - if (_token != address(0) && _token != Constants.ETHER && !isCustomGasToken()) { - // Temporary revert till we support custom gas tokens - if (true) revert CustomGasTokenNotSupported(); - - require( - ERC20(_token).decimals() == GAS_PAYING_TOKEN_DECIMALS, "SystemConfig: bad decimals of gas paying token" - ); - bytes32 name = GasPayingToken.sanitize(ERC20(_token).name()); - bytes32 symbol = GasPayingToken.sanitize(ERC20(_token).symbol()); - - // Set the gas paying token in storage and in the OptimismPortal. - GasPayingToken.set({ _token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol }); - IOptimismPortal2(payable(optimismPortal())).setGasPayingToken({ - _token: _token, - _decimals: GAS_PAYING_TOKEN_DECIMALS, - _name: name, - _symbol: symbol - }); - } - } - /// @notice Updates the unsafe block signer address. Can only be called by the owner. /// @param _unsafeBlockSigner New unsafe block signer address. function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner { diff --git a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol index 2034054619033..b5ceaeb84683f 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol @@ -2,12 +2,9 @@ pragma solidity 0.8.15; // Contracts -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol"; // Libraries -import { Constants } from "src/libraries/Constants.sol"; -import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol"; import { Storage } from "src/libraries/Storage.sol"; @@ -16,9 +13,6 @@ import { IOptimismPortalInterop as IOptimismPortal } from "interfaces/L1/IOptimi import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; -/// @dev This is temporary. Error thrown when a chain uses a custom gas token. -error CustomGasTokenNotSupported(); - /// @custom:proxied true /// @title SystemConfigInterop /// @notice The SystemConfig contract is used to manage configuration of an Optimism network. @@ -76,38 +70,6 @@ contract SystemConfigInterop is SystemConfig { return string.concat(super.version(), "+interop-beta.9"); } - /// @notice Internal setter for the gas paying token address, includes validation. - /// The token must not already be set and must be non zero and not the ether address - /// to set the token address. This prevents the token address from being changed - /// and makes it explicitly opt-in to use custom gas token. Additionally, - /// OptimismPortal's address must be non zero, since otherwise the call to set the - /// config for the gas paying token to OptimismPortal will fail. - /// @param _token Address of the gas paying token. - function _setGasPayingToken(address _token) internal override { - if (_token != address(0) && _token != Constants.ETHER && !isCustomGasToken()) { - // Temporary revert till we support custom gas tokens - if (true) revert CustomGasTokenNotSupported(); - - require( - ERC20(_token).decimals() == GAS_PAYING_TOKEN_DECIMALS, "SystemConfig: bad decimals of gas paying token" - ); - bytes32 name = GasPayingToken.sanitize(ERC20(_token).name()); - bytes32 symbol = GasPayingToken.sanitize(ERC20(_token).symbol()); - - // Set the gas paying token in storage and in the OptimismPortal. - GasPayingToken.set({ _token: _token, _decimals: GAS_PAYING_TOKEN_DECIMALS, _name: name, _symbol: symbol }); - IOptimismPortal(payable(optimismPortal())).setConfig( - ConfigType.SET_GAS_PAYING_TOKEN, - StaticConfig.encodeSetGasPayingToken({ - _token: _token, - _decimals: GAS_PAYING_TOKEN_DECIMALS, - _name: name, - _symbol: symbol - }) - ); - } - } - /// @notice Adds a chain to the interop dependency set. Can only be called by the dependency manager. /// @param _chainId Chain ID of chain to add. function addDependency(uint256 _chainId) external { diff --git a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol index f0ccefa47be85..5242388672f8f 100644 --- a/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L1/L1CrossDomainMessenger.t.sol @@ -697,147 +697,6 @@ contract L1CrossDomainMessenger_Test is CommonTest { assertTrue(l1CrossDomainMessenger.paused()); assertEq(l1CrossDomainMessenger.paused(), superchainConfig.paused()); } - - /// @dev Temporary test that checks that correct calls to sendMessage when using a custom gas token revert with the - /// expected error. - /// @dev Should be removed when/if Custom Gas Token functionality is allowed again. - function test_sendMessage_customGasToken_reverts() external { - skipIfForkTest("Custom gas token is still supported on forked tests"); - - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - - vm.prank(alice); - vm.expectRevert(IOptimismPortal2.CustomGasTokenNotSupported.selector); - l1CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100)); - } - - /// @dev Tests that sendMessage succeeds with a custom gas token when the call value is zero. - function test_sendMessage_customGasTokenButNoValue_succeeds() external { - vm.skip(true, "Custom gas token not supported"); - - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - - // deposit transaction on the optimism portal should be called - vm.expectCall( - address(optimismPortal2), - abi.encodeCall( - IOptimismPortal2.depositTransaction, - ( - Predeploys.L2_CROSS_DOMAIN_MESSENGER, - 0, - l1CrossDomainMessenger.baseGas(hex"ff", 100), - false, - Encoding.encodeCrossDomainMessage( - l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff" - ) - ) - ) - ); - - // TransactionDeposited event - vm.expectEmit(address(optimismPortal2)); - emitTransactionDeposited( - AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), - Predeploys.L2_CROSS_DOMAIN_MESSENGER, - 0, - 0, - l1CrossDomainMessenger.baseGas(hex"ff", 100), - false, - Encoding.encodeCrossDomainMessage(l1CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff") - ); - - // SentMessage event - vm.expectEmit(address(l1CrossDomainMessenger)); - emit SentMessage(recipient, alice, hex"ff", l1CrossDomainMessenger.messageNonce(), 100); - - // SentMessageExtension1 event - vm.expectEmit(address(l1CrossDomainMessenger)); - emit SentMessageExtension1(alice, 0); - - vm.prank(alice); - l1CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100)); - } - - /// @dev Tests that the sendMessage reverts when call value is non-zero with custom gas token. - function test_sendMessage_customGasTokenWithValue_reverts() external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1CrossDomainMessenger_Test: gas paying token functionality DNE on op mainnet"); - - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - - vm.expectRevert("CrossDomainMessenger: cannot send value with custom gas token"); - l1CrossDomainMessenger.sendMessage{ value: 1 }(recipient, hex"aa", uint32(500_000)); - } - - /// @dev Tests that the relayMessage succeeds with a custom gas token when the call value is zero. - function test_relayMessage_customGasTokenAndNoValue_succeeds() external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1CrossDomainMessenger_Test: gas paying token functionality DNE on op mainnet"); - - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - - address target = address(0xabcd); - address sender = Predeploys.L2_CROSS_DOMAIN_MESSENGER; - - vm.expectCall(target, hex"1111"); - - // set the value of op.l2Sender() to be the L2 Cross Domain Messenger. - vm.store(address(optimismPortal2), bytes32(senderSlotIndex), bytes32(abi.encode(sender))); - vm.prank(address(optimismPortal2)); - - vm.expectEmit(address(l1CrossDomainMessenger)); - - bytes32 hash = Hashing.hashCrossDomainMessage( - Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), sender, target, 0, 0, hex"1111" - ); - - emit RelayedMessage(hash); - - l1CrossDomainMessenger.relayMessage( - Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), // nonce - sender, - target, - 0, // value - 0, - hex"1111" - ); - - // the message hash is in the successfulMessages mapping - assertTrue(l1CrossDomainMessenger.successfulMessages(hash)); - // it is not in the received messages mapping - assertEq(l1CrossDomainMessenger.failedMessages(hash), false); - } - - /// @dev Tests that the relayMessage reverts when call value is non-zero with custom gas token. - /// The L2CrossDomainMessenger contract cannot `sendMessage` with value when using a custom gas token. - function test_relayMessage_customGasTokenWithValue_reverts() external virtual { - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address"); - - l1CrossDomainMessenger.relayMessage{ value: 1 }( - Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), - address(0xabcd), - address(0xabcd), - 1, // value - 0, - hex"1111" - ); - } } /// @dev A regression test against a reentrancy vulnerability in the CrossDomainMessenger contract, which diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index 4dbc76af60306..3b9b9b52dabdf 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -29,7 +29,6 @@ contract L1StandardBridge_Getter_Test is CommonTest { assert(l1StandardBridge.superchainConfig() == superchainConfig); returnIfForkTest("L1StandardBridge_Getter_Test: systemConfig() getter DNE on op mainnet"); - assert(l1StandardBridge.systemConfig() == systemConfig); } } @@ -48,7 +47,6 @@ contract L1StandardBridge_Initialize_Test is CommonTest { assertEq(address(impl.OTHER_BRIDGE()), address(0)); assertEq(address(impl.otherBridge()), address(0)); assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE); - assertEq(address(impl.systemConfig()), address(0)); } /// @dev Test that the initialize function sets the correct values. @@ -61,7 +59,6 @@ contract L1StandardBridge_Initialize_Test is CommonTest { assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE); returnIfForkTest("L1StandardBridge_Initialize_Test: systemConfig() getter DNE on op mainnet"); - assertEq(address(l1StandardBridge.systemConfig()), address(systemConfig)); } } @@ -197,26 +194,6 @@ contract L1StandardBridge_Receive_Test is CommonTest { } } -contract L1StandardBridge_Receive_TestFail is CommonTest { - /// @dev Tests receive function reverts with custom gas token. - function testFuzz_receive_customGasToken_reverts(uint256 _value) external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1StandardBridge_Receive_TestFail: gas paying token functionality DNE on op mainnet"); - - vm.prank(alice, alice); - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.deal(alice, _value); - (bool success, bytes memory data) = address(l1StandardBridge).call{ value: _value }(hex""); - assertFalse(success); - assembly { - data := add(data, 0x04) - } - assertEq(abi.decode(data, (string)), "StandardBridge: cannot bridge ETH with custom gas token"); - } -} - contract PreBridgeETH is CommonTest { /// @dev Asserts the expected calls and events for bridging ETH depending /// on whether the bridge call is legacy or not. @@ -306,19 +283,6 @@ contract L1StandardBridge_DepositETH_TestFail is CommonTest { vm.prank(alice); l1StandardBridge.depositETH{ value: 1 }(300, hex""); } - - /// @dev Tests that depositing reverts with custom gas token. - function test_depositETH_customGasToken_reverts() external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1StandardBridge_DepositETH_TestFail: gas paying token functionality DNE on op mainnet"); - - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.prank(alice, alice); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - l1StandardBridge.depositETH(50000, hex"dead"); - } } contract L1StandardBridge_BridgeETH_Test is PreBridgeETH { @@ -335,22 +299,6 @@ contract L1StandardBridge_BridgeETH_Test is PreBridgeETH { } } -contract L1StandardBridge_BridgeETH_TestFail is PreBridgeETH { - /// @dev Tests that bridging eth reverts with custom gas token. - function test_bridgeETH_customGasToken_reverts() external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1StandardBridge_BridgeETH_TestFail: gas paying token functionality DNE on op mainnet"); - - vm.prank(alice, alice); - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l1StandardBridge.bridgeETH(50000, hex"dead"); - } -} - contract PreBridgeETHTo is CommonTest { /// @dev Asserts the expected calls and events for bridging ETH to a different /// address depending on whether the bridge call is legacy or not. @@ -431,29 +379,6 @@ contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo { } } -contract L1StandardBridge_DepositETHTo_TestFail is CommonTest { - /// @dev Tests that depositETHTo reverts with custom gas token. - function testFuzz_depositETHTo_customGasToken_reverts( - uint256 _value, - address _to, - uint32 _minGasLimit, - bytes calldata _extraData - ) - external - { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1StandardBridge_DepositETHTo_TestFail: gas paying token functionality DNE on op mainnet"); - - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.deal(address(this), _value); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l1StandardBridge.depositETHTo{ value: _value }(_to, _minGasLimit, _extraData); - } -} - contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo { /// @dev Tests that bridging ETH to a different address succeeds. /// Emits ETHDepositInitiated and ETHBridgeInitiated events. @@ -468,28 +393,6 @@ contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo { } } -contract L1StandardBridge_BridgeETHTo_TestFail is PreBridgeETHTo { - /// @dev Tests that bridging reverts with custom gas token. - function testFuzz_bridgeETHTo_customGasToken_reverts( - uint256 _value, - uint32 _minGasLimit, - bytes calldata _extraData - ) - external - { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1StandardBridge_BridgeETHTo_TestFail: gas paying token functionality DNE on op mainnet"); - - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.deal(address(this), _value); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l1StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData); - } -} - contract L1StandardBridge_DepositERC20_Test is CommonTest { using stdStorage for StdStorage; @@ -681,35 +584,6 @@ contract L1StandardBridge_FinalizeETHWithdrawal_Test is CommonTest { } } -contract L1StandardBridge_FinalizeETHWithdrawal_TestFail is CommonTest { - /// @dev Tests that finalizeETHWithdrawal reverts with custom gas token. - function testFuzz_finalizeETHWithdrawal_customGasToken_reverts( - uint256 _value, - bytes calldata _extraData - ) - external - { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest( - "L1StandardBridge_FinalizeETHWithdrawal_TestFail: gas paying token functionality DNE on op mainnet" - ); - - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.mockCall( - address(l1StandardBridge.messenger()), - abi.encodeCall(ICrossDomainMessenger.xDomainMessageSender, ()), - abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) - ); - vm.deal(address(l1StandardBridge.messenger()), _value); - vm.prank(address(l1StandardBridge.messenger())); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l1StandardBridge.finalizeETHWithdrawal{ value: _value }(alice, alice, _value, _extraData); - } -} - contract L1StandardBridge_FinalizeERC20Withdrawal_Test is CommonTest { using stdStorage for StdStorage; @@ -795,26 +669,6 @@ contract L1StandardBridge_FinalizeBridgeETH_Test is CommonTest { } contract L1StandardBridge_FinalizeBridgeETH_TestFail is CommonTest { - /// @dev Tests that finalizing bridged reverts with custom gas token. - function testFuzz_finalizeBridgeETH_customGasToken_reverts(uint256 _value, bytes calldata _extraData) external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("L1StandardBridge_FinalizeBridgeETH_TestFail: gas paying token functionality DNE on op mainnet"); - - vm.mockCall( - address(l1StandardBridge.messenger()), - abi.encodeCall(ICrossDomainMessenger.xDomainMessageSender, ()), - abi.encode(address(l1StandardBridge.OTHER_BRIDGE())) - ); - vm.deal(address(l1CrossDomainMessenger), _value); - vm.prank(address(l1CrossDomainMessenger)); - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2)) - ); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l1StandardBridge.finalizeBridgeETH{ value: _value }(alice, alice, _value, _extraData); - } - /// @dev Tests that finalizing bridged ETH reverts if the amount is incorrect. function test_finalizeBridgeETH_incorrectValue_reverts() external { address messenger = address(l1StandardBridge.messenger()); diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index f5c5d2149ba1c..4d55235a47402 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -2,9 +2,7 @@ pragma solidity 0.8.15; // Testing -import { stdError } from "forge-std/Test.sol"; import { VmSafe } from "forge-std/Vm.sol"; -import { MockERC20 } from "solmate/test/utils/mocks/MockERC20.sol"; import { CommonTest } from "test/setup/CommonTest.sol"; import { NextImpl } from "test/mocks/NextImpl.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; @@ -16,15 +14,12 @@ import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; import { Types } from "src/libraries/Types.sol"; import { Hashing } from "src/libraries/Hashing.sol"; import { Constants } from "src/libraries/Constants.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import "src/dispute/lib/Types.sol"; import "src/libraries/PortalErrors.sol"; // Interfaces import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; -import { IL1Block } from "interfaces/L2/IL1Block.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; @@ -309,186 +304,6 @@ contract OptimismPortal2_Test is CommonTest { assertEq(address(optimismPortal2).balance, balanceBefore + _mint); } - /// @dev Temporary test that checks that correct calls to setGasPayingToken when using a custom gas token revert - /// with the expected error. - /// @dev Should be removed when/if Custom Gas Token functionality is allowed again. - function test_setGasPayingToken_customGasToken_reverts( - address _token, - uint8 _decimals, - bytes32 _name, - bytes32 _symbol - ) - external - { - skipIfForkTest("Custom gas token is still supported on forked tests"); - - vm.expectRevert(IOptimismPortal2.CustomGasTokenNotSupported.selector); - optimismPortal2.setGasPayingToken({ _token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol }); - } - - /// @dev Tests that the gas paying token can be set. - function testFuzz_setGasPayingToken_succeeds( - address _token, - uint8 _decimals, - bytes32 _name, - bytes32 _symbol - ) - external - { - vm.skip(true, "Custom gas token not supported"); - - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - - vm.expectEmit(address(optimismPortal2)); - emit TransactionDeposited( - 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001, - Predeploys.L1_BLOCK_ATTRIBUTES, - 0, - abi.encodePacked( - uint256(0), // mint - uint256(0), // value - uint64(200_000), // gasLimit - false, // isCreation, - abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol)) - ) - ); - - vm.prank(address(systemConfig)); - optimismPortal2.setGasPayingToken({ _token: _token, _decimals: _decimals, _name: _name, _symbol: _symbol }); - } - - /// @notice Ensures that the deposit event is correct for the `setGasPayingToken` - /// code path that manually emits a deposit transaction outside of the - /// `depositTransaction` function. This is a simple differential test. - function test_setGasPayingToken_correctEvent_succeeds( - address _token, - string calldata _name, - string calldata _symbol - ) - external - { - vm.skip(true, "Custom gas token not supported"); - - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - - if (bytes(_name).length > 32) { - _name = _name[0:32]; - } - if (bytes(_symbol).length > 32) { - _symbol = _symbol[0:32]; - } - - bytes32 name = GasPayingToken.sanitize(_name); - bytes32 symbol = GasPayingToken.sanitize(_symbol); - - vm.recordLogs(); - - vm.deal(address(systemConfig), 100 ether); - vm.prank(address(systemConfig)); - optimismPortal2.setGasPayingToken({ _token: _token, _decimals: 18, _name: name, _symbol: symbol }); - - vm.prank(Constants.DEPOSITOR_ACCOUNT, Constants.DEPOSITOR_ACCOUNT); - optimismPortal2.depositTransaction({ - _to: Predeploys.L1_BLOCK_ATTRIBUTES, - _value: 0, - _gasLimit: 200_000, - _isCreation: false, - _data: abi.encodeCall(IL1Block.setGasPayingToken, (_token, 18, name, symbol)) - }); - - VmSafe.Log[] memory logs = vm.getRecordedLogs(); - assertEq(logs.length, 2); - - VmSafe.Log memory systemPath = logs[0]; - VmSafe.Log memory userPath = logs[1]; - - assertEq(systemPath.topics.length, 4); - assertEq(systemPath.topics.length, userPath.topics.length); - assertEq(systemPath.topics[0], userPath.topics[0]); - assertEq(systemPath.topics[1], userPath.topics[1]); - assertEq(systemPath.topics[2], userPath.topics[2]); - assertEq(systemPath.topics[3], userPath.topics[3]); - assertEq(systemPath.data, userPath.data); - } - - /// @dev Tests that the gas paying token cannot be set by a non-system config. - function test_setGasPayingToken_notSystemConfig_fails(address _caller) external { - vm.skip(true, "Custom gas token not supported"); - - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - - vm.assume(_caller != address(systemConfig)); - vm.prank(_caller); - vm.expectRevert(Unauthorized.selector); - optimismPortal2.setGasPayingToken({ _token: address(0), _decimals: 0, _name: "", _symbol: "" }); - } - - /// @dev Temporary test that checks that correct calls to depositERC20Transaction when using a custom gas token - /// revert - /// with the expected error. - /// @dev Should be removed when/if Custom Gas Token functionality is allowed again. - function test_depositERC20Transaction_customGasToken_reverts() external { - skipIfForkTest("Custom gas token is still supported on forked tests"); - - vm.expectRevert(IOptimismPortal2.CustomGasTokenNotSupported.selector); - optimismPortal2.depositERC20Transaction(address(0), 0, 0, 0, false, ""); - } - - /// @dev Tests that `depositERC20Transaction` reverts when the gas paying token is ether. - function test_depositERC20Transaction_noCustomGasToken_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - - // Check that the gas paying token is set to ether - (address token,) = systemConfig.gasPayingToken(); - assertEq(token, Constants.ETHER); - - vm.expectRevert(OnlyCustomGasToken.selector); - optimismPortal2.depositERC20Transaction(address(0), 0, 0, 0, false, ""); - } - - function test_depositERC20Transaction_balanceOverflow_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - vm.mockCall(address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(42), 18)); - - // The balance slot - vm.store(address(optimismPortal2), bytes32(uint256(61)), bytes32(type(uint256).max)); - assertEq(optimismPortal2.balance(), type(uint256).max); - - vm.expectRevert(stdError.arithmeticError); - optimismPortal2.depositERC20Transaction({ - _to: address(0), - _mint: 1, - _value: 1, - _gasLimit: 10_000, - _isCreation: false, - _data: "" - }); - } - - /// @dev Tests that `balance()` returns the correct balance when the gas paying token is ether. - function testFuzz_balance_ether_succeeds(uint256 _amount) external { - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - // Check that the gas paying token is set to ether - (address token,) = systemConfig.gasPayingToken(); - assertEq(token, Constants.ETHER); - - // Increase the balance of the gas paying token - vm.deal(address(optimismPortal2), _amount); - - // Check that the balance has been correctly updated - assertEq(optimismPortal2.balance(), address(optimismPortal2).balance); - } - /// @dev Tests that the donateETH function donates ETH and does no state read/write function test_donateETH_succeeds(uint256 _amount) external { vm.startPrank(alice); @@ -1004,152 +819,6 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { assert(bob.balance == bobBalanceBefore + 100); } - /// @dev Tests that `finalizeWithdrawalTransaction` reverts when using a custom gas token. - /// @dev Should be removed when/if Custom Gas Token functionality is allowed again. - function test_finalizeWithdrawalTransaction_customGasToken_reverts() external { - Types.WithdrawalTransaction memory _defaultTx_noData = Types.WithdrawalTransaction({ - nonce: 0, - sender: alice, - target: bob, - value: 100, - gasLimit: 100_000, - data: hex"" - }); - // Get withdrawal proof data we can use for testing. - ( - bytes32 _stateRoot_noData, - bytes32 _storageRoot_noData, - bytes32 _outputRoot_noData, - bytes32 _withdrawalHash_noData, - bytes[] memory _withdrawalProof_noData - ) = ffi.getProveWithdrawalTransactionInputs(_defaultTx_noData); - // Setup a dummy output root proof for reuse. - Types.OutputRootProof memory _outputRootProof_noData = Types.OutputRootProof({ - version: bytes32(uint256(0)), - stateRoot: _stateRoot_noData, - messagePasserStorageRoot: _storageRoot_noData, - latestBlockhash: bytes32(uint256(0)) - }); - uint256 _proposedBlockNumber_noData = 0xFF; - IFaultDisputeGame game_noData = IFaultDisputeGame( - payable( - address( - disputeGameFactory.create( - optimismPortal2.respectedGameType(), - Claim.wrap(_outputRoot_noData), - abi.encode(_proposedBlockNumber_noData) - ) - ) - ) - ); - uint256 _proposedGameIndex_noData = disputeGameFactory.gameCount() - 1; - // Warp beyond the chess clocks and finalize the game. - vm.warp(block.timestamp + game_noData.maxClockDuration().raw() + 1 seconds); - // Fund the portal so that we can withdraw ETH. - vm.store(address(optimismPortal2), bytes32(uint256(61)), bytes32(uint256(0xFFFFFFFF))); - deal(address(L1Token), address(optimismPortal2), 0xFFFFFFFF); - - // modify the gas token to be non ether - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(L1Token), 18) - ); - - vm.expectEmit(address(optimismPortal2)); - emit WithdrawalProven(_withdrawalHash_noData, alice, bob); - vm.expectEmit(address(optimismPortal2)); - emit WithdrawalProvenExtension1(_withdrawalHash_noData, address(this)); - optimismPortal2.proveWithdrawalTransaction({ - _tx: _defaultTx_noData, - _disputeGameIndex: _proposedGameIndex_noData, - _outputRootProof: _outputRootProof_noData, - _withdrawalProof: _withdrawalProof_noData - }); - - // Warp and resolve the dispute game. - game_noData.resolveClaim(0, 0); - game_noData.resolve(); - vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1 seconds); - - vm.expectRevert(IOptimismPortal2.CustomGasTokenNotSupported.selector); - optimismPortal2.finalizeWithdrawalTransaction(_defaultTx_noData); - } - - /// @dev Tests that `finalizeWithdrawalTransaction` succeeds when _tx.data is empty and with a custom gas token. - function test_finalizeWithdrawalTransaction_noTxDataNonEtherGasToken_succeeds() external { - vm.skip(true, "Custom gas token not supported"); - - Types.WithdrawalTransaction memory _defaultTx_noData = Types.WithdrawalTransaction({ - nonce: 0, - sender: alice, - target: bob, - value: 100, - gasLimit: 100_000, - data: hex"" - }); - // Get withdrawal proof data we can use for testing. - ( - bytes32 _stateRoot_noData, - bytes32 _storageRoot_noData, - bytes32 _outputRoot_noData, - bytes32 _withdrawalHash_noData, - bytes[] memory _withdrawalProof_noData - ) = ffi.getProveWithdrawalTransactionInputs(_defaultTx_noData); - // Setup a dummy output root proof for reuse. - Types.OutputRootProof memory _outputRootProof_noData = Types.OutputRootProof({ - version: bytes32(uint256(0)), - stateRoot: _stateRoot_noData, - messagePasserStorageRoot: _storageRoot_noData, - latestBlockhash: bytes32(uint256(0)) - }); - uint256 _proposedBlockNumber_noData = 0xFF; - IFaultDisputeGame game_noData = IFaultDisputeGame( - payable( - address( - disputeGameFactory.create( - optimismPortal2.respectedGameType(), - Claim.wrap(_outputRoot_noData), - abi.encode(_proposedBlockNumber_noData) - ) - ) - ) - ); - uint256 _proposedGameIndex_noData = disputeGameFactory.gameCount() - 1; - // Warp beyond the chess clocks and finalize the game. - vm.warp(block.timestamp + game_noData.maxClockDuration().raw() + 1 seconds); - // Fund the portal so that we can withdraw ETH. - vm.store(address(optimismPortal2), bytes32(uint256(61)), bytes32(uint256(0xFFFFFFFF))); - deal(address(L1Token), address(optimismPortal2), 0xFFFFFFFF); - - // modify the gas token to be non ether - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(L1Token), 18) - ); - - uint256 bobBalanceBefore = L1Token.balanceOf(bob); - - vm.expectEmit(address(optimismPortal2)); - emit WithdrawalProven(_withdrawalHash_noData, alice, bob); - vm.expectEmit(address(optimismPortal2)); - emit WithdrawalProvenExtension1(_withdrawalHash_noData, address(this)); - optimismPortal2.proveWithdrawalTransaction({ - _tx: _defaultTx_noData, - _disputeGameIndex: _proposedGameIndex_noData, - _outputRootProof: _outputRootProof_noData, - _withdrawalProof: _withdrawalProof_noData - }); - - // Warp and resolve the dispute game. - game_noData.resolveClaim(0, 0); - game_noData.resolve(); - vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1 seconds); - - vm.expectEmit(true, true, false, true); - emit WithdrawalFinalized(_withdrawalHash_noData, true); - optimismPortal2.finalizeWithdrawalTransaction(_defaultTx_noData); - - assert(L1Token.balanceOf(bob) == bobBalanceBefore + 100); - } - /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. function test_finalizeWithdrawalTransaction_provenWithdrawalHashEther_succeeds() external { uint256 bobBalanceBefore = address(bob).balance; @@ -1238,32 +907,6 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { assert(address(bob).balance == bobBalanceBefore + 100); } - /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. - function test_finalizeWithdrawalTransaction_provenWithdrawalHashNonEtherTargetToken_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - vm.mockCall( - address(systemConfig), - abi.encodeCall(systemConfig.gasPayingToken, ()), - abi.encode(address(_defaultTx.target), 18) - ); - - optimismPortal2.proveWithdrawalTransaction({ - _tx: _defaultTx, - _disputeGameIndex: _proposedGameIndex, - _outputRootProof: _outputRootProof, - _withdrawalProof: _withdrawalProof - }); - - // Warp to after the finalization period - game.resolveClaim(0, 0); - game.resolve(); - vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); - - vm.expectRevert(BadTarget.selector); - optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); - } - /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused. function test_finalizeWithdrawalTransaction_paused_reverts() external { vm.prank(optimismPortal2.guardian()); @@ -1885,381 +1528,3 @@ contract OptimismPortal2_ResourceFuzz_Test is CommonTest { }); } } - -contract OptimismPortal2WithMockERC20_Test is OptimismPortal2_FinalizeWithdrawal_Test { - MockERC20 token; - - function setUp() public virtual override { - super.setUp(); - token = new MockERC20("Test", "TST", 18); - - // TODO(opcm upgrades): remove skip once upgrade path is implemented - skipIfForkTest("OptimismPortal2_Test: gas paying token functionality DNE on op mainnet"); - } - - function depositERC20Transaction( - address _from, - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes calldata _data - ) - internal - { - if (_isCreation) { - _to = address(0); - } - if (_data.length > 120_000) { - _data = _data[0:120_000]; - } - IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); - _gasLimit = - uint64(bound(_gasLimit, optimismPortal2.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); - - // Mint the token to the contract and approve the token for the portal - token.mint(address(this), _mint); - token.approve(address(optimismPortal2), _mint); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - bytes memory opaqueData = abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data); - - vm.expectEmit(address(optimismPortal2)); - emit TransactionDeposited( - _from, // from - _to, - uint256(0), // DEPOSIT_VERSION - opaqueData - ); - - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(_to, _mint, _value, _gasLimit, _isCreation, _data); - - // Assert final balance equals the deposited amount - assertEq(token.balanceOf(address(optimismPortal2)), _mint); - assertEq(optimismPortal2.balance(), _mint); - } - - /// @dev Tests that `depositERC20Transaction` succeeds when msg.sender == tx.origin. - function testFuzz_depositERC20Transaction_senderIsOrigin_succeeds( - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes calldata _data - ) - external - { - vm.skip(true, "Custom gas token not supported"); - - // Ensure that msg.sender == tx.origin - vm.startPrank(address(this), address(this)); - - depositERC20Transaction({ - _from: address(this), - _to: _to, - _mint: _mint, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data - }); - } - - /// @dev Tests that `depositERC20Transaction` succeeds when msg.sender != tx.origin. - function testFuzz_depositERC20Transaction_senderNotOrigin_succeeds( - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes calldata _data - ) - external - { - vm.skip(true, "Custom gas token not supported"); - - // Ensure that msg.sender != tx.origin - vm.startPrank(address(this), address(1)); - - depositERC20Transaction({ - _from: AddressAliasHelper.applyL1ToL2Alias(address(this)), - _to: _to, - _mint: _mint, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data - }); - } - - /// @dev Tests that `depositERC20Transaction` reverts when not enough of the token is approved. - function test_depositERC20Transaction_notEnoughAmount_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - vm.expectRevert(stdError.arithmeticError); - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(address(0), 1, 0, 0, false, ""); - } - - /// @dev Tests that `depositERC20Transaction` reverts when token balance does not update correctly after transfer. - function test_depositERC20Transaction_incorrectTokenBalance_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // Mint the token to the contract and approve the token for the portal - token.mint(address(this), 100); - token.approve(address(optimismPortal2), 100); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - // Mock the token balance - vm.mockCall(address(token), abi.encodeCall(token.balanceOf, (address(optimismPortal2))), abi.encode(0)); - - // Call minimumGasLimit(0) before vm.expectRevert to ensure vm.expectRevert is for depositERC20Transaction - uint64 gasLimit = optimismPortal2.minimumGasLimit(0); - - vm.expectRevert(TransferFailed.selector); - - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(address(1), 100, 0, gasLimit, false, ""); - } - - /// @dev Tests that `depositERC20Transaction` reverts when creating a contract with a non-zero target. - function test_depositERC20Transaction_isCreationNotZeroTarget_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - // Call minimumGasLimit(0) before vm.expectRevert to ensure vm.expectRevert is for depositERC20Transaction - uint64 gasLimit = optimismPortal2.minimumGasLimit(0); - - vm.expectRevert(BadTarget.selector); - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(address(1), 0, 0, gasLimit, true, ""); - } - - /// @dev Tests that `depositERC20Transaction` reverts when the gas limit is too low. - function test_depositERC20Transaction_gasLimitTooLow_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - vm.expectRevert(SmallGasLimit.selector); - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(address(0), 0, 0, 0, false, ""); - } - - /// @dev Tests that `depositERC20Transaction` reverts when the data is too large. - function test_depositERC20Transaction_dataTooLarge_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - bytes memory data = new bytes(120_001); - data[120_000] = 0x01; - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - uint64 gasLimit = optimismPortal2.minimumGasLimit(120_001); - vm.expectRevert(LargeCalldata.selector); - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(address(0), 0, 0, gasLimit, false, data); - } - - /// @dev Tests that `balance()` returns the correct balance when the gas paying token is not ether. - function testFuzz_balance_nonEther_succeeds(uint256 _amount) external { - vm.skip(true, "Custom gas token not supported"); - - // Mint the token to the contract and approve the token for the portal - token.mint(address(this), _amount); - token.approve(address(optimismPortal2), _amount); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction(address(0), _amount, 0, optimismPortal2.minimumGasLimit(0), false, ""); - - // Check that the balance has been correctly updated - assertEq(optimismPortal2.balance(), _amount); - } - - /// @dev Tests that `finalizeWithdrawalTransaction` succeeds. - function test_finalizeWithdrawalTransaction_provenWithdrawalHashWithNonEther_succeeds() external { - vm.skip(true, "Custom gas token not supported"); - - // Mint the token to the contract and approve the token for the portal - token.mint(address(this), _defaultTx.value); - token.approve(address(optimismPortal2), _defaultTx.value); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - // Deposit the token into the portal - optimismPortal2.depositERC20Transaction( - address(bob), _defaultTx.value, 0, optimismPortal2.minimumGasLimit(0), false, "" - ); - - assertEq(optimismPortal2.balance(), _defaultTx.value); - - vm.expectEmit(address(optimismPortal2)); - emit WithdrawalProven(_withdrawalHash, alice, bob); - optimismPortal2.proveWithdrawalTransaction({ - _tx: _defaultTx, - _disputeGameIndex: _proposedGameIndex, - _outputRootProof: _outputRootProof, - _withdrawalProof: _withdrawalProof - }); - - // Warp past the finalization period. - game.resolveClaim(0, 0); - game.resolve(); - vm.warp(block.timestamp + optimismPortal2.proofMaturityDelaySeconds() + 1); - - vm.expectEmit(address(optimismPortal2)); - emit WithdrawalFinalized(_withdrawalHash, true); - - vm.expectCall(_defaultTx.target, 0, _defaultTx.data); - - vm.expectCall(address(token), 0, abi.encodeCall(token.transfer, (_defaultTx.target, _defaultTx.value))); - - optimismPortal2.finalizeWithdrawalTransaction(_defaultTx); - - assertEq(optimismPortal2.balance(), 0); - assertEq(token.balanceOf(address(bob)), 100); - } - - /// @dev Helper for depositing a transaction. - function depositTransaction( - address _from, - address _to, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes calldata _data - ) - internal - { - if (_isCreation) { - _to = address(0); - } - if (_data.length > 120_000) { - _data = _data[0:120_000]; - } - - IResourceMetering.ResourceConfig memory rcfg = systemConfig.resourceConfig(); - _gasLimit = - uint64(bound(_gasLimit, optimismPortal2.minimumGasLimit(uint64(_data.length)), rcfg.maxResourceLimit)); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - bytes memory opaqueData = abi.encodePacked(uint256(0), _value, _gasLimit, _isCreation, _data); - - vm.expectEmit(address(optimismPortal2)); - emit TransactionDeposited( - _from, // from - _to, - uint256(0), // DEPOSIT_VERSION - opaqueData - ); - - // Deposit the token into the portal - optimismPortal2.depositTransaction(_to, _value, _gasLimit, _isCreation, _data); - - // Assert final balance equals the deposited amount - assertEq(token.balanceOf(address(optimismPortal2)), 0); - assertEq(optimismPortal2.balance(), 0); - } - - /// @dev Tests that `depositTransaction` succeeds when a custom gas token is used but the msg.value is zero. - function testFuzz_depositTransaction_customGasTokenWithNoValueAndSenderIsOrigin_succeeds( - address _to, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes calldata _data - ) - external - { - vm.skip(true, "Custom gas token not supported"); - - // Ensure that msg.sender == tx.origin - vm.startPrank(address(this), address(this)); - - depositTransaction({ - _from: address(this), - _to: _to, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data - }); - } - - /// @dev Tests that `depositTransaction` succeeds when a custom gas token is used but the msg.value is zero. - function testFuzz_depositTransaction_customGasTokenWithNoValueAndSenderNotOrigin_succeeds( - address _to, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes calldata _data - ) - external - { - vm.skip(true, "Custom gas token not supported"); - - // Ensure that msg.sender != tx.origin - vm.startPrank(address(this), address(1)); - - depositTransaction({ - _from: AddressAliasHelper.applyL1ToL2Alias(address(this)), - _to: _to, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data - }); - } - - /// @dev Tests that `depositTransaction` fails when a custom gas token is used and msg.value is non-zero. - function test_depositTransaction_customGasTokenWithValue_reverts() external { - vm.skip(true, "Custom gas token not supported"); - - // Mock the gas paying token to be the ERC20 token - vm.mockCall( - address(systemConfig), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(token), 18) - ); - - vm.expectRevert(NoValue.selector); - - // Deposit the token into the portal - optimismPortal2.depositTransaction{ value: 100 }(address(0), 0, 0, false, ""); - } -} diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index 25b9dac11ab60..8e867ddd7e694 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -4,18 +4,12 @@ pragma solidity 0.8.15; // Testing import { CommonTest } from "test/setup/CommonTest.sol"; -// Contracts -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - // Libraries import { Constants } from "src/libraries/Constants.sol"; -import { Predeploys } from "src/libraries/Predeploys.sol"; -import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; // Interfaces import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; -import { IL1Block } from "interfaces/L2/IL1Block.sol"; contract SystemConfig_Init is CommonTest { event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); @@ -73,10 +67,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { assertEq(address(impl.disputeGameFactory()), address(0)); assertEq(address(impl.optimismPortal()), address(0)); assertEq(address(impl.optimismMintableERC20Factory()), address(0)); - // Check gas paying token - (address token, uint8 decimals) = impl.gasPayingToken(); - assertEq(token, Constants.ETHER); - assertEq(decimals, 18); } /// @dev Tests that initialization sets the correct values. @@ -109,10 +99,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { assertEq(address(systemConfig.disputeGameFactory()), address(disputeGameFactory)); assertEq(address(systemConfig.optimismPortal()), address(optimismPortal2)); assertEq(address(systemConfig.optimismMintableERC20Factory()), address(optimismMintableERC20Factory)); - // Check gas paying token - (address token, uint8 decimals) = systemConfig.gasPayingToken(); - assertEq(token, Constants.ETHER); - assertEq(decimals, 18); } } @@ -143,8 +129,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(0) }) }); } @@ -173,8 +158,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(0) }) }); assertEq(systemConfig.startBlock(), block.number); @@ -204,8 +188,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(0) }) }); assertEq(systemConfig.startBlock(), 1); @@ -314,191 +297,10 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: address(0) - }) - }); - } -} - -contract SystemConfig_Init_CustomGasToken is SystemConfig_Init { - ERC20 token; - - function setUp() public override { - vm.skip(true, "Custom gas token not supported"); - - token = new ERC20("Silly", "SIL"); - super.enableCustomGasToken(address(token)); - - super.setUp(); - } - - /// @dev Helper to clean storage and then initialize the system config with an arbitrary gas token address. - function cleanStorageAndInit(address _gasPayingToken) internal { - vm.store(address(systemConfig), bytes32(0), bytes32(0)); // initailizer - vm.store(address(systemConfig), GasPayingToken.GAS_PAYING_TOKEN_SLOT, bytes32(0)); - vm.store(address(systemConfig), GasPayingToken.GAS_PAYING_TOKEN_NAME_SLOT, bytes32(0)); - vm.store(address(systemConfig), GasPayingToken.GAS_PAYING_TOKEN_SYMBOL_SLOT, bytes32(0)); - - systemConfig.initialize({ - _owner: alice, - _basefeeScalar: 2100, - _blobbasefeeScalar: 1000000, - _batcherHash: bytes32(hex"abcd"), - _gasLimit: 30_000_000, - _unsafeBlockSigner: address(1), - _config: Constants.DEFAULT_RESOURCE_CONFIG(), - _batchInbox: address(0), - _addresses: ISystemConfig.Addresses({ - l1CrossDomainMessenger: address(0), - l1ERC721Bridge: address(0), - disputeGameFactory: address(0), - l1StandardBridge: address(0), - optimismPortal: address(optimismPortal2), - optimismMintableERC20Factory: address(0), - gasPayingToken: _gasPayingToken + optimismMintableERC20Factory: address(0) }) }); } - - /// @dev Tests that initialization sets the correct values and getters work. - function test_initialize_customGasToken_succeeds() external view { - (address addr, uint8 decimals) = systemConfig.gasPayingToken(); - assertEq(addr, address(token)); - assertEq(decimals, 18); - - assertEq(systemConfig.gasPayingTokenName(), token.name()); - assertEq(systemConfig.gasPayingTokenSymbol(), token.symbol()); - } - - /// @dev Tests that initialization sets the correct values and getters work. - function testFuzz_initialize_customGasToken_succeeds( - address _token, - string calldata _name, - string calldata _symbol - ) - external - { - // don't use vm's address - vm.assume(_token != address(vm)); - // don't use console's address - vm.assume(_token != CONSOLE); - // don't use create2 deployer's address - vm.assume(_token != CREATE2_FACTORY); - // don't use default test's address - vm.assume(_token != DEFAULT_TEST_CONTRACT); - // don't use multicall3's address - vm.assume(_token != MULTICALL3_ADDRESS); - - // Using vm.assume() would cause too many test rejections. - string memory name = _name; - if (bytes(_name).length > 32) { - name = _name[:32]; - } - - // Using vm.assume() would cause too many test rejections. - string memory symbol = _symbol; - if (bytes(_symbol).length > 32) { - symbol = _symbol[:32]; - } - - vm.mockCall(_token, abi.encodeCall(token.decimals, ()), abi.encode(18)); - vm.mockCall(_token, abi.encodeCall(token.name, ()), abi.encode(name)); - vm.mockCall(_token, abi.encodeCall(token.symbol, ()), abi.encode(symbol)); - - cleanStorageAndInit(_token); - - (address addr, uint8 decimals) = systemConfig.gasPayingToken(); - assertEq(decimals, 18); - - if (_token == address(0) || _token == Constants.ETHER) { - assertEq(addr, Constants.ETHER); - assertEq(systemConfig.gasPayingTokenName(), "Ether"); - assertEq(systemConfig.gasPayingTokenSymbol(), "ETH"); - } else { - assertEq(addr, _token); - assertEq(systemConfig.gasPayingTokenName(), name); - assertEq(systemConfig.gasPayingTokenSymbol(), symbol); - } - } - - /// @dev Tests that initialization sets the correct values and getters work when token address passed is 0. - function test_initialize_customGasTokenWithZeroTokenAddress_succeeds() external { - cleanStorageAndInit(address(0)); - - (address addr, uint8 decimals) = systemConfig.gasPayingToken(); - assertEq(addr, address(Constants.ETHER)); - assertEq(decimals, 18); - - assertEq(systemConfig.gasPayingTokenName(), "Ether"); - assertEq(systemConfig.gasPayingTokenSymbol(), "ETH"); - } - - /// @dev Tests that initialization sets the correct values and getters work when token address is Constants.ETHER - function test_initialize_customGasTokenWithEtherTokenAddress_succeeds() external { - cleanStorageAndInit(Constants.ETHER); - - (address addr, uint8 decimals) = systemConfig.gasPayingToken(); - assertEq(addr, address(Constants.ETHER)); - assertEq(decimals, 18); - - assertEq(systemConfig.gasPayingTokenName(), "Ether"); - assertEq(systemConfig.gasPayingTokenSymbol(), "ETH"); - } - - /// @dev Tests that initialization fails if decimals are not 18. - function test_initialize_customGasTokenWrongDecimals_fails() external { - vm.mockCall(address(token), abi.encodeCall(token.decimals, ()), abi.encode(8)); - vm.expectRevert("SystemConfig: bad decimals of gas paying token"); - - cleanStorageAndInit(address(token)); - } - - /// @dev Tests that initialization fails if name is too long. - function test_initialize_customGasTokenNameTooLong_fails() external { - string memory name = new string(32); - name = string.concat(name, "a"); - - vm.mockCall(address(token), abi.encodeCall(token.name, ()), abi.encode(name)); - vm.expectRevert("GasPayingToken: string cannot be greater than 32 bytes"); - - cleanStorageAndInit(address(token)); - } - - /// @dev Tests that initialization fails if symbol is too long. - function test_initialize_customGasTokenSymbolTooLong_fails() external { - string memory symbol = new string(33); - symbol = string.concat(symbol, "a"); - - vm.mockCall(address(token), abi.encodeCall(token.symbol, ()), abi.encode(symbol)); - vm.expectRevert("GasPayingToken: string cannot be greater than 32 bytes"); - - cleanStorageAndInit(address(token)); - } - - /// @dev Tests that initialization works with OptimismPortal. - function test_initialize_customGasTokenCall_succeeds() external { - vm.expectCall( - address(optimismPortal2), - abi.encodeCall(optimismPortal2.setGasPayingToken, (address(token), 18, bytes32("Silly"), bytes32("SIL"))) - ); - - vm.expectEmit(address(optimismPortal2)); - emit TransactionDeposited( - 0xDeaDDEaDDeAdDeAdDEAdDEaddeAddEAdDEAd0001, - Predeploys.L1_BLOCK_ATTRIBUTES, - 0, // deposit version - abi.encodePacked( - uint256(0), // mint - uint256(0), // value - uint64(200_000), // gasLimit - false, // isCreation, - abi.encodeCall(IL1Block.setGasPayingToken, (address(token), 18, bytes32("Silly"), bytes32("SIL"))) - ) - ); - - cleanStorageAndInit(address(token)); - } } contract SystemConfig_Setters_TestFail is SystemConfig_Init { diff --git a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol index bc01f347c9104..c9115041e3938 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol @@ -4,16 +4,10 @@ pragma solidity 0.8.15; // Testing import { CommonTest } from "test/setup/CommonTest.sol"; -// Contracts -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - // Libraries -import { Constants } from "src/libraries/Constants.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol"; -import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; // Interfaces -import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol"; import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; @@ -26,112 +20,6 @@ contract SystemConfigInterop_Test is CommonTest { super.setUp(); } - /// @dev Temporary test that checks that correct calls to initialize when using a custom gas token revert with the - /// expected error. - /// @dev Should be removed when/if Custom Gas Token functionality is allowed again. - function test_initialize_customGasToken_reverts() external { - vm.expectRevert(ISystemConfig.CustomGasTokenNotSupported.selector); - _cleanStorageAndInit(address(L1Token)); - } - - /// @dev Tests that when the decimals is not 18, initialization reverts. - function test_initialize_decimalsIsNot18_reverts(uint8 decimals) external { - vm.skip(true, "Custom gas token not supported"); - - vm.assume(decimals != 18); - address _token = address(L1Token); - - vm.mockCall(_token, abi.encodeCall(ERC20.name, ()), abi.encode("Token")); - vm.mockCall(_token, abi.encodeCall(ERC20.symbol, ()), abi.encode("TKN")); - vm.mockCall(_token, abi.encodeCall(ERC20.decimals, ()), abi.encode(decimals)); - - vm.expectRevert("SystemConfig: bad decimals of gas paying token"); - _cleanStorageAndInit(_token); - } - - /// @dev Temporary test that checks that correct calls to setGasPayingToken when using a custom gas token revert - /// with the expected error. - /// @dev Should be removed when/if Custom Gas Token functionality is allowed again. - function test_setGasPayingToken_customGasToken_reverts( - address _token, - string calldata _name, - string calldata _symbol - ) - external - { - assumeNotForgeAddress(_token); - vm.assume(_token != address(0)); - vm.assume(_token != Constants.ETHER); - - // Using vm.assume() would cause too many test rejections. - string memory name = _name; - if (bytes(_name).length > 32) { - name = _name[:32]; - } - - // Using vm.assume() would cause too many test rejections. - string memory symbol = _symbol; - if (bytes(_symbol).length > 32) { - symbol = _symbol[:32]; - } - - vm.mockCall(_token, abi.encodeCall(ERC20.decimals, ()), abi.encode(18)); - vm.mockCall(_token, abi.encodeCall(ERC20.name, ()), abi.encode(name)); - vm.mockCall(_token, abi.encodeCall(ERC20.symbol, ()), abi.encode(symbol)); - - vm.expectRevert(ISystemConfig.CustomGasTokenNotSupported.selector); - _cleanStorageAndInit(_token); - } - - /// @dev Tests that the gas paying token can be set. - function testFuzz_setGasPayingToken_succeeds( - address _token, - string calldata _name, - string calldata _symbol - ) - public - { - vm.skip(true, "Custom gas token not supported"); - - assumeNotForgeAddress(_token); - vm.assume(_token != address(0)); - vm.assume(_token != Constants.ETHER); - - // Using vm.assume() would cause too many test rejections. - string memory name = _name; - if (bytes(_name).length > 32) { - name = _name[:32]; - } - - // Using vm.assume() would cause too many test rejections. - string memory symbol = _symbol; - if (bytes(_symbol).length > 32) { - symbol = _symbol[:32]; - } - - vm.mockCall(_token, abi.encodeCall(ERC20.decimals, ()), abi.encode(18)); - vm.mockCall(_token, abi.encodeCall(ERC20.name, ()), abi.encode(name)); - vm.mockCall(_token, abi.encodeCall(ERC20.symbol, ()), abi.encode(symbol)); - - vm.expectCall( - address(optimismPortal2), - abi.encodeCall( - IOptimismPortalInterop.setConfig, - ( - ConfigType.SET_GAS_PAYING_TOKEN, - StaticConfig.encodeSetGasPayingToken({ - _token: _token, - _decimals: 18, - _name: GasPayingToken.sanitize(name), - _symbol: GasPayingToken.sanitize(symbol) - }) - ) - ) - ); - - _cleanStorageAndInit(_token); - } - /// @dev Tests that a dependency can be added. function testFuzz_addDependency_succeeds(uint256 _chainId) public { vm.expectCall( @@ -176,35 +64,6 @@ contract SystemConfigInterop_Test is CommonTest { _systemConfigInterop().removeDependency(_chainId); } - /// @dev Helper to clean storage and then initialize the system config with an arbitrary gas token address. - function _cleanStorageAndInit(address _token) internal { - // Wipe out the initialized slot so the proxy can be initialized again - vm.store(address(systemConfig), bytes32(0), bytes32(0)); - vm.store(address(systemConfig), GasPayingToken.GAS_PAYING_TOKEN_SLOT, bytes32(0)); - vm.store(address(systemConfig), GasPayingToken.GAS_PAYING_TOKEN_NAME_SLOT, bytes32(0)); - vm.store(address(systemConfig), GasPayingToken.GAS_PAYING_TOKEN_SYMBOL_SLOT, bytes32(0)); - - systemConfig.initialize({ - _owner: alice, - _basefeeScalar: 2100, - _blobbasefeeScalar: 1000000, - _batcherHash: bytes32(hex"abcd"), - _gasLimit: 30_000_000, - _unsafeBlockSigner: address(1), - _config: Constants.DEFAULT_RESOURCE_CONFIG(), - _batchInbox: address(0), - _addresses: ISystemConfig.Addresses({ - l1CrossDomainMessenger: address(0), - l1ERC721Bridge: address(0), - disputeGameFactory: address(0), - l1StandardBridge: address(0), - optimismPortal: address(optimismPortal2), - optimismMintableERC20Factory: address(0), - gasPayingToken: _token - }) - }); - } - /// @dev Returns the SystemConfigInterop instance. function _systemConfigInterop() internal view returns (ISystemConfigInterop) { return ISystemConfigInterop(address(systemConfig)); diff --git a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol index bb673d7304cc8..470c6d82d8599 100644 --- a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol @@ -311,105 +311,4 @@ contract L2CrossDomainMessenger_Test is CommonTest { assertEq(l2CrossDomainMessenger.successfulMessages(hash), true); assertEq(l2CrossDomainMessenger.failedMessages(hash), true); } - - /// @dev Tests that sendMessage succeeds with a custom gas token when the call value is zero. - function test_sendMessage_customGasTokenButNoValue_succeeds() external { - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - - bytes memory xDomainCallData = - Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff"); - vm.expectCall( - address(l2ToL1MessagePasser), - abi.encodeCall( - IL2ToL1MessagePasser.initiateWithdrawal, - (address(l1CrossDomainMessenger), l2CrossDomainMessenger.baseGas(hex"ff", 100), xDomainCallData) - ) - ); - - // MessagePassed event - vm.expectEmit(true, true, true, true); - emit MessagePassed( - l2ToL1MessagePasser.messageNonce(), - address(l2CrossDomainMessenger), - address(l1CrossDomainMessenger), - 0, - l2CrossDomainMessenger.baseGas(hex"ff", 100), - xDomainCallData, - Hashing.hashWithdrawal( - Types.WithdrawalTransaction({ - nonce: l2ToL1MessagePasser.messageNonce(), - sender: address(l2CrossDomainMessenger), - target: address(l1CrossDomainMessenger), - value: 0, - gasLimit: l2CrossDomainMessenger.baseGas(hex"ff", 100), - data: xDomainCallData - }) - ) - ); - - vm.prank(alice); - l2CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100)); - } - - /// @dev Tests that the sendMessage reverts when call value is non-zero with custom gas token. - function test_sendMessage_customGasTokenWithValue_reverts() external { - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - - vm.expectRevert("CrossDomainMessenger: cannot send value with custom gas token"); - l2CrossDomainMessenger.sendMessage{ value: 1 }(recipient, hex"ff", uint32(100)); - } - - /// @dev Tests that the relayMessage succeeds with a custom gas token when the call value is zero. - function test_relayMessage_customGasTokenAndNoValue_succeeds() external { - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - - address target = address(0xabcd); - address sender = address(l1CrossDomainMessenger); - address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); - - vm.expectCall(target, hex"1111"); - - vm.prank(caller); - - vm.expectEmit(true, true, true, true); - - bytes32 hash = - Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, hex"1111"); - - emit RelayedMessage(hash); - - l2CrossDomainMessenger.relayMessage( - Encoding.encodeVersionedNonce(0, 1), // nonce - sender, - target, - 0, // value - 0, - hex"1111" - ); - - // the message hash is in the successfulMessages mapping - assert(l2CrossDomainMessenger.successfulMessages(hash)); - // it is not in the received messages mapping - assertEq(l2CrossDomainMessenger.failedMessages(hash), false); - } - - /// @dev Tests that the relayMessage reverts when call value is non-zero with custom gas token. - /// The L1CrossDomainMessenger `sendMessage` function cannot send value with a custom gas token. - function test_relayMessage_customGasTokenWithValue_reverts() external virtual { - // Mock the gasPayingToken function to return a custom gas token - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address"); - - l2CrossDomainMessenger.relayMessage{ value: 1 }( - Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), - address(0xabcd), - address(0xabcd), - 1, // value - 0, - hex"1111" - ); - } } diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol index 43a22f6a95f5a..48d0f978d359b 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol @@ -127,19 +127,6 @@ contract L2StandardBridge_Test is CommonTest { assertEq(address(l2ToL1MessagePasser).balance, 100); } - /// @dev Tests that the receive function reverts with custom gas token. - function testFuzz_receive_customGasToken_reverts(uint256 _value) external { - vm.prank(alice, alice); - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - vm.deal(alice, _value); - (bool success, bytes memory data) = address(l2StandardBridge).call{ value: _value }(hex""); - assertFalse(success); - assembly { - data := add(data, 0x04) - } - assertEq(abi.decode(data, (string)), "StandardBridge: cannot bridge ETH with custom gas token"); - } - /// @dev Tests that `withdraw` reverts if the amount is not equal to the value sent. function test_withdraw_insufficientValue_reverts() external { assertEq(address(l2ToL1MessagePasser).balance, 0); @@ -167,90 +154,6 @@ contract L2StandardBridge_Test is CommonTest { l2StandardBridge.withdrawTo{ value: 100 }(address(L2Token), alice, 100, 1, hex""); } - /// @dev Tests that `withdraw` reverts with custom gas token. - function test_withdraw_customGasToken_reverts() external { - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex""); - } - - /// @dev Tests that `withdraw` reverts with custom gas token. - function test_withdrawERC20_customGasToken_reverts() external { - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdraw(address(L1Token), 1, 1, hex""); - } - - /// @dev Tests that `withdraw` reverts with custom gas token. - function test_withdrawERC20WithValue_customGasToken_reverts() external { - vm.deal(alice, 1 ether); - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdraw{ value: 1 ether }(address(L1Token), 1, 1, hex""); - } - - /// @dev Tests that `withdraw` with value reverts with custom gas token. - function test_withdraw_customGasTokenWithValue_reverts() external { - vm.deal(alice, 1 ether); - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdraw{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex""); - } - - /// @dev Tests that `withdrawTo` reverts with custom gas token. - function test_withdrawTo_customGasToken_reverts() external { - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdrawTo(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex""); - } - - /// @dev Tests that `withdrawTo` reverts with custom gas token. - function test_withdrawToERC20_customGasToken_reverts() external { - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdrawTo(address(L2Token), bob, 1, 1, hex""); - } - - /// @dev Tests that `withdrawTo` reverts with custom gas token. - function test_withdrawToERC20WithValue_customGasToken_reverts() external { - vm.deal(alice, 1 ether); - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdrawTo{ value: 1 ether }(address(L2Token), bob, 1, 1, hex""); - } - - /// @dev Tests that `withdrawTo` with value reverts with custom gas token. - function test_withdrawTo_customGasTokenWithValue_reverts() external { - vm.deal(alice, 1 ether); - vm.mockCall( - address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18)) - ); - vm.expectRevert("L2StandardBridge: not supported with custom gas token"); - vm.prank(alice, alice); - l2StandardBridge.withdrawTo{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex""); - } - /// @dev Tests that the legacy `withdraw` interface on the L2StandardBridge /// successfully initiates a withdrawal. function test_withdraw_ether_succeeds() external { @@ -574,15 +477,6 @@ contract L2StandardBridge_Bridge_Test is CommonTest { l2StandardBridge.bridgeETH{ value: _value }(_minGasLimit, _extraData); } - /// @dev Tests that bridging reverts with custom gas token. - function test_bridgeETH_customGasToken_reverts() external { - vm.prank(alice, alice); - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l2StandardBridge.bridgeETH(50000, hex"dead"); - } - /// @dev Tests that bridging ETH to a different address succeeds. function testFuzz_bridgeETHTo_succeeds(uint256 _value, uint32 _minGasLimit, bytes calldata _extraData) external { uint256 nonce = l2CrossDomainMessenger.messageNonce(); @@ -619,20 +513,6 @@ contract L2StandardBridge_Bridge_Test is CommonTest { l2StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData); } - - /// @dev Tests that bridging reverts with custom gas token. - function testFuzz_bridgeETHTo_customGasToken_reverts( - uint256 _value, - uint32 _minGasLimit, - bytes calldata _extraData - ) - external - { - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - vm.deal(address(this), _value); - l2StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData); - } } contract L2StandardBridge_FinalizeBridgeETH_Test is CommonTest { @@ -655,22 +535,6 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is CommonTest { l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex""); } - - /// @dev Tests that finalizing bridged reverts with custom gas token. - function test_finalizeBridgeETH_customGasToken_reverts() external { - address messenger = address(l2StandardBridge.messenger()); - vm.mockCall( - messenger, - abi.encodeCall(ICrossDomainMessenger.xDomainMessageSender, ()), - abi.encode(address(l2StandardBridge.OTHER_BRIDGE())) - ); - vm.deal(address(l2CrossDomainMessenger), 1); - vm.prank(address(l2CrossDomainMessenger)); - vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); - vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); - - l2StandardBridge.finalizeBridgeETH(alice, alice, 1, hex""); - } } contract L2StandardBridge_FinalizeBridgeERC20_Test is CommonTest { diff --git a/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol b/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol index 68add058f60dd..4ca84d96b0209 100644 --- a/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/invariants/SystemConfig.t.sol @@ -44,8 +44,7 @@ contract SystemConfig_GasLimitBoundaries_Invariant is Test { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(0) }) ) ) diff --git a/packages/contracts-bedrock/test/vendor/Initializable.t.sol b/packages/contracts-bedrock/test/vendor/Initializable.t.sol index e870a502aa745..095da92a75675 100644 --- a/packages/contracts-bedrock/test/vendor/Initializable.t.sol +++ b/packages/contracts-bedrock/test/vendor/Initializable.t.sol @@ -10,7 +10,6 @@ import { Process } from "scripts/libraries/Process.sol"; // Libraries import { LibString } from "@solady/utils/LibString.sol"; -import { Constants } from "src/libraries/Constants.sol"; import { GameType } from "src/dispute/lib/Types.sol"; // Interfaces @@ -182,8 +181,7 @@ contract Initializer_Test is CommonTest { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(0) }) ) ) @@ -218,8 +216,7 @@ contract Initializer_Test is CommonTest { l1StandardBridge: address(0), disputeGameFactory: address(0), optimismPortal: address(0), - optimismMintableERC20Factory: address(0), - gasPayingToken: Constants.ETHER + optimismMintableERC20Factory: address(0) }) ) ) From 607dfb75dcbc90f85c39713c6bd9571e6c4f0249 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 10 Jan 2025 14:40:50 +0100 Subject: [PATCH 02/15] fixes --- .../contracts-bedrock/snapshots/semver-lock.json | 14 +++++++------- .../src/L1/OPContractsManager.sol | 4 ++-- .../contracts-bedrock/src/L1/OptimismPortal2.sol | 4 ++-- .../src/L1/SystemConfigInterop.sol | 4 ++-- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 66144ad6c9965..8c70ec21ae9da 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -16,15 +16,15 @@ "sourceCodeHash": "0x00e9b0495b83e34a10ab532ec2a35d55c5fa79e144f2c5a7f6d3299588c8f533" }, "src/L1/OPContractsManager.sol": { - "initCodeHash": "0x7ce1bca09a7ecc97846bb8625d2eb94d79a46dd86e5a0621687f5c07d2c43fe8", - "sourceCodeHash": "0x1fa87a9891a94fc89ed378a7514c22c2ee9c365af141b4f821a21ce5761939db" + "initCodeHash": "0xfd462d5475c21f4f8be1be22657f3dcef8962df6874bf8e36995fcc51bca6312", + "sourceCodeHash": "0x92b9739d1b2a1ed69f7a732afafcb32cde8eef26bfba4f2a25f64f0c71efac99" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x023c91cd71cb0b7d4763483a3cc955f6f39c29a91846a91042576743fff8bd19", - "sourceCodeHash": "0x6624394b7c273411f4e8e3b65899e3928160897cfbcc06c0943d571a78bf538f" + "initCodeHash": "0x32ba32dce7717119f4f868925140e2c92d010ea5378c8923d40dc83e299fd961", + "sourceCodeHash": "0x8db762caddc1ef283ae70e6111d560aefde427ce5f8b57703100d708d268f6f8" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x45af565db1fc8b32357e91f2490558cd650478416f84005375cfae55393eaab5", + "initCodeHash": "0x70ce9058c15f9fbddc4a3df14dbdad2a734845260cbe05f4eceba9d3239a033a", "sourceCodeHash": "0xcbd298a6a8bdb5afc8ee18796a3a506104e43ac9532e5e4c56885128f2c234f2" }, "src/L1/ProtocolVersions.sol": { @@ -40,8 +40,8 @@ "sourceCodeHash": "0x6a503695a4378634b10d8ba7b31e5be1b48c5db81e1108c7ab93b55917ca786f" }, "src/L1/SystemConfigInterop.sol": { - "initCodeHash": "0x8784fa8262f3490e2838007de0dd3d2b15c06bb8b79e0a65601d193ba8e692f5", - "sourceCodeHash": "0xd521302c9dd02f0136b036b1cb88ed4f467b48b64251617cf3eb3581a47db294" + "initCodeHash": "0xd89526ba331c24f8ca5ce1eef1554ad573e3aa9e6845a5b0ec23ee8f3497a84a", + "sourceCodeHash": "0x10806bbaa0d0e1dca571b720bd9690dd55cbf57038ab5887ecfdce689b0ae94e" }, "src/L2/BaseFeeVault.sol": { "initCodeHash": "0xc403d4c555d8e69a2699e01d192ae7327136701fa02da10a6d75a584b3c364c9", diff --git a/packages/contracts-bedrock/src/L1/OPContractsManager.sol b/packages/contracts-bedrock/src/L1/OPContractsManager.sol index 0132e3bb0fd96..36bae2d68bb38 100644 --- a/packages/contracts-bedrock/src/L1/OPContractsManager.sol +++ b/packages/contracts-bedrock/src/L1/OPContractsManager.sol @@ -114,8 +114,8 @@ contract OPContractsManager is ISemver { // -------- Constants and Variables -------- - /// @custom:semver 1.0.0-beta.27 - string public constant version = "1.0.0-beta.27"; + /// @custom:semver 1.0.0-beta.28 + string public constant version = "1.0.0-beta.28"; /// @notice Represents the interface version so consumers know how to decode the DeployOutput struct /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used. diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index ceaa08c2cbb59..f74354a1ebbff 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -181,9 +181,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { } /// @notice Semantic version. - /// @custom:semver 3.11.0-beta.10 + /// @custom:semver 3.11.0-beta.11 function version() public pure virtual returns (string memory) { - return "3.11.0-beta.10"; + return "3.11.0-beta.11"; } /// @notice Constructs the OptimismPortal contract. diff --git a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol index b5ceaeb84683f..fbc09531efdcb 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfigInterop.sol @@ -65,9 +65,9 @@ contract SystemConfigInterop is SystemConfig { Storage.setAddress(DEPENDENCY_MANAGER_SLOT, _dependencyManager); } - /// @custom:semver +interop-beta.9 + /// @custom:semver +interop-beta.10 function version() public pure override returns (string memory) { - return string.concat(super.version(), "+interop-beta.9"); + return string.concat(super.version(), "+interop-beta.10"); } /// @notice Adds a chain to the interop dependency set. Can only be called by the dependency manager. From 8a93ff3ebcc569cec4418e50d419ea84bbdcf742 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 10 Jan 2025 15:05:23 +0100 Subject: [PATCH 03/15] fixes --- .../src/L1/OptimismPortal2.sol | 4 +--- .../test/universal/Specs.t.sol | 22 ------------------- 2 files changed, 1 insertion(+), 25 deletions(-) diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index f74354a1ebbff..da63577408059 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -394,8 +394,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // Set the l2Sender so contracts know who triggered this withdrawal on L2. l2Sender = _tx.sender; - bool success; - // Trigger the call to the target contract. We use a custom low level method // SafeCall.callWithMinGas to ensure two key properties // 1. Target contracts cannot force this call to run out of gas by returning a very large @@ -403,7 +401,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // 2. The amount of gas provided to the execution context of the target is at least the // gas limit specified by the user. If there is not enough gas in the current context // to accomplish this, `callWithMinGas` will revert. - success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data); + bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data); // Reset the l2Sender back to the default value. l2Sender = Constants.DEFAULT_L2_SENDER; diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 14dcbc9bc884d..7f4ea83777dfb 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -125,7 +125,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("paused()") }); _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("otherMessenger()") }); _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("portal()") }); - _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("systemConfig()") }); _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("relayMessage(uint256,address,address,uint256,uint256,bytes)"), @@ -207,7 +206,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "L1StandardBridge", _sel: _getSel("paused()") }); _addSpec({ _name: "L1StandardBridge", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "L1StandardBridge", _sel: _getSel("version()") }); - _addSpec({ _name: "L1StandardBridge", _sel: _getSel("systemConfig()") }); // OptimismPortalInterop _addSpec({ @@ -261,12 +259,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("respectedGameTypeUpdatedAt()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("proofSubmitters(bytes32,uint256)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("numProofSubmitters(bytes32)") }); - _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("balance()") }); - _addSpec({ - _name: "OptimismPortalInterop", - _sel: _getSel("depositERC20Transaction(address,uint256,uint256,uint64,bool,bytes)") - }); - _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("setGasPayingToken(address,uint8,bytes32,bytes32)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: IOptimismPortalInterop.setConfig.selector, @@ -313,12 +305,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameTypeUpdatedAt()") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("proofSubmitters(bytes32,uint256)") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("numProofSubmitters(bytes32)") }); - _addSpec({ _name: "OptimismPortal2", _sel: _getSel("balance()") }); - _addSpec({ - _name: "OptimismPortal2", - _sel: _getSel("depositERC20Transaction(address,uint256,uint256,uint64,bool,bytes)") - }); - _addSpec({ _name: "OptimismPortal2", _sel: _getSel("setGasPayingToken(address,uint8,bytes32,bytes32)") }); // ProtocolVersions _addSpec({ _name: "ProtocolVersions", _sel: _getSel("RECOMMENDED_SLOT()") }); @@ -395,10 +381,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("BATCH_INBOX_SLOT()") }); - _addSpec({ _name: "SystemConfig", _sel: _getSel("gasPayingToken()") }); - _addSpec({ _name: "SystemConfig", _sel: _getSel("gasPayingTokenName()") }); - _addSpec({ _name: "SystemConfig", _sel: _getSel("gasPayingTokenSymbol()") }); - _addSpec({ _name: "SystemConfig", _sel: _getSel("isCustomGasToken()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("DISPUTE_GAME_FACTORY_SLOT()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("disputeGameFactory()") }); _addSpec({ @@ -471,10 +453,6 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("BATCH_INBOX_SLOT()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasPayingToken()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasPayingTokenName()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasPayingTokenSymbol()") }); - _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("isCustomGasToken()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("DISPUTE_GAME_FACTORY_SLOT()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("disputeGameFactory()") }); _addSpec({ From 757db2a1d45d92e53ad2d324b5dc1b1a36f86529 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 10 Jan 2025 15:20:59 +0100 Subject: [PATCH 04/15] remove CGT code --- packages/contracts-bedrock/snapshots/semver-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 8c70ec21ae9da..fabdc9c8159ff 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -21,7 +21,7 @@ }, "src/L1/OptimismPortal2.sol": { "initCodeHash": "0x32ba32dce7717119f4f868925140e2c92d010ea5378c8923d40dc83e299fd961", - "sourceCodeHash": "0x8db762caddc1ef283ae70e6111d560aefde427ce5f8b57703100d708d268f6f8" + "sourceCodeHash": "0x258b7edfe6c8be55ca8d14df30512233f1b443c3a858d38ef33f6bbad1be38d3" }, "src/L1/OptimismPortalInterop.sol": { "initCodeHash": "0x70ce9058c15f9fbddc4a3df14dbdad2a734845260cbe05f4eceba9d3239a033a", From de06b6e4ab81caee0a0048a62c835f657da30071 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 10 Jan 2025 18:50:39 +0100 Subject: [PATCH 05/15] fixes --- .../interfaces/L1/IL1CrossDomainMessenger.sol | 1 + .../interfaces/L1/IL1StandardBridge.sol | 1 + packages/contracts-bedrock/snapshots/.gas-snapshot | 4 ++-- .../snapshots/abi/L1CrossDomainMessenger.json | 13 +++++++++++++ .../snapshots/abi/L1StandardBridge.json | 13 +++++++++++++ .../contracts-bedrock/snapshots/semver-lock.json | 10 +++++----- .../src/L1/L1CrossDomainMessenger.sol | 4 +++- .../contracts-bedrock/src/L1/L1StandardBridge.sol | 4 +++- packages/contracts-bedrock/src/L1/SystemConfig.sol | 3 --- .../test/L1/L1StandardBridge.t.sol | 3 +++ .../contracts-bedrock/test/universal/Specs.t.sol | 2 ++ 11 files changed, 46 insertions(+), 12 deletions(-) diff --git a/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol b/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol index 4047c57d56131..578a975d32fa0 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1CrossDomainMessenger.sol @@ -16,6 +16,7 @@ interface IL1CrossDomainMessenger is ICrossDomainMessenger { external; function portal() external view returns (IOptimismPortal); function superchainConfig() external view returns (ISuperchainConfig); + function systemConfig() external view returns (ISystemConfig); function version() external view returns (string memory); function __constructor__() external; diff --git a/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol b/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol index abafca5457273..847ea76b44d2e 100644 --- a/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol +++ b/packages/contracts-bedrock/interfaces/L1/IL1StandardBridge.sol @@ -70,6 +70,7 @@ interface IL1StandardBridge is IStandardBridge { external; function l2TokenBridge() external view returns (address); function superchainConfig() external view returns (ISuperchainConfig); + function systemConfig() external view returns (ISystemConfig); function version() external view returns (string memory); function __constructor__() external; diff --git a/packages/contracts-bedrock/snapshots/.gas-snapshot b/packages/contracts-bedrock/snapshots/.gas-snapshot index 66c6653d40960..f4423374db136 100644 --- a/packages/contracts-bedrock/snapshots/.gas-snapshot +++ b/packages/contracts-bedrock/snapshots/.gas-snapshot @@ -6,8 +6,8 @@ GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() ( GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 356541) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954770) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 551668) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4063689) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 551690) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4063711) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450376) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3496103) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 59849) \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json index 62e328c3f532e..85747ae92c3e3 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json +++ b/packages/contracts-bedrock/snapshots/abi/L1CrossDomainMessenger.json @@ -345,6 +345,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "systemConfig", + "outputs": [ + { + "internalType": "contract ISystemConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json index 5483d5bcef38e..45480499fe9f4 100644 --- a/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json +++ b/packages/contracts-bedrock/snapshots/abi/L1StandardBridge.json @@ -502,6 +502,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "systemConfig", + "outputs": [ + { + "internalType": "contract ISystemConfig", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "version", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index fabdc9c8159ff..bc3b3999966ad 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -4,16 +4,16 @@ "sourceCodeHash": "0xae49c741c8cd546981ab59b85b88e9fc1055c4fae085e7078d601b42464f86e6" }, "src/L1/L1CrossDomainMessenger.sol": { - "initCodeHash": "0xd1d16d47e0a769931585952fc12824a8cfd029cd7d658da7e025c06b85386460", - "sourceCodeHash": "0xa4ab39a89f34ef556c6e3e1864808de3361220b3dd25e7d1b47ef4bd6763642f" + "initCodeHash": "0x4b045c9e0fcfa37838edf154e6e75be4a60406204eccf0d606dfd55da80d266d", + "sourceCodeHash": "0xc92887952f5108a770c3fee8a61c70f740a0a55c2e9ed0aebe266a7c53c71dc3" }, "src/L1/L1ERC721Bridge.sol": { "initCodeHash": "0x280488bce8b4fb364740c59de14c423851902088f384e077bccc79b9df48528a", "sourceCodeHash": "0xe12b9e6c4e4ac2e2c9a03f07c7689f6bf2231922536072812cf1f37a5a276e73" }, "src/L1/L1StandardBridge.sol": { - "initCodeHash": "0xfcf1bf7b7009f24f0336ae6e3905497cfb52bfe4767ad63176b710330db8e7cb", - "sourceCodeHash": "0x00e9b0495b83e34a10ab532ec2a35d55c5fa79e144f2c5a7f6d3299588c8f533" + "initCodeHash": "0xe5f5ab77cc5586ecd94cc687b98f25d8fd7f9bb146a942653a2ec9be7e68f070", + "sourceCodeHash": "0x51f0876ab8410ce32838483f8f59ad6d1c5b4a368e47415b30e44baf291a394b" }, "src/L1/OPContractsManager.sol": { "initCodeHash": "0xfd462d5475c21f4f8be1be22657f3dcef8962df6874bf8e36995fcc51bca6312", @@ -37,7 +37,7 @@ }, "src/L1/SystemConfig.sol": { "initCodeHash": "0xf0bfbb889687af7d4e006f40b269bbd9e4d967cdd9c1f29900017ff11b1f5095", - "sourceCodeHash": "0x6a503695a4378634b10d8ba7b31e5be1b48c5db81e1108c7ab93b55917ca786f" + "sourceCodeHash": "0x2dde897735c0cd699f15a1927bf6f75c2da220c1934021ee93315708d5b5f995" }, "src/L1/SystemConfigInterop.sol": { "initCodeHash": "0xd89526ba331c24f8ca5ce1eef1554ad573e3aa9e6845a5b0ec23ee8f3497a84a", diff --git a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol index aa80e6be9ab2b..1946c2a9fc09d 100644 --- a/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol +++ b/packages/contracts-bedrock/src/L1/L1CrossDomainMessenger.sol @@ -28,7 +28,7 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { IOptimismPortal public portal; /// @notice Address of the SystemConfig contract. - ISystemConfig internal systemConfig; + ISystemConfig public systemConfig; /// @notice Semantic version. /// @custom:semver 2.4.1-beta.6 @@ -58,6 +58,8 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { } /// @inheritdoc CrossDomainMessenger + /// @dev This is added to maintain compatibility with the CrossDomainMessenger abstract contract and should always + /// return the ether address and 18 decimals. function gasPayingToken() internal pure override returns (address addr_, uint8 decimals_) { return (Constants.ETHER, 18); } diff --git a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol index 38aec179a7023..61cd481e27129 100644 --- a/packages/contracts-bedrock/src/L1/L1StandardBridge.sol +++ b/packages/contracts-bedrock/src/L1/L1StandardBridge.sol @@ -83,7 +83,7 @@ contract L1StandardBridge is StandardBridge, ISemver { ISuperchainConfig public superchainConfig; /// @notice Address of the SystemConfig contract. - ISystemConfig internal systemConfig; + ISystemConfig public systemConfig; /// @notice Constructs the L1StandardBridge contract. constructor() StandardBridge() { @@ -120,6 +120,8 @@ contract L1StandardBridge is StandardBridge, ISemver { } /// @inheritdoc StandardBridge + /// @dev This is added to maintain compatibility with the CrossDomainMessenger abstract contract and should always + /// return the ether address and 18 decimals. function gasPayingToken() internal pure override returns (address addr_, uint8 decimals_) { return (Constants.ETHER, 18); } diff --git a/packages/contracts-bedrock/src/L1/SystemConfig.sol b/packages/contracts-bedrock/src/L1/SystemConfig.sol index 9ac633e06aaf2..8d36a591812de 100644 --- a/packages/contracts-bedrock/src/L1/SystemConfig.sol +++ b/packages/contracts-bedrock/src/L1/SystemConfig.sol @@ -83,9 +83,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver { bytes32 public constant DISPUTE_GAME_FACTORY_SLOT = bytes32(uint256(keccak256("systemconfig.disputegamefactory")) - 1); - /// @notice The number of decimals that the gas paying token has. - uint8 internal constant GAS_PAYING_TOKEN_DECIMALS = 18; - /// @notice The maximum gas limit that can be set for L2 blocks. This limit is used to enforce that the blocks /// on L2 are not too large to process and prove. Over time, this value can be increased as various /// optimizations and improvements are made to the system at large. diff --git a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol index 3b9b9b52dabdf..0bb4c753053ae 100644 --- a/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L1/L1StandardBridge.t.sol @@ -29,6 +29,7 @@ contract L1StandardBridge_Getter_Test is CommonTest { assert(l1StandardBridge.superchainConfig() == superchainConfig); returnIfForkTest("L1StandardBridge_Getter_Test: systemConfig() getter DNE on op mainnet"); + assert(l1StandardBridge.systemConfig() == systemConfig); } } @@ -47,6 +48,7 @@ contract L1StandardBridge_Initialize_Test is CommonTest { assertEq(address(impl.OTHER_BRIDGE()), address(0)); assertEq(address(impl.otherBridge()), address(0)); assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE); + assertEq(address(impl.systemConfig()), address(0)); } /// @dev Test that the initialize function sets the correct values. @@ -59,6 +61,7 @@ contract L1StandardBridge_Initialize_Test is CommonTest { assertEq(address(l2StandardBridge), Predeploys.L2_STANDARD_BRIDGE); returnIfForkTest("L1StandardBridge_Initialize_Test: systemConfig() getter DNE on op mainnet"); + assertEq(address(l1StandardBridge.systemConfig()), address(systemConfig)); } } diff --git a/packages/contracts-bedrock/test/universal/Specs.t.sol b/packages/contracts-bedrock/test/universal/Specs.t.sol index 7f4ea83777dfb..8dd7e924491bb 100644 --- a/packages/contracts-bedrock/test/universal/Specs.t.sol +++ b/packages/contracts-bedrock/test/universal/Specs.t.sol @@ -125,6 +125,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("paused()") }); _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("otherMessenger()") }); _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("portal()") }); + _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("systemConfig()") }); _addSpec({ _name: "L1CrossDomainMessenger", _sel: _getSel("relayMessage(uint256,address,address,uint256,uint256,bytes)"), @@ -206,6 +207,7 @@ contract Specification_Test is CommonTest { _addSpec({ _name: "L1StandardBridge", _sel: _getSel("paused()") }); _addSpec({ _name: "L1StandardBridge", _sel: _getSel("superchainConfig()") }); _addSpec({ _name: "L1StandardBridge", _sel: _getSel("version()") }); + _addSpec({ _name: "L1StandardBridge", _sel: _getSel("systemConfig()") }); // OptimismPortalInterop _addSpec({ From 896cf49a6f56e8a210a0c27667d4271976fe5ebb Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Fri, 10 Jan 2025 18:57:38 +0100 Subject: [PATCH 06/15] fixes --- .../interfaces/L1/IOptimismPortalInterop.sol | 1 + .../snapshots/abi/OptimismPortalInterop.json | 5 +++++ packages/contracts-bedrock/snapshots/semver-lock.json | 4 ++-- packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol | 4 ++++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol index 1b8037ffc3563..ed5f980e1839f 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol @@ -10,6 +10,7 @@ import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; interface IOptimismPortalInterop { + error CustomGasTokenNotSupported(); error AlreadyFinalized(); error BadTarget(); error Blacklisted(); diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json index 2ded911c4d591..3a22e3528dd18 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json @@ -785,6 +785,11 @@ "name": "ContentLengthMismatch", "type": "error" }, + { + "inputs": [], + "name": "CustomGasTokenNotSupported", + "type": "error" + }, { "inputs": [], "name": "EmptyItem", diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index bc3b3999966ad..0861f04d39c55 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -24,8 +24,8 @@ "sourceCodeHash": "0x258b7edfe6c8be55ca8d14df30512233f1b443c3a858d38ef33f6bbad1be38d3" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x70ce9058c15f9fbddc4a3df14dbdad2a734845260cbe05f4eceba9d3239a033a", - "sourceCodeHash": "0xcbd298a6a8bdb5afc8ee18796a3a506104e43ac9532e5e4c56885128f2c234f2" + "initCodeHash": "0x358745851c6c177e25d511d3eae710beee2f12b6b563a5b3c7534e073385f6c0", + "sourceCodeHash": "0xbb6acc3e88af9594ffcb8a2f30860511b76e09024330e70052316668fe55fd1f" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0x0000ec89712d8b4609873f1ba76afffd4205bf9110818995c90134dbec12e91e", diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 466efab8da0ac..eb691e6f1bf8e 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -12,6 +12,9 @@ import { Unauthorized } from "src/libraries/PortalErrors.sol"; // Interfaces import { IL1BlockInterop, ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; +/// @notice Error thrown when attempting to use custom gas token specific actions. +error CustomGasTokenNotSupported(); + /// @custom:proxied true /// @title OptimismPortalInterop /// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 @@ -35,6 +38,7 @@ contract OptimismPortalInterop is OptimismPortal2 { /// @param _value Encoded value of the configuration. function setConfig(ConfigType _type, bytes memory _value) external { if (msg.sender != address(systemConfig)) revert Unauthorized(); + if (_type == ConfigType.SET_GAS_PAYING_TOKEN) revert CustomGasTokenNotSupported(); // Set L2 deposit gas as used without paying burning gas. Ensures that deposits cannot use too much L2 gas. // This value must be large enough to cover the cost of calling `L1Block.setConfig`. From 69ac8a2d83cc65198ac917a3a132a3d8e8b6c0de Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 10:45:54 +0100 Subject: [PATCH 07/15] restore L2 tests --- .../test/L2/L2CrossDomainMessenger.t.sol | 102 +++++++++++++++++ .../test/L2/L2StandardBridge.t.sol | 105 ++++++++++++++++++ 2 files changed, 207 insertions(+) diff --git a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol index 470c6d82d8599..ca1fd3c2d2d55 100644 --- a/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol +++ b/packages/contracts-bedrock/test/L2/L2CrossDomainMessenger.t.sol @@ -16,6 +16,7 @@ import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; // Interfaces import { IL2CrossDomainMessenger } from "interfaces/L2/IL2CrossDomainMessenger.sol"; import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; +import { IGasToken } from "src/libraries/GasPayingToken.sol"; contract L2CrossDomainMessenger_Test is CommonTest { /// @dev Receiver address for testing @@ -311,4 +312,105 @@ contract L2CrossDomainMessenger_Test is CommonTest { assertEq(l2CrossDomainMessenger.successfulMessages(hash), true); assertEq(l2CrossDomainMessenger.failedMessages(hash), true); } + + /// @dev Tests that sendMessage succeeds with a custom gas token when the call value is zero. + function test_sendMessage_customGasTokenButNoValue_succeeds() external { + // Mock the gasPayingToken function to return a custom gas token + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + + bytes memory xDomainCallData = + Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff"); + vm.expectCall( + address(l2ToL1MessagePasser), + abi.encodeCall( + IL2ToL1MessagePasser.initiateWithdrawal, + (address(l1CrossDomainMessenger), l2CrossDomainMessenger.baseGas(hex"ff", 100), xDomainCallData) + ) + ); + + // MessagePassed event + vm.expectEmit(true, true, true, true); + emit MessagePassed( + l2ToL1MessagePasser.messageNonce(), + address(l2CrossDomainMessenger), + address(l1CrossDomainMessenger), + 0, + l2CrossDomainMessenger.baseGas(hex"ff", 100), + xDomainCallData, + Hashing.hashWithdrawal( + Types.WithdrawalTransaction({ + nonce: l2ToL1MessagePasser.messageNonce(), + sender: address(l2CrossDomainMessenger), + target: address(l1CrossDomainMessenger), + value: 0, + gasLimit: l2CrossDomainMessenger.baseGas(hex"ff", 100), + data: xDomainCallData + }) + ) + ); + + vm.prank(alice); + l2CrossDomainMessenger.sendMessage(recipient, hex"ff", uint32(100)); + } + + /// @dev Tests that the sendMessage reverts when call value is non-zero with custom gas token. + function test_sendMessage_customGasTokenWithValue_reverts() external { + // Mock the gasPayingToken function to return a custom gas token + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + + vm.expectRevert("CrossDomainMessenger: cannot send value with custom gas token"); + l2CrossDomainMessenger.sendMessage{ value: 1 }(recipient, hex"ff", uint32(100)); + } + + /// @dev Tests that the relayMessage succeeds with a custom gas token when the call value is zero. + function test_relayMessage_customGasTokenAndNoValue_succeeds() external { + // Mock the gasPayingToken function to return a custom gas token + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + + address target = address(0xabcd); + address sender = address(l1CrossDomainMessenger); + address caller = AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)); + + vm.expectCall(target, hex"1111"); + + vm.prank(caller); + + vm.expectEmit(true, true, true, true); + + bytes32 hash = + Hashing.hashCrossDomainMessage(Encoding.encodeVersionedNonce(0, 1), sender, target, 0, 0, hex"1111"); + + emit RelayedMessage(hash); + + l2CrossDomainMessenger.relayMessage( + Encoding.encodeVersionedNonce(0, 1), // nonce + sender, + target, + 0, // value + 0, + hex"1111" + ); + + // the message hash is in the successfulMessages mapping + assert(l2CrossDomainMessenger.successfulMessages(hash)); + // it is not in the received messages mapping + assertEq(l2CrossDomainMessenger.failedMessages(hash), false); + } + + /// @dev Tests that the relayMessage reverts when call value is non-zero with custom gas token. + /// The L1CrossDomainMessenger `sendMessage` function cannot send value with a custom gas token. + function test_relayMessage_customGasTokenWithValue_reverts() external virtual { + // Mock the gasPayingToken function to return a custom gas token + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address"); + + l2CrossDomainMessenger.relayMessage{ value: 1 }( + Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }), + address(0xabcd), + address(0xabcd), + 1, // value + 0, + hex"1111" + ); + } } diff --git a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol index 48d0f978d359b..70ccc5122e7d3 100644 --- a/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol +++ b/packages/contracts-bedrock/test/L2/L2StandardBridge.t.sol @@ -20,6 +20,7 @@ import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenge import { IStandardBridge } from "interfaces/universal/IStandardBridge.sol"; import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; import { IL2StandardBridge } from "interfaces/L2/IL2StandardBridge.sol"; +import { IGasToken } from "src/libraries/GasPayingToken.sol"; contract L2StandardBridge_Test is CommonTest { using stdStorage for StdStorage; @@ -127,6 +128,19 @@ contract L2StandardBridge_Test is CommonTest { assertEq(address(l2ToL1MessagePasser).balance, 100); } + /// @dev Tests that the receive function reverts with custom gas token. + function testFuzz_receive_customGasToken_reverts(uint256 _value) external { + vm.prank(alice, alice); + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + vm.deal(alice, _value); + (bool success, bytes memory data) = address(l2StandardBridge).call{ value: _value }(hex""); + assertFalse(success); + assembly { + data := add(data, 0x04) + } + assertEq(abi.decode(data, (string)), "StandardBridge: cannot bridge ETH with custom gas token"); + } + /// @dev Tests that `withdraw` reverts if the amount is not equal to the value sent. function test_withdraw_insufficientValue_reverts() external { assertEq(address(l2ToL1MessagePasser).balance, 0); @@ -154,6 +168,74 @@ contract L2StandardBridge_Test is CommonTest { l2StandardBridge.withdrawTo{ value: 100 }(address(L2Token), alice, 100, 1, hex""); } + /// @dev Tests that `withdraw` reverts with custom gas token. + function test_withdraw_customGasToken_reverts() external { + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex""); + } + + /// @dev Tests that `withdraw` reverts with custom gas token. + function test_withdrawERC20_customGasToken_reverts() external { + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdraw(address(L1Token), 1, 1, hex""); + } + + /// @dev Tests that `withdraw` reverts with custom gas token. + function test_withdrawERC20WithValue_customGasToken_reverts() external { + vm.deal(alice, 1 ether); + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdraw{ value: 1 ether }(address(L1Token), 1, 1, hex""); + } + + /// @dev Tests that `withdraw` with value reverts with custom gas token. + function test_withdraw_customGasTokenWithValue_reverts() external { + vm.deal(alice, 1 ether); + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdraw{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex""); + } + + /// @dev Tests that `withdrawTo` reverts with custom gas token. + function test_withdrawTo_customGasToken_reverts() external { + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdrawTo(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex""); + } + + /// @dev Tests that `withdrawTo` reverts with custom gas token. + function test_withdrawToERC20_customGasToken_reverts() external { + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdrawTo(address(L2Token), bob, 1, 1, hex""); + } + + /// @dev Tests that `withdrawTo` reverts with custom gas token. + function test_withdrawToERC20WithValue_customGasToken_reverts() external { + vm.deal(alice, 1 ether); + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdrawTo{ value: 1 ether }(address(L2Token), bob, 1, 1, hex""); + } + + /// @dev Tests that `withdrawTo` with value reverts with custom gas token. + function test_withdrawTo_customGasTokenWithValue_reverts() external { + vm.deal(alice, 1 ether); + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18))); + vm.expectRevert("L2StandardBridge: not supported with custom gas token"); + vm.prank(alice, alice); + l2StandardBridge.withdrawTo{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex""); + } + /// @dev Tests that the legacy `withdraw` interface on the L2StandardBridge /// successfully initiates a withdrawal. function test_withdraw_ether_succeeds() external { @@ -477,6 +559,15 @@ contract L2StandardBridge_Bridge_Test is CommonTest { l2StandardBridge.bridgeETH{ value: _value }(_minGasLimit, _extraData); } + /// @dev Tests that bridging reverts with custom gas token. + function test_bridgeETH_customGasToken_reverts() external { + vm.prank(alice, alice); + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); + + l2StandardBridge.bridgeETH(50000, hex"dead"); + } + /// @dev Tests that bridging ETH to a different address succeeds. function testFuzz_bridgeETHTo_succeeds(uint256 _value, uint32 _minGasLimit, bytes calldata _extraData) external { uint256 nonce = l2CrossDomainMessenger.messageNonce(); @@ -513,6 +604,20 @@ contract L2StandardBridge_Bridge_Test is CommonTest { l2StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData); } + + /// @dev Tests that bridging reverts with custom gas token. + function testFuzz_bridgeETHTo_customGasToken_reverts( + uint256 _value, + uint32 _minGasLimit, + bytes calldata _extraData + ) + external + { + vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2))); + vm.expectRevert("StandardBridge: cannot bridge ETH with custom gas token"); + vm.deal(address(this), _value); + l2StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData); + } } contract L2StandardBridge_FinalizeBridgeETH_Test is CommonTest { From 41547acf3a3b86c6b55535edba288130af51a6fd Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 17:19:22 +0100 Subject: [PATCH 08/15] make _balance a spacer, inline unnecessary internal function --- .../contracts-bedrock/snapshots/.gas-snapshot | 12 +++--- .../snapshots/semver-lock.json | 6 +-- .../storageLayout/OptimismPortal2.json | 2 +- .../storageLayout/OptimismPortalInterop.json | 2 +- .../src/L1/OptimismPortal2.sol | 39 +++---------------- 5 files changed, 16 insertions(+), 45 deletions(-) diff --git a/packages/contracts-bedrock/snapshots/.gas-snapshot b/packages/contracts-bedrock/snapshots/.gas-snapshot index f4423374db136..438d98f55c8b7 100644 --- a/packages/contracts-bedrock/snapshots/.gas-snapshot +++ b/packages/contracts-bedrock/snapshots/.gas-snapshot @@ -4,10 +4,10 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5144) GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531) GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 356541) -GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954770) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 551690) -GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4063711) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450376) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3496103) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 356487) +GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954716) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 551636) +GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4063829) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450322) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3496221) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 59849) \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 60c25c7f38249..5cbf943fc89f1 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -20,11 +20,11 @@ "sourceCodeHash": "0x819e5e9867e09d16346daf81cfc9c129bf9026308055d1fbb6623b4f8818e613" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x32ba32dce7717119f4f868925140e2c92d010ea5378c8923d40dc83e299fd961", - "sourceCodeHash": "0x258b7edfe6c8be55ca8d14df30512233f1b443c3a858d38ef33f6bbad1be38d3" + "initCodeHash": "0x2121a97875875150106a54a71c6c4c03afe90b3364e416be047f55fdeab57204", + "sourceCodeHash": "0x9a5722f32a683565922704db0c87dfac41e61fa634d8dc8cde3706ef48915f78" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x358745851c6c177e25d511d3eae710beee2f12b6b563a5b3c7534e073385f6c0", + "initCodeHash": "0x09ffe45f91bf59315b9fd4a2941b819ed8b1bb0d8643a630c6193bd67acea0ed", "sourceCodeHash": "0xbb6acc3e88af9594ffcb8a2f30860511b76e09024330e70052316668fe55fd1f" }, "src/L1/ProtocolVersions.sol": { diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json index 0fdd65b3e88fb..654695522e049 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortal2.json @@ -120,7 +120,7 @@ }, { "bytes": "32", - "label": "_balance", + "label": "spacer_61_0_32", "offset": 0, "slot": "61", "type": "uint256" diff --git a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json index 0fdd65b3e88fb..654695522e049 100644 --- a/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/storageLayout/OptimismPortalInterop.json @@ -120,7 +120,7 @@ }, { "bytes": "32", - "label": "_balance", + "label": "spacer_61_0_32", "offset": 0, "slot": "61", "type": "uint256" diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index da63577408059..29619e7dd2752 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -132,12 +132,10 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// proof submission should be used when finalizing a withdrawal. mapping(bytes32 => address[]) public proofSubmitters; - /// @notice Represents the amount of native asset minted in L2. This may not - /// be 100% accurate due to the ability to send ether to the contract - /// without triggering a deposit transaction. It also is used to prevent - /// overflows for L2 account balances when custom gas tokens are used. - /// It is not safe to trust `ERC20.balanceOf` as it may lie. - uint256 internal _balance; + /// @custom:legacy + /// @custom:spacer _balance + /// @notice Spacer taking up the legacy `_balance` slot. + uint256 private spacer_61_0_32; /// @notice Emitted when a transaction is deposited from L1 to L2. /// The parameters of this event are read by the rollup node and used to derive deposit @@ -437,33 +435,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { public payable metered(_gasLimit) - { - _depositTransaction({ - _to: _to, - _mint: msg.value, - _value: _value, - _gasLimit: _gasLimit, - _isCreation: _isCreation, - _data: _data - }); - } - - /// @notice Common logic for creating deposit transactions. - /// @param _to Target address on L2. - /// @param _mint Units of asset to deposit into L2. - /// @param _value Units of asset to send on L2 to the recipient. - /// @param _gasLimit Amount of L2 gas to purchase by burning gas on L1. - /// @param _isCreation Whether or not the transaction is a contract creation. - /// @param _data Data to trigger the recipient with. - function _depositTransaction( - address _to, - uint256 _mint, - uint256 _value, - uint64 _gasLimit, - bool _isCreation, - bytes memory _data - ) - internal { // Just to be safe, make sure that people specify address(0) as the target when doing // contract creations. @@ -488,7 +459,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { // Compute the opaque data that will be emitted as part of the TransactionDeposited event. // We use opaque data so that we can update the TransactionDeposited event in the future // without breaking the current interface. - bytes memory opaqueData = abi.encodePacked(_mint, _value, _gasLimit, _isCreation, _data); + bytes memory opaqueData = abi.encodePacked(msg.value, _value, _gasLimit, _isCreation, _data); // Emit a TransactionDeposited event so that the rollup node can derive a deposit // transaction for this deposit. From 43876aaba0a6e2fc318f30449bf68d8138f032b7 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 19:44:47 +0100 Subject: [PATCH 09/15] add version tests --- packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol | 6 ++++++ .../contracts-bedrock/test/L1/OptimismPortalInterop.t.sol | 6 ++++++ packages/contracts-bedrock/test/L1/SystemConfig.t.sol | 6 ++++++ .../contracts-bedrock/test/L1/SystemConfigInterop.t.sol | 6 ++++++ 4 files changed, 24 insertions(+) diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index c8f262ffe281f..b34ab1e1667a2 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -34,6 +34,12 @@ contract OptimismPortal2_Test is CommonTest { depositor = makeAddr("depositor"); } + /// @notice Tests that the version function returns a valid string. We avoid testing the + /// specific value of the string as it changes frequently. + function test_version_succeeds() external view { + assert(bytes(l2StandardBridge.version()).length > 0); + } + /// @dev Tests that the constructor sets the correct values. /// @notice Marked virtual to be overridden in /// test/kontrol/deployment/DeploymentSummary.t.sol diff --git a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol index 6d3eb8de7da04..50181fbbaef44 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol @@ -21,6 +21,12 @@ contract OptimismPortalInterop_Test is CommonTest { super.setUp(); } + /// @notice Tests that the version function returns a valid string. We avoid testing the + /// specific value of the string as it changes frequently. + function test_version_succeeds() external view { + assert(bytes(l2StandardBridge.version()).length > 0); + } + /// @dev Tests that the config for the gas paying token cannot be set. function testFuzz_setConfig_gasPayingToken_reverts(bytes calldata _value) public { vm.prank(address(_optimismPortalInterop().systemConfig())); diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index 187ee4f6df79f..1bc88d53d8f34 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -41,6 +41,12 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { optimismMintableERC20Factory = artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy"); } + /// @notice Tests that the version function returns a valid string. We avoid testing the + /// specific value of the string as it changes frequently. + function test_version_succeeds() external view { + assert(bytes(l2StandardBridge.version()).length > 0); + } + /// @dev Tests that constructor sets the correct values. function test_constructor_succeeds() external view { ISystemConfig impl = ISystemConfig(systemConfigImpl); diff --git a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol index c9115041e3938..4bc90e9fbeb74 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol @@ -20,6 +20,12 @@ contract SystemConfigInterop_Test is CommonTest { super.setUp(); } + /// @notice Tests that the version function returns a valid string. We avoid testing the + /// specific value of the string as it changes frequently. + function test_version_succeeds() external view { + assert(bytes(l2StandardBridge.version()).length > 0); + } + /// @dev Tests that a dependency can be added. function testFuzz_addDependency_succeeds(uint256 _chainId) public { vm.expectCall( From 387f2008d6cc2688dfdd22ae14aaaf55800bef2a Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 19:53:52 +0100 Subject: [PATCH 10/15] add version tests --- packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol | 2 +- packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol | 2 +- packages/contracts-bedrock/test/L1/SystemConfig.t.sol | 2 +- packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index b34ab1e1667a2..fef3faaddf94c 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -37,7 +37,7 @@ contract OptimismPortal2_Test is CommonTest { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. function test_version_succeeds() external view { - assert(bytes(l2StandardBridge.version()).length > 0); + assert(bytes(optimismPortal2.version()).length > 0); } /// @dev Tests that the constructor sets the correct values. diff --git a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol index 50181fbbaef44..07ca34969cd2f 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortalInterop.t.sol @@ -24,7 +24,7 @@ contract OptimismPortalInterop_Test is CommonTest { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. function test_version_succeeds() external view { - assert(bytes(l2StandardBridge.version()).length > 0); + assert(bytes(_optimismPortalInterop().version()).length > 0); } /// @dev Tests that the config for the gas paying token cannot be set. diff --git a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol index 1bc88d53d8f34..a1d2a22f427a1 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfig.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfig.t.sol @@ -44,7 +44,7 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. function test_version_succeeds() external view { - assert(bytes(l2StandardBridge.version()).length > 0); + assert(bytes(systemConfig.version()).length > 0); } /// @dev Tests that constructor sets the correct values. diff --git a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol index 4bc90e9fbeb74..2f953ef7413f4 100644 --- a/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol +++ b/packages/contracts-bedrock/test/L1/SystemConfigInterop.t.sol @@ -23,7 +23,7 @@ contract SystemConfigInterop_Test is CommonTest { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. function test_version_succeeds() external view { - assert(bytes(l2StandardBridge.version()).length > 0); + assert(bytes(_systemConfigInterop().version()).length > 0); } /// @dev Tests that a dependency can be added. From c027b73845c30a631bc9e6276b7732486702b803 Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 20:42:49 +0100 Subject: [PATCH 11/15] add version tests --- packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index fef3faaddf94c..a6012326db779 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -36,7 +36,8 @@ contract OptimismPortal2_Test is CommonTest { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. - function test_version_succeeds() external view { + function test_version_succeeds() external { + skipIfForkTest("OptimismPortal2_Test: cannot test version of optimismportal2 on forked network"); assert(bytes(optimismPortal2.version()).length > 0); } From c3ae2df33ea72c171145907d34095e57fd29e7ef Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 20:45:12 +0100 Subject: [PATCH 12/15] add version tests --- packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index a6012326db779..3c7be1261e688 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -37,7 +37,6 @@ contract OptimismPortal2_Test is CommonTest { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. function test_version_succeeds() external { - skipIfForkTest("OptimismPortal2_Test: cannot test version of optimismportal2 on forked network"); assert(bytes(optimismPortal2.version()).length > 0); } From cca6a3e017fc7c12bac221eaaa680bdfddd2091a Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 20:54:05 +0100 Subject: [PATCH 13/15] ... --- packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index 3c7be1261e688..fef3faaddf94c 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -36,7 +36,7 @@ contract OptimismPortal2_Test is CommonTest { /// @notice Tests that the version function returns a valid string. We avoid testing the /// specific value of the string as it changes frequently. - function test_version_succeeds() external { + function test_version_succeeds() external view { assert(bytes(optimismPortal2.version()).length > 0); } From 96ea65ead5c519aba8664835e1a6910b57ca012e Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 21:08:21 +0100 Subject: [PATCH 14/15] fixes --- packages/contracts-bedrock/src/L1/OptimismPortal2.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index 29619e7dd2752..1456e19cc18b8 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -17,9 +17,6 @@ import { BadTarget, LargeCalldata, SmallGasLimit, - TransferFailed, - OnlyCustomGasToken, - NoValue, Unauthorized, CallPaused, GasEstimation, From 76cae02fb6cdbd85cf2f26f87a943ca41407b12e Mon Sep 17 00:00:00 2001 From: Michael Amadi Date: Mon, 13 Jan 2025 21:22:21 +0100 Subject: [PATCH 15/15] fixes --- packages/contracts-bedrock/snapshots/semver-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 9cffb97e06615..24d8b23d28249 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -21,7 +21,7 @@ }, "src/L1/OptimismPortal2.sol": { "initCodeHash": "0x2121a97875875150106a54a71c6c4c03afe90b3364e416be047f55fdeab57204", - "sourceCodeHash": "0x9a5722f32a683565922704db0c87dfac41e61fa634d8dc8cde3706ef48915f78" + "sourceCodeHash": "0x96e3de3ef0025a6def702eeb481acd2d2d88971fd418be657472f51a98029773" }, "src/L1/OptimismPortalInterop.sol": { "initCodeHash": "0x09ffe45f91bf59315b9fd4a2941b819ed8b1bb0d8643a630c6193bd67acea0ed",