Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

OPSM: Deploy Permissioned Game #12064

Merged
merged 15 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion op-chain-ops/deployer/integration_test/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ import (
const TestParams = `
participants:
- el_type: geth
el_extra_params:
- "--gcmode=archive"
cl_type: lighthouse
network_params:
prefunded_accounts: '{ "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266": { "balance": "1000000ETH" } }'
Expand All @@ -41,6 +43,7 @@ network_params:
}'
network_id: "77799777"
seconds_per_slot: 3
genesis_delay: 0
`

type deployerKey struct{}
Expand All @@ -56,7 +59,7 @@ func (d *deployerKey) String() string {
func TestEndToEndApply(t *testing.T) {
kurtosisutil.Test(t)

lgr := testlog.Logger(t, slog.LevelInfo)
lgr := testlog.Logger(t, slog.LevelDebug)

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down Expand Up @@ -189,6 +192,10 @@ func TestEndToEndApply(t *testing.T) {
{"DelayedWETHPermissionlessGameProxyAddress", chainState.DelayedWETHPermissionlessGameProxyAddress},
}
for _, addr := range chainAddrs {
// TODO Delete this `if`` block once FaultDisputeGameAddress is deployed.
if addr.name == "FaultDisputeGameAddress" {
continue
}
t.Run(fmt.Sprintf("chain %s - %s", chainState.ID, addr.name), func(t *testing.T) {
code, err := l1Client.CodeAt(ctx, addr.addr, nil)
require.NoError(t, err)
Expand Down
52 changes: 42 additions & 10 deletions packages/contracts-bedrock/scripts/DeployImplementations.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";

import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Bytes } from "src/libraries/Bytes.sol";

import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
import { Proxy } from "src/universal/Proxy.sol";
Expand All @@ -23,6 +24,7 @@ import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol";
import { MIPS } from "src/cannon/MIPS.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol";

import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
import { ProtocolVersions } from "src/L1/ProtocolVersions.sol";
Expand Down Expand Up @@ -514,10 +516,11 @@ contract DeployImplementations is Script {
blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(L1ChugSplashProxy).creationCode), salt);
blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(type(ResolvedDelegateProxy).creationCode), salt);
blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(type(AnchorStateRegistry).creationCode), salt);
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(type(PermissionedDisputeGame).creationCode, salt);
vm.stopBroadcast();
// forgefmt: disable-end

OPStackManager.ImplementationSetter[] memory setters = new OPStackManager.ImplementationSetter[](7);
OPStackManager.ImplementationSetter[] memory setters = new OPStackManager.ImplementationSetter[](9);
setters[0] = OPStackManager.ImplementationSetter({
name: "L1ERC721Bridge",
info: OPStackManager.Implementation(address(_dio.l1ERC721BridgeImpl()), L1ERC721Bridge.initialize.selector)
Expand All @@ -543,13 +546,22 @@ contract DeployImplementations is Script {
name: "L1StandardBridge",
info: OPStackManager.Implementation(address(_dio.l1StandardBridgeImpl()), L1StandardBridge.initialize.selector)
});

setters[6] = OPStackManager.ImplementationSetter({
name: "DisputeGameFactory",
info: OPStackManager.Implementation(
address(_dio.disputeGameFactoryImpl()), DisputeGameFactory.initialize.selector
)
});
setters[7] = OPStackManager.ImplementationSetter({
name: "DelayedWETH",
info: OPStackManager.Implementation(address(_dio.delayedWETHImpl()), DelayedWETH.initialize.selector)
});
setters[8] = OPStackManager.ImplementationSetter({
name: "MIPS",
// MIPS is a singleton for all chains, so it doesn't need to be initialized, so the
// selector is just `bytes4(0)`.
info: OPStackManager.Implementation(address(_dio.mipsSingleton()), bytes4(0))
});

// This call contains a broadcast to deploy OPSM which is proxied.
OPStackManager opsmProxy = createOPSMContract(_dii, _dio, blueprints, release, setters);
Expand Down Expand Up @@ -617,14 +629,14 @@ contract DeployImplementations is Script {
// The fault proofs contracts are configured as follows:
// | Contract | Proxied | Deployment | MCP Ready |
// |-------------------------|---------|-----------------------------------|------------|
// | DisputeGameFactory | Yes | Bespoke | Yes | X
// | AnchorStateRegistry | Yes | Bespoke | No | X
// | FaultDisputeGame | No | Bespoke | No | Todo
// | PermissionedDisputeGame | No | Bespoke | No | Todo
// | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No | Todo: Proxies.
// | PreimageOracle | No | Shared | N/A | X
// | MIPS | No | Shared | N/A | X
// | OptimismPortal2 | Yes | Shared | No | X
// | DisputeGameFactory | Yes | Bespoke | Yes |
// | AnchorStateRegistry | Yes | Bespoke | No |
// | FaultDisputeGame | No | Bespoke | No | Not yet supported by OPCM
// | PermissionedDisputeGame | No | Bespoke | No |
// | DelayedWETH | Yes | Two bespoke (one per DisputeGame) | No |
// | PreimageOracle | No | Shared | N/A |
// | MIPS | No | Shared | N/A |
// | OptimismPortal2 | Yes | Shared | No |
//
// 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
Expand Down Expand Up @@ -731,6 +743,26 @@ contract DeployImplementations is Script {
}
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);
}
}

// Similar to how DeploySuperchain.s.sol contains a lot of comments to thoroughly document the script
Expand Down
38 changes: 30 additions & 8 deletions packages/contracts-bedrock/scripts/DeployOPChain.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { BaseDeployIO } from "scripts/utils/BaseDeployIO.sol";

import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";

Expand All @@ -23,7 +24,7 @@ import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol";
import { GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";
import { Claim, GameType, GameTypes, Hash, OutputRoot } from "src/dispute/lib/Types.sol";

import { OPStackManager } from "src/L1/OPStackManager.sol";
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
Expand Down Expand Up @@ -201,7 +202,7 @@ contract DeployOPChainOutput is BaseDeployIO {
address(_disputeGameFactoryProxy),
address(_anchorStateRegistryProxy),
address(_anchorStateRegistryImpl),
address(_faultDisputeGame),
// address(_faultDisputeGame),
address(_permissionedDisputeGame),
address(_delayedWETHPermissionedGameProxy),
address(_delayedWETHPermissionlessGameProxy)
Expand Down Expand Up @@ -289,18 +290,32 @@ contract DeployOPChainOutput is BaseDeployIO {
// -------- Deployment Assertions --------

function assertValidDeploy(DeployOPChainInput _doi) internal {
assertValidAnchorStateRegistryProxy(_doi);
assertValidAnchorStateRegistryImpl(_doi);
assertValidAnchorStateRegistryProxy(_doi);
assertValidDelayedWETHs(_doi);
assertValidDisputeGameFactory(_doi);
assertValidL1CrossDomainMessenger(_doi);
assertValidL1ERC721Bridge(_doi);
assertValidL1StandardBridge(_doi);
assertValidOptimismMintableERC20Factory(_doi);
assertValidOptimismPortal(_doi);
assertValidPermissionedDisputeGame(_doi);
assertValidSystemConfig(_doi);
// TODO Other FP assertions like the dispute games, anchor state registry, etc.
// TODO add initialization assertions
}

function assertValidPermissionedDisputeGame(DeployOPChainInput _doi) internal view {
PermissionedDisputeGame game = permissionedDisputeGame();

require(GameType.unwrap(game.gameType()) == GameType.unwrap(GameTypes.PERMISSIONED_CANNON), "DPG-10");
require(Claim.unwrap(game.absolutePrestate()) == bytes32(hex"dead"), "DPG-20");

OPStackManager opsm = _doi.opsmProxy();
(address mips,) = opsm.implementations(opsm.latestRelease(), "MIPS");
require(game.vm() == IBigStepper(mips), "DPG-30");

require(address(game.weth()) == address(delayedWETHPermissionedGameProxy()), "DPG-40");
require(address(game.anchorStateRegistry()) == address(anchorStateRegistryProxy()), "DPG-50");
require(game.l2ChainId() == _doi.l2ChainId(), "DPG-60");
}

function assertValidAnchorStateRegistryProxy(DeployOPChainInput) internal {
Expand Down Expand Up @@ -436,7 +451,14 @@ contract DeployOPChainOutput is BaseDeployIO {
}

function assertValidDisputeGameFactory(DeployOPChainInput) internal view {
// TODO add in once FP support is added.
DisputeGameFactory factory = disputeGameFactoryProxy();

DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 });

require(
address(factory.gameImpls(GameTypes.PERMISSIONED_CANNON)) == address(permissionedDisputeGame()), "DF-10"
);
require(factory.owner() == address(opChainProxyAdmin()), "DF-20");
}

function assertValidDelayedWETHs(DeployOPChainInput) internal view {
Expand Down Expand Up @@ -480,7 +502,7 @@ contract DeployOPChain is Script {
vm.label(address(deployOutput.disputeGameFactoryProxy), "disputeGameFactoryProxy");
vm.label(address(deployOutput.anchorStateRegistryProxy), "anchorStateRegistryProxy");
vm.label(address(deployOutput.anchorStateRegistryImpl), "anchorStateRegistryImpl");
vm.label(address(deployOutput.faultDisputeGame), "faultDisputeGame");
// vm.label(address(deployOutput.faultDisputeGame), "faultDisputeGame");
vm.label(address(deployOutput.permissionedDisputeGame), "permissionedDisputeGame");
vm.label(address(deployOutput.delayedWETHPermissionedGameProxy), "delayedWETHPermissionedGameProxy");
vm.label(address(deployOutput.delayedWETHPermissionlessGameProxy), "delayedWETHPermissionlessGameProxy");
Expand All @@ -498,7 +520,7 @@ contract DeployOPChain is Script {
_doo.set(_doo.disputeGameFactoryProxy.selector, address(deployOutput.disputeGameFactoryProxy));
_doo.set(_doo.anchorStateRegistryProxy.selector, address(deployOutput.anchorStateRegistryProxy));
_doo.set(_doo.anchorStateRegistryImpl.selector, address(deployOutput.anchorStateRegistryImpl));
_doo.set(_doo.faultDisputeGame.selector, address(deployOutput.faultDisputeGame));
// _doo.set(_doo.faultDisputeGame.selector, address(deployOutput.faultDisputeGame));
_doo.set(_doo.permissionedDisputeGame.selector, address(deployOutput.permissionedDisputeGame));
_doo.set(_doo.delayedWETHPermissionedGameProxy.selector, address(deployOutput.delayedWETHPermissionedGameProxy));
_doo.set(
Expand Down
4 changes: 2 additions & 2 deletions packages/contracts-bedrock/semver-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649"
},
"src/L1/OPStackManager.sol": {
"initCodeHash": "0x4bffecbd95e63f9bd04ab8e3c6a804cc25e0cd151ebeb7f8d6b9330332e6eb20",
"sourceCodeHash": "0x850f1eacc77f1a5c680625196618bc4b4332cb68924d9eddd57c749bedcd7c94"
"initCodeHash": "0x5b451782192b8429f6822c88270c4f0dbd10342518c5695ecf4dff7b5ebfb4e4",
"sourceCodeHash": "0x4a9c242ce96471437ec97662d2365a7bda376db765c630a41cbe238811f1df51"
},
"src/L1/OptimismPortal.sol": {
"initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190",
Expand Down
25 changes: 25 additions & 0 deletions packages/contracts-bedrock/snapshots/abi/OPStackManager.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPStackManager.Blueprints",
Expand Down Expand Up @@ -298,6 +308,16 @@
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPStackManager.Blueprints",
Expand Down Expand Up @@ -499,6 +519,11 @@
"name": "EmptyInitcode",
"type": "error"
},
{
"inputs": [],
"name": "IdentityPrecompileCallFailed",
"type": "error"
},
{
"inputs": [],
"name": "InvalidChainId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,16 @@
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPStackManager.Blueprints",
Expand Down Expand Up @@ -298,6 +308,16 @@
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPStackManager.Blueprints",
Expand Down Expand Up @@ -499,6 +519,11 @@
"name": "EmptyInitcode",
"type": "error"
},
{
"inputs": [],
"name": "IdentityPrecompileCallFailed",
"type": "error"
},
{
"inputs": [],
"name": "InvalidChainId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,39 @@
"slot": "0",
"type": "bool"
},
{
"bytes": "192",
"label": "blueprint",
"offset": 0,
"slot": "1",
"type": "struct OPStackManager.Blueprints"
},
{
"bytes": "32",
"label": "latestRelease",
"offset": 0,
"slot": "7",
"slot": "1",
"type": "string"
},
{
"bytes": "32",
"label": "implementations",
"offset": 0,
"slot": "8",
"slot": "2",
"type": "mapping(string => mapping(string => struct OPStackManager.Implementation))"
},
{
"bytes": "32",
"label": "systemConfigs",
"offset": 0,
"slot": "9",
"slot": "3",
"type": "mapping(uint256 => contract SystemConfig)"
},
{
"bytes": "256",
"label": "blueprint",
"offset": 0,
"slot": "4",
"type": "struct OPStackManager.Blueprints"
},
{
"bytes": "1600",
"label": "__gap",
"offset": 0,
"slot": "12",
"type": "uint256[50]"
}
]
Loading