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

contracts: system config standard L2 genesis #12308

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -1018,7 +1018,7 @@ func (d *L1Deployments) Check(deployConfig *DeployConfig) error {
continue
}
if deployConfig.UseFaultProofs &&
(name == "OptimismPortal") {
(name == "OptimismPortal" || name == "L2OutputOracle" || name == "L2OutputOracleProxy") {
continue
}
if !deployConfig.UseAltDA &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -515,9 +515,10 @@ library ChainAssertions {
/// @dev Asserts that for a given contract the value of a storage slot at an offset is 1.
function assertSlotValueIsOne(address _contractAddress, uint256 _slot, uint256 _offset) internal view {
bytes32 slotVal = vm.load(_contractAddress, bytes32(_slot));
uint8 val = uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF);
require(
uint8((uint256(slotVal) >> (_offset * 8)) & 0xFF) == uint8(1),
"Storage value is not 1 at the given slot and offset"
val == uint8(1) || val == uint8(0xff),
"Storage value is not 1 or 0xff at the given slot and offset"
);
}
}
211 changes: 99 additions & 112 deletions packages/contracts-bedrock/scripts/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -263,19 +263,6 @@ contract Deploy is Deployer {
// Deploy Current OPChain Contracts
deployOpChain();

// Deploy and setup the legacy (pre-faultproofs) contracts
deployERC1967Proxy("L2OutputOracleProxy");
deployL2OutputOracle();
initializeL2OutputOracle();

// The OptimismPortalProxy contract is used both with and without Fault Proofs enabled, and is deployed by
// deployOPChain. So we only need to deploy the legacy OptimismPortal implementation and initialize with it
// when Fault Proofs are disabled.
if (!cfg.useFaultProofs()) {
deployOptimismPortal();
initializeOptimismPortal();
}

if (cfg.useAltDA()) {
bytes32 typeHash = keccak256(bytes(cfg.daCommitmentType()));
bytes32 keccakHash = keccak256(bytes("KeccakCommitment"));
Expand Down Expand Up @@ -361,6 +348,13 @@ contract Deploy is Deployer {

deployAnchorStateRegistry();

// Deploy and setup the legacy (pre-faultproofs) contracts
if (!cfg.useFaultProofs()) {
deployERC1967Proxy("L2OutputOracleProxy");
deployL2OutputOracle();
initializeL2OutputOracle();
}

initializeOpChain();

setAlphabetFaultGameImplementation({ _allowUpgrade: false });
Expand All @@ -381,9 +375,9 @@ contract Deploy is Deployer {
deploySystemConfig();
deployL1StandardBridge();
deployL1ERC721Bridge();
deployOptimismPortal();

// Fault proofs
deployOptimismPortal2();
deployDisputeGameFactory();
deployDelayedWETH();
deployPreimageOracle();
Expand Down Expand Up @@ -412,13 +406,8 @@ contract Deploy is Deployer {
/// initialize function
function initializeOpChain() public {
console.log("Initializing Op Chain proxies");
// The OptimismPortal Proxy is shared between the legacy and current deployment path, so we should initialize
// the OptimismPortal2 only if using FaultProofs.
if (cfg.useFaultProofs()) {
console.log("Fault proofs enabled. Initializing the OptimismPortal proxy with the OptimismPortal2.");
initializeOptimismPortal2();
}

initializeOptimismPortal();
initializeSystemConfig();
initializeL1StandardBridge();
initializeL1ERC721Bridge();
Expand Down Expand Up @@ -621,50 +610,49 @@ contract Deploy is Deployer {

/// @notice Deploy the OptimismPortal
function deployOptimismPortal() public broadcast returns (address addr_) {
if (cfg.useInterop()) {
console.log("Attempting to deploy OptimismPortal with interop, this config is a noop");
}

addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismPortal.__constructor__, ()))
});

// Override the `OptimismPortal` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.OptimismPortal = addr_;
ChainAssertions.checkOptimismPortal({ _contracts: contracts, _cfg: cfg, _isProxy: false });
}

/// @notice Deploy the OptimismPortal2
function deployOptimismPortal2() public broadcast returns (address addr_) {
// Could also verify this inside DeployConfig but doing it here is a bit more reliable.
require(
uint32(cfg.respectedGameType()) == cfg.respectedGameType(), "Deploy: respectedGameType must fit into uint32"
);
if (cfg.useFaultProofs()) {
// Could also verify this inside DeployConfig but doing it here is a bit more reliable.
require(
uint32(cfg.respectedGameType()) == cfg.respectedGameType(), "Deploy: respectedGameType must fit into uint32"
);

addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal2",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortal2.__constructor__,
(cfg.proofMaturityDelaySeconds(), cfg.disputeGameFinalityDelaySeconds())
addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal2",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortal2.__constructor__,
(cfg.proofMaturityDelaySeconds(), cfg.disputeGameFinalityDelaySeconds())
)
)
)
});
});

// Override the `OptimismPortal2` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal2` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.OptimismPortal2 = addr_;
ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
} else {
if (cfg.useInterop()) {
console.log("Attempting to deploy OptimismPortal with interop, this config is a noop");
}

// Override the `OptimismPortal2` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal2` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.OptimismPortal2 = addr_;
ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismPortal.__constructor__, ()))
});

// Override the `OptimismPortal` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxiesUnstrict();
contracts.OptimismPortal = addr_;
ChainAssertions.checkOptimismPortal({ _contracts: contracts, _cfg: cfg, _isProxy: false });
}
}

