Commit 6c44b0b5 authored by Michael Amadi's avatar Michael Amadi Committed by GitHub

remove CGT code (#13686)

* remove CGT code

* fixes

* fixes

* remove CGT code

* fixes

* fixes

* restore L2 tests

* make _balance a spacer, inline unnecessary internal function

* add version tests

* add version tests

* add version tests

* add version tests

* ...

* fixes

* fixes
parent bfb9de20
...@@ -9,7 +9,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; ...@@ -9,7 +9,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
interface IOptimismPortal2 { interface IOptimismPortal2 {
error CustomGasTokenNotSupported();
error AlreadyFinalized(); error AlreadyFinalized();
error BadTarget(); error BadTarget();
error Blacklisted(); error Blacklisted();
...@@ -24,13 +23,10 @@ interface IOptimismPortal2 { ...@@ -24,13 +23,10 @@ interface IOptimismPortal2 {
error InvalidMerkleProof(); error InvalidMerkleProof();
error InvalidProof(); error InvalidProof();
error LargeCalldata(); error LargeCalldata();
error NoValue();
error NonReentrant(); error NonReentrant();
error OnlyCustomGasToken();
error OutOfGas(); error OutOfGas();
error ProposalNotValidated(); error ProposalNotValidated();
error SmallGasLimit(); error SmallGasLimit();
error TransferFailed();
error Unauthorized(); error Unauthorized();
error UnexpectedList(); error UnexpectedList();
error UnexpectedString(); error UnexpectedString();
...@@ -46,18 +42,8 @@ interface IOptimismPortal2 { ...@@ -46,18 +42,8 @@ interface IOptimismPortal2 {
receive() external payable; receive() external payable;
function balance() external view returns (uint256);
function blacklistDisputeGame(IDisputeGame _disputeGame) external; function blacklistDisputeGame(IDisputeGame _disputeGame) external;
function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; 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( function depositTransaction(
address _to, address _to,
uint256 _value, uint256 _value,
...@@ -109,7 +95,6 @@ interface IOptimismPortal2 { ...@@ -109,7 +95,6 @@ interface IOptimismPortal2 {
returns (IDisputeGame disputeGameProxy, uint64 timestamp); // nosemgrep returns (IDisputeGame disputeGameProxy, uint64 timestamp); // nosemgrep
function respectedGameType() external view returns (GameType); function respectedGameType() external view returns (GameType);
function respectedGameTypeUpdatedAt() external view returns (uint64); function respectedGameTypeUpdatedAt() external view returns (uint64);
function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external;
function setRespectedGameType(GameType _gameType) external; function setRespectedGameType(GameType _gameType) external;
function superchainConfig() external view returns (ISuperchainConfig); function superchainConfig() external view returns (ISuperchainConfig);
function systemConfig() external view returns (ISystemConfig); function systemConfig() external view returns (ISystemConfig);
......
...@@ -25,13 +25,10 @@ interface IOptimismPortalInterop { ...@@ -25,13 +25,10 @@ interface IOptimismPortalInterop {
error InvalidMerkleProof(); error InvalidMerkleProof();
error InvalidProof(); error InvalidProof();
error LargeCalldata(); error LargeCalldata();
error NoValue();
error NonReentrant(); error NonReentrant();
error OnlyCustomGasToken();
error OutOfGas(); error OutOfGas();
error ProposalNotValidated(); error ProposalNotValidated();
error SmallGasLimit(); error SmallGasLimit();
error TransferFailed();
error Unauthorized(); error Unauthorized();
error UnexpectedList(); error UnexpectedList();
error UnexpectedString(); error UnexpectedString();
...@@ -47,18 +44,8 @@ interface IOptimismPortalInterop { ...@@ -47,18 +44,8 @@ interface IOptimismPortalInterop {
receive() external payable; receive() external payable;
function balance() external view returns (uint256);
function blacklistDisputeGame(IDisputeGame _disputeGame) external; function blacklistDisputeGame(IDisputeGame _disputeGame) external;
function checkWithdrawal(bytes32 _withdrawalHash, address _proofSubmitter) external view; 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( function depositTransaction(
address _to, address _to,
uint256 _value, uint256 _value,
...@@ -111,7 +98,6 @@ interface IOptimismPortalInterop { ...@@ -111,7 +98,6 @@ interface IOptimismPortalInterop {
function respectedGameType() external view returns (GameType); function respectedGameType() external view returns (GameType);
function respectedGameTypeUpdatedAt() external view returns (uint64); function respectedGameTypeUpdatedAt() external view returns (uint64);
function setConfig(ConfigType _type, bytes memory _value) external; 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 setRespectedGameType(GameType _gameType) external;
function superchainConfig() external view returns (ISuperchainConfig); function superchainConfig() external view returns (ISuperchainConfig);
function systemConfig() external view returns (ISystemConfig); function systemConfig() external view returns (ISystemConfig);
......
...@@ -5,8 +5,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.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. /// @notice This interface corresponds to the Custom Gas Token version of the SystemConfig contract.
interface ISystemConfig { interface ISystemConfig {
error CustomGasTokenNotSupported();
enum UpdateType { enum UpdateType {
BATCHER, BATCHER,
FEE_SCALARS, FEE_SCALARS,
...@@ -22,7 +20,6 @@ interface ISystemConfig { ...@@ -22,7 +20,6 @@ interface ISystemConfig {
address disputeGameFactory; address disputeGameFactory;
address optimismPortal; address optimismPortal;
address optimismMintableERC20Factory; address optimismMintableERC20Factory;
address gasPayingToken;
} }
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);
...@@ -47,9 +44,6 @@ interface ISystemConfig { ...@@ -47,9 +44,6 @@ interface ISystemConfig {
function gasLimit() external view returns (uint64); function gasLimit() external view returns (uint64);
function eip1559Denominator() external view returns (uint32); function eip1559Denominator() external view returns (uint32);
function eip1559Elasticity() 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( function initialize(
address _owner, address _owner,
uint32 _basefeeScalar, uint32 _basefeeScalar,
...@@ -62,7 +56,6 @@ interface ISystemConfig { ...@@ -62,7 +56,6 @@ interface ISystemConfig {
Addresses memory _addresses Addresses memory _addresses
) )
external; external;
function isCustomGasToken() external view returns (bool);
function l1CrossDomainMessenger() external view returns (address addr_); function l1CrossDomainMessenger() external view returns (address addr_);
function l1ERC721Bridge() external view returns (address addr_); function l1ERC721Bridge() external view returns (address addr_);
function l1StandardBridge() external view returns (address addr_); function l1StandardBridge() external view returns (address addr_);
......
...@@ -5,8 +5,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; ...@@ -5,8 +5,6 @@ import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
interface ISystemConfigInterop { interface ISystemConfigInterop {
error CustomGasTokenNotSupported();
event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data);
event Initialized(uint8 version); event Initialized(uint8 version);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
...@@ -29,10 +27,6 @@ interface ISystemConfigInterop { ...@@ -29,10 +27,6 @@ interface ISystemConfigInterop {
function gasLimit() external view returns (uint64); function gasLimit() external view returns (uint64);
function eip1559Denominator() external view returns (uint32); function eip1559Denominator() external view returns (uint32);
function eip1559Elasticity() 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 l1CrossDomainMessenger() external view returns (address addr_);
function l1ERC721Bridge() external view returns (address addr_); function l1ERC721Bridge() external view returns (address addr_);
function l1StandardBridge() external view returns (address addr_); function l1StandardBridge() external view returns (address addr_);
......
...@@ -530,8 +530,7 @@ contract Deploy is Deployer { ...@@ -530,8 +530,7 @@ contract Deploy is Deployer {
l1StandardBridge: artifacts.mustGetAddress("L1StandardBridgeProxy"), l1StandardBridge: artifacts.mustGetAddress("L1StandardBridgeProxy"),
disputeGameFactory: artifacts.mustGetAddress("DisputeGameFactoryProxy"), disputeGameFactory: artifacts.mustGetAddress("DisputeGameFactoryProxy"),
optimismPortal: artifacts.mustGetAddress("OptimismPortalProxy"), optimismPortal: artifacts.mustGetAddress("OptimismPortalProxy"),
optimismMintableERC20Factory: artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy"), optimismMintableERC20Factory: artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy")
gasPayingToken: customGasTokenAddress
}) })
) )
) )
......
...@@ -563,8 +563,6 @@ contract DeployOPChain is Script { ...@@ -563,8 +563,6 @@ contract DeployOPChain is Script {
systemConfig.optimismMintableERC20Factory() == address(_doo.optimismMintableERC20FactoryProxy()), systemConfig.optimismMintableERC20Factory() == address(_doo.optimismMintableERC20FactoryProxy()),
"SYSCON-210" "SYSCON-210"
); );
(address gasPayingToken,) = systemConfig.gasPayingToken();
require(gasPayingToken == Constants.ETHER, "SYSCON-220");
} }
function assertValidL1CrossDomainMessenger(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal { function assertValidL1CrossDomainMessenger(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
......
...@@ -4,10 +4,10 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm ...@@ -4,10 +4,10 @@ GasBenchMark_L1BlockInterop_SetValuesInterop:test_setL1BlockValuesInterop_benchm
GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5144) GasBenchMark_L1BlockInterop_SetValuesInterop_Warm:test_setL1BlockValuesInterop_benchmark() (gas: 5144)
GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531) GasBenchMark_L1Block_SetValuesEcotone:test_setL1BlockValuesEcotone_benchmark() (gas: 158531)
GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597) GasBenchMark_L1Block_SetValuesEcotone_Warm:test_setL1BlockValuesEcotone_benchmark() (gas: 7597)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369264) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 356487)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967493) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2954716)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564413) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 551636)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076606) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4063829)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467092) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 450322)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512819) GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3496221)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72667) GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 59849)
\ No newline at end of file \ No newline at end of file
...@@ -19,19 +19,6 @@ ...@@ -19,19 +19,6 @@
"stateMutability": "payable", "stateMutability": "payable",
"type": "receive" "type": "receive"
}, },
{
"inputs": [],
"name": "balance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
...@@ -63,44 +50,6 @@ ...@@ -63,44 +50,6 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "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": [ "inputs": [
{ {
...@@ -602,34 +551,6 @@ ...@@ -602,34 +551,6 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "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": [ "inputs": [
{ {
...@@ -846,11 +767,6 @@ ...@@ -846,11 +767,6 @@
"name": "ContentLengthMismatch", "name": "ContentLengthMismatch",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "CustomGasTokenNotSupported",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "EmptyItem", "name": "EmptyItem",
...@@ -896,21 +812,11 @@ ...@@ -896,21 +812,11 @@
"name": "LargeCalldata", "name": "LargeCalldata",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "NoValue",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "NonReentrant", "name": "NonReentrant",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "OnlyCustomGasToken",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "OutOfGas", "name": "OutOfGas",
...@@ -926,11 +832,6 @@ ...@@ -926,11 +832,6 @@
"name": "SmallGasLimit", "name": "SmallGasLimit",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "TransferFailed",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "Unauthorized", "name": "Unauthorized",
......
...@@ -19,19 +19,6 @@ ...@@ -19,19 +19,6 @@
"stateMutability": "payable", "stateMutability": "payable",
"type": "receive" "type": "receive"
}, },
{
"inputs": [],
"name": "balance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [ "inputs": [
{ {
...@@ -63,44 +50,6 @@ ...@@ -63,44 +50,6 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "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": [ "inputs": [
{ {
...@@ -620,34 +569,6 @@ ...@@ -620,34 +569,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "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": [ "inputs": [
{ {
...@@ -914,21 +835,11 @@ ...@@ -914,21 +835,11 @@
"name": "LargeCalldata", "name": "LargeCalldata",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "NoValue",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "NonReentrant", "name": "NonReentrant",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "OnlyCustomGasToken",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "OutOfGas", "name": "OutOfGas",
...@@ -944,11 +855,6 @@ ...@@ -944,11 +855,6 @@
"name": "SmallGasLimit", "name": "SmallGasLimit",
"type": "error" "type": "error"
}, },
{
"inputs": [],
"name": "TransferFailed",
"type": "error"
},
{ {
"inputs": [], "inputs": [],
"name": "Unauthorized", "name": "Unauthorized",
......
...@@ -238,50 +238,6 @@ ...@@ -238,50 +238,6 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "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": [ "inputs": [
{ {
...@@ -387,11 +343,6 @@ ...@@ -387,11 +343,6 @@
"internalType": "address", "internalType": "address",
"name": "optimismMintableERC20Factory", "name": "optimismMintableERC20Factory",
"type": "address" "type": "address"
},
{
"internalType": "address",
"name": "gasPayingToken",
"type": "address"
} }
], ],
"internalType": "struct SystemConfig.Addresses", "internalType": "struct SystemConfig.Addresses",
...@@ -404,19 +355,6 @@ ...@@ -404,19 +355,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [],
"name": "isCustomGasToken",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "l1CrossDomainMessenger", "name": "l1CrossDomainMessenger",
...@@ -800,10 +738,5 @@ ...@@ -800,10 +738,5 @@
], ],
"name": "OwnershipTransferred", "name": "OwnershipTransferred",
"type": "event" "type": "event"
},
{
"inputs": [],
"name": "CustomGasTokenNotSupported",
"type": "error"
} }
] ]
\ No newline at end of file
...@@ -259,50 +259,6 @@ ...@@ -259,50 +259,6 @@
"stateMutability": "view", "stateMutability": "view",
"type": "function" "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": [ "inputs": [
{ {
...@@ -408,21 +364,11 @@ ...@@ -408,21 +364,11 @@
"internalType": "address", "internalType": "address",
"name": "optimismMintableERC20Factory", "name": "optimismMintableERC20Factory",
"type": "address" "type": "address"
},
{
"internalType": "address",
"name": "gasPayingToken",
"type": "address"
} }
], ],
"internalType": "struct SystemConfig.Addresses", "internalType": "struct SystemConfig.Addresses",
"name": "_addresses", "name": "_addresses",
"type": "tuple" "type": "tuple"
},
{
"internalType": "address",
"name": "_dependencyManager",
"type": "address"
} }
], ],
"name": "initialize", "name": "initialize",
...@@ -535,16 +481,16 @@ ...@@ -535,16 +481,16 @@
"internalType": "address", "internalType": "address",
"name": "optimismMintableERC20Factory", "name": "optimismMintableERC20Factory",
"type": "address" "type": "address"
},
{
"internalType": "address",
"name": "gasPayingToken",
"type": "address"
} }
], ],
"internalType": "struct SystemConfig.Addresses", "internalType": "struct SystemConfig.Addresses",
"name": "_addresses", "name": "_addresses",
"type": "tuple" "type": "tuple"
},
{
"internalType": "address",
"name": "_dependencyManager",
"type": "address"
} }
], ],
"name": "initialize", "name": "initialize",
...@@ -552,19 +498,6 @@ ...@@ -552,19 +498,6 @@
"stateMutability": "nonpayable", "stateMutability": "nonpayable",
"type": "function" "type": "function"
}, },
{
"inputs": [],
"name": "isCustomGasToken",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{ {
"inputs": [], "inputs": [],
"name": "l1CrossDomainMessenger", "name": "l1CrossDomainMessenger",
...@@ -961,10 +894,5 @@ ...@@ -961,10 +894,5 @@
], ],
"name": "OwnershipTransferred", "name": "OwnershipTransferred",
"type": "event" "type": "event"
},
{
"inputs": [],
"name": "CustomGasTokenNotSupported",
"type": "error"
} }
] ]
\ No newline at end of file
...@@ -4,28 +4,28 @@ ...@@ -4,28 +4,28 @@
"sourceCodeHash": "0xae49c741c8cd546981ab59b85b88e9fc1055c4fae085e7078d601b42464f86e6" "sourceCodeHash": "0xae49c741c8cd546981ab59b85b88e9fc1055c4fae085e7078d601b42464f86e6"
}, },
"src/L1/L1CrossDomainMessenger.sol": { "src/L1/L1CrossDomainMessenger.sol": {
"initCodeHash": "0x192b98a93759f2044ee1ea56270cd203d4f16210c06be388f29b8c1114b9329d", "initCodeHash": "0x4b045c9e0fcfa37838edf154e6e75be4a60406204eccf0d606dfd55da80d266d",
"sourceCodeHash": "0xfa18fb2e6ac73a143303b07735239a383ae84bd0d0042cceb8253f4784e07afb" "sourceCodeHash": "0xc92887952f5108a770c3fee8a61c70f740a0a55c2e9ed0aebe266a7c53c71dc3"
}, },
"src/L1/L1ERC721Bridge.sol": { "src/L1/L1ERC721Bridge.sol": {
"initCodeHash": "0x280488bce8b4fb364740c59de14c423851902088f384e077bccc79b9df48528a", "initCodeHash": "0x280488bce8b4fb364740c59de14c423851902088f384e077bccc79b9df48528a",
"sourceCodeHash": "0xe12b9e6c4e4ac2e2c9a03f07c7689f6bf2231922536072812cf1f37a5a276e73" "sourceCodeHash": "0xe12b9e6c4e4ac2e2c9a03f07c7689f6bf2231922536072812cf1f37a5a276e73"
}, },
"src/L1/L1StandardBridge.sol": { "src/L1/L1StandardBridge.sol": {
"initCodeHash": "0x7d7030359826f64714ef0c2a5198901812fb0a99e949f23fe54ccf87a0df2e67", "initCodeHash": "0xe5f5ab77cc5586ecd94cc687b98f25d8fd7f9bb146a942653a2ec9be7e68f070",
"sourceCodeHash": "0xa91b445bdc666a02ba18e3b91ba94b6d54bbe65da714002fc734814201319d57" "sourceCodeHash": "0x51f0876ab8410ce32838483f8f59ad6d1c5b4a368e47415b30e44baf291a394b"
}, },
"src/L1/OPContractsManager.sol": { "src/L1/OPContractsManager.sol": {
"initCodeHash": "0xe0c14a8fee7ad4c4e28a3ff6ca4e726721a6c3fea0a74ab7eac7ef07fe4da0ae", "initCodeHash": "0x8bef0b53e7102491957d3ea12ff4857d735dada6af3ef122376bcf3f5489c9b9",
"sourceCodeHash": "0xe0f5413e0a0a335016d773f02ef6bd25551416635981e83b7a4da601b9b65bc4" "sourceCodeHash": "0x819e5e9867e09d16346daf81cfc9c129bf9026308055d1fbb6623b4f8818e613"
}, },
"src/L1/OptimismPortal2.sol": { "src/L1/OptimismPortal2.sol": {
"initCodeHash": "0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac", "initCodeHash": "0x2121a97875875150106a54a71c6c4c03afe90b3364e416be047f55fdeab57204",
"sourceCodeHash": "0xe67f0c01c9c9ba67d279304f9db84eebeb2e93d9f2728fea95c7a194f0ae338a" "sourceCodeHash": "0x96e3de3ef0025a6def702eeb481acd2d2d88971fd418be657472f51a98029773"
}, },
"src/L1/OptimismPortalInterop.sol": { "src/L1/OptimismPortalInterop.sol": {
"initCodeHash": "0x917b3b31a149b5aab96539208f4810d207875f6f2563a45c50ed13a7940066c0", "initCodeHash": "0x09ffe45f91bf59315b9fd4a2941b819ed8b1bb0d8643a630c6193bd67acea0ed",
"sourceCodeHash": "0xae2fbe02c0f8685692babeed0252ae8a624dc6d3bfb082fc3807d7b84869004b" "sourceCodeHash": "0xbb6acc3e88af9594ffcb8a2f30860511b76e09024330e70052316668fe55fd1f"
}, },
"src/L1/ProtocolVersions.sol": { "src/L1/ProtocolVersions.sol": {
"initCodeHash": "0x0000ec89712d8b4609873f1ba76afffd4205bf9110818995c90134dbec12e91e", "initCodeHash": "0x0000ec89712d8b4609873f1ba76afffd4205bf9110818995c90134dbec12e91e",
...@@ -36,12 +36,12 @@ ...@@ -36,12 +36,12 @@
"sourceCodeHash": "0xafa784ea78818a382ff3a61e2d84be58c7978110c06b9273db68c0213ead02d3" "sourceCodeHash": "0xafa784ea78818a382ff3a61e2d84be58c7978110c06b9273db68c0213ead02d3"
}, },
"src/L1/SystemConfig.sol": { "src/L1/SystemConfig.sol": {
"initCodeHash": "0xbb18eef17cdc1d0d307b0241e818820063e3ce3c7021ea3bb3a85ff6e79659e1", "initCodeHash": "0xf0bfbb889687af7d4e006f40b269bbd9e4d967cdd9c1f29900017ff11b1f5095",
"sourceCodeHash": "0x5d6a9ef41fed54479f742345368e693ec1fcabdb60118081c03fe9da3a5d27ed" "sourceCodeHash": "0x2dde897735c0cd699f15a1927bf6f75c2da220c1934021ee93315708d5b5f995"
}, },
"src/L1/SystemConfigInterop.sol": { "src/L1/SystemConfigInterop.sol": {
"initCodeHash": "0x0d61e2a95122417e9bf074a8fc0bce6f2b03268985d09580a83099dc9016c72d", "initCodeHash": "0xd89526ba331c24f8ca5ce1eef1554ad573e3aa9e6845a5b0ec23ee8f3497a84a",
"sourceCodeHash": "0x673ec83b89680b44945af89229b286f26df07a5938d497df5def47872d331cf3" "sourceCodeHash": "0x10806bbaa0d0e1dca571b720bd9690dd55cbf57038ab5887ecfdce689b0ae94e"
}, },
"src/L2/BaseFeeVault.sol": { "src/L2/BaseFeeVault.sol": {
"initCodeHash": "0xc403d4c555d8e69a2699e01d192ae7327136701fa02da10a6d75a584b3c364c9", "initCodeHash": "0xc403d4c555d8e69a2699e01d192ae7327136701fa02da10a6d75a584b3c364c9",
......
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
}, },
{ {
"bytes": "32", "bytes": "32",
"label": "_balance", "label": "spacer_61_0_32",
"offset": 0, "offset": 0,
"slot": "61", "slot": "61",
"type": "uint256" "type": "uint256"
......
...@@ -120,7 +120,7 @@ ...@@ -120,7 +120,7 @@
}, },
{ {
"bytes": "32", "bytes": "32",
"label": "_balance", "label": "spacer_61_0_32",
"offset": 0, "offset": 0,
"slot": "61", "slot": "61",
"type": "uint256" "type": "uint256"
......
...@@ -6,6 +6,7 @@ import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol"; ...@@ -6,6 +6,7 @@ import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
// Libraries // Libraries
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { Constants } from "src/libraries/Constants.sol";
// Interfaces // Interfaces
import { ISemver } from "interfaces/universal/ISemver.sol"; import { ISemver } from "interfaces/universal/ISemver.sol";
...@@ -30,8 +31,8 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { ...@@ -30,8 +31,8 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
ISystemConfig public systemConfig; ISystemConfig public systemConfig;
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 2.4.1-beta.5 /// @custom:semver 2.4.1-beta.6
string public constant version = "2.4.1-beta.5"; string public constant version = "2.4.1-beta.6";
/// @notice Constructs the L1CrossDomainMessenger contract. /// @notice Constructs the L1CrossDomainMessenger contract.
constructor() { constructor() {
...@@ -57,8 +58,10 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver { ...@@ -57,8 +58,10 @@ contract L1CrossDomainMessenger is CrossDomainMessenger, ISemver {
} }
/// @inheritdoc CrossDomainMessenger /// @inheritdoc CrossDomainMessenger
function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { /// @dev This is added to maintain compatibility with the CrossDomainMessenger abstract contract and should always
(addr_, decimals_) = systemConfig.gasPayingToken(); /// return the ether address and 18 decimals.
function gasPayingToken() internal pure override returns (address addr_, uint8 decimals_) {
return (Constants.ETHER, 18);
} }
/// @notice Getter function for the OptimismPortal contract on this chain. /// @notice Getter function for the OptimismPortal contract on this chain.
......
...@@ -6,6 +6,7 @@ import { StandardBridge } from "src/universal/StandardBridge.sol"; ...@@ -6,6 +6,7 @@ import { StandardBridge } from "src/universal/StandardBridge.sol";
// Libraries // Libraries
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { Constants } from "src/libraries/Constants.sol";
// Interfaces // Interfaces
import { ISemver } from "interfaces/universal/ISemver.sol"; import { ISemver } from "interfaces/universal/ISemver.sol";
...@@ -75,8 +76,8 @@ contract L1StandardBridge is StandardBridge, ISemver { ...@@ -75,8 +76,8 @@ contract L1StandardBridge is StandardBridge, ISemver {
); );
/// @notice Semantic version. /// @notice Semantic version.
/// @custom:semver 2.2.1-beta.5 /// @custom:semver 2.2.1-beta.6
string public constant version = "2.2.1-beta.5"; string public constant version = "2.2.1-beta.6";
/// @notice Address of the SuperchainConfig contract. /// @notice Address of the SuperchainConfig contract.
ISuperchainConfig public superchainConfig; ISuperchainConfig public superchainConfig;
...@@ -119,8 +120,10 @@ contract L1StandardBridge is StandardBridge, ISemver { ...@@ -119,8 +120,10 @@ contract L1StandardBridge is StandardBridge, ISemver {
} }
/// @inheritdoc StandardBridge /// @inheritdoc StandardBridge
function gasPayingToken() internal view override returns (address addr_, uint8 decimals_) { /// @dev This is added to maintain compatibility with the CrossDomainMessenger abstract contract and should always
(addr_, decimals_) = systemConfig.gasPayingToken(); /// return the ether address and 18 decimals.
function gasPayingToken() internal pure override returns (address addr_, uint8 decimals_) {
return (Constants.ETHER, 18);
} }
/// @custom:legacy /// @custom:legacy
......
...@@ -138,8 +138,8 @@ contract OPContractsManager is ISemver { ...@@ -138,8 +138,8 @@ contract OPContractsManager is ISemver {
// -------- Constants and Variables -------- // -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.28 /// @custom:semver 1.0.0-beta.29
string public constant version = "1.0.0-beta.28"; string public constant version = "1.0.0-beta.29";
/// @notice Represents the interface version so consumers know how to decode the DeployOutput struct /// @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. /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used.
...@@ -750,8 +750,7 @@ contract OPContractsManager is ISemver { ...@@ -750,8 +750,7 @@ contract OPContractsManager is ISemver {
l1StandardBridge: address(_output.l1StandardBridgeProxy), l1StandardBridge: address(_output.l1StandardBridgeProxy),
disputeGameFactory: address(_output.disputeGameFactoryProxy), disputeGameFactory: address(_output.disputeGameFactoryProxy),
optimismPortal: address(_output.optimismPortalProxy), optimismPortal: address(_output.optimismPortalProxy),
optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy), optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy)
gasPayingToken: Constants.ETHER
}); });
assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger); assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger);
......
...@@ -12,15 +12,11 @@ import { Constants } from "src/libraries/Constants.sol"; ...@@ -12,15 +12,11 @@ import { Constants } from "src/libraries/Constants.sol";
import { Types } from "src/libraries/Types.sol"; import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol"; import { Hashing } from "src/libraries/Hashing.sol";
import { SecureMerkleTrie } from "src/libraries/trie/SecureMerkleTrie.sol"; import { SecureMerkleTrie } from "src/libraries/trie/SecureMerkleTrie.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { import {
BadTarget, BadTarget,
LargeCalldata, LargeCalldata,
SmallGasLimit, SmallGasLimit,
TransferFailed,
OnlyCustomGasToken,
NoValue,
Unauthorized, Unauthorized,
CallPaused, CallPaused,
GasEstimation, GasEstimation,
...@@ -44,10 +40,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; ...@@ -44,10 +40,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { IDisputeGame } from "interfaces/dispute/IDisputeGame.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 /// @custom:proxied true
/// @title OptimismPortal2 /// @title OptimismPortal2
...@@ -137,12 +129,10 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -137,12 +129,10 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
/// proof submission should be used when finalizing a withdrawal. /// proof submission should be used when finalizing a withdrawal.
mapping(bytes32 => address[]) public proofSubmitters; mapping(bytes32 => address[]) public proofSubmitters;
/// @notice Represents the amount of native asset minted in L2. This may not /// @custom:legacy
/// be 100% accurate due to the ability to send ether to the contract /// @custom:spacer _balance
/// without triggering a deposit transaction. It also is used to prevent /// @notice Spacer taking up the legacy `_balance` slot.
/// overflows for L2 account balances when custom gas tokens are used. uint256 private spacer_61_0_32;
/// It is not safe to trust `ERC20.balanceOf` as it may lie.
uint256 internal _balance;
/// @notice Emitted when a transaction is deposited from L1 to L2. /// @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 /// The parameters of this event are read by the rollup node and used to derive deposit
...@@ -186,9 +176,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -186,9 +176,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
} }
/// @notice Semantic version. /// @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) { 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. /// @notice Constructs the OptimismPortal contract.
...@@ -232,19 +222,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -232,19 +222,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
__ResourceMetering_init(); __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. /// @notice Getter function for the address of the guardian.
/// Public getter is legacy and will be removed in the future. Use `SuperchainConfig.guardian()` instead. /// Public getter is legacy and will be removed in the future. Use `SuperchainConfig.guardian()` instead.
/// @return Address of the guardian. /// @return Address of the guardian.
...@@ -294,11 +271,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -294,11 +271,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
// Intentionally empty. // 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. /// @notice Getter for the resource config.
/// Used internally by the ResourceMetering contract. /// Used internally by the ResourceMetering contract.
/// The SystemConfig is the source of truth for the resource config. /// The SystemConfig is the source of truth for the resource config.
...@@ -417,53 +389,14 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -417,53 +389,14 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
// Set the l2Sender so contracts know who triggered this withdrawal on L2. // Set the l2Sender so contracts know who triggered this withdrawal on L2.
l2Sender = _tx.sender; l2Sender = _tx.sender;
bool success; // Trigger the call to the target contract. We use a custom low level method
(address token,) = gasPayingToken(); // SafeCall.callWithMinGas to ensure two key properties
if (token == Constants.ETHER) { // 1. Target contracts cannot force this call to run out of gas by returning a very large
// Trigger the call to the target contract. We use a custom low level method // amount of data (and this is OK because we don't care about the returndata here).
// SafeCall.callWithMinGas to ensure two key properties // 2. The amount of gas provided to the execution context of the target is at least the
// 1. Target contracts cannot force this call to run out of gas by returning a very large // gas limit specified by the user. If there is not enough gas in the current context
// amount of data (and this is OK because we don't care about the returndata here). // to accomplish this, `callWithMinGas` will revert.
// 2. The amount of gas provided to the execution context of the target is at least the bool success = SafeCall.callWithMinGas(_tx.target, _tx.gasLimit, _tx.value, _tx.data);
// 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;
}
}
// Reset the l2Sender back to the default value. // Reset the l2Sender back to the default value.
l2Sender = Constants.DEFAULT_L2_SENDER; l2Sender = Constants.DEFAULT_L2_SENDER;
...@@ -480,58 +413,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -480,58 +413,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 /// @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 /// 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 /// address will be aliased when retrieved using `tx.origin` or `msg.sender`. Consider
...@@ -551,40 +432,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -551,40 +432,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
public public
payable payable
metered(_gasLimit) 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,
_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 // Just to be safe, make sure that people specify address(0) as the target when doing
// contract creations. // contract creations.
...@@ -609,41 +456,13 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { ...@@ -609,41 +456,13 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
// Compute the opaque data that will be emitted as part of the TransactionDeposited event. // 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 // We use opaque data so that we can update the TransactionDeposited event in the future
// without breaking the current interface. // 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 // Emit a TransactionDeposited event so that the rollup node can derive a deposit
// transaction for this deposit. // transaction for this deposit.
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData); 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. /// @notice Blacklists a dispute game. Should only be used in the event that a dispute game resolves incorrectly.
/// @param _disputeGame Dispute game to blacklist. /// @param _disputeGame Dispute game to blacklist.
function blacklistDisputeGame(IDisputeGame _disputeGame) external { function blacklistDisputeGame(IDisputeGame _disputeGame) external {
......
...@@ -12,6 +12,9 @@ import { Unauthorized } from "src/libraries/PortalErrors.sol"; ...@@ -12,6 +12,9 @@ import { Unauthorized } from "src/libraries/PortalErrors.sol";
// Interfaces // Interfaces
import { IL1BlockInterop, ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; 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 /// @custom:proxied true
/// @title OptimismPortalInterop /// @title OptimismPortalInterop
/// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1 /// @notice The OptimismPortal is a low-level contract responsible for passing messages between L1
...@@ -25,9 +28,9 @@ contract OptimismPortalInterop is OptimismPortal2 { ...@@ -25,9 +28,9 @@ contract OptimismPortalInterop is OptimismPortal2 {
OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds) OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds)
{ } { }
/// @custom:semver +interop-beta.7 /// @custom:semver +interop-beta.8
function version() public pure override returns (string memory) { 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. /// @notice Sets static configuration options for the L2 system.
...@@ -35,6 +38,7 @@ contract OptimismPortalInterop is OptimismPortal2 { ...@@ -35,6 +38,7 @@ contract OptimismPortalInterop is OptimismPortal2 {
/// @param _value Encoded value of the configuration. /// @param _value Encoded value of the configuration.
function setConfig(ConfigType _type, bytes memory _value) external { function setConfig(ConfigType _type, bytes memory _value) external {
if (msg.sender != address(systemConfig)) revert Unauthorized(); 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. // 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`. // This value must be large enough to cover the cost of calling `L1Block.setConfig`.
......
...@@ -3,27 +3,20 @@ pragma solidity 0.8.15; ...@@ -3,27 +3,20 @@ pragma solidity 0.8.15;
// Contracts // Contracts
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// Libraries // Libraries
import { Storage } from "src/libraries/Storage.sol"; import { Storage } from "src/libraries/Storage.sol";
import { Constants } from "src/libraries/Constants.sol";
import { GasPayingToken, IGasToken } from "src/libraries/GasPayingToken.sol";
// Interfaces // Interfaces
import { ISemver } from "interfaces/universal/ISemver.sol"; import { ISemver } from "interfaces/universal/ISemver.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
import { IResourceMetering } from "interfaces/L1/IResourceMetering.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 /// @custom:proxied true
/// @title SystemConfig /// @title SystemConfig
/// @notice The SystemConfig contract is used to manage configuration of an Optimism network. /// @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 /// All configuration is stored on L1 and picked up by L2 as part of the derviation of
/// the L2 chain. /// the L2 chain.
contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { contract SystemConfig is OwnableUpgradeable, ISemver {
/// @notice Enum representing different types of updates. /// @notice Enum representing different types of updates.
/// @custom:value BATCHER Represents an update to the batcher hash. /// @custom:value BATCHER Represents an update to the batcher hash.
/// @custom:value FEE_SCALARS Represents an update to l1 data fee scalars. /// @custom:value FEE_SCALARS Represents an update to l1 data fee scalars.
...@@ -48,7 +41,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -48,7 +41,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
address disputeGameFactory; address disputeGameFactory;
address optimismPortal; address optimismPortal;
address optimismMintableERC20Factory; address optimismMintableERC20Factory;
address gasPayingToken;
} }
/// @notice Version identifier, used for upgrades. /// @notice Version identifier, used for upgrades.
...@@ -91,9 +83,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -91,9 +83,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
bytes32 public constant DISPUTE_GAME_FACTORY_SLOT = bytes32 public constant DISPUTE_GAME_FACTORY_SLOT =
bytes32(uint256(keccak256("systemconfig.disputegamefactory")) - 1); 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 /// @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 /// 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. /// optimizations and improvements are made to the system at large.
...@@ -140,9 +129,9 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -140,9 +129,9 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data); event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);
/// @notice Semantic version. /// @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) { 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. /// @notice Constructs the SystemConfig contract.
...@@ -197,7 +186,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -197,7 +186,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
Storage.setAddress(OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT, _addresses.optimismMintableERC20Factory); Storage.setAddress(OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT, _addresses.optimismMintableERC20Factory);
_setStartBlock(); _setStartBlock();
_setGasPayingToken(_addresses.gasPayingToken);
_setResourceConfig(_config); _setResourceConfig(_config);
} }
...@@ -268,55 +256,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken { ...@@ -268,55 +256,6 @@ contract SystemConfig is OwnableUpgradeable, ISemver, IGasToken {
startBlock_ = Storage.getUint(START_BLOCK_SLOT); 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. /// @notice Updates the unsafe block signer address. Can only be called by the owner.
/// @param _unsafeBlockSigner New unsafe block signer address. /// @param _unsafeBlockSigner New unsafe block signer address.
function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner { function setUnsafeBlockSigner(address _unsafeBlockSigner) external onlyOwner {
......
...@@ -2,12 +2,9 @@ ...@@ -2,12 +2,9 @@
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Contracts // Contracts
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol"; import { SystemConfig } from "src/L1/SystemConfig.sol";
// Libraries // Libraries
import { Constants } from "src/libraries/Constants.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
import { StaticConfig } from "src/libraries/StaticConfig.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol";
import { Storage } from "src/libraries/Storage.sol"; import { Storage } from "src/libraries/Storage.sol";
...@@ -16,9 +13,6 @@ import { IOptimismPortalInterop as IOptimismPortal } from "interfaces/L1/IOptimi ...@@ -16,9 +13,6 @@ import { IOptimismPortalInterop as IOptimismPortal } from "interfaces/L1/IOptimi
import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
import { ConfigType } from "interfaces/L2/IL1BlockInterop.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 /// @custom:proxied true
/// @title SystemConfigInterop /// @title SystemConfigInterop
/// @notice The SystemConfig contract is used to manage configuration of an Optimism network. /// @notice The SystemConfig contract is used to manage configuration of an Optimism network.
...@@ -71,41 +65,9 @@ contract SystemConfigInterop is SystemConfig { ...@@ -71,41 +65,9 @@ contract SystemConfigInterop is SystemConfig {
Storage.setAddress(DEPENDENCY_MANAGER_SLOT, _dependencyManager); Storage.setAddress(DEPENDENCY_MANAGER_SLOT, _dependencyManager);
} }
/// @custom:semver +interop-beta.9 /// @custom:semver +interop-beta.10
function version() public pure override returns (string memory) { 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 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. /// @notice Adds a chain to the interop dependency set. Can only be called by the dependency manager.
......
...@@ -697,147 +697,6 @@ contract L1CrossDomainMessenger_Test is CommonTest { ...@@ -697,147 +697,6 @@ contract L1CrossDomainMessenger_Test is CommonTest {
assertTrue(l1CrossDomainMessenger.paused()); assertTrue(l1CrossDomainMessenger.paused());
assertEq(l1CrossDomainMessenger.paused(), superchainConfig.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 /// @dev A regression test against a reentrancy vulnerability in the CrossDomainMessenger contract, which
......
...@@ -198,26 +198,6 @@ contract L1StandardBridge_Receive_Test is CommonTest { ...@@ -198,26 +198,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 { contract PreBridgeETH is CommonTest {
/// @dev Asserts the expected calls and events for bridging ETH depending /// @dev Asserts the expected calls and events for bridging ETH depending
/// on whether the bridge call is legacy or not. /// on whether the bridge call is legacy or not.
...@@ -307,19 +287,6 @@ contract L1StandardBridge_DepositETH_TestFail is CommonTest { ...@@ -307,19 +287,6 @@ contract L1StandardBridge_DepositETH_TestFail is CommonTest {
vm.prank(alice); vm.prank(alice);
l1StandardBridge.depositETH{ value: 1 }(300, hex""); 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 { contract L1StandardBridge_BridgeETH_Test is PreBridgeETH {
...@@ -336,22 +303,6 @@ contract L1StandardBridge_BridgeETH_Test is PreBridgeETH { ...@@ -336,22 +303,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 { contract PreBridgeETHTo is CommonTest {
/// @dev Asserts the expected calls and events for bridging ETH to a different /// @dev Asserts the expected calls and events for bridging ETH to a different
/// address depending on whether the bridge call is legacy or not. /// address depending on whether the bridge call is legacy or not.
...@@ -432,29 +383,6 @@ contract L1StandardBridge_DepositETHTo_Test is PreBridgeETHTo { ...@@ -432,29 +383,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 { contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo {
/// @dev Tests that bridging ETH to a different address succeeds. /// @dev Tests that bridging ETH to a different address succeeds.
/// Emits ETHDepositInitiated and ETHBridgeInitiated events. /// Emits ETHDepositInitiated and ETHBridgeInitiated events.
...@@ -469,28 +397,6 @@ contract L1StandardBridge_BridgeETHTo_Test is PreBridgeETHTo { ...@@ -469,28 +397,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 { contract L1StandardBridge_DepositERC20_Test is CommonTest {
using stdStorage for StdStorage; using stdStorage for StdStorage;
...@@ -682,35 +588,6 @@ contract L1StandardBridge_FinalizeETHWithdrawal_Test is CommonTest { ...@@ -682,35 +588,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 { contract L1StandardBridge_FinalizeERC20Withdrawal_Test is CommonTest {
using stdStorage for StdStorage; using stdStorage for StdStorage;
...@@ -796,26 +673,6 @@ contract L1StandardBridge_FinalizeBridgeETH_Test is CommonTest { ...@@ -796,26 +673,6 @@ contract L1StandardBridge_FinalizeBridgeETH_Test is CommonTest {
} }
contract L1StandardBridge_FinalizeBridgeETH_TestFail 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. /// @dev Tests that finalizing bridged ETH reverts if the amount is incorrect.
function test_finalizeBridgeETH_incorrectValue_reverts() external { function test_finalizeBridgeETH_incorrectValue_reverts() external {
address messenger = address(l1StandardBridge.messenger()); address messenger = address(l1StandardBridge.messenger());
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
pragma solidity 0.8.15; pragma solidity 0.8.15;
// Testing // Testing
import { stdError } from "forge-std/Test.sol";
import { VmSafe } from "forge-std/Vm.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 { CommonTest } from "test/setup/CommonTest.sol";
import { NextImpl } from "test/mocks/NextImpl.sol"; import { NextImpl } from "test/mocks/NextImpl.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
...@@ -16,8 +14,6 @@ import { SuperchainConfig } from "src/L1/SuperchainConfig.sol"; ...@@ -16,8 +14,6 @@ import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { Types } from "src/libraries/Types.sol"; import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol"; import { Hashing } from "src/libraries/Hashing.sol";
import { Constants } from "src/libraries/Constants.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 { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Types.sol";
...@@ -25,7 +21,6 @@ import "src/libraries/PortalErrors.sol"; ...@@ -25,7 +21,6 @@ import "src/libraries/PortalErrors.sol";
// Interfaces // Interfaces
import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
import { IL1Block } from "interfaces/L2/IL1Block.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol"; import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol";
import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
...@@ -39,6 +34,12 @@ contract OptimismPortal2_Test is CommonTest { ...@@ -39,6 +34,12 @@ contract OptimismPortal2_Test is CommonTest {
depositor = makeAddr("depositor"); 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(optimismPortal2.version()).length > 0);
}
/// @dev Tests that the constructor sets the correct values. /// @dev Tests that the constructor sets the correct values.
/// @notice Marked virtual to be overridden in /// @notice Marked virtual to be overridden in
/// test/kontrol/deployment/DeploymentSummary.t.sol /// test/kontrol/deployment/DeploymentSummary.t.sol
...@@ -310,186 +311,6 @@ contract OptimismPortal2_Test is CommonTest { ...@@ -310,186 +311,6 @@ contract OptimismPortal2_Test is CommonTest {
assertEq(address(optimismPortal2).balance, balanceBefore + _mint); 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 /// @dev Tests that the donateETH function donates ETH and does no state read/write
function test_donateETH_succeeds(uint256 _amount) external { function test_donateETH_succeeds(uint256 _amount) external {
vm.startPrank(alice); vm.startPrank(alice);
...@@ -1005,152 +826,6 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1005,152 +826,6 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
assert(bob.balance == bobBalanceBefore + 100); 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. /// @dev Tests that `finalizeWithdrawalTransaction` succeeds.
function test_finalizeWithdrawalTransaction_provenWithdrawalHashEther_succeeds() external { function test_finalizeWithdrawalTransaction_provenWithdrawalHashEther_succeeds() external {
uint256 bobBalanceBefore = address(bob).balance; uint256 bobBalanceBefore = address(bob).balance;
...@@ -1239,32 +914,6 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest { ...@@ -1239,32 +914,6 @@ contract OptimismPortal2_FinalizeWithdrawal_Test is CommonTest {
assert(address(bob).balance == bobBalanceBefore + 100); 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. /// @dev Tests that `finalizeWithdrawalTransaction` reverts if the contract is paused.
function test_finalizeWithdrawalTransaction_paused_reverts() external { function test_finalizeWithdrawalTransaction_paused_reverts() external {
vm.prank(optimismPortal2.guardian()); vm.prank(optimismPortal2.guardian());
...@@ -1886,381 +1535,3 @@ contract OptimismPortal2_ResourceFuzz_Test is CommonTest { ...@@ -1886,381 +1535,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, "");
}
}
...@@ -21,20 +21,16 @@ contract OptimismPortalInterop_Test is CommonTest { ...@@ -21,20 +21,16 @@ contract OptimismPortalInterop_Test is CommonTest {
super.setUp(); super.setUp();
} }
/// @dev Tests that the config for the gas paying token can be set. /// @notice Tests that the version function returns a valid string. We avoid testing the
function testFuzz_setConfig_gasPayingToken_succeeds(bytes calldata _value) public { /// specific value of the string as it changes frequently.
vm.expectEmit(address(optimismPortal2)); function test_version_succeeds() external view {
emitTransactionDeposited({ assert(bytes(_optimismPortalInterop().version()).length > 0);
_from: Constants.DEPOSITOR_ACCOUNT, }
_to: Predeploys.L1_BLOCK_ATTRIBUTES,
_value: 0,
_mint: 0,
_gasLimit: 200_000,
_isCreation: false,
_data: abi.encodeCall(IL1BlockInterop.setConfig, (ConfigType.SET_GAS_PAYING_TOKEN, _value))
});
/// @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())); vm.prank(address(_optimismPortalInterop().systemConfig()));
vm.expectRevert(IOptimismPortalInterop.CustomGasTokenNotSupported.selector);
_optimismPortalInterop().setConfig(ConfigType.SET_GAS_PAYING_TOKEN, _value); _optimismPortalInterop().setConfig(ConfigType.SET_GAS_PAYING_TOKEN, _value);
} }
......
...@@ -4,19 +4,13 @@ pragma solidity 0.8.15; ...@@ -4,19 +4,13 @@ pragma solidity 0.8.15;
// Testing // Testing
import { CommonTest } from "test/setup/CommonTest.sol"; import { CommonTest } from "test/setup/CommonTest.sol";
// Contracts
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// Libraries // Libraries
import { Constants } from "src/libraries/Constants.sol"; import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Interfaces // Interfaces
import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { IL1Block } from "interfaces/L2/IL1Block.sol";
contract SystemConfig_Init is CommonTest { contract SystemConfig_Init is CommonTest {
event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data); event ConfigUpdate(uint256 indexed version, ISystemConfig.UpdateType indexed updateType, bytes data);
...@@ -47,6 +41,12 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { ...@@ -47,6 +41,12 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
optimismMintableERC20Factory = artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy"); 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(systemConfig.version()).length > 0);
}
/// @dev Tests that constructor sets the correct values. /// @dev Tests that constructor sets the correct values.
function test_constructor_succeeds() external view { function test_constructor_succeeds() external view {
ISystemConfig impl = ISystemConfig(systemConfigImpl); ISystemConfig impl = ISystemConfig(systemConfigImpl);
...@@ -74,10 +74,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { ...@@ -74,10 +74,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
assertEq(address(impl.disputeGameFactory()), address(0)); assertEq(address(impl.disputeGameFactory()), address(0));
assertEq(address(impl.optimismPortal()), address(0)); assertEq(address(impl.optimismPortal()), address(0));
assertEq(address(impl.optimismMintableERC20Factory()), 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. /// @dev Tests that initialization sets the correct values.
...@@ -110,10 +106,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { ...@@ -110,10 +106,6 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
assertEq(address(systemConfig.disputeGameFactory()), address(disputeGameFactory)); assertEq(address(systemConfig.disputeGameFactory()), address(disputeGameFactory));
assertEq(address(systemConfig.optimismPortal()), address(optimismPortal2)); assertEq(address(systemConfig.optimismPortal()), address(optimismPortal2));
assertEq(address(systemConfig.optimismMintableERC20Factory()), address(optimismMintableERC20Factory)); assertEq(address(systemConfig.optimismMintableERC20Factory()), address(optimismMintableERC20Factory));
// Check gas paying token
(address token, uint8 decimals) = systemConfig.gasPayingToken();
assertEq(token, Constants.ETHER);
assertEq(decimals, 18);
} }
} }
...@@ -144,8 +136,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { ...@@ -144,8 +136,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: address(0), optimismMintableERC20Factory: address(0)
gasPayingToken: Constants.ETHER
}) })
}); });
} }
...@@ -174,8 +165,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { ...@@ -174,8 +165,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: address(0), optimismMintableERC20Factory: address(0)
gasPayingToken: Constants.ETHER
}) })
}); });
assertEq(systemConfig.startBlock(), block.number); assertEq(systemConfig.startBlock(), block.number);
...@@ -205,8 +195,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test { ...@@ -205,8 +195,7 @@ contract SystemConfig_Initialize_TestFail is SystemConfig_Initialize_Test {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: address(0), optimismMintableERC20Factory: address(0)
gasPayingToken: Constants.ETHER
}) })
}); });
assertEq(systemConfig.startBlock(), 1); assertEq(systemConfig.startBlock(), 1);
...@@ -315,193 +304,12 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init { ...@@ -315,193 +304,12 @@ contract SystemConfig_Init_ResourceConfig is SystemConfig_Init {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: 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
})
});
}
/// @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 { contract SystemConfig_Setters_TestFail is SystemConfig_Init {
/// @dev Tests that `setBatcherHash` reverts if the caller is not the owner. /// @dev Tests that `setBatcherHash` reverts if the caller is not the owner.
function test_setBatcherHash_notOwner_reverts() external { function test_setBatcherHash_notOwner_reverts() external {
......
...@@ -4,16 +4,10 @@ pragma solidity 0.8.15; ...@@ -4,16 +4,10 @@ pragma solidity 0.8.15;
// Testing // Testing
import { CommonTest } from "test/setup/CommonTest.sol"; import { CommonTest } from "test/setup/CommonTest.sol";
// Contracts
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
// Libraries // Libraries
import { Constants } from "src/libraries/Constants.sol";
import { StaticConfig } from "src/libraries/StaticConfig.sol"; import { StaticConfig } from "src/libraries/StaticConfig.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
// Interfaces // Interfaces
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol"; import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol";
import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol"; import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol";
import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol";
...@@ -26,110 +20,10 @@ contract SystemConfigInterop_Test is CommonTest { ...@@ -26,110 +20,10 @@ contract SystemConfigInterop_Test is CommonTest {
super.setUp(); super.setUp();
} }
/// @dev Temporary test that checks that correct calls to initialize when using a custom gas token revert with the /// @notice Tests that the version function returns a valid string. We avoid testing the
/// expected error. /// specific value of the string as it changes frequently.
/// @dev Should be removed when/if Custom Gas Token functionality is allowed again. function test_version_succeeds() external view {
function test_initialize_customGasToken_reverts() external { assert(bytes(_systemConfigInterop().version()).length > 0);
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. /// @dev Tests that a dependency can be added.
...@@ -176,35 +70,6 @@ contract SystemConfigInterop_Test is CommonTest { ...@@ -176,35 +70,6 @@ contract SystemConfigInterop_Test is CommonTest {
_systemConfigInterop().removeDependency(_chainId); _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. /// @dev Returns the SystemConfigInterop instance.
function _systemConfigInterop() internal view returns (ISystemConfigInterop) { function _systemConfigInterop() internal view returns (ISystemConfigInterop) {
return ISystemConfigInterop(address(systemConfig)); return ISystemConfigInterop(address(systemConfig));
......
...@@ -16,6 +16,7 @@ import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; ...@@ -16,6 +16,7 @@ import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
// Interfaces // Interfaces
import { IL2CrossDomainMessenger } from "interfaces/L2/IL2CrossDomainMessenger.sol"; import { IL2CrossDomainMessenger } from "interfaces/L2/IL2CrossDomainMessenger.sol";
import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol";
import { IGasToken } from "src/libraries/GasPayingToken.sol";
contract L2CrossDomainMessenger_Test is CommonTest { contract L2CrossDomainMessenger_Test is CommonTest {
/// @dev Receiver address for testing /// @dev Receiver address for testing
...@@ -315,7 +316,7 @@ contract L2CrossDomainMessenger_Test is CommonTest { ...@@ -315,7 +316,7 @@ contract L2CrossDomainMessenger_Test is CommonTest {
/// @dev Tests that sendMessage succeeds with a custom gas token when the call value is zero. /// @dev Tests that sendMessage succeeds with a custom gas token when the call value is zero.
function test_sendMessage_customGasTokenButNoValue_succeeds() external { function test_sendMessage_customGasTokenButNoValue_succeeds() external {
// Mock the gasPayingToken function to return a custom gas token // 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.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2)));
bytes memory xDomainCallData = bytes memory xDomainCallData =
Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff"); Encoding.encodeCrossDomainMessage(l2CrossDomainMessenger.messageNonce(), alice, recipient, 0, 100, hex"ff");
...@@ -355,7 +356,7 @@ contract L2CrossDomainMessenger_Test is CommonTest { ...@@ -355,7 +356,7 @@ contract L2CrossDomainMessenger_Test is CommonTest {
/// @dev Tests that the sendMessage reverts when call value is non-zero with custom gas token. /// @dev Tests that the sendMessage reverts when call value is non-zero with custom gas token.
function test_sendMessage_customGasTokenWithValue_reverts() external { function test_sendMessage_customGasTokenWithValue_reverts() external {
// Mock the gasPayingToken function to return a custom gas token // 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.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2)));
vm.expectRevert("CrossDomainMessenger: cannot send value with custom gas token"); vm.expectRevert("CrossDomainMessenger: cannot send value with custom gas token");
l2CrossDomainMessenger.sendMessage{ value: 1 }(recipient, hex"ff", uint32(100)); l2CrossDomainMessenger.sendMessage{ value: 1 }(recipient, hex"ff", uint32(100));
...@@ -364,7 +365,7 @@ contract L2CrossDomainMessenger_Test is CommonTest { ...@@ -364,7 +365,7 @@ contract L2CrossDomainMessenger_Test is CommonTest {
/// @dev Tests that the relayMessage succeeds with a custom gas token when the call value is zero. /// @dev Tests that the relayMessage succeeds with a custom gas token when the call value is zero.
function test_relayMessage_customGasTokenAndNoValue_succeeds() external { function test_relayMessage_customGasTokenAndNoValue_succeeds() external {
// Mock the gasPayingToken function to return a custom gas token // 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.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2)));
address target = address(0xabcd); address target = address(0xabcd);
address sender = address(l1CrossDomainMessenger); address sender = address(l1CrossDomainMessenger);
...@@ -400,7 +401,7 @@ contract L2CrossDomainMessenger_Test is CommonTest { ...@@ -400,7 +401,7 @@ contract L2CrossDomainMessenger_Test is CommonTest {
/// The L1CrossDomainMessenger `sendMessage` function cannot send value with a custom gas token. /// The L1CrossDomainMessenger `sendMessage` function cannot send value with a custom gas token.
function test_relayMessage_customGasTokenWithValue_reverts() external virtual { function test_relayMessage_customGasTokenWithValue_reverts() external virtual {
// Mock the gasPayingToken function to return a custom gas token // 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.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"); vm.expectRevert("CrossDomainMessenger: value must be zero unless message is from a system address");
l2CrossDomainMessenger.relayMessage{ value: 1 }( l2CrossDomainMessenger.relayMessage{ value: 1 }(
......
...@@ -20,6 +20,7 @@ import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenge ...@@ -20,6 +20,7 @@ import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenge
import { IStandardBridge } from "interfaces/universal/IStandardBridge.sol"; import { IStandardBridge } from "interfaces/universal/IStandardBridge.sol";
import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol"; import { IL2ToL1MessagePasser } from "interfaces/L2/IL2ToL1MessagePasser.sol";
import { IL2StandardBridge } from "interfaces/L2/IL2StandardBridge.sol"; import { IL2StandardBridge } from "interfaces/L2/IL2StandardBridge.sol";
import { IGasToken } from "src/libraries/GasPayingToken.sol";
contract L2StandardBridge_Test is CommonTest { contract L2StandardBridge_Test is CommonTest {
using stdStorage for StdStorage; using stdStorage for StdStorage;
...@@ -130,7 +131,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -130,7 +131,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that the receive function reverts with custom gas token. /// @dev Tests that the receive function reverts with custom gas token.
function testFuzz_receive_customGasToken_reverts(uint256 _value) external { function testFuzz_receive_customGasToken_reverts(uint256 _value) external {
vm.prank(alice, alice); vm.prank(alice, alice);
vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(2)));
vm.deal(alice, _value); vm.deal(alice, _value);
(bool success, bytes memory data) = address(l2StandardBridge).call{ value: _value }(hex""); (bool success, bytes memory data) = address(l2StandardBridge).call{ value: _value }(hex"");
assertFalse(success); assertFalse(success);
...@@ -169,9 +170,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -169,9 +170,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdraw` reverts with custom gas token. /// @dev Tests that `withdraw` reverts with custom gas token.
function test_withdraw_customGasToken_reverts() external { function test_withdraw_customGasToken_reverts() external {
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex""); l2StandardBridge.withdraw(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex"");
...@@ -179,9 +178,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -179,9 +178,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdraw` reverts with custom gas token. /// @dev Tests that `withdraw` reverts with custom gas token.
function test_withdrawERC20_customGasToken_reverts() external { function test_withdrawERC20_customGasToken_reverts() external {
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdraw(address(L1Token), 1, 1, hex""); l2StandardBridge.withdraw(address(L1Token), 1, 1, hex"");
...@@ -190,9 +187,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -190,9 +187,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdraw` reverts with custom gas token. /// @dev Tests that `withdraw` reverts with custom gas token.
function test_withdrawERC20WithValue_customGasToken_reverts() external { function test_withdrawERC20WithValue_customGasToken_reverts() external {
vm.deal(alice, 1 ether); vm.deal(alice, 1 ether);
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdraw{ value: 1 ether }(address(L1Token), 1, 1, hex""); l2StandardBridge.withdraw{ value: 1 ether }(address(L1Token), 1, 1, hex"");
...@@ -201,9 +196,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -201,9 +196,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdraw` with value reverts with custom gas token. /// @dev Tests that `withdraw` with value reverts with custom gas token.
function test_withdraw_customGasTokenWithValue_reverts() external { function test_withdraw_customGasTokenWithValue_reverts() external {
vm.deal(alice, 1 ether); vm.deal(alice, 1 ether);
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdraw{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex""); l2StandardBridge.withdraw{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), 1, 1, hex"");
...@@ -211,9 +204,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -211,9 +204,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdrawTo` reverts with custom gas token. /// @dev Tests that `withdrawTo` reverts with custom gas token.
function test_withdrawTo_customGasToken_reverts() external { function test_withdrawTo_customGasToken_reverts() external {
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdrawTo(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex""); l2StandardBridge.withdrawTo(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex"");
...@@ -221,9 +212,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -221,9 +212,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdrawTo` reverts with custom gas token. /// @dev Tests that `withdrawTo` reverts with custom gas token.
function test_withdrawToERC20_customGasToken_reverts() external { function test_withdrawToERC20_customGasToken_reverts() external {
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdrawTo(address(L2Token), bob, 1, 1, hex""); l2StandardBridge.withdrawTo(address(L2Token), bob, 1, 1, hex"");
...@@ -232,9 +221,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -232,9 +221,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdrawTo` reverts with custom gas token. /// @dev Tests that `withdrawTo` reverts with custom gas token.
function test_withdrawToERC20WithValue_customGasToken_reverts() external { function test_withdrawToERC20WithValue_customGasToken_reverts() external {
vm.deal(alice, 1 ether); vm.deal(alice, 1 ether);
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdrawTo{ value: 1 ether }(address(L2Token), bob, 1, 1, hex""); l2StandardBridge.withdrawTo{ value: 1 ether }(address(L2Token), bob, 1, 1, hex"");
...@@ -243,9 +230,7 @@ contract L2StandardBridge_Test is CommonTest { ...@@ -243,9 +230,7 @@ contract L2StandardBridge_Test is CommonTest {
/// @dev Tests that `withdrawTo` with value reverts with custom gas token. /// @dev Tests that `withdrawTo` with value reverts with custom gas token.
function test_withdrawTo_customGasTokenWithValue_reverts() external { function test_withdrawTo_customGasTokenWithValue_reverts() external {
vm.deal(alice, 1 ether); vm.deal(alice, 1 ether);
vm.mockCall( vm.mockCall(address(l1Block), abi.encodeCall(IGasToken.gasPayingToken, ()), abi.encode(address(1), uint8(18)));
address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(18))
);
vm.expectRevert("L2StandardBridge: not supported with custom gas token"); vm.expectRevert("L2StandardBridge: not supported with custom gas token");
vm.prank(alice, alice); vm.prank(alice, alice);
l2StandardBridge.withdrawTo{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex""); l2StandardBridge.withdrawTo{ value: 1 ether }(address(Predeploys.LEGACY_ERC20_ETH), bob, 1, 1, hex"");
...@@ -577,7 +562,7 @@ contract L2StandardBridge_Bridge_Test is CommonTest { ...@@ -577,7 +562,7 @@ contract L2StandardBridge_Bridge_Test is CommonTest {
/// @dev Tests that bridging reverts with custom gas token. /// @dev Tests that bridging reverts with custom gas token.
function test_bridgeETH_customGasToken_reverts() external { function test_bridgeETH_customGasToken_reverts() external {
vm.prank(alice, alice); vm.prank(alice, alice);
vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); 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.expectRevert("StandardBridge: cannot bridge ETH with custom gas token");
l2StandardBridge.bridgeETH(50000, hex"dead"); l2StandardBridge.bridgeETH(50000, hex"dead");
...@@ -628,7 +613,7 @@ contract L2StandardBridge_Bridge_Test is CommonTest { ...@@ -628,7 +613,7 @@ contract L2StandardBridge_Bridge_Test is CommonTest {
) )
external external
{ {
vm.mockCall(address(l1Block), abi.encodeCall(systemConfig.gasPayingToken, ()), abi.encode(address(1), uint8(2))); 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.expectRevert("StandardBridge: cannot bridge ETH with custom gas token");
vm.deal(address(this), _value); vm.deal(address(this), _value);
l2StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData); l2StandardBridge.bridgeETHTo{ value: _value }(bob, _minGasLimit, _extraData);
...@@ -655,22 +640,6 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is CommonTest { ...@@ -655,22 +640,6 @@ contract L2StandardBridge_FinalizeBridgeETH_Test is CommonTest {
l2StandardBridge.finalizeBridgeETH{ value: 100 }(alice, alice, 100, hex""); 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 { contract L2StandardBridge_FinalizeBridgeERC20_Test is CommonTest {
......
...@@ -44,8 +44,7 @@ contract SystemConfig_GasLimitBoundaries_Invariant is Test { ...@@ -44,8 +44,7 @@ contract SystemConfig_GasLimitBoundaries_Invariant is Test {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: address(0), optimismMintableERC20Factory: address(0)
gasPayingToken: Constants.ETHER
}) })
) )
) )
......
...@@ -261,12 +261,6 @@ contract Specification_Test is CommonTest { ...@@ -261,12 +261,6 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("respectedGameTypeUpdatedAt()") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("respectedGameTypeUpdatedAt()") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("proofSubmitters(bytes32,uint256)") }); _addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("proofSubmitters(bytes32,uint256)") });
_addSpec({ _name: "OptimismPortalInterop", _sel: _getSel("numProofSubmitters(bytes32)") }); _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({ _addSpec({
_name: "OptimismPortalInterop", _name: "OptimismPortalInterop",
_sel: IOptimismPortalInterop.setConfig.selector, _sel: IOptimismPortalInterop.setConfig.selector,
...@@ -313,12 +307,6 @@ contract Specification_Test is CommonTest { ...@@ -313,12 +307,6 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameTypeUpdatedAt()") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("respectedGameTypeUpdatedAt()") });
_addSpec({ _name: "OptimismPortal2", _sel: _getSel("proofSubmitters(bytes32,uint256)") }); _addSpec({ _name: "OptimismPortal2", _sel: _getSel("proofSubmitters(bytes32,uint256)") });
_addSpec({ _name: "OptimismPortal2", _sel: _getSel("numProofSubmitters(bytes32)") }); _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 // ProtocolVersions
_addSpec({ _name: "ProtocolVersions", _sel: _getSel("RECOMMENDED_SLOT()") }); _addSpec({ _name: "ProtocolVersions", _sel: _getSel("RECOMMENDED_SLOT()") });
...@@ -395,10 +383,6 @@ contract Specification_Test is CommonTest { ...@@ -395,10 +383,6 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") });
_addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") });
_addSpec({ _name: "SystemConfig", _sel: _getSel("BATCH_INBOX_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("DISPUTE_GAME_FACTORY_SLOT()") });
_addSpec({ _name: "SystemConfig", _sel: _getSel("disputeGameFactory()") }); _addSpec({ _name: "SystemConfig", _sel: _getSel("disputeGameFactory()") });
_addSpec({ _addSpec({
...@@ -471,10 +455,6 @@ contract Specification_Test is CommonTest { ...@@ -471,10 +455,6 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_PORTAL_SLOT()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("BATCH_INBOX_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("DISPUTE_GAME_FACTORY_SLOT()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("disputeGameFactory()") }); _addSpec({ _name: "SystemConfigInterop", _sel: _getSel("disputeGameFactory()") });
_addSpec({ _addSpec({
......
...@@ -10,7 +10,6 @@ import { Process } from "scripts/libraries/Process.sol"; ...@@ -10,7 +10,6 @@ import { Process } from "scripts/libraries/Process.sol";
// Libraries // Libraries
import { LibString } from "@solady/utils/LibString.sol"; import { LibString } from "@solady/utils/LibString.sol";
import { Constants } from "src/libraries/Constants.sol";
import { GameType } from "src/dispute/lib/Types.sol"; import { GameType } from "src/dispute/lib/Types.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol"; import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
...@@ -183,8 +182,7 @@ contract Initializer_Test is CommonTest { ...@@ -183,8 +182,7 @@ contract Initializer_Test is CommonTest {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: address(0), optimismMintableERC20Factory: address(0)
gasPayingToken: Constants.ETHER
}) })
) )
) )
...@@ -219,8 +217,7 @@ contract Initializer_Test is CommonTest { ...@@ -219,8 +217,7 @@ contract Initializer_Test is CommonTest {
l1StandardBridge: address(0), l1StandardBridge: address(0),
disputeGameFactory: address(0), disputeGameFactory: address(0),
optimismPortal: address(0), optimismPortal: address(0),
optimismMintableERC20Factory: address(0), optimismMintableERC20Factory: address(0)
gasPayingToken: Constants.ETHER
}) })
) )
) )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment