Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
3f4d94a4
Unverified
Commit
3f4d94a4
authored
Jan 11, 2025
by
Matthew Slipper
Committed by
GitHub
Jan 12, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ctb: Implement addGameType method on OPCM (#13653)
parent
3d3deab1
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
770 additions
and
64 deletions
+770
-64
DeployImplementations.s.sol
...tracts-bedrock/scripts/deploy/DeployImplementations.s.sol
+15
-36
DeployOPCM.s.sol
packages/contracts-bedrock/scripts/deploy/DeployOPCM.s.sol
+3
-1
OPContractsManager.json
...s/contracts-bedrock/snapshots/abi/OPContractsManager.json
+128
-0
OPContractsManagerInterop.json
...acts-bedrock/snapshots/abi/OPContractsManagerInterop.json
+128
-0
semver-lock.json
packages/contracts-bedrock/snapshots/semver-lock.json
+2
-2
OPContractsManager.json
...s-bedrock/snapshots/storageLayout/OPContractsManager.json
+2
-2
OPContractsManagerInterop.json
...ck/snapshots/storageLayout/OPContractsManagerInterop.json
+2
-2
OPContractsManager.sol
packages/contracts-bedrock/src/L1/OPContractsManager.sol
+183
-21
Blueprint.sol
packages/contracts-bedrock/src/libraries/Blueprint.sol
+51
-0
OPContractsManager.t.sol
packages/contracts-bedrock/test/L1/OPContractsManager.t.sol
+252
-0
AnchorStateRegistry.t.sol
.../contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol
+2
-0
Specs.t.sol
packages/contracts-bedrock/test/universal/Specs.t.sol
+2
-0
No files found.
packages/contracts-bedrock/scripts/deploy/DeployImplementations.s.sol
View file @
3f4d94a4
...
@@ -9,8 +9,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
...
@@ -9,8 +9,6 @@ import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
import { Bytes } from "src/libraries/Bytes.sol";
import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol";
import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol";
import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol";
import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol";
import { IMIPS } from "interfaces/cannon/IMIPS.sol";
import { IMIPS } from "interfaces/cannon/IMIPS.sol";
...
@@ -493,14 +491,22 @@ contract DeployImplementations is Script {
...
@@ -493,14 +491,22 @@ contract DeployImplementations is Script {
bytes32 salt = _dii.salt();
bytes32 salt = _dii.salt();
OPContractsManager.Blueprints memory blueprints;
OPContractsManager.Blueprints memory blueprints;
address checkAddress;
vm.startBroadcast(msg.sender);
vm.startBroadcast(msg.sender);
blueprints.addressManager = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AddressManager")), salt);
(blueprints.addressManager, checkAddress) = Blueprint.create(vm.getCode("AddressManager"), salt);
blueprints.proxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("Proxy")), salt);
require(checkAddress == address(0), "OPCM-10");
blueprints.proxyAdmin = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ProxyAdmin")), salt);
(blueprints.proxy, checkAddress) = Blueprint.create(vm.getCode("Proxy"), salt);
blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("L1ChugSplashProxy")), salt);
require(checkAddress == address(0), "OPCM-20");
blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ResolvedDelegateProxy")), salt);
(blueprints.proxyAdmin, checkAddress) = Blueprint.create(vm.getCode("ProxyAdmin"), salt);
blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AnchorStateRegistry")), salt);
require(checkAddress == address(0), "OPCM-30");
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(vm.getCode("PermissionedDisputeGame"), salt);
(blueprints.l1ChugSplashProxy, checkAddress) = Blueprint.create(vm.getCode("L1ChugSplashProxy"), salt);
require(checkAddress == address(0), "OPCM-40");
(blueprints.resolvedDelegateProxy, checkAddress) = Blueprint.create(vm.getCode("ResolvedDelegateProxy"), salt);
require(checkAddress == address(0), "OPCM-50");
(blueprints.anchorStateRegistry, checkAddress) = Blueprint.create(vm.getCode("AnchorStateRegistry"), salt);
require(checkAddress == address(0), "OPCM-60");
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = Blueprint.create(vm.getCode("PermissionedDisputeGame"), salt);
(blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) = Blueprint.create(vm.getCode("FaultDisputeGame"), salt);
vm.stopBroadcast();
vm.stopBroadcast();
// forgefmt: disable-end
// forgefmt: disable-end
...
@@ -862,33 +868,6 @@ contract DeployImplementations is Script {
...
@@ -862,33 +868,6 @@ contract DeployImplementations is Script {
dio_ = DeployImplementationsOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsOutput"));
dio_ = DeployImplementationsOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsOutput"));
}
}
function deployBytecode(bytes memory _bytecode, bytes32 _salt) public returns (address newContract_) {
assembly ("memory-safe") {
newContract_ := create2(0, add(_bytecode, 0x20), mload(_bytecode), _salt)
}
require(newContract_ != address(0), "DeployImplementations: create2 failed");
}
function deployBigBytecode(
bytes memory _bytecode,
bytes32 _salt
)
public
returns (address newContract1_, address newContract2_)
{
// Preamble needs 3 bytes.
uint256 maxInitCodeSize = 24576 - 3;
require(_bytecode.length > maxInitCodeSize, "DeployImplementations: Use deployBytecode instead");
bytes memory part1Slice = Bytes.slice(_bytecode, 0, maxInitCodeSize);
bytes memory part1 = Blueprint.blueprintDeployerBytecode(part1Slice);
bytes memory part2Slice = Bytes.slice(_bytecode, maxInitCodeSize, _bytecode.length - maxInitCodeSize);
bytes memory part2 = Blueprint.blueprintDeployerBytecode(part2Slice);
newContract1_ = deployBytecode(part1, _salt);
newContract2_ = deployBytecode(part2, _salt);
}
// Zero address is returned if the address is not found in '_standardVersionsToml'.
// Zero address is returned if the address is not found in '_standardVersionsToml'.
function getReleaseAddress(
function getReleaseAddress(
string memory _version,
string memory _version,
...
...
packages/contracts-bedrock/scripts/deploy/DeployOPCM.s.sol
View file @
3f4d94a4
...
@@ -198,7 +198,9 @@ contract DeployOPCM is Script {
...
@@ -198,7 +198,9 @@ contract DeployOPCM is Script {
resolvedDelegateProxy: _doi.resolvedDelegateProxyBlueprint(),
resolvedDelegateProxy: _doi.resolvedDelegateProxyBlueprint(),
anchorStateRegistry: _doi.anchorStateRegistryBlueprint(),
anchorStateRegistry: _doi.anchorStateRegistryBlueprint(),
permissionedDisputeGame1: _doi.permissionedDisputeGame1Blueprint(),
permissionedDisputeGame1: _doi.permissionedDisputeGame1Blueprint(),
permissionedDisputeGame2: _doi.permissionedDisputeGame2Blueprint()
permissionedDisputeGame2: _doi.permissionedDisputeGame2Blueprint(),
permissionlessDisputeGame1: address(0),
permissionlessDisputeGame2: address(0)
});
});
OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({
OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({
l1ERC721BridgeImpl: address(_doi.l1ERC721BridgeImpl()),
l1ERC721BridgeImpl: address(_doi.l1ERC721BridgeImpl()),
...
...
packages/contracts-bedrock/snapshots/abi/OPContractsManager.json
View file @
3f4d94a4
...
@@ -57,6 +57,16 @@
...
@@ -57,6 +57,16 @@
"internalType"
:
"address"
,
"internalType"
:
"address"
,
"name"
:
"permissionedDisputeGame2"
,
"name"
:
"permissionedDisputeGame2"
,
"type"
:
"address"
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame1"
,
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame2"
,
"type"
:
"address"
}
}
],
],
"internalType"
:
"struct OPContractsManager.Blueprints"
,
"internalType"
:
"struct OPContractsManager.Blueprints"
,
...
@@ -132,6 +142,104 @@
...
@@ -132,6 +142,104 @@
"stateMutability"
:
"view"
,
"stateMutability"
:
"view"
,
"type"
:
"function"
"type"
:
"function"
},
},
{
"inputs"
:
[
{
"components"
:
[
{
"internalType"
:
"string"
,
"name"
:
"saltMixer"
,
"type"
:
"string"
},
{
"internalType"
:
"contract ISystemConfig"
,
"name"
:
"systemConfig"
,
"type"
:
"address"
},
{
"internalType"
:
"contract IProxyAdmin"
,
"name"
:
"proxyAdmin"
,
"type"
:
"address"
},
{
"internalType"
:
"contract IDelayedWETH"
,
"name"
:
"delayedWETH"
,
"type"
:
"address"
},
{
"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"
:
"uint256"
,
"name"
:
"initialBond"
,
"type"
:
"uint256"
},
{
"internalType"
:
"contract IBigStepper"
,
"name"
:
"vm"
,
"type"
:
"address"
},
{
"internalType"
:
"bool"
,
"name"
:
"permissioned"
,
"type"
:
"bool"
}
],
"internalType"
:
"struct OPContractsManager.AddGameInput[]"
,
"name"
:
"_gameConfigs"
,
"type"
:
"tuple[]"
}
],
"name"
:
"addGameType"
,
"outputs"
:
[
{
"components"
:
[
{
"internalType"
:
"contract IDelayedWETH"
,
"name"
:
"delayedWETH"
,
"type"
:
"address"
},
{
"internalType"
:
"contract IFaultDisputeGame"
,
"name"
:
"faultDisputeGame"
,
"type"
:
"address"
}
],
"internalType"
:
"struct OPContractsManager.AddGameOutput[]"
,
"name"
:
""
,
"type"
:
"tuple[]"
}
],
"stateMutability"
:
"nonpayable"
,
"type"
:
"function"
},
{
{
"inputs"
:
[],
"inputs"
:
[],
"name"
:
"blueprints"
,
"name"
:
"blueprints"
,
...
@@ -177,6 +285,16 @@
...
@@ -177,6 +285,16 @@
"internalType"
:
"address"
,
"internalType"
:
"address"
,
"name"
:
"permissionedDisputeGame2"
,
"name"
:
"permissionedDisputeGame2"
,
"type"
:
"address"
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame1"
,
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame2"
,
"type"
:
"address"
}
}
],
],
"internalType"
:
"struct OPContractsManager.Blueprints"
,
"internalType"
:
"struct OPContractsManager.Blueprints"
,
...
@@ -596,6 +714,11 @@
...
@@ -596,6 +714,11 @@
"name"
:
"InvalidChainId"
,
"name"
:
"InvalidChainId"
,
"type"
:
"error"
"type"
:
"error"
},
},
{
"inputs"
:
[],
"name"
:
"InvalidGameConfigs"
,
"type"
:
"error"
},
{
{
"inputs"
:
[
"inputs"
:
[
{
{
...
@@ -622,6 +745,11 @@
...
@@ -622,6 +745,11 @@
"name"
:
"NotABlueprint"
,
"name"
:
"NotABlueprint"
,
"type"
:
"error"
"type"
:
"error"
},
},
{
"inputs"
:
[],
"name"
:
"OnlyDelegatecall"
,
"type"
:
"error"
},
{
{
"inputs"
:
[],
"inputs"
:
[],
"name"
:
"ReservedBitsSet"
,
"name"
:
"ReservedBitsSet"
,
...
...
packages/contracts-bedrock/snapshots/abi/OPContractsManagerInterop.json
View file @
3f4d94a4
...
@@ -57,6 +57,16 @@
...
@@ -57,6 +57,16 @@
"internalType"
:
"address"
,
"internalType"
:
"address"
,
"name"
:
"permissionedDisputeGame2"
,
"name"
:
"permissionedDisputeGame2"
,
"type"
:
"address"
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame1"
,
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame2"
,
"type"
:
"address"
}
}
],
],
"internalType"
:
"struct OPContractsManager.Blueprints"
,
"internalType"
:
"struct OPContractsManager.Blueprints"
,
...
@@ -132,6 +142,104 @@
...
@@ -132,6 +142,104 @@
"stateMutability"
:
"view"
,
"stateMutability"
:
"view"
,
"type"
:
"function"
"type"
:
"function"
},
},
{
"inputs"
:
[
{
"components"
:
[
{
"internalType"
:
"string"
,
"name"
:
"saltMixer"
,
"type"
:
"string"
},
{
"internalType"
:
"contract ISystemConfig"
,
"name"
:
"systemConfig"
,
"type"
:
"address"
},
{
"internalType"
:
"contract IProxyAdmin"
,
"name"
:
"proxyAdmin"
,
"type"
:
"address"
},
{
"internalType"
:
"contract IDelayedWETH"
,
"name"
:
"delayedWETH"
,
"type"
:
"address"
},
{
"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"
:
"uint256"
,
"name"
:
"initialBond"
,
"type"
:
"uint256"
},
{
"internalType"
:
"contract IBigStepper"
,
"name"
:
"vm"
,
"type"
:
"address"
},
{
"internalType"
:
"bool"
,
"name"
:
"permissioned"
,
"type"
:
"bool"
}
],
"internalType"
:
"struct OPContractsManager.AddGameInput[]"
,
"name"
:
"_gameConfigs"
,
"type"
:
"tuple[]"
}
],
"name"
:
"addGameType"
,
"outputs"
:
[
{
"components"
:
[
{
"internalType"
:
"contract IDelayedWETH"
,
"name"
:
"delayedWETH"
,
"type"
:
"address"
},
{
"internalType"
:
"contract IFaultDisputeGame"
,
"name"
:
"faultDisputeGame"
,
"type"
:
"address"
}
],
"internalType"
:
"struct OPContractsManager.AddGameOutput[]"
,
"name"
:
""
,
"type"
:
"tuple[]"
}
],
"stateMutability"
:
"nonpayable"
,
"type"
:
"function"
},
{
{
"inputs"
:
[],
"inputs"
:
[],
"name"
:
"blueprints"
,
"name"
:
"blueprints"
,
...
@@ -177,6 +285,16 @@
...
@@ -177,6 +285,16 @@
"internalType"
:
"address"
,
"internalType"
:
"address"
,
"name"
:
"permissionedDisputeGame2"
,
"name"
:
"permissionedDisputeGame2"
,
"type"
:
"address"
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame1"
,
"type"
:
"address"
},
{
"internalType"
:
"address"
,
"name"
:
"permissionlessDisputeGame2"
,
"type"
:
"address"
}
}
],
],
"internalType"
:
"struct OPContractsManager.Blueprints"
,
"internalType"
:
"struct OPContractsManager.Blueprints"
,
...
@@ -596,6 +714,11 @@
...
@@ -596,6 +714,11 @@
"name"
:
"InvalidChainId"
,
"name"
:
"InvalidChainId"
,
"type"
:
"error"
"type"
:
"error"
},
},
{
"inputs"
:
[],
"name"
:
"InvalidGameConfigs"
,
"type"
:
"error"
},
{
{
"inputs"
:
[
"inputs"
:
[
{
{
...
@@ -622,6 +745,11 @@
...
@@ -622,6 +745,11 @@
"name"
:
"NotABlueprint"
,
"name"
:
"NotABlueprint"
,
"type"
:
"error"
"type"
:
"error"
},
},
{
"inputs"
:
[],
"name"
:
"OnlyDelegatecall"
,
"type"
:
"error"
},
{
{
"inputs"
:
[],
"inputs"
:
[],
"name"
:
"ReservedBitsSet"
,
"name"
:
"ReservedBitsSet"
,
...
...
packages/contracts-bedrock/snapshots/semver-lock.json
View file @
3f4d94a4
...
@@ -16,8 +16,8 @@
...
@@ -16,8 +16,8 @@
"sourceCodeHash"
:
"0xa91b445bdc666a02ba18e3b91ba94b6d54bbe65da714002fc734814201319d57"
"sourceCodeHash"
:
"0xa91b445bdc666a02ba18e3b91ba94b6d54bbe65da714002fc734814201319d57"
},
},
"src/L1/OPContractsManager.sol"
:
{
"src/L1/OPContractsManager.sol"
:
{
"initCodeHash"
:
"0x
4b413cbe79bd10d41d8f3e9f0408e773dd49ced823d457b9f9aa92f446828105
"
,
"initCodeHash"
:
"0x
e0c14a8fee7ad4c4e28a3ff6ca4e726721a6c3fea0a74ab7eac7ef07fe4da0ae
"
,
"sourceCodeHash"
:
"0xe
5179a20ae40d4e4773c52df98bac67e73e04044bec9e8750073b4e2f14fe81b
"
"sourceCodeHash"
:
"0xe
0f5413e0a0a335016d773f02ef6bd25551416635981e83b7a4da601b9b65bc4
"
},
},
"src/L1/OptimismPortal2.sol"
:
{
"src/L1/OptimismPortal2.sol"
:
{
"initCodeHash"
:
"0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac"
,
"initCodeHash"
:
"0x7e533474310583593c2d57d30fcd1ec11e1568dbaaf37a2dd28c5cc574068bac"
,
...
...
packages/contracts-bedrock/snapshots/storageLayout/OPContractsManager.json
View file @
3f4d94a4
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
"type"
:
"string"
"type"
:
"string"
},
},
{
{
"bytes"
:
"
256
"
,
"bytes"
:
"
320
"
,
"label"
:
"blueprint"
,
"label"
:
"blueprint"
,
"offset"
:
0
,
"offset"
:
0
,
"slot"
:
"1"
,
"slot"
:
"1"
,
...
@@ -17,7 +17,7 @@
...
@@ -17,7 +17,7 @@
"bytes"
:
"288"
,
"bytes"
:
"288"
,
"label"
:
"implementation"
,
"label"
:
"implementation"
,
"offset"
:
0
,
"offset"
:
0
,
"slot"
:
"
9
"
,
"slot"
:
"
11
"
,
"type"
:
"struct OPContractsManager.Implementations"
"type"
:
"struct OPContractsManager.Implementations"
}
}
]
]
\ No newline at end of file
packages/contracts-bedrock/snapshots/storageLayout/OPContractsManagerInterop.json
View file @
3f4d94a4
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
"type"
:
"string"
"type"
:
"string"
},
},
{
{
"bytes"
:
"
256
"
,
"bytes"
:
"
320
"
,
"label"
:
"blueprint"
,
"label"
:
"blueprint"
,
"offset"
:
0
,
"offset"
:
0
,
"slot"
:
"1"
,
"slot"
:
"1"
,
...
@@ -17,7 +17,7 @@
...
@@ -17,7 +17,7 @@
"bytes"
:
"288"
,
"bytes"
:
"288"
,
"label"
:
"implementation"
,
"label"
:
"implementation"
,
"offset"
:
0
,
"offset"
:
0
,
"slot"
:
"
9
"
,
"slot"
:
"
11
"
,
"type"
:
"struct OPContractsManager.Implementations"
"type"
:
"struct OPContractsManager.Implementations"
}
}
]
]
\ No newline at end of file
packages/contracts-bedrock/src/L1/OPContractsManager.sol
View file @
3f4d94a4
...
@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
...
@@ -4,6 +4,7 @@ pragma solidity 0.8.15;
// Libraries
// Libraries
import { Blueprint } from "src/libraries/Blueprint.sol";
import { Blueprint } from "src/libraries/Blueprint.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Bytes } from "src/libraries/Bytes.sol";
import { Claim, Duration, GameType, GameTypes } from "src/dispute/lib/Types.sol";
import { Claim, Duration, GameType, GameTypes } from "src/dispute/lib/Types.sol";
// Interfaces
// Interfaces
...
@@ -97,6 +98,8 @@ contract OPContractsManager is ISemver {
...
@@ -97,6 +98,8 @@ contract OPContractsManager is ISemver {
address anchorStateRegistry;
address anchorStateRegistry;
address permissionedDisputeGame1;
address permissionedDisputeGame1;
address permissionedDisputeGame2;
address permissionedDisputeGame2;
address permissionlessDisputeGame1;
address permissionlessDisputeGame2;
}
}
/// @notice The latest implementation contracts for the OP Stack.
/// @notice The latest implementation contracts for the OP Stack.
...
@@ -112,10 +115,31 @@ contract OPContractsManager is ISemver {
...
@@ -112,10 +115,31 @@ contract OPContractsManager is ISemver {
address mipsImpl;
address mipsImpl;
}
}
struct AddGameInput {
string saltMixer;
ISystemConfig systemConfig;
IProxyAdmin proxyAdmin;
IDelayedWETH delayedWETH;
GameType disputeGameType;
Claim disputeAbsolutePrestate;
uint256 disputeMaxGameDepth;
uint256 disputeSplitDepth;
Duration disputeClockExtension;
Duration disputeMaxClockDuration;
uint256 initialBond;
IBigStepper vm;
bool permissioned;
}
struct AddGameOutput {
IDelayedWETH delayedWETH;
IFaultDisputeGame faultDisputeGame;
}
// -------- Constants and Variables --------
// -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.2
7
/// @custom:semver 1.0.0-beta.2
8
string public constant version = "1.0.0-beta.2
7
";
string public constant version = "1.0.0-beta.2
8
";
/// @notice Represents the interface version so consumers know how to decode the DeployOutput struct
/// @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.
/// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used.
...
@@ -139,6 +163,10 @@ contract OPContractsManager is ISemver {
...
@@ -139,6 +163,10 @@ contract OPContractsManager is ISemver {
/// @notice Addresses of the latest implementation contracts.
/// @notice Addresses of the latest implementation contracts.
Implementations internal implementation;
Implementations internal implementation;
/// @notice The OPContractsManager contract that is currently being used. This is needed in the upgrade function
/// which is intended to be DELEGATECALLed.
OPContractsManager internal immutable thisOPCM;
// -------- Events --------
// -------- Events --------
/// @notice Emitted when a new OP Stack chain is deployed.
/// @notice Emitted when a new OP Stack chain is deployed.
...
@@ -173,6 +201,12 @@ contract OPContractsManager is ISemver {
...
@@ -173,6 +201,12 @@ contract OPContractsManager is ISemver {
/// @notice Thrown when the starting anchor roots are not provided.
/// @notice Thrown when the starting anchor roots are not provided.
error InvalidStartingAnchorRoots();
error InvalidStartingAnchorRoots();
/// @notice Thrown when certain methods are called outside of a DELEGATECALL.
error OnlyDelegatecall();
/// @notice Thrown when game configs passed to addGameType are invalid.
error InvalidGameConfigs();
// -------- Methods --------
// -------- Methods --------
constructor(
constructor(
...
@@ -190,6 +224,7 @@ contract OPContractsManager is ISemver {
...
@@ -190,6 +224,7 @@ contract OPContractsManager is ISemver {
blueprint = _blueprints;
blueprint = _blueprints;
implementation = _implementations;
implementation = _implementations;
thisOPCM = this;
}
}
function deploy(DeployInput calldata _input) external returns (DeployOutput memory) {
function deploy(DeployInput calldata _input) external returns (DeployOutput memory) {
...
@@ -279,7 +314,22 @@ contract OPContractsManager is ISemver {
...
@@ -279,7 +314,22 @@ contract OPContractsManager is ISemver {
blueprint.permissionedDisputeGame1,
blueprint.permissionedDisputeGame1,
blueprint.permissionedDisputeGame2,
blueprint.permissionedDisputeGame2,
computeSalt(l2ChainId, saltMixer, "PermissionedDisputeGame"),
computeSalt(l2ChainId, saltMixer, "PermissionedDisputeGame"),
encodePermissionedDisputeGameConstructor(_input, output)
encodePermissionedFDGConstructor(
IFaultDisputeGame.GameConstructorParams({
gameType: _input.disputeGameType,
absolutePrestate: _input.disputeAbsolutePrestate,
maxGameDepth: _input.disputeMaxGameDepth,
splitDepth: _input.disputeSplitDepth,
clockExtension: _input.disputeClockExtension,
maxClockDuration: _input.disputeMaxClockDuration,
vm: IBigStepper(implementation.mipsImpl),
weth: IDelayedWETH(payable(address(output.delayedWETHPermissionedGameProxy))),
anchorStateRegistry: IAnchorStateRegistry(address(output.anchorStateRegistryProxy)),
l2ChainId: _input.l2ChainId
}),
_input.roles.proposer,
_input.roles.challenger
)
)
)
);
);
...
@@ -363,6 +413,118 @@ contract OPContractsManager is ISemver {
...
@@ -363,6 +413,118 @@ contract OPContractsManager is ISemver {
return output;
return output;
}
}
/// @notice addGameType deploys a new dispute game and links it to the DisputeGameFactory. The inputted _gameConfigs
/// must be added in ascending GameType order.
function addGameType(AddGameInput[] memory _gameConfigs) external returns (AddGameOutput[] memory) {
if (address(this) == address(thisOPCM)) revert OnlyDelegatecall();
if (_gameConfigs.length == 0) revert InvalidGameConfigs();
AddGameOutput[] memory outputs = new AddGameOutput[](_gameConfigs.length);
Blueprints memory bps = thisOPCM.blueprints();
// Store last game config as an int256 so that we can ensure that the same game config is not added twice.
// Using int256 generates cheaper, simpler bytecode.
int256 lastGameConfig = -1;
for (uint256 i = 0; i < _gameConfigs.length; i++) {
AddGameInput memory gameConfig = _gameConfigs[i];
// This conversion is safe because the GameType is a uint32, which will always fit in an int256.
int256 gameTypeInt = int256(uint256(gameConfig.disputeGameType.raw()));
// Ensure that the game configs are added in ascending order, and not duplicated.
if (lastGameConfig >= gameTypeInt) revert InvalidGameConfigs();
lastGameConfig = gameTypeInt;
// Grab the FDG from the SystemConfig.
IFaultDisputeGame fdg = IFaultDisputeGame(
address(
IDisputeGameFactory(gameConfig.systemConfig.disputeGameFactory()).gameImpls(
GameTypes.PERMISSIONED_CANNON
)
)
);
// Pull out the chain ID.
uint256 l2ChainId = fdg.l2ChainId();
// Deploy a new DelayedWETH proxy for this game if one hasn't already been specified. Leaving
/// gameConfig.delayedWETH as the zero address will cause a new DelayedWETH to be deployed for this game.
if (address(gameConfig.delayedWETH) == address(0)) {
outputs[i].delayedWETH = IDelayedWETH(
payable(deployProxy(l2ChainId, gameConfig.proxyAdmin, gameConfig.saltMixer, "DelayedWETH"))
);
// Initialize the proxy.
upgradeAndCall(
gameConfig.proxyAdmin,
address(outputs[i].delayedWETH),
thisOPCM.implementations().delayedWETHImpl,
abi.encodeCall(IDelayedWETH.initialize, (gameConfig.proxyAdmin.owner(), superchainConfig))
);
} else {
outputs[i].delayedWETH = gameConfig.delayedWETH;
}
// The below sections are functionally the same. Both deploy a new dispute game. The dispute game type is
// either permissioned or permissionless depending on game config.
if (gameConfig.permissioned) {
IPermissionedDisputeGame pdg = IPermissionedDisputeGame(address(fdg));
outputs[i].faultDisputeGame = IFaultDisputeGame(
Blueprint.deployFrom(
bps.permissionedDisputeGame1,
bps.permissionedDisputeGame2,
computeSalt(l2ChainId, gameConfig.saltMixer, "PermissionedDisputeGame"),
encodePermissionedFDGConstructor(
IFaultDisputeGame.GameConstructorParams(
gameConfig.disputeGameType,
gameConfig.disputeAbsolutePrestate,
gameConfig.disputeMaxGameDepth,
gameConfig.disputeSplitDepth,
gameConfig.disputeClockExtension,
gameConfig.disputeMaxClockDuration,
gameConfig.vm,
outputs[i].delayedWETH,
pdg.anchorStateRegistry(),
l2ChainId
),
pdg.proposer(),
pdg.challenger()
)
)
);
} else {
outputs[i].faultDisputeGame = IFaultDisputeGame(
Blueprint.deployFrom(
bps.permissionlessDisputeGame1,
bps.permissionlessDisputeGame2,
computeSalt(l2ChainId, gameConfig.saltMixer, "PermissionlessDisputeGame"),
encodePermissionlessFDGConstructor(
IFaultDisputeGame.GameConstructorParams(
gameConfig.disputeGameType,
gameConfig.disputeAbsolutePrestate,
gameConfig.disputeMaxGameDepth,
gameConfig.disputeSplitDepth,
gameConfig.disputeClockExtension,
gameConfig.disputeMaxClockDuration,
gameConfig.vm,
outputs[i].delayedWETH,
fdg.anchorStateRegistry(),
l2ChainId
)
)
)
);
}
// As a last step, register the new game type with the DisputeGameFactory. If the game type already exists,
// then its implementation will be overwritten.
IDisputeGameFactory dgf = IDisputeGameFactory(gameConfig.systemConfig.disputeGameFactory());
dgf.setImplementation(gameConfig.disputeGameType, IDisputeGame(address(outputs[i].faultDisputeGame)));
dgf.setInitBond(gameConfig.disputeGameType, gameConfig.initialBond);
}
return outputs;
}
// -------- Utilities --------
// -------- Utilities --------
/// @notice Verifies that all inputs are valid and reverts if any are invalid.
/// @notice Verifies that all inputs are valid and reverts if any are invalid.
...
@@ -420,7 +582,7 @@ contract OPContractsManager is ISemver {
...
@@ -420,7 +582,7 @@ contract OPContractsManager is ISemver {
returns (address)
returns (address)
{
{
bytes32 salt = computeSalt(_l2ChainId, _saltMixer, _contractName);
bytes32 salt = computeSalt(_l2ChainId, _saltMixer, _contractName);
return Blueprint.deployFrom(
blueprint
.proxy, salt, abi.encode(_proxyAdmin));
return Blueprint.deployFrom(
thisOPCM.blueprints()
.proxy, salt, abi.encode(_proxyAdmin));
}
}
// -------- Initializer Encoding --------
// -------- Initializer Encoding --------
...
@@ -539,29 +701,29 @@ contract OPContractsManager is ISemver {
...
@@ -539,29 +701,29 @@ contract OPContractsManager is ISemver {
return abi.encodeCall(IDelayedWETH.initialize, (_input.roles.opChainProxyAdminOwner, superchainConfig));
return abi.encodeCall(IDelayedWETH.initialize, (_input.roles.opChainProxyAdminOwner, superchainConfig));
}
}
function encodePermissionedDisputeGameConstructor(
function encodePermissionlessFDGConstructor(IFaultDisputeGame.GameConstructorParams memory _params)
DeployInput memory _input,
internal
DeployOutput memory _output
view
virtual
returns (bytes memory)
{
bytes memory dataWithSelector = abi.encodeCall(IFaultDisputeGame.__constructor__, (_params));
return Bytes.slice(dataWithSelector, 4);
}
function encodePermissionedFDGConstructor(
IFaultDisputeGame.GameConstructorParams memory _params,
address _proposer,
address _challenger
)
)
internal
internal
view
view
virtual
virtual
returns (bytes memory)
returns (bytes memory)
{
{
return abi.encode(
bytes memory dataWithSelector =
_input.disputeGameType,
abi.encodeCall(IPermissionedDisputeGame.__constructor__, (_params, _proposer, _challenger));
_input.disputeAbsolutePrestate,
return Bytes.slice(dataWithSelector, 4);
_input.disputeMaxGameDepth,
_input.disputeSplitDepth,
_input.disputeClockExtension,
_input.disputeMaxClockDuration,
IBigStepper(implementation.mipsImpl),
IDelayedWETH(payable(address(_output.delayedWETHPermissionedGameProxy))),
IAnchorStateRegistry(address(_output.anchorStateRegistryProxy)),
_input.l2ChainId,
_input.roles.proposer,
_input.roles.challenger
);
}
}
/// @notice Returns default, standard config arguments for the SystemConfig initializer.
/// @notice Returns default, standard config arguments for the SystemConfig initializer.
...
...
packages/contracts-bedrock/src/libraries/Blueprint.sol
View file @
3f4d94a4
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity ^0.8.0;
import { Bytes } from "src/libraries/Bytes.sol";
/// @notice Methods for working with ERC-5202 blueprint contracts.
/// @notice Methods for working with ERC-5202 blueprint contracts.
/// https://eips.ethereum.org/EIPS/eip-5202
/// https://eips.ethereum.org/EIPS/eip-5202
library Blueprint {
library Blueprint {
...
@@ -157,6 +159,50 @@ library Blueprint {
...
@@ -157,6 +159,50 @@ library Blueprint {
if (newContract_ == address(0)) revert DeploymentFailed();
if (newContract_ == address(0)) revert DeploymentFailed();
}
}
/// @notice Deploys a blueprint contract with the given `_rawBytecode` and `_salt`. If the blueprint is too large to
/// fit in a single deployment, it is split across two addresses. It is the responsibility of the caller to handle
/// large contracts by checking if the second return value is not address(0).
function create(
bytes memory _rawBytecode,
bytes32 _salt
)
internal
returns (address newContract1_, address newContract2_)
{
if (_rawBytecode.length <= maxInitCodeSize()) {
newContract1_ = deploySmallBytecode(blueprintDeployerBytecode(_rawBytecode), _salt);
return (newContract1_, address(0));
}
(newContract1_, newContract2_) = deployBigBytecode(_rawBytecode, _salt);
}
/// @notice Deploys a blueprint contract that can fit in a single address.
function deploySmallBytecode(bytes memory _bytecode, bytes32 _salt) internal returns (address newContract_) {
assembly ("memory-safe") {
newContract_ := create2(0, add(_bytecode, 0x20), mload(_bytecode), _salt)
}
require(newContract_ != address(0), "Blueprint: create2 failed");
}
/// @notice Deploys a two blueprint contracts, splitting the bytecode across both of them.
function deployBigBytecode(
bytes memory _bytecode,
bytes32 _salt
)
internal
returns (address newContract1_, address newContract2_)
{
uint32 maxSize = maxInitCodeSize();
bytes memory part1Slice = Bytes.slice(_bytecode, 0, maxSize);
bytes memory part1 = blueprintDeployerBytecode(part1Slice);
bytes memory part2Slice = Bytes.slice(_bytecode, maxSize, _bytecode.length - maxSize);
bytes memory part2 = blueprintDeployerBytecode(part2Slice);
newContract1_ = deploySmallBytecode(part1, _salt);
newContract2_ = deploySmallBytecode(part2, _salt);
}
/// @notice Convert a bytes array to a uint256.
/// @notice Convert a bytes array to a uint256.
function bytesToUint(bytes memory _b) internal pure returns (uint256) {
function bytesToUint(bytes memory _b) internal pure returns (uint256) {
if (_b.length > 32) revert BytesArrayTooLong();
if (_b.length > 32) revert BytesArrayTooLong();
...
@@ -166,4 +212,9 @@ library Blueprint {
...
@@ -166,4 +212,9 @@ library Blueprint {
}
}
return number;
return number;
}
}
/// @notice Returns the maximum init code size for each blueprint. The preamble needs 3 bytes.
function maxInitCodeSize() internal pure returns (uint32) {
return 24576 - 3;
}
}
}
packages/contracts-bedrock/test/L1/OPContractsManager.t.sol
View file @
3f4d94a4
...
@@ -9,6 +9,26 @@ import { DeployOPChain_TestBase } from "test/opcm/DeployOPChain.t.sol";
...
@@ -9,6 +9,26 @@ import { DeployOPChain_TestBase } from "test/opcm/DeployOPChain.t.sol";
import { OPContractsManager } from "src/L1/OPContractsManager.sol";
import { OPContractsManager } from "src/L1/OPContractsManager.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
import { IProtocolVersions } from "interfaces/L1/IProtocolVersions.sol";
import { IPreimageOracle } from "interfaces/cannon/IPreimageOracle.sol";
import { IPermissionedDisputeGame } from "interfaces/dispute/IPermissionedDisputeGame.sol";
import { IDelayedWETH } from "interfaces/dispute/IDelayedWETH.sol";
import { Blueprint } from "src/libraries/Blueprint.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol";
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { IBigStepper } from "interfaces/dispute/IBigStepper.sol";
import { DelayedWETH } from "src/dispute/DelayedWETH.sol";
import { MIPS } from "src/cannon/MIPS.sol";
import { GameType, Duration, Hash, Claim } from "src/dispute/lib/LibUDT.sol";
import { OutputRoot } from "src/dispute/lib/Types.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
// Exposes internal functions for testing.
// Exposes internal functions for testing.
contract OPContractsManager_Harness is OPContractsManager {
contract OPContractsManager_Harness is OPContractsManager {
...
@@ -148,3 +168,235 @@ contract OPContractsManager_InternalMethods_Test is Test {
...
@@ -148,3 +168,235 @@ contract OPContractsManager_InternalMethods_Test is Test {
vm.assertEq(expected, actual);
vm.assertEq(expected, actual);
}
}
}
}
contract OPContractsManager_AddGameType_Test is Test {
OPContractsManager internal opcm;
OPContractsManager.DeployOutput internal chainDeployOutput;
function setUp() public {
ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig"));
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions"));
bytes32 salt = hex"01";
OPContractsManager.Blueprints memory blueprints;
(blueprints.addressManager,) = Blueprint.create(vm.getCode("AddressManager"), salt);
(blueprints.proxy,) = Blueprint.create(vm.getCode("Proxy"), salt);
(blueprints.proxyAdmin,) = Blueprint.create(vm.getCode("ProxyAdmin"), salt);
(blueprints.l1ChugSplashProxy,) = Blueprint.create(vm.getCode("L1ChugSplashProxy"), salt);
(blueprints.resolvedDelegateProxy,) = Blueprint.create(vm.getCode("ResolvedDelegateProxy"), salt);
(blueprints.anchorStateRegistry,) = Blueprint.create(vm.getCode("AnchorStateRegistry"), salt);
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) =
Blueprint.create(vm.getCode("PermissionedDisputeGame"), salt);
(blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) =
Blueprint.create(vm.getCode("FaultDisputeGame"), salt);
IPreimageOracle oracle = IPreimageOracle(address(new PreimageOracle(126000, 86400)));
OPContractsManager.Implementations memory impls = OPContractsManager.Implementations({
l1ERC721BridgeImpl: address(new L1ERC721Bridge()),
optimismPortalImpl: address(new OptimismPortal2(1, 1)),
systemConfigImpl: address(new SystemConfig()),
optimismMintableERC20FactoryImpl: address(new OptimismMintableERC20Factory()),
l1CrossDomainMessengerImpl: address(new L1CrossDomainMessenger()),
l1StandardBridgeImpl: address(new L1StandardBridge()),
disputeGameFactoryImpl: address(new DisputeGameFactory()),
delayedWETHImpl: address(new DelayedWETH(3)),
mipsImpl: address(new MIPS(oracle))
});
vm.etch(address(superchainConfigProxy), hex"01");
vm.etch(address(protocolVersionsProxy), hex"01");
opcm = new OPContractsManager(superchainConfigProxy, protocolVersionsProxy, "dev", blueprints, impls);
AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](1);
roots[0] = AnchorStateRegistry.StartingAnchorRoot({
outputRoot: OutputRoot({ root: Hash.wrap(hex"dead"), l2BlockNumber: 0 }),
gameType: GameType.wrap(1)
});
chainDeployOutput = opcm.deploy(
OPContractsManager.DeployInput({
roles: OPContractsManager.Roles({
opChainProxyAdminOwner: address(this),
systemConfigOwner: address(this),
batcher: address(this),
unsafeBlockSigner: address(this),
proposer: address(this),
challenger: address(this)
}),
basefeeScalar: 1,
blobBasefeeScalar: 1,
startingAnchorRoots: abi.encode(roots),
l2ChainId: 100,
saltMixer: "hello",
gasLimit: 30_000_000,
disputeGameType: GameType.wrap(1),
disputeAbsolutePrestate: Claim.wrap(
bytes32(hex"038512e02c4c3f7bdaec27d00edf55b7155e0905301e1a88083e4e0a6764d54c")
),
disputeMaxGameDepth: 73,
disputeSplitDepth: 30,
disputeClockExtension: Duration.wrap(10800),
disputeMaxClockDuration: Duration.wrap(302400)
})
);
}
function test_addGameType_permissioned_succeeds() public {
OPContractsManager.AddGameInput memory input = newGameInputFactory(true);
OPContractsManager.AddGameOutput memory output = addGameType(input);
assertValidGameType(input, output);
IPermissionedDisputeGame newPDG = IPermissionedDisputeGame(address(output.faultDisputeGame));
IPermissionedDisputeGame oldPDG = chainDeployOutput.permissionedDisputeGame;
assertEq(newPDG.proposer(), oldPDG.proposer(), "proposer mismatch");
assertEq(newPDG.challenger(), oldPDG.challenger(), "challenger mismatch");
}
function test_addGameType_permissionless_succeeds() public {
OPContractsManager.AddGameInput memory input = newGameInputFactory(false);
OPContractsManager.AddGameOutput memory output = addGameType(input);
assertValidGameType(input, output);
IPermissionedDisputeGame notPDG = IPermissionedDisputeGame(address(output.faultDisputeGame));
vm.expectRevert(); // nosemgrep: sol-safety-expectrevert-no-args
notPDG.proposer();
}
function test_addGameType_reusedDelayedWETH_succeeds() public {
IDelayedWETH delayedWETH = IDelayedWETH(payable(address(new DelayedWETH(1))));
vm.etch(address(delayedWETH), hex"01");
OPContractsManager.AddGameInput memory input = newGameInputFactory(false);
input.delayedWETH = delayedWETH;
OPContractsManager.AddGameOutput memory output = addGameType(input);
assertValidGameType(input, output);
assertEq(address(output.delayedWETH), address(delayedWETH), "delayedWETH address mismatch");
}
function test_addGameType_outOfOrderInputs_reverts() public {
OPContractsManager.AddGameInput memory input1 = newGameInputFactory(false);
input1.disputeGameType = GameType.wrap(2);
OPContractsManager.AddGameInput memory input2 = newGameInputFactory(false);
input2.disputeGameType = GameType.wrap(1);
OPContractsManager.AddGameInput[] memory inputs = new OPContractsManager.AddGameInput[](2);
inputs[0] = input1;
inputs[1] = input2;
// For the sake of completeness, we run the call again to validate the success behavior.
(bool success,) = address(opcm).delegatecall(abi.encodeCall(OPContractsManager.addGameType, (inputs)));
assertFalse(success, "addGameType should have failed");
}
function test_addGameType_duplicateGameType_reverts() public {
OPContractsManager.AddGameInput memory input = newGameInputFactory(false);
OPContractsManager.AddGameInput[] memory inputs = new OPContractsManager.AddGameInput[](2);
inputs[0] = input;
inputs[1] = input;
// See test above for why we run the call twice.
(bool success, bytes memory revertData) =
address(opcm).delegatecall(abi.encodeCall(OPContractsManager.addGameType, (inputs)));
assertFalse(success, "addGameType should have failed");
assertEq(bytes4(revertData), OPContractsManager.InvalidGameConfigs.selector, "revertData mismatch");
}
function test_addGameType_zeroLengthInput_reverts() public {
OPContractsManager.AddGameInput[] memory inputs = new OPContractsManager.AddGameInput[](0);
(bool success, bytes memory revertData) =
address(opcm).delegatecall(abi.encodeCall(OPContractsManager.addGameType, (inputs)));
assertFalse(success, "addGameType should have failed");
assertEq(bytes4(revertData), OPContractsManager.InvalidGameConfigs.selector, "revertData mismatch");
}
function test_addGameType_notDelegateCall_reverts() public {
OPContractsManager.AddGameInput memory input = newGameInputFactory(true);
OPContractsManager.AddGameInput[] memory inputs = new OPContractsManager.AddGameInput[](1);
inputs[0] = input;
vm.expectRevert(OPContractsManager.OnlyDelegatecall.selector);
opcm.addGameType(inputs);
}
function addGameType(OPContractsManager.AddGameInput memory input)
internal
returns (OPContractsManager.AddGameOutput memory)
{
OPContractsManager.AddGameInput[] memory inputs = new OPContractsManager.AddGameInput[](1);
inputs[0] = input;
(bool success, bytes memory rawGameOut) =
address(opcm).delegatecall(abi.encodeCall(OPContractsManager.addGameType, (inputs)));
assertTrue(success, "addGameType failed");
OPContractsManager.AddGameOutput[] memory addGameOutAll =
abi.decode(rawGameOut, (OPContractsManager.AddGameOutput[]));
return addGameOutAll[0];
}
function newGameInputFactory(bool permissioned) internal view returns (OPContractsManager.AddGameInput memory) {
return OPContractsManager.AddGameInput({
saltMixer: "hello",
systemConfig: chainDeployOutput.systemConfigProxy,
proxyAdmin: chainDeployOutput.opChainProxyAdmin,
delayedWETH: IDelayedWETH(payable(address(0))),
disputeGameType: GameType.wrap(2000),
disputeAbsolutePrestate: Claim.wrap(bytes32(hex"deadbeef1234")),
disputeMaxGameDepth: 73,
disputeSplitDepth: 30,
disputeClockExtension: Duration.wrap(10800),
disputeMaxClockDuration: Duration.wrap(302400),
initialBond: 1 ether,
vm: IBigStepper(address(opcm.implementations().mipsImpl)),
permissioned: permissioned
});
}
function assertValidGameType(
OPContractsManager.AddGameInput memory agi,
OPContractsManager.AddGameOutput memory ago
)
internal
view
{
// Check the config for the game itself
assertEq(ago.faultDisputeGame.gameType().raw(), agi.disputeGameType.raw(), "gameType mismatch");
assertEq(
ago.faultDisputeGame.absolutePrestate().raw(),
agi.disputeAbsolutePrestate.raw(),
"absolutePrestate mismatch"
);
assertEq(ago.faultDisputeGame.maxGameDepth(), agi.disputeMaxGameDepth, "maxGameDepth mismatch");
assertEq(ago.faultDisputeGame.splitDepth(), agi.disputeSplitDepth, "splitDepth mismatch");
assertEq(
ago.faultDisputeGame.clockExtension().raw(), agi.disputeClockExtension.raw(), "clockExtension mismatch"
);
assertEq(
ago.faultDisputeGame.maxClockDuration().raw(),
agi.disputeMaxClockDuration.raw(),
"maxClockDuration mismatch"
);
assertEq(address(ago.faultDisputeGame.vm()), address(agi.vm), "vm address mismatch");
assertEq(address(ago.faultDisputeGame.weth()), address(ago.delayedWETH), "delayedWETH address mismatch");
assertEq(
address(ago.faultDisputeGame.anchorStateRegistry()),
address(chainDeployOutput.anchorStateRegistryProxy),
"ASR address mismatch"
);
// Check the DGF
assertEq(
chainDeployOutput.disputeGameFactoryProxy.gameImpls(agi.disputeGameType).gameType().raw(),
agi.disputeGameType.raw(),
"gameType mismatch"
);
assertEq(
address(chainDeployOutput.disputeGameFactoryProxy.gameImpls(agi.disputeGameType)),
address(ago.faultDisputeGame),
"gameImpl address mismatch"
);
assertEq(address(ago.faultDisputeGame.weth()), address(ago.delayedWETH), "weth address mismatch");
assertEq(
chainDeployOutput.disputeGameFactoryProxy.initBonds(agi.disputeGameType), agi.initialBond, "bond mismatch"
);
}
}
packages/contracts-bedrock/test/dispute/AnchorStateRegistry.t.sol
View file @
3f4d94a4
...
@@ -8,6 +8,8 @@ import { FaultDisputeGame_Init, _changeClaimStatus } from "test/dispute/FaultDis
...
@@ -8,6 +8,8 @@ import { FaultDisputeGame_Init, _changeClaimStatus } from "test/dispute/FaultDis
import "src/dispute/lib/Types.sol";
import "src/dispute/lib/Types.sol";
import "src/dispute/lib/Errors.sol";
import "src/dispute/lib/Errors.sol";
import { Hash } from "src/dispute/lib/Types.sol";
contract AnchorStateRegistry_Init is FaultDisputeGame_Init {
contract AnchorStateRegistry_Init is FaultDisputeGame_Init {
function setUp() public virtual override {
function setUp() public virtual override {
// Duplicating the initialization/setup logic of FaultDisputeGame_Test.
// Duplicating the initialization/setup logic of FaultDisputeGame_Test.
...
...
packages/contracts-bedrock/test/universal/Specs.t.sol
View file @
3f4d94a4
...
@@ -781,6 +781,7 @@ contract Specification_Test is CommonTest {
...
@@ -781,6 +781,7 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.blueprints.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.blueprints.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.implementations.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.implementations.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.addGameType.selector });
// OPContractsManagerInterop
// OPContractsManagerInterop
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") });
...
@@ -792,6 +793,7 @@ contract Specification_Test is CommonTest {
...
@@ -792,6 +793,7 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.blueprints.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.blueprints.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.implementations.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.implementations.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.addGameType.selector });
// DeputyGuardianModule
// DeputyGuardianModule
_addSpec({
_addSpec({
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment