Commit 2f2554af authored by Maurelian's avatar Maurelian Committed by GitHub

Add AnchorStateRegistry Implementation to OPSM (#11955)

* feat: Add ASR proxy to OPStackManager

* feat: Add AnchorStateRegistry blueprint

* feat: Add AnchorStateRegistry Implementation

* feat: Return startingAnchorInputs as bytes

The op-deployer tooling does not support structs, therefore we need to
return a more generic type for compatibility.

* rebuild snapshots

* fix: ASR initializer encoding

* handoff commit with op-deployer debugging

debugging op-deployer test
wip: literal anchor roots

* test and golang fixes

* hardcode permissioned state

* hardcode 0xdead as the starting anchor root

* chore: fix semver lock

* fix: no permissionless root, remove hash from 0xdead

* fix: use 0xdead root properly

* fix: set the override in the input contract

* Fix tests and accidental mutation of `Implementation` struct

* lint

* semver

* Update op-chain-ops/deployer/opsm/opchain.go
Co-authored-by: default avatarMaurelian <john@oplabs.co>

* Update packages/contracts-bedrock/scripts/DeployOPChain.s.sol

---------
Co-authored-by: default avatarMatthew Slipper <me@matthewslipper.com>
Co-authored-by: default avatarMatt Solomon <matt@mattsolomon.dev>
parent 6933bfea
...@@ -9,6 +9,12 @@ import ( ...@@ -9,6 +9,12 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum-optimism/optimism/op-chain-ops/script"
) )
// PermissionedGameStartingAnchorRoots is a root of bytes32(hex"dead") for the permissioned game at block 0,
// and no root for the permissionless game.
var PermissionedGameStartingAnchorRoots = []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xde, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}
type DeployOPChainInput struct { type DeployOPChainInput struct {
OpChainProxyAdminOwner common.Address OpChainProxyAdminOwner common.Address
SystemConfigOwner common.Address SystemConfigOwner common.Address
...@@ -27,6 +33,10 @@ func (input *DeployOPChainInput) InputSet() bool { ...@@ -27,6 +33,10 @@ func (input *DeployOPChainInput) InputSet() bool {
return true return true
} }
func (input *DeployOPChainInput) StartingAnchorRoots() []byte {
return PermissionedGameStartingAnchorRoots
}
type DeployOPChainOutput struct { type DeployOPChainOutput struct {
OpChainProxyAdmin common.Address OpChainProxyAdmin common.Address
AddressManager common.Address AddressManager common.Address
...@@ -65,6 +75,7 @@ func DeployOPChain(host *script.Host, input DeployOPChainInput) (DeployOPChainOu ...@@ -65,6 +75,7 @@ func DeployOPChain(host *script.Host, input DeployOPChainInput) (DeployOPChainOu
return dco, fmt.Errorf("failed to insert DeployOPChainInput precompile: %w", err) return dco, fmt.Errorf("failed to insert DeployOPChainInput precompile: %w", err)
} }
defer cleanupInput() defer cleanupInput()
host.Label(inputAddr, "DeployOPChainInput")
cleanupOutput, err := script.WithPrecompileAtAddress[*DeployOPChainOutput](host, outputAddr, &dco, cleanupOutput, err := script.WithPrecompileAtAddress[*DeployOPChainOutput](host, outputAddr, &dco,
script.WithFieldSetter[*DeployOPChainOutput]) script.WithFieldSetter[*DeployOPChainOutput])
...@@ -72,6 +83,7 @@ func DeployOPChain(host *script.Host, input DeployOPChainInput) (DeployOPChainOu ...@@ -72,6 +83,7 @@ func DeployOPChain(host *script.Host, input DeployOPChainInput) (DeployOPChainOu
return dco, fmt.Errorf("failed to insert DeployOPChainOutput precompile: %w", err) return dco, fmt.Errorf("failed to insert DeployOPChainOutput precompile: %w", err)
} }
defer cleanupOutput() defer cleanupOutput()
host.Label(outputAddr, "DeployOPChainOutput")
deployScript, cleanupDeploy, err := script.WithScript[DeployOPChainScript](host, "DeployOPChain.s.sol", "DeployOPChain") deployScript, cleanupDeploy, err := script.WithScript[DeployOPChainScript](host, "DeployOPChain.s.sol", "DeployOPChain")
if err != nil { if err != nil {
......
...@@ -617,14 +617,14 @@ contract DeployImplementations is Script { ...@@ -617,14 +617,14 @@ contract DeployImplementations is Script {
// The fault proofs contracts are configured as follows: // The fault proofs contracts are configured as follows:
// | Contract | Proxied | Deployment | MCP Ready | // | Contract | Proxied | Deployment | MCP Ready |
// |-------------------------|---------|-----------------------------------|------------| // |-------------------------|---------|-----------------------------------|------------|
// | DisputeGameFactory | Yes | Bespoke | Yes | // | DisputeGameFactory | Yes | Bespoke | Yes | X
// | AnchorStateRegistry | Yes | Bespoke | No | // | AnchorStateRegistry | Yes | Bespoke | No | X
// | FaultDisputeGame | No | Bespoke | No | // | FaultDisputeGame | No | Bespoke | No | Todo
// | PermissionedDisputeGame | No | Bespoke | No | // | PermissionedDisputeGame | No | Bespoke | No | Todo
// | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No | // | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No | Todo: Proxies.
// | PreimageOracle | No | Shared | N/A | // | PreimageOracle | No | Shared | N/A | X
// | MIPS | No | Shared | N/A | // | MIPS | No | Shared | N/A | X
// | OptimismPortal2 | Yes | Shared | No | // | OptimismPortal2 | Yes | Shared | No | X
// //
// This script only deploys the shared contracts. The bespoke contracts are deployed by // This script only deploys the shared contracts. The bespoke contracts are deployed by
// `DeployOPChain.s.sol`. When the shared contracts are proxied, the contracts deployed here are // `DeployOPChain.s.sol`. When the shared contracts are proxied, the contracts deployed here are
......
...@@ -15,6 +15,7 @@ import { Constants } from "src/libraries/Constants.sol"; ...@@ -15,6 +15,7 @@ import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
import { Proxy } from "src/universal/Proxy.sol";
import { AddressManager } from "src/legacy/AddressManager.sol"; import { AddressManager } from "src/legacy/AddressManager.sol";
import { DelayedWETH } from "src/dispute/DelayedWETH.sol"; import { DelayedWETH } from "src/dispute/DelayedWETH.sol";
...@@ -22,6 +23,7 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; ...@@ -22,6 +23,7 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol"; import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol"; import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol"; import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol";
import { GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
import { OPStackManager } from "src/L1/OPStackManager.sol"; import { OPStackManager } from "src/L1/OPStackManager.sol";
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol"; import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
...@@ -116,6 +118,26 @@ contract DeployOPChainInput is BaseDeployIO { ...@@ -116,6 +118,26 @@ contract DeployOPChainInput is BaseDeployIO {
return _l2ChainId; return _l2ChainId;
} }
function startingAnchorRoots() public pure returns (bytes memory) {
// WARNING: For now always hardcode the starting permissioned game anchor root to 0xdead,
// and we do not set anything for the permissioned game. This is because we currently only
// support deploying straight to permissioned games, and the starting root does not
// matter for that, as long as it is non-zero, since no games will be played. We do not
// deploy the permissionless game (and therefore do not set a starting root for it here)
// because to to update to the permissionless game, we will need to update its starting
// anchor root and deploy a new permissioned dispute game contract anyway.
//
// You can `console.logBytes(abi.encode(defaultStartingAnchorRoots))` to get the bytes that
// are hardcoded into `op-chain-ops/deployer/opsm/opchain.go`
AnchorStateRegistry.StartingAnchorRoot[] memory defaultStartingAnchorRoots =
new AnchorStateRegistry.StartingAnchorRoot[](1);
defaultStartingAnchorRoots[0] = AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.PERMISSIONED_CANNON,
outputRoot: OutputRoot({ root: Hash.wrap(bytes32(hex"dead")), l2BlockNumber: 0 })
});
return abi.encode(defaultStartingAnchorRoots);
}
// TODO: Check that opsm is proxied and it has an implementation. // TODO: Check that opsm is proxied and it has an implementation.
function opsmProxy() public view returns (OPStackManager) { function opsmProxy() public view returns (OPStackManager) {
require(address(_opsmProxy) != address(0), "DeployOPChainInput: not set"); require(address(_opsmProxy) != address(0), "DeployOPChainInput: not set");
...@@ -162,7 +184,7 @@ contract DeployOPChainOutput is BaseDeployIO { ...@@ -162,7 +184,7 @@ contract DeployOPChainOutput is BaseDeployIO {
// forgefmt: disable-end // forgefmt: disable-end
} }
function checkOutput(DeployOPChainInput _doi) public view { function checkOutput(DeployOPChainInput _doi) public {
// With 16 addresses, we'd get a stack too deep error if we tried to do this inline as a // With 16 addresses, we'd get a stack too deep error if we tried to do this inline as a
// single call to `Solarray.addresses`. So we split it into two calls. // single call to `Solarray.addresses`. So we split it into two calls.
address[] memory addrs1 = Solarray.addresses( address[] memory addrs1 = Solarray.addresses(
...@@ -266,7 +288,9 @@ contract DeployOPChainOutput is BaseDeployIO { ...@@ -266,7 +288,9 @@ contract DeployOPChainOutput is BaseDeployIO {
// -------- Deployment Assertions -------- // -------- Deployment Assertions --------
function assertValidDeploy(DeployOPChainInput _doi) internal view { function assertValidDeploy(DeployOPChainInput _doi) internal {
assertValidAnchorStateRegistryProxy(_doi);
assertValidAnchorStateRegistryImpl(_doi);
assertValidDelayedWETHs(_doi); assertValidDelayedWETHs(_doi);
assertValidDisputeGameFactory(_doi); assertValidDisputeGameFactory(_doi);
assertValidL1CrossDomainMessenger(_doi); assertValidL1CrossDomainMessenger(_doi);
...@@ -279,6 +303,32 @@ contract DeployOPChainOutput is BaseDeployIO { ...@@ -279,6 +303,32 @@ contract DeployOPChainOutput is BaseDeployIO {
// TODO add initialization assertions // TODO add initialization assertions
} }
function assertValidAnchorStateRegistryProxy(DeployOPChainInput) internal {
// First we check the proxy as itself.
Proxy proxy = Proxy(payable(address(anchorStateRegistryProxy())));
vm.prank(address(0));
address admin = proxy.admin();
require(admin == address(opChainProxyAdmin()), "ANCHORP-10");
// Then we check the proxy as ASR.
DeployUtils.assertInitialized({ _contractAddress: address(anchorStateRegistryProxy()), _slot: 0, _offset: 0 });
vm.prank(address(0));
address impl = proxy.implementation();
require(impl == address(anchorStateRegistryImpl()), "ANCHORP-20");
require(
address(anchorStateRegistryProxy().disputeGameFactory()) == address(disputeGameFactoryProxy()), "ANCHORP-30"
);
}
function assertValidAnchorStateRegistryImpl(DeployOPChainInput) internal view {
AnchorStateRegistry registry = anchorStateRegistryImpl();
DeployUtils.assertInitialized({ _contractAddress: address(registry), _slot: 0, _offset: 0 });
require(address(registry.disputeGameFactory()) == address(disputeGameFactoryProxy()), "ANCHORI-10");
}
function assertValidSystemConfig(DeployOPChainInput _doi) internal view { function assertValidSystemConfig(DeployOPChainInput _doi) internal view {
SystemConfig systemConfig = systemConfigProxy(); SystemConfig systemConfig = systemConfigProxy();
...@@ -412,7 +462,8 @@ contract DeployOPChain is Script { ...@@ -412,7 +462,8 @@ contract DeployOPChain is Script {
roles: roles, roles: roles,
basefeeScalar: _doi.basefeeScalar(), basefeeScalar: _doi.basefeeScalar(),
blobBasefeeScalar: _doi.blobBaseFeeScalar(), blobBasefeeScalar: _doi.blobBaseFeeScalar(),
l2ChainId: _doi.l2ChainId() l2ChainId: _doi.l2ChainId(),
startingAnchorRoots: _doi.startingAnchorRoots()
}); });
vm.broadcast(msg.sender); vm.broadcast(msg.sender);
......
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
"sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649"
}, },
"src/L1/OPStackManager.sol": { "src/L1/OPStackManager.sol": {
"initCodeHash": "0x022b3f6a80eb637972dd0d9ce8666a037c4b916889f44f86771d8c3add9d615d", "initCodeHash": "0x4bffecbd95e63f9bd04ab8e3c6a804cc25e0cd151ebeb7f8d6b9330332e6eb20",
"sourceCodeHash": "0xb085725e18c1a0cc1826b770e403ecad765fce686bb80555bf0f6c3c67b21cba" "sourceCodeHash": "0x850f1eacc77f1a5c680625196618bc4b4332cb68924d9eddd57c749bedcd7c94"
}, },
"src/L1/OptimismPortal.sol": { "src/L1/OptimismPortal.sol": {
"initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190",
......
...@@ -134,6 +134,11 @@ ...@@ -134,6 +134,11 @@
"internalType": "uint256", "internalType": "uint256",
"name": "l2ChainId", "name": "l2ChainId",
"type": "uint256" "type": "uint256"
},
{
"internalType": "bytes",
"name": "startingAnchorRoots",
"type": "bytes"
} }
], ],
"internalType": "struct OPStackManager.DeployInput", "internalType": "struct OPStackManager.DeployInput",
......
...@@ -134,6 +134,11 @@ ...@@ -134,6 +134,11 @@
"internalType": "uint256", "internalType": "uint256",
"name": "l2ChainId", "name": "l2ChainId",
"type": "uint256" "type": "uint256"
},
{
"internalType": "bytes",
"name": "startingAnchorRoots",
"type": "bytes"
} }
], ],
"internalType": "struct OPStackManager.DeployInput", "internalType": "struct OPStackManager.DeployInput",
......
...@@ -55,6 +55,9 @@ contract OPStackManager is ISemver, Initializable { ...@@ -55,6 +55,9 @@ contract OPStackManager is ISemver, Initializable {
uint32 basefeeScalar; uint32 basefeeScalar;
uint32 blobBasefeeScalar; uint32 blobBasefeeScalar;
uint256 l2ChainId; uint256 l2ChainId;
// The correct type is AnchorStateRegistry.StartingAnchorRoot[] memory,
// but OP Deployer does not yet support structs.
bytes startingAnchorRoots;
} }
/// @notice The full set of outputs from deploying a new OP Stack chain. /// @notice The full set of outputs from deploying a new OP Stack chain.
...@@ -115,8 +118,8 @@ contract OPStackManager is ISemver, Initializable { ...@@ -115,8 +118,8 @@ contract OPStackManager is ISemver, Initializable {
// -------- Constants and Variables -------- // -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.3 /// @custom:semver 1.0.0-beta.4
string public constant version = "1.0.0-beta.3"; string public constant version = "1.0.0-beta.4";
/// @notice Address of the SuperchainConfig contract shared by all chains. /// @notice Address of the SuperchainConfig contract shared by all chains.
SuperchainConfig public immutable superchainConfig; SuperchainConfig public immutable superchainConfig;
...@@ -206,8 +209,6 @@ contract OPStackManager is ISemver, Initializable { ...@@ -206,8 +209,6 @@ contract OPStackManager is ISemver, Initializable {
// -------- TODO: Placeholders -------- // -------- TODO: Placeholders --------
// For contracts we don't yet deploy, we set the outputs to dummy proxies so they have code to pass assertions. // For contracts we don't yet deploy, we set the outputs to dummy proxies so they have code to pass assertions.
// We do these first, that way the disputeGameFactoryProxy is set when passed to the SystemConfig input. // We do these first, that way the disputeGameFactoryProxy is set when passed to the SystemConfig input.
output.anchorStateRegistryProxy = AnchorStateRegistry(deployProxy(l2ChainId, output.opChainProxyAdmin, "3"));
output.anchorStateRegistryImpl = AnchorStateRegistry(deployProxy(l2ChainId, output.opChainProxyAdmin, "4"));
output.faultDisputeGame = FaultDisputeGame(deployProxy(l2ChainId, output.opChainProxyAdmin, "5")); output.faultDisputeGame = FaultDisputeGame(deployProxy(l2ChainId, output.opChainProxyAdmin, "5"));
output.permissionedDisputeGame = PermissionedDisputeGame(deployProxy(l2ChainId, output.opChainProxyAdmin, "6")); output.permissionedDisputeGame = PermissionedDisputeGame(deployProxy(l2ChainId, output.opChainProxyAdmin, "6"));
output.delayedWETHPermissionedGameProxy = output.delayedWETHPermissionedGameProxy =
...@@ -266,7 +267,7 @@ contract OPStackManager is ISemver, Initializable { ...@@ -266,7 +267,7 @@ contract OPStackManager is ISemver, Initializable {
); );
// -------- Set and Initialize Proxy Implementations -------- // -------- Set and Initialize Proxy Implementations --------
Implementation storage impl; Implementation memory impl;
bytes memory data; bytes memory data;
impl = getLatestImplementation("L1ERC721Bridge"); impl = getLatestImplementation("L1ERC721Bridge");
...@@ -293,10 +294,16 @@ contract OPStackManager is ISemver, Initializable { ...@@ -293,10 +294,16 @@ contract OPStackManager is ISemver, Initializable {
data = encodeL1StandardBridgeInitializer(impl.initializer, output); data = encodeL1StandardBridgeInitializer(impl.initializer, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), impl.logic, data); upgradeAndCall(output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), impl.logic, data);
// TODO: also call setImplementation() once the dispute games are deployed.
impl = getLatestImplementation("DisputeGameFactory"); impl = getLatestImplementation("DisputeGameFactory");
data = encodeDisputeGameFactoryInitializer(impl.initializer, _input); data = encodeDisputeGameFactoryInitializer(impl.initializer, _input);
upgradeAndCall(output.opChainProxyAdmin, address(output.disputeGameFactoryProxy), impl.logic, data); upgradeAndCall(output.opChainProxyAdmin, address(output.disputeGameFactoryProxy), impl.logic, data);
impl.logic = address(output.anchorStateRegistryImpl);
impl.initializer = AnchorStateRegistry.initialize.selector;
data = encodeAnchorStateRegistryInitializer(impl.initializer, _input);
upgradeAndCall(output.opChainProxyAdmin, address(output.anchorStateRegistryProxy), impl.logic, data);
// -------- Finalize Deployment -------- // -------- Finalize Deployment --------
// Transfer ownership of the ProxyAdmin from this contract to the specified owner. // Transfer ownership of the ProxyAdmin from this contract to the specified owner.
output.opChainProxyAdmin.transferOwnership(_input.roles.opChainProxyAdminOwner); output.opChainProxyAdmin.transferOwnership(_input.roles.opChainProxyAdminOwner);
...@@ -345,9 +352,11 @@ contract OPStackManager is ISemver, Initializable { ...@@ -345,9 +352,11 @@ contract OPStackManager is ISemver, Initializable {
return Blueprint.deployFrom(blueprint.proxy, salt, abi.encode(_proxyAdmin)); return Blueprint.deployFrom(blueprint.proxy, salt, abi.encode(_proxyAdmin));
} }
/// @notice Returns the implementation data for a contract name. /// @notice Returns the implementation data for a contract name. Makes a copy of the internal
function getLatestImplementation(string memory _name) internal view returns (Implementation storage) { // Implementation struct in storage to prevent accidental mutation of the internal data.
return implementations[latestRelease][_name]; function getLatestImplementation(string memory _name) internal view returns (Implementation memory) {
Implementation storage impl = implementations[latestRelease][_name];
return Implementation({ logic: impl.logic, initializer: impl.initializer });
} }
// -------- Initializer Encoding -------- // -------- Initializer Encoding --------
...@@ -464,6 +473,21 @@ contract OPStackManager is ISemver, Initializable { ...@@ -464,6 +473,21 @@ contract OPStackManager is ISemver, Initializable {
return abi.encodeWithSelector(_selector, _input.roles.opChainProxyAdminOwner); return abi.encodeWithSelector(_selector, _input.roles.opChainProxyAdminOwner);
} }
function encodeAnchorStateRegistryInitializer(
bytes4 _selector,
DeployInput memory _input
)
internal
view
virtual
returns (bytes memory)
{
// this line fails in the op-deployer tests because it is not passing in any data
AnchorStateRegistry.StartingAnchorRoot[] memory startingAnchorRoots =
abi.decode(_input.startingAnchorRoots, (AnchorStateRegistry.StartingAnchorRoot[]));
return abi.encodeWithSelector(_selector, startingAnchorRoots, superchainConfig);
}
/// @notice Returns default, standard config arguments for the SystemConfig initializer. /// @notice Returns default, standard config arguments for the SystemConfig initializer.
/// This is used by subclasses to reduce code duplication. /// This is used by subclasses to reduce code duplication.
function defaultSystemConfigParams( function defaultSystemConfigParams(
......
...@@ -31,6 +31,8 @@ import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol"; ...@@ -31,6 +31,8 @@ import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol";
import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
import { GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
contract DeployOPChainInput_Test is Test { contract DeployOPChainInput_Test is Test {
DeployOPChainInput doi; DeployOPChainInput doi;
...@@ -336,9 +338,29 @@ contract DeployOPChain_TestBase is Test { ...@@ -336,9 +338,29 @@ contract DeployOPChain_TestBase is Test {
uint32 basefeeScalar = 100; uint32 basefeeScalar = 100;
uint32 blobBaseFeeScalar = 200; uint32 blobBaseFeeScalar = 200;
uint256 l2ChainId = 300; uint256 l2ChainId = 300;
AnchorStateRegistry.StartingAnchorRoot[] startingAnchorRoots;
OPStackManager opsm = OPStackManager(address(0)); OPStackManager opsm = OPStackManager(address(0));
function setUp() public virtual { function setUp() public virtual {
// Set defaults for reference types
uint256 cannonBlock = 400;
uint256 permissionedBlock = 500;
startingAnchorRoots.push(
AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.CANNON,
outputRoot: OutputRoot({ root: Hash.wrap(keccak256("defaultOutputRootCannon")), l2BlockNumber: cannonBlock })
})
);
startingAnchorRoots.push(
AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.PERMISSIONED_CANNON,
outputRoot: OutputRoot({
root: Hash.wrap(keccak256("defaultOutputRootPermissioned")),
l2BlockNumber: permissionedBlock
})
})
);
// Initialize deploy scripts. // Initialize deploy scripts.
DeploySuperchain deploySuperchain = new DeploySuperchain(); DeploySuperchain deploySuperchain = new DeploySuperchain();
(DeploySuperchainInput dsi, DeploySuperchainOutput dso) = deploySuperchain.etchIOContracts(); (DeploySuperchainInput dsi, DeploySuperchainOutput dso) = deploySuperchain.etchIOContracts();
...@@ -389,7 +411,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { ...@@ -389,7 +411,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
return keccak256(abi.encode(_seed, _i)); return keccak256(abi.encode(_seed, _i));
} }
function testFuzz_run_memory_succeeds(bytes32 _seed) public { function testFuzz_run_memory_succeed(bytes32 _seed) public {
opChainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0)))); opChainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0))));
systemConfigOwner = address(uint160(uint256(hash(_seed, 1)))); systemConfigOwner = address(uint160(uint256(hash(_seed, 1))));
batcher = address(uint160(uint256(hash(_seed, 2)))); batcher = address(uint160(uint256(hash(_seed, 2))));
...@@ -398,7 +420,26 @@ contract DeployOPChain_Test is DeployOPChain_TestBase { ...@@ -398,7 +420,26 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
challenger = address(uint160(uint256(hash(_seed, 5)))); challenger = address(uint160(uint256(hash(_seed, 5))));
basefeeScalar = uint32(uint256(hash(_seed, 6))); basefeeScalar = uint32(uint256(hash(_seed, 6)));
blobBaseFeeScalar = uint32(uint256(hash(_seed, 7))); blobBaseFeeScalar = uint32(uint256(hash(_seed, 7)));
l2ChainId = uint256(uint256(hash(_seed, 8))); l2ChainId = uint256(hash(_seed, 8));
// Set the initial anchor states. The typical usage we expect is to pass in one root per game type.
uint256 cannonBlock = uint256(hash(_seed, 9));
uint256 permissionedBlock = uint256(hash(_seed, 10));
startingAnchorRoots.push(
AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.CANNON,
outputRoot: OutputRoot({ root: Hash.wrap(keccak256(abi.encode(_seed, 11))), l2BlockNumber: cannonBlock })
})
);
startingAnchorRoots.push(
AnchorStateRegistry.StartingAnchorRoot({
gameType: GameTypes.PERMISSIONED_CANNON,
outputRoot: OutputRoot({
root: Hash.wrap(keccak256(abi.encode(_seed, 12))),
l2BlockNumber: permissionedBlock
})
})
);
doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner); doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner);
doi.set(doi.systemConfigOwner.selector, systemConfigOwner); doi.set(doi.systemConfigOwner.selector, systemConfigOwner);
......
...@@ -62,7 +62,8 @@ contract OPStackManager_Deploy_Test is DeployOPChain_TestBase { ...@@ -62,7 +62,8 @@ contract OPStackManager_Deploy_Test is DeployOPChain_TestBase {
}), }),
basefeeScalar: _doi.basefeeScalar(), basefeeScalar: _doi.basefeeScalar(),
blobBasefeeScalar: _doi.blobBaseFeeScalar(), blobBasefeeScalar: _doi.blobBaseFeeScalar(),
l2ChainId: _doi.l2ChainId() l2ChainId: _doi.l2ChainId(),
startingAnchorRoots: _doi.startingAnchorRoots()
}); });
} }
......
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