Skip to content
Merged
9 changes: 5 additions & 4 deletions packages/contracts-bedrock/interfaces/L1/IETHLockbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.0;
import { ISemver } from "interfaces/universal/ISemver.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IPAOBase } from "interfaces/L1/IPAOBase.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";

interface IETHLockbox is IPAOBase, ISemver {
error ETHLockbox_Unauthorized();
Expand All @@ -20,17 +21,17 @@ interface IETHLockbox is IPAOBase, ISemver {
event LiquidityMigrated(address indexed lockbox);
event LiquidityReceived(address indexed lockbox);

function initialize(address _superchainConfig, address[] calldata _portals) external;
function initialize(ISuperchainConfig _superchainConfig, IOptimismPortal2[] calldata _portals) external;
function superchainConfig() external view returns (ISuperchainConfig);
function paused() external view returns (bool);
function authorizedPortals(address) external view returns (bool);
function authorizedLockboxes(address) external view returns (bool);
function receiveLiquidity() external payable;
function lockETH() external payable;
function unlockETH(uint256 _value) external;
function authorizePortal(address _portal) external;
function authorizeLockbox(address _lockbox) external;
function migrateLiquidity(address _lockbox) external;
function authorizePortal(IOptimismPortal2 _portal) external;
function authorizeLockbox(IETHLockbox _lockbox) external;
function migrateLiquidity(IETHLockbox _lockbox) external;

function __constructor__() external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ interface IOptimismPortal2 is IPAOBase {
function disputeGameFactory() external view returns (IDisputeGameFactory);
function disputeGameFinalityDelaySeconds() external view returns (uint256);
function donateETH() external payable;
function updateLockbox(address _newLockbox) external;
function updateLockbox(IETHLockbox _newLockbox) external;
function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external;
function finalizeWithdrawalTransactionExternalProof(
Types.WithdrawalTransaction memory _tx,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ interface IOptimismPortalInterop is IPAOBase {
function disputeGameFactory() external view returns (IDisputeGameFactory);
function disputeGameFinalityDelaySeconds() external view returns (uint256);
function donateETH() external payable;
function updateLockbox(address _newLockbox) external;
function updateLockbox(IETHLockbox _newLockbox) external;
function finalizeWithdrawalTransaction(Types.WithdrawalTransaction memory _tx) external;
function finalizeWithdrawalTransactionExternalProof(
Types.WithdrawalTransaction memory _tx,
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IL1CrossDomainMessenger } from "interfaces/L1/IL1CrossDomainMessenger.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
import { IOptimismPortal2 as IOptimismPortal } from "interfaces/L1/IOptimismPortal2.sol";
import { IL1ERC721Bridge } from "interfaces/L1/IL1ERC721Bridge.sol";
import { IL1StandardBridge } from "interfaces/L1/IL1StandardBridge.sol";
import { ProtocolVersion, IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
Expand Down Expand Up @@ -368,7 +368,7 @@ library ChainAssertions {
internal
view
{
IOptimismPortal2 portal = IOptimismPortal2(payable(_contracts.OptimismPortal));
IOptimismPortal portal = IOptimismPortal(payable(_contracts.OptimismPortal));
console.log(
"Running chain assertions on the OptimismPortal2 %s at %s",
_isProxy ? "proxy" : "implementation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"
import { IAnchorStateRegistry } from "interfaces/dispute/IAnchorStateRegistry.sol";
import { IOPContractsManager } from "interfaces/L1/IOPContractsManager.sol";
import { IOPContractsManagerInterop } from "interfaces/L1/IOPContractsManagerInterop.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
import { IOptimismPortal2 as IOptimismPortal } from "interfaces/L1/IOptimismPortal2.sol";
import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { IL1CrossDomainMessenger } from "interfaces/L1/IL1CrossDomainMessenger.sol";
Expand Down Expand Up @@ -150,7 +150,7 @@ contract DeployImplementationsInput is BaseDeployIO {
contract DeployImplementationsOutput is BaseDeployIO {
IOPContractsManager internal _opcm;
IDelayedWETH internal _delayedWETHImpl;
IOptimismPortal2 internal _optimismPortalImpl;
IOptimismPortal internal _optimismPortalImpl;
IETHLockbox internal _ethLockboxImpl;
IPreimageOracle internal _preimageOracleSingleton;
IMIPS internal _mipsSingleton;
Expand All @@ -171,7 +171,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
if (_sel == this.opcm.selector) _opcm = IOPContractsManager(_addr);
else if (_sel == this.superchainConfigImpl.selector) _superchainConfigImpl = ISuperchainConfig(_addr);
else if (_sel == this.protocolVersionsImpl.selector) _protocolVersionsImpl = IProtocolVersions(_addr);
else if (_sel == this.optimismPortalImpl.selector) _optimismPortalImpl = IOptimismPortal2(payable(_addr));
else if (_sel == this.optimismPortalImpl.selector) _optimismPortalImpl = IOptimismPortal(payable(_addr));
else if (_sel == this.ethLockboxImpl.selector) _ethLockboxImpl = IETHLockbox(payable(_addr));
else if (_sel == this.delayedWETHImpl.selector) _delayedWETHImpl = IDelayedWETH(payable(_addr));
else if (_sel == this.preimageOracleSingleton.selector) _preimageOracleSingleton = IPreimageOracle(_addr);
Expand Down Expand Up @@ -231,7 +231,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
return _protocolVersionsImpl;
}

function optimismPortalImpl() public view returns (IOptimismPortal2) {
function optimismPortalImpl() public view returns (IOptimismPortal) {
DeployUtils.assertValidContractAddress(address(_optimismPortalImpl));
return _optimismPortalImpl;
}
Expand Down Expand Up @@ -316,7 +316,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
}

function assertValidOptimismPortalImpl(DeployImplementationsInput) internal view {
IOptimismPortal2 portal = optimismPortalImpl();
IOptimismPortal portal = optimismPortalImpl();

DeployUtils.assertInitialized({ _contractAddress: address(portal), _isProxy: false, _slot: 0, _offset: 0 });

Expand Down Expand Up @@ -726,11 +726,11 @@ contract DeployImplementations is Script {
virtual
{
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
IOptimismPortal2 impl = IOptimismPortal2(
IOptimismPortal impl = IOptimismPortal(
DeployUtils.createDeterministic({
_name: "OptimismPortal2",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(IOptimismPortal2.__constructor__, (proofMaturityDelaySeconds))
abi.encodeCall(IOptimismPortal.__constructor__, (proofMaturityDelaySeconds))
),
_salt: _salt
})
Expand Down
12 changes: 7 additions & 5 deletions packages/contracts-bedrock/scripts/deploy/DeployOPChain.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol";
import { Claim, Duration, GameType, GameTypes, Hash } from "src/dispute/lib/Types.sol";

import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
import { IOptimismPortal2 as IOptimismPortal } from "interfaces/L1/IOptimismPortal2.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { IL1CrossDomainMessenger } from "interfaces/L1/IL1CrossDomainMessenger.sol";
import { IL1ERC721Bridge } from "interfaces/L1/IL1ERC721Bridge.sol";
Expand Down Expand Up @@ -225,7 +225,7 @@ contract DeployOPChainOutput is BaseDeployIO {
IOptimismMintableERC20Factory internal _optimismMintableERC20FactoryProxy;
IL1StandardBridge internal _l1StandardBridgeProxy;
IL1CrossDomainMessenger internal _l1CrossDomainMessengerProxy;
IOptimismPortal2 internal _optimismPortalProxy;
IOptimismPortal internal _optimismPortalProxy;
IETHLockbox internal _ethLockboxProxy;
IDisputeGameFactory internal _disputeGameFactoryProxy;
IAnchorStateRegistry internal _anchorStateRegistryProxy;
Expand All @@ -244,7 +244,7 @@ contract DeployOPChainOutput is BaseDeployIO {
else if (_sel == this.optimismMintableERC20FactoryProxy.selector) _optimismMintableERC20FactoryProxy = IOptimismMintableERC20Factory(_addr) ;
else if (_sel == this.l1StandardBridgeProxy.selector) _l1StandardBridgeProxy = IL1StandardBridge(payable(_addr)) ;
else if (_sel == this.l1CrossDomainMessengerProxy.selector) _l1CrossDomainMessengerProxy = IL1CrossDomainMessenger(_addr) ;
else if (_sel == this.optimismPortalProxy.selector) _optimismPortalProxy = IOptimismPortal2(payable(_addr)) ;
else if (_sel == this.optimismPortalProxy.selector) _optimismPortalProxy = IOptimismPortal(payable(_addr)) ;
else if (_sel == this.ethLockboxProxy.selector) _ethLockboxProxy = IETHLockbox(payable(_addr)) ;
else if (_sel == this.disputeGameFactoryProxy.selector) _disputeGameFactoryProxy = IDisputeGameFactory(_addr) ;
else if (_sel == this.anchorStateRegistryProxy.selector) _anchorStateRegistryProxy = IAnchorStateRegistry(_addr) ;
Expand Down Expand Up @@ -296,7 +296,7 @@ contract DeployOPChainOutput is BaseDeployIO {
return _l1CrossDomainMessengerProxy;
}

function optimismPortalProxy() public returns (IOptimismPortal2) {
function optimismPortalProxy() public returns (IOptimismPortal) {
DeployUtils.assertValidContractAddress(address(_optimismPortalProxy));
DeployUtils.assertERC1967ImplementationSet(address(_optimismPortalProxy));
return _optimismPortalProxy;
Expand Down Expand Up @@ -607,7 +607,7 @@ contract DeployOPChain is Script {
}

function assertValidOptimismPortal(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
IOptimismPortal2 portal = _doo.optimismPortalProxy();
IOptimismPortal portal = _doo.optimismPortalProxy();
ISuperchainConfig superchainConfig = ISuperchainConfig(address(_doi.opcm().superchainConfig()));

require(address(portal.anchorStateRegistry()) == address(_doo.anchorStateRegistryProxy()), "PORTAL-10");
Expand All @@ -624,13 +624,15 @@ contract DeployOPChain is Script {

// Check once the portal is updated to use the new lockbox.
require(address(portal.ethLockbox()) == address(_doo.ethLockboxProxy()), "PORTAL-90");
require(portal.PAO() == _doi.opChainProxyAdminOwner(), "PORTAL-100");
}

function assertValidETHLockbox(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
IETHLockbox lockbox = _doo.ethLockboxProxy();

require(address(lockbox.superchainConfig()) == address(_doi.opcm().superchainConfig()), "ETHLOCKBOX-10");
require(lockbox.authorizedPortals(address(_doo.optimismPortalProxy())), "ETHLOCKBOX-20");
require(lockbox.PAO() == _doi.opChainProxyAdminOwner(), "ETHLOCKBOX-30");
}

function assertValidDisputeGameFactory(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
Expand Down
15 changes: 0 additions & 15 deletions packages/contracts-bedrock/scripts/libraries/DeployUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -366,21 +366,6 @@ library DeployUtils {
}
}

function assertInitializedOZv5(address _contractAddress, bool _isProxy) internal view {
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

bytes32 slotVal = vm.load(_contractAddress, INITIALIZABLE_STORAGE);
uint64 initialized = uint64(uint256(slotVal) & 0xFFFFFFFFFFFFFFFF);
if (_isProxy) {
require(initialized == 1, "DeployUtils: storage value is not 1 at the given slot and offset");
} else {
require(
initialized == type(uint64).max, "DeployUtils: storage value is not 0xff at the given slot and offset"
);
}
}

/// @notice Etches a contract, labels it, and allows cheatcodes for it.
/// @param _etchTo Address of the contract to etch.
/// @param _cname The contract name (also used to label the contract).
Expand Down
10 changes: 5 additions & 5 deletions packages/contracts-bedrock/snapshots/abi/ETHLockbox.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract IETHLockbox",
"name": "_lockbox",
"type": "address"
}
Expand All @@ -33,7 +33,7 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract IOptimismPortal2",
"name": "_portal",
"type": "address"
}
Expand Down Expand Up @@ -84,12 +84,12 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract ISuperchainConfig",
"name": "_superchainConfig",
"type": "address"
},
{
"internalType": "address[]",
"internalType": "contract IOptimismPortal2[]",
"name": "_portals",
"type": "address[]"
}
Expand All @@ -109,7 +109,7 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract IETHLockbox",
"name": "_lockbox",
"type": "address"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract IETHLockbox",
"name": "_newLockbox",
"type": "address"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@
{
"inputs": [
{
"internalType": "address",
"internalType": "contract IETHLockbox",
"name": "_newLockbox",
"type": "address"
}
Expand Down
6 changes: 3 additions & 3 deletions packages/contracts-bedrock/snapshots/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"src/L1/ETHLockbox.sol": {
"initCodeHash": "0xb5da33c92a6f0bc00eaaaec5d0b99c9c15a9dd9d7a25c416cd6740a96e7fc4d5",
"sourceCodeHash": "0xc9ac52290abc2f3c7071e12116593f4bad504961ffa11825161072a5aa94c23c"
"sourceCodeHash": "0x12af194d8fe23ff1c15c378151c7cb9e5a3854531b69c1153475432ef9f73d5e"
},
"src/L1/L1CrossDomainMessenger.sol": {
"initCodeHash": "0x03a3c0eb2418aba9f93bb89723ba2ee7cb9e1988ca00f380503c960149c85b7a",
Expand All @@ -21,7 +21,7 @@
},
"src/L1/OPContractsManager.sol": {
"initCodeHash": "0x6eaf1dcd6b87f4372445e8a8936efa4e9879cfd05c1de8a306acb69266ee03d9",
"sourceCodeHash": "0x624703c5d5b8a1d36ff44b61d1a1512e3a1776f179f2cc386f28d1b789c9fe9b"
"sourceCodeHash": "0x9205651bfa81ac60fc331892c792ae6f668601556270ac6a5cda9c5e2258f524"
},
"src/L1/OPContractsManagerInterop.sol": {
"initCodeHash": "0x7865201a60d422cda5b33a2ff22b4ab707a15ba54016182d2a6cca367d618d74",
Expand All @@ -33,7 +33,7 @@
},
"src/L1/OptimismPortal2.sol": {
"initCodeHash": "0x084ac1d109f9bdaba389fdad4dc3887af745b825356e1c70bc5ba43a23a8c7b7",
"sourceCodeHash": "0x91acba845145aca7a342cdafb55129546acefce122562739ebc0fdb655edad1a"
"sourceCodeHash": "0xf23dea8126e89157c43561cee63f8701118c3017d7662ed066d3fa157f32b441"
},
"src/L1/OptimismPortalInterop.sol": {
"initCodeHash": "0x5f0e909be4f924aaf4742a84ed1dd134d84e5b91101e8cbd6c7ffbf893b4da84",
Expand Down
33 changes: 20 additions & 13 deletions packages/contracts-bedrock/src/L1/ETHLockbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Constants } from "src/libraries/Constants.sol";
import { ISemver } from "interfaces/universal/ISemver.sol";
import { IOptimismPortal2 as IOptimismPortal } from "interfaces/L1/IOptimismPortal2.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IETHLockbox } from "interfaces/L1/IETHLockbox.sol";

/// @custom:proxied true
/// @title ETHLockbox
Expand Down Expand Up @@ -82,18 +83,24 @@ contract ETHLockbox is PAOBase, Initializable, ISemver {
/// @notice Initializer.
/// @param _superchainConfig The address of the SuperchainConfig contract.
/// @param _portals The addresses of the portals to authorize.
function initialize(address _superchainConfig, address[] calldata _portals) external initializer {
function initialize(
ISuperchainConfig _superchainConfig,
IOptimismPortal[] calldata _portals
)
external
initializer
{
superchainConfig = ISuperchainConfig(_superchainConfig);
for (uint256 i; i < _portals.length; i++) {
_authorizePortal(_portals[i]);
_authorizePortal(address(_portals[i]));
}
}

/// @notice Authorizes a portal to lock and unlock ETH.
/// @param _portal The address of the portal to authorize.
function authorizePortal(address _portal) external {
function authorizePortal(IOptimismPortal _portal) external {
if (msg.sender != PAO()) revert ETHLockbox_Unauthorized();
_authorizePortal(_portal);
_authorizePortal(address(_portal));
}

/// @notice Getter for the current paused status.
Expand Down Expand Up @@ -133,24 +140,24 @@ contract ETHLockbox is PAOBase, Initializable, ISemver {

/// @notice Authorizes an ETH lockbox to migrate its liquidity to the current ETH lockbox.
/// @param _lockbox The address of the ETH lockbox to authorize.
function authorizeLockbox(address _lockbox) external {
function authorizeLockbox(IETHLockbox _lockbox) external {
if (msg.sender != PAO()) revert ETHLockbox_Unauthorized();
if (!_samePAO(_lockbox)) revert ETHLockbox_DifferentPAO();
if (authorizedLockboxes[_lockbox]) revert ETHLockbox_AlreadyAuthorized();
if (!_samePAO(address(_lockbox))) revert ETHLockbox_DifferentPAO();
if (authorizedLockboxes[address(_lockbox)]) revert ETHLockbox_AlreadyAuthorized();

authorizedLockboxes[_lockbox] = true;
emit LockboxAuthorized(_lockbox);
authorizedLockboxes[address(_lockbox)] = true;
emit LockboxAuthorized(address(_lockbox));
}

/// @notice Migrates liquidity from the current ETH lockbox to another.
/// @param _lockbox The address of the ETH lockbox to migrate liquidity to.
function migrateLiquidity(address _lockbox) external {
function migrateLiquidity(IETHLockbox _lockbox) external {
if (msg.sender != PAO()) revert ETHLockbox_Unauthorized();
if (!_samePAO(_lockbox)) revert ETHLockbox_DifferentPAO();
if (!_samePAO(address(_lockbox))) revert ETHLockbox_DifferentPAO();

ETHLockbox(_lockbox).receiveLiquidity{ value: address(this).balance }();
IETHLockbox(_lockbox).receiveLiquidity{ value: address(this).balance }();

emit LiquidityMigrated(_lockbox);
emit LiquidityMigrated(address(_lockbox));
}

/// @notice Authorizes a portal to lock and unlock ETH.
Expand Down
Loading