Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: introduce SharedLockbox #141

Draft
wants to merge 20 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
bf3278f
feat: add shared lockbox (#126)
0xDiscotech Nov 20, 2024
0324436
Merge pull request #136 from defi-wonderland/chore/sync-develop
agusduha Nov 22, 2024
27a4515
feat: integrate portal to lockbox (#139)
agusduha Nov 26, 2024
9476989
feat: add liquidity migrator contract with its unit test and interfac…
0xDiscotech Nov 27, 2024
b240094
feat: integrate system config with superchain config (#140)
agusduha Nov 27, 2024
3254d14
feat: manage dependency set on superchain config (#138)
0xDiscotech Nov 28, 2024
2c7d996
chore: add zero dependencies check (#142)
0xDiscotech Nov 28, 2024
7111d13
Merge branch 'develop' into fix/merge-conflict-lockbox
agusduha Nov 28, 2024
4a45ed2
fix: pre pr
agusduha Nov 28, 2024
cae605e
Merge pull request #143 from defi-wonderland/fix/merge-conflict-lockbox
agusduha Nov 28, 2024
37dccaf
feat: Add pause check (#145)
agusduha Nov 29, 2024
8bef762
Merge branch 'develop' into fix/merge-conflict-lockbox-2
agusduha Dec 9, 2024
036b1d5
fix: pre pr and interfaces imports
agusduha Dec 9, 2024
9163c9c
Merge pull request #147 from defi-wonderland/fix/merge-conflict-lockb…
agusduha Dec 9, 2024
6f5c86d
feat: add upgrader role to superchain config (#163)
agusduha Dec 19, 2024
85d49dc
feat: use superchain config lockbox in portal (#164)
agusduha Dec 19, 2024
078bb36
Merge branch 'develop' into fix/merge-conflict-lockbox-3
agusduha Dec 19, 2024
657c97b
fix: pre pr
agusduha Dec 19, 2024
36a8897
Merge pull request #165 from defi-wonderland/fix/merge-conflict-lockb…
agusduha Dec 20, 2024
3b9eba9
feat: liquidity migrator deployment (#166)
agusduha Dec 24, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var excludeContracts = []string{

// TODO: Interfaces that need to be fixed
"IInitializable", "IOptimismMintableERC20", "ILegacyMintableERC20",
"KontrolCheatsBase", "ISystemConfigInterop", "IResolvedDelegateProxy",
"KontrolCheatsBase", "IResolvedDelegateProxy",
}

type ContractDefinition struct {
Expand Down
29 changes: 22 additions & 7 deletions packages/contracts-bedrock/scripts/deploy/ChainAssertions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
import { IL2OutputOracle } from "src/L1/interfaces/IL2OutputOracle.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { ISharedLockbox } from "src/L1/interfaces/ISharedLockbox.sol";
import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol";
import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol";
import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol";
Expand Down Expand Up @@ -139,27 +140,26 @@ library ChainAssertions {
/// @notice Asserts that the SystemConfigInterop is setup correctly
function checkSystemConfigInterop(
Types.ContractSet memory _contracts,
Types.ContractSet memory _proxies,
DeployConfig _cfg,
bool _isProxy
)
internal
view
{
ISystemConfigInterop config = ISystemConfigInterop(_contracts.SystemConfig);
ISuperchainConfig superchainConfig = ISuperchainConfig(_proxies.SuperchainConfig);

console.log(
"Running chain assertions on the SystemConfigInterop %s at %s",
_isProxy ? "proxy" : "implementation",
address(config)
);

checkSystemConfig(_contracts, _cfg, _isProxy);
if (_isProxy) {
// TODO: this is not being set in the deployment, nor is a config value.
// Update this when it has an entry in hardhat.json
require(config.dependencyManager() == address(0), "CHECK-SCFGI-10");
} else {
require(config.dependencyManager() == address(0), "CHECK-SCFGI-20");
}

require(config.dependencyCounter() == 0, "CHECK-SCFGI-10");
require(config.SUPERCHAIN_CONFIG() == address(superchainConfig), "CHECK-SCFGI-20");
}

/// @notice Asserts that the L1CrossDomainMessenger is setup correctly
Expand Down Expand Up @@ -577,6 +577,21 @@ library ChainAssertions {
// TODO: Add assertions for blueprints and setters?
}

/// @notice Asserts that the SharedLockbox is setup correctly
function checkSharedLockbox(Types.ContractSet memory _contracts, bool _isProxy) internal view {
ISharedLockbox sharedLockbox = ISharedLockbox(_contracts.SharedLockbox);
ISuperchainConfig superchainConfig = ISuperchainConfig(_contracts.SuperchainConfig);

console.log(
"Running chain assertions on the SharedLockbox %s at %s",
_isProxy ? "proxy" : "implementation",
address(sharedLockbox)
);

require(address(sharedLockbox) != address(0), "CHECK-SLB-10");
require(sharedLockbox.SUPERCHAIN_CONFIG() == address(superchainConfig), "CHECK-SLB-20");
}

/// @dev Asserts that for a given contract the value of a storage slot at an offset is 1 or 0xff.
/// A call to `initialize` will set it to 1 and a call to _disableInitializers will set it to 0xff.
function assertInitializedSlotIsSet(address _contractAddress, uint256 _slot, uint256 _offset) internal view {
Expand Down
34 changes: 29 additions & 5 deletions packages/contracts-bedrock/scripts/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ contract Deploy is Deployer {
L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"),
ProtocolVersions: getAddress("ProtocolVersionsProxy"),
SuperchainConfig: getAddress("SuperchainConfigProxy"),
OPContractsManager: getAddress("OPContractsManager")
OPContractsManager: getAddress("OPContractsManager"),
SharedLockbox: getAddress("SharedLockboxProxy")
});
}

Expand All @@ -183,7 +184,8 @@ contract Deploy is Deployer {
L1ERC721Bridge: getAddress("L1ERC721Bridge"),
ProtocolVersions: getAddress("ProtocolVersions"),
SuperchainConfig: getAddress("SuperchainConfig"),
OPContractsManager: getAddress("OPContractsManager")
OPContractsManager: getAddress("OPContractsManager"),
SharedLockbox: getAddress("SharedLockbox")
});
}

Expand Down Expand Up @@ -222,16 +224,19 @@ contract Deploy is Deployer {
/// @notice Deploy a new OP Chain using an existing SuperchainConfig and ProtocolVersions
/// @param _superchainConfigProxy Address of the existing SuperchainConfig proxy
/// @param _protocolVersionsProxy Address of the existing ProtocolVersions proxy
/// @param _sharedLockboxProxy Address of the existing SharedLockbox proxy
/// @param _includeDump Whether to include a state dump after deployment
function runWithSuperchain(
address payable _superchainConfigProxy,
address payable _protocolVersionsProxy,
address payable _sharedLockboxProxy,
bool _includeDump
)
public
{
require(_superchainConfigProxy != address(0), "Deploy: must specify address for superchain config proxy");
require(_protocolVersionsProxy != address(0), "Deploy: must specify address for protocol versions proxy");
require(_sharedLockboxProxy != address(0), "Deploy: must specify address for shared lockbox proxy");

vm.chainId(cfg.l1ChainID());

Expand All @@ -245,6 +250,10 @@ contract Deploy is Deployer {
save("ProtocolVersions", pvProxy.implementation());
save("ProtocolVersionsProxy", _protocolVersionsProxy);

IProxy slProxy = IProxy(_sharedLockboxProxy);
save("SharedLockbox", slProxy.implementation());
save("SharedLockboxProxy", _sharedLockboxProxy);

_run(false);

if (_includeDump) {
Expand Down Expand Up @@ -324,9 +333,10 @@ contract Deploy is Deployer {
////////////////////////////////////////////////////////////////

/// @notice Deploy a full system with a new SuperchainConfig
/// The Superchain system has 2 singleton contracts which lie outside of an OP Chain:
/// The Superchain system has 3 singleton contracts which lie outside of an OP Chain:
/// 1. The SuperchainConfig contract
/// 2. The ProtocolVersions contract
/// 3. The SharedLockbox contract
function deploySuperchain() public {
console.log("Setting up Superchain");
DeploySuperchain ds = new DeploySuperchain();
Expand All @@ -348,11 +358,18 @@ contract Deploy is Deployer {
save("SuperchainConfig", address(dso.superchainConfigImpl()));
save("ProtocolVersionsProxy", address(dso.protocolVersionsProxy()));
save("ProtocolVersions", address(dso.protocolVersionsImpl()));
save("SharedLockboxProxy", address(dso.sharedLockboxProxy()));
save("SharedLockbox", address(dso.sharedLockboxImpl()));

// First run assertions for the ProtocolVersions and SuperchainConfig proxy contracts.
// First run assertions for the ProtocolVersions, SuperchainConfig and SharedLockbox proxy contracts.
Types.ContractSet memory contracts = _proxies();
ChainAssertions.checkProtocolVersions({ _contracts: contracts, _cfg: cfg, _isProxy: true });
ChainAssertions.checkSuperchainConfig({ _contracts: contracts, _cfg: cfg, _isProxy: true, _isPaused: false });
ChainAssertions.checkSharedLockbox({ _contracts: contracts, _isProxy: true });

// Then replace the SharedLockbox proxy with the implementation address and run assertions on it.
contracts.SharedLockbox = mustGetAddress("SharedLockbox");
ChainAssertions.checkSharedLockbox({ _contracts: contracts, _isProxy: false });

// Then replace the ProtocolVersions proxy with the implementation address and run assertions on it.
contracts.ProtocolVersions = mustGetAddress("ProtocolVersions");
Expand Down Expand Up @@ -384,6 +401,7 @@ contract Deploy is Deployer {
);
dii.set(dii.superchainConfigProxy.selector, mustGetAddress("SuperchainConfigProxy"));
dii.set(dii.protocolVersionsProxy.selector, mustGetAddress("ProtocolVersionsProxy"));
dii.set(dii.sharedLockboxProxy.selector, mustGetAddress("SharedLockboxProxy"));
dii.set(dii.salt.selector, _implSalt());

if (_isInterop) {
Expand Down Expand Up @@ -433,7 +451,13 @@ contract Deploy is Deployer {
_oracle: IPreimageOracle(address(dio.preimageOracleSingleton()))
});
if (_isInterop) {
ChainAssertions.checkSystemConfigInterop({ _contracts: contracts, _cfg: cfg, _isProxy: false });
Types.ContractSet memory proxies = _proxies();
ChainAssertions.checkSystemConfigInterop({
_contracts: contracts,
_proxies: proxies,
_cfg: cfg,
_isProxy: false
});
} else {
ChainAssertions.checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { LibString } from "@solady/utils/LibString.sol";
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol";
import { ISharedLockbox } from "src/L1/interfaces/ISharedLockbox.sol";

import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
Expand All @@ -26,7 +27,6 @@ import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol";
import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol";
import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol";

import { OPContractsManagerInterop } from "src/L1/OPContractsManagerInterop.sol";
import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol";
import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol";

Expand All @@ -53,6 +53,7 @@ contract DeployImplementationsInput is BaseDeployIO {
// Outputs from DeploySuperchain.s.sol.
ISuperchainConfig internal _superchainConfigProxy;
IProtocolVersions internal _protocolVersionsProxy;
ISharedLockbox internal _sharedLockboxProxy;

string internal _standardVersionsToml;

Expand Down Expand Up @@ -88,6 +89,7 @@ contract DeployImplementationsInput is BaseDeployIO {
require(_addr != address(0), "DeployImplementationsInput: cannot set zero address");
if (_sel == this.superchainConfigProxy.selector) _superchainConfigProxy = ISuperchainConfig(_addr);
else if (_sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = IProtocolVersions(_addr);
else if (_sel == this.sharedLockboxProxy.selector) _sharedLockboxProxy = ISharedLockbox(_addr);
else revert("DeployImplementationsInput: unknown selector");
}

Expand Down Expand Up @@ -153,6 +155,11 @@ contract DeployImplementationsInput is BaseDeployIO {
require(address(_protocolVersionsProxy) != address(0), "DeployImplementationsInput: not set");
return _protocolVersionsProxy;
}

function sharedLockboxProxy() public view returns (ISharedLockbox) {
require(address(_sharedLockboxProxy) != address(0), "DeployImplementationsInput: not set");
return _sharedLockboxProxy;
}
}

contract DeployImplementationsOutput is BaseDeployIO {
Expand Down Expand Up @@ -711,13 +718,15 @@ 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)
IOptimismPortal2.__constructor__,
(proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds, sharedLockbox)
)
)
})
Expand Down Expand Up @@ -916,64 +925,23 @@ contract DeployImplementations is Script {
// - `OptimismPortalInterop is OptimismPortal`: A different portal implementation is used, and
// it's ABI is the same.
// - `SystemConfigInterop is SystemConfig`: A different system config implementation is used, and
// it's initializer has a different signature. This signature is different because there is a
// new input parameter, the `dependencyManager`.
// - Because of the different system config initializer, there is a new input parameter (dependencyManager).
// it's constructor has a different signature. This signature is different because there is a
// new input parameter, the `superchainConfig`.
// - Because of the different system config constructor, there is a new input parameter (superchainConfig).
//
// Similar to how inheritance was used to develop the new portal and system config contracts, we use
// inheritance to modify up to all of the deployer contracts. For this interop example, what this
// means is we need:
// - An `OPContractsManagerInterop is OPContractsManager` that knows how to encode the calldata for the
// new system config initializer.
// - A `DeployImplementationsInterop is DeployImplementations` that:
// - Deploys OptimismPortalInterop instead of OptimismPortal.
// - Deploys SystemConfigInterop instead of SystemConfig.
// - Deploys OPContractsManagerInterop instead of OPContractsManager, which contains the updated logic
// for encoding the SystemConfig initializer.
// - Updates the OPCM release setter logic to use the updated initializer.
// - A `DeployOPChainInterop is DeployOPChain` that allows the updated input parameter to be passed.
//
// Most of the complexity in the above flow comes from the the new input for the updated SystemConfig
// initializer. If all function signatures were the same, all we'd have to change is the contract
// implementations that are deployed then set in the OPCM. For now, to simplify things until we
// resolve https://github.com/ethereum-optimism/optimism/issues/11783, we just assume this new role
// is the same as the proxy admin owner.
contract DeployImplementationsInterop is DeployImplementations {
function createOPCMContract(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio,
OPContractsManager.Blueprints memory _blueprints,
string memory _l1ContractsRelease
)
internal
virtual
override
returns (OPContractsManager opcm_)
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();

OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({
l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()),
optimismPortalImpl: address(_dio.optimismPortalImpl()),
systemConfigImpl: address(_dio.systemConfigImpl()),
optimismMintableERC20FactoryImpl: address(_dio.optimismMintableERC20FactoryImpl()),
l1CrossDomainMessengerImpl: address(_dio.l1CrossDomainMessengerImpl()),
l1StandardBridgeImpl: address(_dio.l1StandardBridgeImpl()),
disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()),
delayedWETHImpl: address(_dio.delayedWETHImpl()),
mipsImpl: address(_dio.mipsSingleton())
});

vm.broadcast(msg.sender);
opcm_ = new OPContractsManagerInterop(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
);

vm.label(address(opcm_), "OPContractsManager");
_dio.set(_dio.opcm.selector, address(opcm_));
}

function deployOptimismPortalImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
Expand All @@ -992,14 +960,15 @@ 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({
_name: "OptimismPortalInterop",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortalInterop.__constructor__,
(proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds)
(proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds, sharedLockbox)
)
)
})
Expand Down Expand Up @@ -1027,11 +996,14 @@ contract DeployImplementationsInterop is DeployImplementations {
if (existingImplementation != address(0)) {
impl = ISystemConfigInterop(existingImplementation);
} else {
address superchainConfig = address(_dii.superchainConfigProxy());
vm.broadcast(msg.sender);
impl = ISystemConfigInterop(
DeployUtils.create1({
_name: "SystemConfigInterop",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfigInterop.__constructor__, ()))
_args: DeployUtils.encodeConstructor(
abi.encodeCall(ISystemConfigInterop.__constructor__, (superchainConfig))
)
})
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ contract DeployOwnership is Deploy {
_save: this,
_salt: _implSalt(),
_name: "SuperchainConfig",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ()))
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, (address(0))))
})
);

Expand Down
Loading