/// @notice Deploy the OptimismPortalInterop contract
Expand Down Expand Up @@ -1279,63 +1267,62 @@ contract Deploy is Deployer {

/// @notice Initialize the OptimismPortal
function initializeOptimismPortal() public broadcast {
console.log("Upgrading and initializing OptimismPortal proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
address optimismPortal = mustGetAddress("OptimismPortal");
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal,
_data: abi.encodeCall(
IOptimismPortal.initialize,
(
IL2OutputOracle(l2OutputOracleProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy)
if (cfg.useFaultProofs()) {
console.log("Upgrading and initializing OptimismPortal2 proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
address optimismPortal2 = mustGetAddress("OptimismPortal2");
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal2,
_data: abi.encodeCall(
IOptimismPortal2.initialize,
(
IDisputeGameFactory(disputeGameFactoryProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy),
GameType.wrap(uint32(cfg.respectedGameType()))
)
)
)
});

IOptimismPortal portal = IOptimismPortal(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal version: %s", version);

ChainAssertions.checkOptimismPortal({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true });
}
});

/// @notice Initialize the OptimismPortal2
function initializeOptimismPortal2() public broadcast {
console.log("Upgrading and initializing OptimismPortal2 proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
address optimismPortal2 = mustGetAddress("OptimismPortal2");
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
IOptimismPortal2 portal = IOptimismPortal2(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal2 version: %s", version);

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal2,
_data: abi.encodeCall(
IOptimismPortal2.initialize,
(
IDisputeGameFactory(disputeGameFactoryProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy),
GameType.wrap(uint32(cfg.respectedGameType()))
ChainAssertions.checkOptimismPortal2({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true });
} else {
console.log("Upgrading and initializing OptimismPortal proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
address optimismPortal = mustGetAddress("OptimismPortal");
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal,
_data: abi.encodeCall(
IOptimismPortal.initialize,
(
IL2OutputOracle(l2OutputOracleProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy)
)
)
)
});
});

IOptimismPortal2 portal = IOptimismPortal2(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal2 version: %s", version);
IOptimismPortal portal = IOptimismPortal(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal version: %s", version);

ChainAssertions.checkOptimismPortal2({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true });
ChainAssertions.checkOptimismPortal({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true });
}
}

/// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner
Expand Down
14 changes: 7 additions & 7 deletions packages/contracts-bedrock/src/L1/OptimismPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -572,17 +572,17 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);
}

/// @notice Sets the gas paying token for the L2 system. This token is used as the
/// L2 native asset. Only the SystemConfig contract can call this function.
function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external {
/// @notice Sets configuration options for the L2 system.
/// @param _type Type of configuration to set.
/// @param _value Encoded value of the configuration.
function setConfig(Types.ConfigType _type, bytes memory _value) external {
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`.
// This value must be large enough to cover the cost of calling `L1Block.setConfig`.
useGas(SYSTEM_DEPOSIT_GAS_LIMIT);

// Emit the special deposit transaction directly that sets the gas paying
// token in the L1Block predeploy contract.
// Emit the special deposit transaction directly that sets the config in the L1Block predeploy contract.
emit TransactionDeposited(
Constants.DEPOSITOR_ACCOUNT,
Predeploys.L1_BLOCK_ATTRIBUTES,
Expand All @@ -592,7 +592,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
uint256(0), // value
uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit
false, // isCreation,
abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol))
abi.encodeCall(IL1Block.setConfig, (_type, _value))
)
);
}
Expand Down
14 changes: 7 additions & 7 deletions packages/contracts-bedrock/src/L1/OptimismPortal2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -586,17 +586,17 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
emit TransactionDeposited(from, _to, DEPOSIT_VERSION, opaqueData);
}

/// @notice Sets the gas paying token for the L2 system. This token is used as the
/// L2 native asset. Only the SystemConfig contract can call this function.
function setGasPayingToken(address _token, uint8 _decimals, bytes32 _name, bytes32 _symbol) external {
/// @notice Sets configuration options for the L2 system.
/// @param _type Type of configuration to set.
/// @param _value Encoded value of the configuration.
function setConfig(Types.ConfigType _type, bytes memory _value) external virtual {
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`.
// This value must be large enough to cover the cost of calling `L1Block.setConfig`.
useGas(SYSTEM_DEPOSIT_GAS_LIMIT);

// Emit the special deposit transaction directly that sets the gas paying
// token in the L1Block predeploy contract.
// Emit the special deposit transaction directly that sets the config in the L1Block predeploy contract.
emit TransactionDeposited(
Constants.DEPOSITOR_ACCOUNT,
Predeploys.L1_BLOCK_ATTRIBUTES,
Expand All @@ -606,7 +606,7 @@ contract OptimismPortal2 is Initializable, ResourceMetering, ISemver {
uint256(0), // value
uint64(SYSTEM_DEPOSIT_GAS_LIMIT), // gasLimit
false, // isCreation,
abi.encodeCall(IL1Block.setGasPayingToken, (_token, _decimals, _name, _symbol))
abi.encodeCall(IL1Block.setConfig, (_type, _value))
)
);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/contracts-bedrock/src/L1/OptimismPortalInterop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ pragma solidity 0.8.15;

// Contracts
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
import { L1BlockInterop, ConfigType } from "src/L2/L1BlockInterop.sol";
import { L1BlockInterop } from "src/L2/L1BlockInterop.sol";

// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Types } from "src/libraries/Types.sol";
import { Constants } from "src/libraries/Constants.sol";
import "src/libraries/PortalErrors.sol";

Expand All @@ -31,7 +32,7 @@ contract OptimismPortalInterop is OptimismPortal2 {
/// @notice Sets static configuration options for the L2 system.
/// @param _type Type of configuration to set.
/// @param _value Encoded value of the configuration.
function setConfig(ConfigType _type, bytes memory _value) external {
function setConfig(Types.ConfigType _type, bytes memory _value) external override {
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.
Expand Down
Loading