diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol index 4bdf44e66d2..b0693bcec9a 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortal2.sol @@ -7,6 +7,7 @@ import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; +import { ISharedLockbox } from "interfaces/L1/ISharedLockbox.sol"; interface IOptimismPortal2 { error AlreadyFinalized(); @@ -69,7 +70,7 @@ interface IOptimismPortal2 { function disputeGameBlacklist(IDisputeGame) external view returns (bool); function disputeGameFactory() external view returns (IDisputeGameFactory); function disputeGameFinalityDelaySeconds() external view returns (uint256); - function sharedLockbox() external view returns (address); + function sharedLockbox() external view returns (ISharedLockbox); function donateETH() external payable; function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; function finalizeWithdrawalTransactionExternalProof( @@ -115,10 +116,5 @@ interface IOptimismPortal2 { function systemConfig() external view returns (ISystemConfig); function version() external pure returns (string memory); - function __constructor__( - uint256 _proofMaturityDelaySeconds, - uint256 _disputeGameFinalityDelaySeconds, - address _sharedLockbox - ) - external; + function __constructor__(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) external; } diff --git a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol index 846a6b6c273..4201790d787 100644 --- a/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol +++ b/packages/contracts-bedrock/interfaces/L1/IOptimismPortalInterop.sol @@ -8,6 +8,7 @@ import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol" import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; +import { ISharedLockbox } from "interfaces/L1/ISharedLockbox.sol"; interface IOptimismPortalInterop { error AlreadyFinalized(); @@ -70,7 +71,7 @@ interface IOptimismPortalInterop { function disputeGameBlacklist(IDisputeGame) external view returns (bool); function disputeGameFactory() external view returns (IDisputeGameFactory); function disputeGameFinalityDelaySeconds() external view returns (uint256); - function sharedLockbox() external view returns (address); + function sharedLockbox() external view returns (ISharedLockbox); function donateETH() external payable; function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external; function finalizeWithdrawalTransactionExternalProof( @@ -117,10 +118,5 @@ interface IOptimismPortalInterop { function systemConfig() external view returns (ISystemConfig); function version() external pure returns (string memory); - function __constructor__( - uint256 _proofMaturityDelaySeconds, - uint256 _disputeGameFinalityDelaySeconds, - address _sharedLockbox - ) - external; + function __constructor__(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) external; } diff --git a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol index 7b625ec9a25..57e8efb82a8 100644 --- a/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol +++ b/packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol @@ -717,15 +717,13 @@ contract DeployImplementations is Script { } else { uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds(); uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds(); - address sharedLockbox = address(_dii.sharedLockboxProxy()); vm.broadcast(msg.sender); impl = IOptimismPortal2( DeployUtils.create1({ _name: "OptimismPortal2", _args: DeployUtils.encodeConstructor( abi.encodeCall( - IOptimismPortal2.__constructor__, - (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds, sharedLockbox) + IOptimismPortal2.__constructor__, (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds) ) ) }) @@ -959,7 +957,6 @@ contract DeployImplementationsInterop is DeployImplementations { } else { uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds(); uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds(); - address sharedLockbox = address(_dii.sharedLockboxProxy()); vm.broadcast(msg.sender); impl = IOptimismPortalInterop( DeployUtils.create1({ @@ -967,7 +964,7 @@ contract DeployImplementationsInterop is DeployImplementations { _args: DeployUtils.encodeConstructor( abi.encodeCall( IOptimismPortalInterop.__constructor__, - (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds, sharedLockbox) + (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds) ) ) }) diff --git a/packages/contracts-bedrock/snapshots/.gas-snapshot b/packages/contracts-bedrock/snapshots/.gas-snapshot index c295d676587..e084f858d5c 100644 --- a/packages/contracts-bedrock/snapshots/.gas-snapshot +++ b/packages/contracts-bedrock/snapshots/.gas-snapshot @@ -8,10 +8,10 @@ GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 369342) GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2967527) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 564475) GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4076690) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467025) -GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512729) -GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72728) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 467064) +GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3512768) +GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 72706) GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 92973) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68422) GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68986) -GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155632) \ No newline at end of file +GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 155610) \ No newline at end of file diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json index 5ca5e6bc7ff..9ec54a2db54 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortal2.json @@ -10,11 +10,6 @@ "internalType": "uint256", "name": "_disputeGameFinalityDelaySeconds", "type": "uint256" - }, - { - "internalType": "address", - "name": "_sharedLockbox", - "type": "address" } ], "stateMutability": "nonpayable", @@ -653,7 +648,7 @@ "name": "sharedLockbox", "outputs": [ { - "internalType": "address", + "internalType": "contract ISharedLockbox", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json index 8eb9ed0f74d..59d72ab1fbc 100644 --- a/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json +++ b/packages/contracts-bedrock/snapshots/abi/OptimismPortalInterop.json @@ -10,11 +10,6 @@ "internalType": "uint256", "name": "_disputeGameFinalityDelaySeconds", "type": "uint256" - }, - { - "internalType": "address", - "name": "_sharedLockbox", - "type": "address" } ], "stateMutability": "nonpayable", @@ -671,7 +666,7 @@ "name": "sharedLockbox", "outputs": [ { - "internalType": "address", + "internalType": "contract ISharedLockbox", "name": "", "type": "address" } diff --git a/packages/contracts-bedrock/snapshots/semver-lock.json b/packages/contracts-bedrock/snapshots/semver-lock.json index 2808138e052..2f4e592dbc5 100644 --- a/packages/contracts-bedrock/snapshots/semver-lock.json +++ b/packages/contracts-bedrock/snapshots/semver-lock.json @@ -28,12 +28,12 @@ "sourceCodeHash": "0xb71e8bc24ea9ebb5692762005f2936ba2a00bf169e1e32f504a0f6e23a349a22" }, "src/L1/OptimismPortal2.sol": { - "initCodeHash": "0x3b7d8df1b988111d84149da579a40bc82b7fcf177cc151f5c504a143f4d342ea", - "sourceCodeHash": "0xf5fe46560360ad9bf5068c81e5a3e01b3df4dd8393e0a25f0b57a12cd51a5223" + "initCodeHash": "0x7829e8451790ad40c04b9a8283a76a0258e8120b4fcff7733262de43e0ee7f9c", + "sourceCodeHash": "0xfdf81493a292b649dcaaf622dd8a851df2bd456f62743682b74d99732ac3e482" }, "src/L1/OptimismPortalInterop.sol": { - "initCodeHash": "0x39b347c4895e627b493364ba4fce0a61659a3ddd4d2d1c5be72a430238b1c987", - "sourceCodeHash": "0x2512df44a0165e83babb347e4f66a24c668e0f37a56e653dca54d3bd08ab5fd8" + "initCodeHash": "0x482e8c9ceb652e6f22ec714778e67bc0673334600818c162a48f31b095f5212f", + "sourceCodeHash": "0xeb7323d25dfcbeac165a27d4bb112c45ca9d04de82b75b2dba22b3b2181514ae" }, "src/L1/ProtocolVersions.sol": { "initCodeHash": "0xb0ff1661226417342001fe9f0b64c340b7c074ff71579abf05399f4e742aaca1", diff --git a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol index de9513abcfd..37d544fef39 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortal2.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortal2.sol @@ -71,9 +71,6 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { /// finalized. uint256 internal immutable DISPUTE_GAME_FINALITY_DELAY_SECONDS; - /// @notice The Shared Lockbox contract. - ISharedLockbox internal immutable SHARED_LOCKBOX; - /// @notice Version of the deposit event. uint256 internal constant DEPOSIT_VERSION = 0; @@ -192,10 +189,9 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { } /// @notice Constructs the OptimismPortal contract. - constructor(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds, address _sharedLockbox) { + constructor(uint256 _proofMaturityDelaySeconds, uint256 _disputeGameFinalityDelaySeconds) { PROOF_MATURITY_DELAY_SECONDS = _proofMaturityDelaySeconds; DISPUTE_GAME_FINALITY_DELAY_SECONDS = _disputeGameFinalityDelaySeconds; - SHARED_LOCKBOX = ISharedLockbox(_sharedLockbox); initialize({ _disputeGameFactory: IDisputeGameFactory(address(0)), @@ -279,8 +275,8 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { } /// @notice Getter for the address of the shared lockbox. - function sharedLockbox() public view returns (address) { - return address(SHARED_LOCKBOX); + function sharedLockbox() public view returns (ISharedLockbox) { + return superchainConfig.SHARED_LOCKBOX(); } /// @notice Computes the minimum gas limit for a deposit. @@ -437,7 +433,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { (address token,) = gasPayingToken(); if (token == Constants.ETHER) { // Unlock and receive the ETH from the shared lockbox. - if (_tx.value != 0) SHARED_LOCKBOX.unlockETH(_tx.value); + if (_tx.value != 0) sharedLockbox().unlockETH(_tx.value); // Trigger the call to the target contract. We use a custom low level method // SafeCall.callWithMinGas to ensure two key properties @@ -570,7 +566,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver { if (token == Constants.ETHER && msg.value != 0) { // Lock the ETH in the shared lockbox. - SHARED_LOCKBOX.lockETH{ value: msg.value }(); + sharedLockbox().lockETH{ value: msg.value }(); } _depositTransaction({ diff --git a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol index 375678f8ec3..2cd7e6ecf9b 100644 --- a/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol +++ b/packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol @@ -20,10 +20,9 @@ import { IL1BlockInterop, ConfigType } from "interfaces/L2/IL1BlockInterop.sol"; contract OptimismPortalInterop is OptimismPortal2 { constructor( uint256 _proofMaturityDelaySeconds, - uint256 _disputeGameFinalityDelaySeconds, - address _sharedLockbox + uint256 _disputeGameFinalityDelaySeconds ) - OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds, _sharedLockbox) + OptimismPortal2(_proofMaturityDelaySeconds, _disputeGameFinalityDelaySeconds) { } /// @custom:semver +interop-beta.5 diff --git a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol index 8101bf8ac38..c34b3e14026 100644 --- a/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol +++ b/packages/contracts-bedrock/test/L1/OptimismPortal2.t.sol @@ -55,7 +55,6 @@ contract OptimismPortal2_Test is CommonTest { assertEq(address(opImpl.superchainConfig()), address(0)); assertEq(opImpl.l2Sender(), Constants.DEFAULT_L2_SENDER); assertEq(opImpl.respectedGameType().raw(), deploy.cfg().respectedGameType()); - assertEq(opImpl.sharedLockbox(), address(sharedLockbox)); } /// @dev Tests that the initializer sets the correct values. @@ -70,7 +69,7 @@ contract OptimismPortal2_Test is CommonTest { assertEq(optimismPortal2.l2Sender(), Constants.DEFAULT_L2_SENDER); assertEq(optimismPortal2.paused(), false); assertEq(optimismPortal2.respectedGameType().raw(), deploy.cfg().respectedGameType()); - assertEq(optimismPortal2.sharedLockbox(), address(sharedLockbox)); + assertEq(address(optimismPortal2.sharedLockbox()), address(sharedLockbox)); } /// @dev Tests that `pause` successfully pauses @@ -134,6 +133,20 @@ contract OptimismPortal2_Test is CommonTest { assertEq(optimismPortal2.paused(), true); } + /// @dev Tests that `sharedLockbox` returns correctly + function testFuzz_sharedLockbox_succeeds(address _caller, address _lockbox) external { + // Mock and expect the SuperchainConfig's SharedLockbox + vm.mockCall( + address(superchainConfig), abi.encodeCall(superchainConfig.SHARED_LOCKBOX, ()), abi.encode(_lockbox) + ); + vm.expectCall(address(superchainConfig), 0, abi.encodeCall(superchainConfig.SHARED_LOCKBOX, ())); + + vm.prank(_caller); + address _result = address(optimismPortal2.sharedLockbox()); + + assertEq(_result, _lockbox); + } + /// @dev Tests that `receive` successdully deposits ETH. function testFuzz_receive_succeeds(uint256 _value) external { vm.expectEmit(address(optimismPortal2));