Commit 28283a92 authored by Blaine Malone's avatar Blaine Malone Committed by GitHub

Configurable Dispute Game Parameters (#12228)

* Configurable Dispute Game Parameters

* fix: more assertions for DeployOPChain.t.sol.

* fix: running pre-pr command.

* fix: changing dispute game types.

* fix: semver lock file change.

* fix: uint64 for maxGameDepth and splitDepth on go side.

* fix: safe casting in solidity
parent 40a70bda
......@@ -36,6 +36,13 @@ type DeployOPChainInput struct {
OpcmProxy common.Address
SaltMixer string
GasLimit uint64
DisputeGameType uint32
DisputeAbsolutePrestate common.Hash
DisputeMaxGameDepth uint64
DisputeSplitDepth uint64
DisputeClockExtension uint64
DisputeMaxClockDuration uint64
}
func (input *DeployOPChainInput) InputSet() bool {
......@@ -119,13 +126,19 @@ type opcmRoles struct {
// opcmDeployInput is the input struct for the deploy method of the OPStackManager contract. We
// define a separate struct here to match what the OPSM contract expects.
type opcmDeployInput struct {
Roles opcmRoles
BasefeeScalar uint32
BlobBasefeeScalar uint32
L2ChainId *big.Int
StartingAnchorRoots []byte
SaltMixer string
GasLimit uint64
Roles opcmRoles
BasefeeScalar uint32
BlobBasefeeScalar uint32
L2ChainId *big.Int
StartingAnchorRoots []byte
SaltMixer string
GasLimit uint64
DisputeGameType uint32
DisputeAbsolutePrestate common.Hash
DisputeMaxGameDepth *big.Int
DisputeSplitDepth *big.Int
DisputeClockExtension uint64
DisputeMaxClockDuration uint64
}
// decodeOutputABIJSON defines an ABI for a fake method called "decodeOutput" that returns the
......@@ -240,12 +253,18 @@ func DeployOPChainRaw(
Proposer: input.Proposer,
Challenger: input.Challenger,
},
BasefeeScalar: input.BasefeeScalar,
BlobBasefeeScalar: input.BlobBaseFeeScalar,
L2ChainId: input.L2ChainId,
StartingAnchorRoots: input.StartingAnchorRoots(),
SaltMixer: input.SaltMixer,
GasLimit: input.GasLimit,
BasefeeScalar: input.BasefeeScalar,
BlobBasefeeScalar: input.BlobBaseFeeScalar,
L2ChainId: input.L2ChainId,
StartingAnchorRoots: input.StartingAnchorRoots(),
SaltMixer: input.SaltMixer,
GasLimit: input.GasLimit,
DisputeGameType: input.DisputeGameType,
DisputeAbsolutePrestate: input.DisputeAbsolutePrestate,
DisputeMaxGameDepth: new(big.Int).SetUint64(input.DisputeMaxGameDepth),
DisputeSplitDepth: new(big.Int).SetUint64(input.DisputeSplitDepth),
DisputeClockExtension: input.DisputeClockExtension,
DisputeMaxClockDuration: input.DisputeMaxClockDuration,
})
if err != nil {
return out, fmt.Errorf("failed to pack deploy input: %w", err)
......
......@@ -29,18 +29,24 @@ func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs,
}
input := opcm.DeployOPChainInput{
OpChainProxyAdminOwner: thisIntent.Roles.ProxyAdminOwner,
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner,
Batcher: thisIntent.Roles.Batcher,
UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner,
Proposer: thisIntent.Roles.Proposer,
Challenger: thisIntent.Roles.Challenger,
BasefeeScalar: 1368,
BlobBaseFeeScalar: 801949,
L2ChainId: chainID.Big(),
OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress,
SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization
GasLimit: 30_000_000, // TODO: make this configurable
OpChainProxyAdminOwner: thisIntent.Roles.ProxyAdminOwner,
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner,
Batcher: thisIntent.Roles.Batcher,
UnsafeBlockSigner: thisIntent.Roles.UnsafeBlockSigner,
Proposer: thisIntent.Roles.Proposer,
Challenger: thisIntent.Roles.Challenger,
BasefeeScalar: 1368,
BlobBaseFeeScalar: 801949,
L2ChainId: chainID.Big(),
OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress,
SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization
GasLimit: 30_000_000,
DisputeGameType: 1, // PERMISSIONED_CANNON Game Type
DisputeAbsolutePrestate: common.HexToHash("0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c"),
DisputeMaxGameDepth: 73,
DisputeSplitDepth: 30,
DisputeClockExtension: 10800, // 3 hours (input in seconds)
DisputeMaxClockDuration: 302400, // 3.5 days (input in seconds)
}
var dco opcm.DeployOPChainOutput
......
......@@ -75,9 +75,15 @@ type L2Config struct {
Challenger common.Address
SystemConfigOwner common.Address
genesis.L2InitializationConfig
Prefund map[common.Address]*big.Int
SaltMixer string
GasLimit uint64
Prefund map[common.Address]*big.Int
SaltMixer string
GasLimit uint64
DisputeGameType uint32
DisputeAbsolutePrestate common.Hash
DisputeMaxGameDepth uint64
DisputeSplitDepth uint64
DisputeClockExtension uint64
DisputeMaxClockDuration uint64
}
func (c *L2Config) Check(log log.Logger) error {
......
......@@ -197,18 +197,24 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
l1Host.SetTxOrigin(cfg.Deployer)
output, err := opcm.DeployOPChain(l1Host, opcm.DeployOPChainInput{
OpChainProxyAdminOwner: cfg.ProxyAdminOwner,
SystemConfigOwner: cfg.SystemConfigOwner,
Batcher: cfg.BatchSenderAddress,
UnsafeBlockSigner: cfg.P2PSequencerAddress,
Proposer: cfg.Proposer,
Challenger: cfg.Challenger,
BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar,
BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar,
L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID),
OpcmProxy: superDeployment.OpcmProxy,
SaltMixer: cfg.SaltMixer,
GasLimit: cfg.GasLimit,
OpChainProxyAdminOwner: cfg.ProxyAdminOwner,
SystemConfigOwner: cfg.SystemConfigOwner,
Batcher: cfg.BatchSenderAddress,
UnsafeBlockSigner: cfg.P2PSequencerAddress,
Proposer: cfg.Proposer,
Challenger: cfg.Challenger,
BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar,
BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar,
L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID),
OpcmProxy: superDeployment.OpcmProxy,
SaltMixer: cfg.SaltMixer,
GasLimit: cfg.GasLimit,
DisputeGameType: cfg.DisputeGameType,
DisputeAbsolutePrestate: cfg.DisputeAbsolutePrestate,
DisputeMaxGameDepth: cfg.DisputeMaxGameDepth,
DisputeSplitDepth: cfg.DisputeSplitDepth,
DisputeClockExtension: cfg.DisputeClockExtension,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration,
})
if err != nil {
return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err)
......
......@@ -249,9 +249,15 @@ func InteropL2DevConfig(l1ChainID, l2ChainID uint64, addrs devkeys.Addresses) (*
UseAltDA: false,
},
},
Prefund: make(map[common.Address]*big.Int),
SaltMixer: "",
GasLimit: 30_000_000,
Prefund: make(map[common.Address]*big.Int),
SaltMixer: "",
GasLimit: 30_000_000,
DisputeGameType: 1, // PERMISSIONED_CANNON Game Type
DisputeAbsolutePrestate: common.HexToHash("0x038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c"),
DisputeMaxGameDepth: 73,
DisputeSplitDepth: 30,
DisputeClockExtension: 10800, // 3 hours (input in seconds)
DisputeMaxClockDuration: 302400, // 3.5 days (input in seconds)
}
// TODO(#11887): consider making the number of prefunded keys configurable.
......
......@@ -24,7 +24,7 @@ import { IDisputeGameFactory } from "src/dispute/interfaces/IDisputeGameFactory.
import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol";
import { IFaultDisputeGame } from "src/dispute/interfaces/IFaultDisputeGame.sol";
import { IPermissionedDisputeGame } from "src/dispute/interfaces/IPermissionedDisputeGame.sol";
import { Claim, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
import { Claim, Duration, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
import { OPContractsManager } from "src/L1/OPContractsManager.sol";
import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol";
......@@ -50,6 +50,14 @@ contract DeployOPChainInput is BaseDeployIO {
string internal _saltMixer;
uint64 internal _gasLimit;
// Configurable dispute game inputs
GameType internal _disputeGameType;
Claim internal _disputeAbsolutePrestate;
uint256 internal _disputeMaxGameDepth;
uint256 internal _disputeSplitDepth;
Duration internal _disputeClockExtension;
Duration internal _disputeMaxClockDuration;
function set(bytes4 _sel, address _addr) public {
require(_addr != address(0), "DeployOPChainInput: cannot set zero address");
if (_sel == this.opChainProxyAdminOwner.selector) _opChainProxyAdminOwner = _addr;
......@@ -72,6 +80,16 @@ contract DeployOPChainInput is BaseDeployIO {
_l2ChainId = _value;
} else if (_sel == this.gasLimit.selector) {
_gasLimit = SafeCast.toUint64(_value);
} else if (_sel == this.disputeGameType.selector) {
_disputeGameType = GameType.wrap(SafeCast.toUint32(_value));
} else if (_sel == this.disputeMaxGameDepth.selector) {
_disputeMaxGameDepth = SafeCast.toUint64(_value);
} else if (_sel == this.disputeSplitDepth.selector) {
_disputeSplitDepth = SafeCast.toUint64(_value);
} else if (_sel == this.disputeClockExtension.selector) {
_disputeClockExtension = Duration.wrap(SafeCast.toUint64(_value));
} else if (_sel == this.disputeMaxClockDuration.selector) {
_disputeMaxClockDuration = Duration.wrap(SafeCast.toUint64(_value));
} else {
revert("DeployOPChainInput: unknown selector");
}
......@@ -83,6 +101,11 @@ contract DeployOPChainInput is BaseDeployIO {
else revert("DeployOPChainInput: unknown selector");
}
function set(bytes4 _sel, bytes32 _value) public {
if (_sel == this.disputeAbsolutePrestate.selector) _disputeAbsolutePrestate = Claim.wrap(_value);
else revert("DeployImplementationsInput: unknown selector");
}
function opChainProxyAdminOwner() public view returns (address) {
require(_opChainProxyAdminOwner != address(0), "DeployOPChainInput: not set");
return _opChainProxyAdminOwner;
......@@ -163,6 +186,30 @@ contract DeployOPChainInput is BaseDeployIO {
function gasLimit() public view returns (uint64) {
return _gasLimit;
}
function disputeGameType() public view returns (GameType) {
return _disputeGameType;
}
function disputeAbsolutePrestate() public view returns (Claim) {
return _disputeAbsolutePrestate;
}
function disputeMaxGameDepth() public view returns (uint256) {
return _disputeMaxGameDepth;
}
function disputeSplitDepth() public view returns (uint256) {
return _disputeSplitDepth;
}
function disputeClockExtension() public view returns (Duration) {
return _disputeClockExtension;
}
function disputeMaxClockDuration() public view returns (Duration) {
return _disputeMaxClockDuration;
}
}
contract DeployOPChainOutput is BaseDeployIO {
......@@ -522,7 +569,13 @@ contract DeployOPChain is Script {
l2ChainId: _doi.l2ChainId(),
startingAnchorRoots: _doi.startingAnchorRoots(),
saltMixer: _doi.saltMixer(),
gasLimit: _doi.gasLimit()
gasLimit: _doi.gasLimit(),
disputeGameType: _doi.disputeGameType(),
disputeAbsolutePrestate: _doi.disputeAbsolutePrestate(),
disputeMaxGameDepth: _doi.disputeMaxGameDepth(),
disputeSplitDepth: _doi.disputeSplitDepth(),
disputeClockExtension: _doi.disputeClockExtension(),
disputeMaxClockDuration: _doi.disputeMaxClockDuration()
});
vm.broadcast(msg.sender);
......
......@@ -32,8 +32,8 @@
"sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649"
},
"src/L1/OPContractsManager.sol": {
"initCodeHash": "0x44fa611dcacad2f61c8ca7ef970e580800b5070d10f9a2a4c04459d6cf4cd180",
"sourceCodeHash": "0xe66886dd90cef90525f5ba2310c9e9d2d910c81c283f9b7cbfcd57c5091473c6"
"initCodeHash": "0xd58cb3978affc5c1457cdd498ff8420c90aef804d4c3b62cf42ab2691986d6d2",
"sourceCodeHash": "0x7bfa6eff76176649fe600303cd60009a0f6e282cbaec55836b5ea1f8875cbeb5"
},
"src/L1/OptimismPortal.sol": {
"initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190",
......
......@@ -172,6 +172,36 @@
"internalType": "uint64",
"name": "gasLimit",
"type": "uint64"
},
{
"internalType": "GameType",
"name": "disputeGameType",
"type": "uint32"
},
{
"internalType": "Claim",
"name": "disputeAbsolutePrestate",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "disputeMaxGameDepth",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "disputeSplitDepth",
"type": "uint256"
},
{
"internalType": "Duration",
"name": "disputeClockExtension",
"type": "uint64"
},
{
"internalType": "Duration",
"name": "disputeMaxClockDuration",
"type": "uint64"
}
],
"internalType": "struct OPContractsManager.DeployInput",
......
......@@ -172,6 +172,36 @@
"internalType": "uint64",
"name": "gasLimit",
"type": "uint64"
},
{
"internalType": "GameType",
"name": "disputeGameType",
"type": "uint32"
},
{
"internalType": "Claim",
"name": "disputeAbsolutePrestate",
"type": "bytes32"
},
{
"internalType": "uint256",
"name": "disputeMaxGameDepth",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "disputeSplitDepth",
"type": "uint256"
},
{
"internalType": "Duration",
"name": "disputeClockExtension",
"type": "uint64"
},
{
"internalType": "Duration",
"name": "disputeMaxClockDuration",
"type": "uint64"
}
],
"internalType": "struct OPContractsManager.DeployInput",
......
......@@ -60,6 +60,13 @@ contract OPContractsManager is ISemver, Initializable {
// The salt mixer is used as part of making the resulting salt unique.
string saltMixer;
uint64 gasLimit;
// Configurable dispute game parameters.
GameType disputeGameType;
Claim disputeAbsolutePrestate;
uint256 disputeMaxGameDepth;
uint256 disputeSplitDepth;
Duration disputeClockExtension;
Duration disputeMaxClockDuration;
}
/// @notice The full set of outputs from deploying a new OP Stack chain.
......@@ -122,8 +129,8 @@ contract OPContractsManager is ISemver, Initializable {
// -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.19
string public constant version = "1.0.0-beta.19";
/// @custom:semver 1.0.0-beta.20
string public constant version = "1.0.0-beta.20";
/// @notice Represents the interface version so consumers know how to decode the DeployOutput struct
/// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used.
......@@ -586,12 +593,12 @@ contract OPContractsManager is ISemver, Initializable {
returns (bytes memory)
{
return abi.encode(
GameType.wrap(1), // Permissioned Cannon
Claim.wrap(bytes32(hex"038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c")), // absolutePrestate
73, // maxGameDepth
30, // splitDepth
Duration.wrap(3 hours), // clockExtension
Duration.wrap(3.5 days), // maxClockDuration
_input.disputeGameType,
_input.disputeAbsolutePrestate,
_input.disputeMaxGameDepth,
_input.disputeSplitDepth,
_input.disputeClockExtension,
_input.disputeMaxClockDuration,
IBigStepper(getLatestImplementation("MIPS").logic),
IDelayedWETH(payable(address(_output.delayedWETHPermissionedGameProxy))),
IAnchorStateRegistry(address(_output.anchorStateRegistryProxy)),
......
......@@ -51,6 +51,13 @@ contract OPContractsManager_Deploy_Test is DeployOPChain_TestBase {
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opcmProxy.selector, address(opcm));
doi.set(doi.gasLimit.selector, gasLimit);
doi.set(doi.disputeGameType.selector, disputeGameType);
doi.set(doi.disputeAbsolutePrestate.selector, disputeAbsolutePrestate);
doi.set(doi.disputeMaxGameDepth.selector, disputeMaxGameDepth);
doi.set(doi.disputeSplitDepth.selector, disputeSplitDepth);
doi.set(doi.disputeClockExtension.selector, disputeClockExtension);
doi.set(doi.disputeMaxClockDuration.selector, disputeMaxClockDuration);
}
// This helper function is used to convert the input struct type defined in DeployOPChain.s.sol
......@@ -70,7 +77,13 @@ contract OPContractsManager_Deploy_Test is DeployOPChain_TestBase {
l2ChainId: _doi.l2ChainId(),
startingAnchorRoots: _doi.startingAnchorRoots(),
saltMixer: _doi.saltMixer(),
gasLimit: _doi.gasLimit()
gasLimit: _doi.gasLimit(),
disputeGameType: _doi.disputeGameType(),
disputeAbsolutePrestate: _doi.disputeAbsolutePrestate(),
disputeMaxGameDepth: _doi.disputeMaxGameDepth(),
disputeSplitDepth: _doi.disputeSplitDepth(),
disputeClockExtension: _doi.disputeClockExtension(),
disputeMaxClockDuration: _doi.disputeMaxClockDuration()
});
}
......
......@@ -33,7 +33,7 @@ import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol";
import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol";
import { IProxy } from "src/universal/interfaces/IProxy.sol";
import { GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
import { Claim, Duration, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
contract DeployOPChainInput_Test is Test {
DeployOPChainInput doi;
......@@ -370,6 +370,13 @@ contract DeployOPChain_TestBase is Test {
OPContractsManager opcm = OPContractsManager(address(0));
string saltMixer = "defaultSaltMixer";
uint64 gasLimit = 30_000_000;
// Configurable dispute game parameters.
uint32 disputeGameType = GameType.unwrap(GameTypes.PERMISSIONED_CANNON);
bytes32 disputeAbsolutePrestate = hex"038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c";
uint256 disputeMaxGameDepth = 73;
uint256 disputeSplitDepth = 30;
uint64 disputeClockExtension = Duration.unwrap(Duration.wrap(3 hours));
uint64 disputeMaxClockDuration = Duration.unwrap(Duration.wrap(3.5 days));
function setUp() public virtual {
// Set defaults for reference types
......@@ -490,6 +497,12 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
doi.set(doi.opcmProxy.selector, address(opcm)); // Not fuzzed since it must be an actual instance.
doi.set(doi.saltMixer.selector, saltMixer);
doi.set(doi.gasLimit.selector, gasLimit);
doi.set(doi.disputeGameType.selector, disputeGameType);
doi.set(doi.disputeAbsolutePrestate.selector, disputeAbsolutePrestate);
doi.set(doi.disputeMaxGameDepth.selector, disputeMaxGameDepth);
doi.set(doi.disputeSplitDepth.selector, disputeSplitDepth);
doi.set(doi.disputeClockExtension.selector, disputeClockExtension);
doi.set(doi.disputeMaxClockDuration.selector, disputeMaxClockDuration);
deployOPChain.run(doi, doo);
......@@ -507,6 +520,12 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
assertEq(l2ChainId, doi.l2ChainId(), "900");
assertEq(saltMixer, doi.saltMixer(), "1000");
assertEq(gasLimit, doi.gasLimit(), "1100");
assertEq(disputeGameType, GameType.unwrap(doi.disputeGameType()), "1200");
assertEq(disputeAbsolutePrestate, Claim.unwrap(doi.disputeAbsolutePrestate()), "1300");
assertEq(disputeMaxGameDepth, doi.disputeMaxGameDepth(), "1400");
assertEq(disputeSplitDepth, doi.disputeSplitDepth(), "1500");
assertEq(disputeClockExtension, Duration.unwrap(doi.disputeClockExtension()), "1600");
assertEq(disputeMaxClockDuration, Duration.unwrap(doi.disputeMaxClockDuration()), "1700");
// Assert inputs were properly passed through to the contract initializers.
assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "2100");
......
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