Commit 6823d676 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

op-e2e: Nuke allocs (#13364)

* op-e2e: Nuke allocs

This PR integrates op-deployer with op-e2e for the purposes of generating L1/L2 allocs on-the-fly. As a result, there is no longer any need to run `make devnet-allocs` or otherwise continue maintaining the legacy Python devnet. The generated allocs are at parity with those generated by the Python devnet - i.e., they contain the Alphabet VM, the fast fault game, and the deploy config customizations in `devnetL1.json`.

One notable change here is that the ability to generate new allocs files for L2OO chains will no longer be possible post-Holocene. To continue supporting the L2OO tests for the time being, the L2OO allocs files have been archived at the Holocene fork.

Cleaning up the old devnet will be handled separately.

* fix broken tests

* bring back l2oo test

* swap more keys

* more keys

* swap prestates

* remove dead code

* fix prestate proof

* Code review updates

* toml fields
parent a602c5c3
...@@ -34,6 +34,7 @@ require ( ...@@ -34,6 +34,7 @@ require (
github.com/libp2p/go-libp2p-mplex v0.9.0 github.com/libp2p/go-libp2p-mplex v0.9.0
github.com/libp2p/go-libp2p-pubsub v0.12.0 github.com/libp2p/go-libp2p-pubsub v0.12.0
github.com/libp2p/go-libp2p-testing v0.12.0 github.com/libp2p/go-libp2p-testing v0.12.0
github.com/lmittmann/w3 v0.17.1
github.com/mattn/go-isatty v0.0.20 github.com/mattn/go-isatty v0.0.20
github.com/minio/minio-go/v7 v7.0.81 github.com/minio/minio-go/v7 v7.0.81
github.com/multiformats/go-base32 v0.1.0 github.com/multiformats/go-base32 v0.1.0
...@@ -157,7 +158,7 @@ require ( ...@@ -157,7 +158,7 @@ require (
github.com/libp2p/go-yamux/v4 v4.0.1 // indirect github.com/libp2p/go-yamux/v4 v4.0.1 // indirect
github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mholt/archiver v3.1.1+incompatible // indirect github.com/mholt/archiver v3.1.1+incompatible // indirect
github.com/miekg/dns v1.1.62 // indirect github.com/miekg/dns v1.1.62 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
...@@ -208,7 +209,7 @@ require ( ...@@ -208,7 +209,7 @@ require (
github.com/quic-go/quic-go v0.46.0 // indirect github.com/quic-go/quic-go v0.46.0 // indirect
github.com/quic-go/webtransport-go v0.8.0 // indirect github.com/quic-go/webtransport-go v0.8.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect
github.com/rs/cors v1.11.0 // indirect github.com/rs/cors v1.11.0 // indirect
github.com/rs/xid v1.6.0 // indirect github.com/rs/xid v1.6.0 // indirect
......
...@@ -485,6 +485,8 @@ github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQsc ...@@ -485,6 +485,8 @@ github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQsc
github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU=
github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ= github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
github.com/lmittmann/w3 v0.17.1 h1:zdXIimmNmYfqOFur+Jqc9Yqwtq6jwnsQufbTOnSAtW4=
github.com/lmittmann/w3 v0.17.1/go.mod h1:WVUGMbL83WYBu4Sge3SVlW3qIG4VaHe+S8+UUnwz9Eg=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
...@@ -509,8 +511,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE ...@@ -509,8 +511,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU= github.com/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
...@@ -711,8 +713,8 @@ github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YV ...@@ -711,8 +713,8 @@ github.com/quic-go/webtransport-go v0.8.0/go.mod h1:N99tjprW432Ut5ONql/aUhSLT0YV
github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk= github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU= github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
......
package foundry package foundry
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"maps" "maps"
...@@ -76,9 +77,19 @@ func (d *forgeAllocsDump) OnAccount(address *common.Address, account state.DumpA ...@@ -76,9 +77,19 @@ func (d *forgeAllocsDump) OnAccount(address *common.Address, account state.DumpA
} }
} }
// Copy returns a deep copy of the ForgeAllocs. We can't
// perform a shallow copy here because some tests modify
// the accounts individually.
func (d *ForgeAllocs) Copy() *ForgeAllocs { func (d *ForgeAllocs) Copy() *ForgeAllocs {
out := make(types.GenesisAlloc, len(d.Accounts)) out := make(types.GenesisAlloc, len(d.Accounts))
maps.Copy(out, d.Accounts) for k, v := range d.Accounts {
out[k] = types.Account{
Code: bytes.Clone(v.Code),
Storage: maps.Clone(v.Storage),
Balance: new(big.Int).Set(v.Balance),
Nonce: v.Nonce,
}
}
return &ForgeAllocs{Accounts: out} return &ForgeAllocs{Accounts: out}
} }
......
...@@ -218,6 +218,7 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme ...@@ -218,6 +218,7 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
DisputeSplitDepth: cfg.DisputeSplitDepth, DisputeSplitDepth: cfg.DisputeSplitDepth,
DisputeClockExtension: cfg.DisputeClockExtension, DisputeClockExtension: cfg.DisputeClockExtension,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration, DisputeMaxClockDuration: cfg.DisputeMaxClockDuration,
StartingAnchorRoots: opcm.PermissionedGameStartingAnchorRoots,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err) return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err)
......
...@@ -45,6 +45,15 @@ type Locator struct { ...@@ -45,6 +45,15 @@ type Locator struct {
Tag string Tag string
} }
func NewFileLocator(path string) (*Locator, error) {
u, err := url.Parse("file://" + path)
if err != nil {
return nil, fmt.Errorf("failed to parse URL: %w", err)
}
return &Locator{URL: u}, nil
}
func (a *Locator) UnmarshalText(text []byte) error { func (a *Locator) UnmarshalText(text []byte) error {
str := string(text) str := string(text)
......
...@@ -3,6 +3,8 @@ package inspect ...@@ -3,6 +3,8 @@ package inspect
import ( import (
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
...@@ -18,6 +20,33 @@ type L1Contracts struct { ...@@ -18,6 +20,33 @@ type L1Contracts struct {
ImplementationsDeployment ImplementationsDeployment `json:"implementationsDeployment"` ImplementationsDeployment ImplementationsDeployment `json:"implementationsDeployment"`
} }
func (l L1Contracts) AsL1Deployments() *genesis.L1Deployments {
return &genesis.L1Deployments{
AddressManager: l.OpChainDeployment.AddressManagerAddress,
DisputeGameFactory: l.ImplementationsDeployment.DisputeGameFactoryImplAddress,
DisputeGameFactoryProxy: l.OpChainDeployment.DisputeGameFactoryProxyAddress,
L1CrossDomainMessenger: l.ImplementationsDeployment.L1CrossDomainMessengerImplAddress,
L1CrossDomainMessengerProxy: l.OpChainDeployment.L1CrossDomainMessengerProxyAddress,
L1ERC721Bridge: l.ImplementationsDeployment.L1ERC721BridgeImplAddress,
L1ERC721BridgeProxy: l.OpChainDeployment.L1ERC721BridgeProxyAddress,
L1StandardBridge: l.ImplementationsDeployment.L1StandardBridgeImplAddress,
L1StandardBridgeProxy: l.OpChainDeployment.L1StandardBridgeProxyAddress,
L2OutputOracle: common.Address{},
L2OutputOracleProxy: common.Address{},
OptimismMintableERC20Factory: l.ImplementationsDeployment.OptimismMintableERC20FactoryImplAddress,
OptimismMintableERC20FactoryProxy: l.OpChainDeployment.OptimismMintableERC20FactoryProxyAddress,
OptimismPortal: l.ImplementationsDeployment.OptimismPortalImplAddress,
OptimismPortalProxy: l.OpChainDeployment.OptimismPortalProxyAddress,
ProxyAdmin: l.OpChainDeployment.ProxyAdminAddress,
SystemConfig: l.ImplementationsDeployment.SystemConfigImplAddress,
SystemConfigProxy: l.OpChainDeployment.SystemConfigProxyAddress,
ProtocolVersions: l.SuperchainDeployment.ProtocolVersionsImplAddress,
ProtocolVersionsProxy: l.SuperchainDeployment.ProtocolVersionsProxyAddress,
DataAvailabilityChallenge: l.OpChainDeployment.DataAvailabilityChallengeImplAddress,
DataAvailabilityChallengeProxy: l.OpChainDeployment.DataAvailabilityChallengeProxyAddress,
}
}
type SuperchainDeployment struct { type SuperchainDeployment struct {
ProxyAdminAddress common.Address `json:"proxyAdminAddress"` ProxyAdminAddress common.Address `json:"proxyAdminAddress"`
SuperchainConfigProxyAddress common.Address `json:"superchainConfigProxyAddress"` SuperchainConfigProxyAddress common.Address `json:"superchainConfigProxyAddress"`
...@@ -42,6 +71,8 @@ type OpChainDeployment struct { ...@@ -42,6 +71,8 @@ type OpChainDeployment struct {
PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"` PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"`
DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"` DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"`
// DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"` // DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"`
DataAvailabilityChallengeProxyAddress common.Address `json:"dataAvailabilityChallengeProxyAddress"`
DataAvailabilityChallengeImplAddress common.Address `json:"dataAvailabilityChallengeImplAddress"`
} }
type ImplementationsDeployment struct { type ImplementationsDeployment struct {
...@@ -110,6 +141,8 @@ func L1(globalState *state.State, chainID common.Hash) (*L1Contracts, error) { ...@@ -110,6 +141,8 @@ func L1(globalState *state.State, chainID common.Hash) (*L1Contracts, error) {
FaultDisputeGameAddress: chainState.FaultDisputeGameAddress, FaultDisputeGameAddress: chainState.FaultDisputeGameAddress,
PermissionedDisputeGameAddress: chainState.PermissionedDisputeGameAddress, PermissionedDisputeGameAddress: chainState.PermissionedDisputeGameAddress,
DelayedWETHPermissionedGameProxyAddress: chainState.DelayedWETHPermissionedGameProxyAddress, DelayedWETHPermissionedGameProxyAddress: chainState.DelayedWETHPermissionedGameProxyAddress,
DataAvailabilityChallengeProxyAddress: chainState.DataAvailabilityChallengeProxyAddress,
DataAvailabilityChallengeImplAddress: chainState.DataAvailabilityChallengeImplAddress,
// DelayedWETHPermissionlessGameProxyAddress: chainState.DelayedWETHPermissionlessGameProxyAddress, // DelayedWETHPermissionlessGameProxyAddress: chainState.DelayedWETHPermissionlessGameProxyAddress,
}, },
ImplementationsDeployment: ImplementationsDeployment{ ImplementationsDeployment: ImplementationsDeployment{
......
...@@ -182,11 +182,7 @@ func TestApplyExistingOPCM(t *testing.T) { ...@@ -182,11 +182,7 @@ func TestApplyExistingOPCM(t *testing.T) {
func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, versions standard.L1Versions) { func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, versions standard.L1Versions) {
op_e2e.InitParallel(t) op_e2e.InitParallel(t)
anvil.Test(t) require.NotEmpty(t, forkRPCUrl, "no fork RPC URL provided")
if forkRPCUrl == "" {
t.Skip("no fork RPC URL provided")
}
lgr := testlog.Logger(t, slog.LevelDebug) lgr := testlog.Logger(t, slog.LevelDebug)
...@@ -406,7 +402,6 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve ...@@ -406,7 +402,6 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve
//Use a custom equality function to compare the genesis allocs //Use a custom equality function to compare the genesis allocs
//because the reflect-based one is really slow //because the reflect-based one is really slow
actAllocs := st.Chains[0].Allocs.Data.Accounts actAllocs := st.Chains[0].Allocs.Data.Accounts
require.Equal(t, len(expAllocs), len(actAllocs))
for addr, expAcc := range expAllocs { for addr, expAcc := range expAllocs {
actAcc, ok := actAllocs[addr] actAcc, ok := actAllocs[addr]
require.True(t, ok) require.True(t, ok)
...@@ -420,11 +415,17 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve ...@@ -420,11 +415,17 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve
} }
storageChecker(addr, actAcc.Storage) storageChecker(addr, actAcc.Storage)
} }
for addr := range actAllocs {
if _, ok := expAllocs[addr]; ok {
continue
}
t.Logf("unexpected account: %s", addr.Hex())
}
} }
func TestGlobalOverrides(t *testing.T) { func TestGlobalOverrides(t *testing.T) {
op_e2e.InitParallel(t) op_e2e.InitParallel(t)
kurtosisutil.Test(t)
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
...@@ -499,9 +500,9 @@ func TestProofParamOverrides(t *testing.T) { ...@@ -499,9 +500,9 @@ func TestProofParamOverrides(t *testing.T) {
opts, intent, st := setupGenesisChain(t, defaultL1ChainID) opts, intent, st := setupGenesisChain(t, defaultL1ChainID)
intent.GlobalDeployOverrides = map[string]any{ intent.GlobalDeployOverrides = map[string]any{
"withdrawalDelaySeconds": standard.WithdrawalDelaySeconds + 1, "faultGameWithdrawalDelay": standard.WithdrawalDelaySeconds + 1,
"minProposalSizeBytes": standard.MinProposalSizeBytes + 1, "preimageOracleMinProposalSize": standard.MinProposalSizeBytes + 1,
"challengePeriodSeconds": standard.ChallengePeriodSeconds + 1, "preimageOracleChallengePeriod": standard.ChallengePeriodSeconds + 1,
"proofMaturityDelaySeconds": standard.ProofMaturityDelaySeconds + 1, "proofMaturityDelaySeconds": standard.ProofMaturityDelaySeconds + 1,
"disputeGameFinalityDelaySeconds": standard.DisputeGameFinalityDelaySeconds + 1, "disputeGameFinalityDelaySeconds": standard.DisputeGameFinalityDelaySeconds + 1,
"mipsVersion": standard.MIPSVersion + 1, "mipsVersion": standard.MIPSVersion + 1,
...@@ -529,17 +530,17 @@ func TestProofParamOverrides(t *testing.T) { ...@@ -529,17 +530,17 @@ func TestProofParamOverrides(t *testing.T) {
address common.Address address common.Address
}{ }{
{ {
"withdrawalDelaySeconds", "faultGameWithdrawalDelay",
uint64Caster, uint64Caster,
st.ImplementationsDeployment.DelayedWETHImplAddress, st.ImplementationsDeployment.DelayedWETHImplAddress,
}, },
{ {
"minProposalSizeBytes", "preimageOracleMinProposalSize",
uint64Caster, uint64Caster,
st.ImplementationsDeployment.PreimageOracleSingletonAddress, st.ImplementationsDeployment.PreimageOracleSingletonAddress,
}, },
{ {
"challengePeriodSeconds", "preimageOracleChallengePeriod",
uint64Caster, uint64Caster,
st.ImplementationsDeployment.PreimageOracleSingletonAddress, st.ImplementationsDeployment.PreimageOracleSingletonAddress,
}, },
...@@ -708,7 +709,9 @@ func TestAdditionalDisputeGames(t *testing.T) { ...@@ -708,7 +709,9 @@ func TestAdditionalDisputeGames(t *testing.T) {
defer cancel() defer cancel()
opts, intent, st := setupGenesisChain(t, defaultL1ChainID) opts, intent, st := setupGenesisChain(t, defaultL1ChainID)
(&intent.Chains[0].Roles).L1ProxyAdminOwner = crypto.PubkeyToAddress(opts.DeployerPrivateKey.PublicKey) deployerAddr := crypto.PubkeyToAddress(opts.DeployerPrivateKey.PublicKey)
(&intent.Chains[0].Roles).L1ProxyAdminOwner = deployerAddr
intent.SuperchainRoles.Guardian = deployerAddr
intent.GlobalDeployOverrides = map[string]any{ intent.GlobalDeployOverrides = map[string]any{
"challengePeriodSeconds": 1, "challengePeriodSeconds": 1,
} }
...@@ -726,6 +729,7 @@ func TestAdditionalDisputeGames(t *testing.T) { ...@@ -726,6 +729,7 @@ func TestAdditionalDisputeGames(t *testing.T) {
UseCustomOracle: true, UseCustomOracle: true,
OracleMinProposalSize: 10000, OracleMinProposalSize: 10000,
OracleChallengePeriodSeconds: 120, OracleChallengePeriodSeconds: 120,
MakeRespected: true,
VMType: state.VMTypeAlphabet, VMType: state.VMTypeAlphabet,
}, },
} }
...@@ -848,7 +852,7 @@ func newIntent( ...@@ -848,7 +852,7 @@ func newIntent(
ProtocolVersionsOwner: addrFor(t, dk, devkeys.SuperchainDeployerKey.Key(l1ChainID)), ProtocolVersionsOwner: addrFor(t, dk, devkeys.SuperchainDeployerKey.Key(l1ChainID)),
Guardian: addrFor(t, dk, devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)), Guardian: addrFor(t, dk, devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)),
}, },
FundDevAccounts: true, FundDevAccounts: false,
L1ContractsLocator: l1Loc, L1ContractsLocator: l1Loc,
L2ContractsLocator: l2Loc, L2ContractsLocator: l2Loc,
Chains: []*state.ChainIntent{ Chains: []*state.ChainIntent{
......
package opcm
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/lmittmann/w3"
)
var anchorRootFunc = w3.MustNewFunc(`
dummy((uint32 gameType, (bytes32 root, uint256 l2BlockNumber) outputRoot)[] roots)
`, "")
type StartingAnchorRoot struct {
GameType uint32
Root common.Hash
L2BlockNumber *big.Int
}
var DefaultStartingAnchorRoot = StartingAnchorRoot{
GameType: 1,
Root: common.Hash{0xde, 0xad},
L2BlockNumber: common.Big0,
}
type encodingStartingAnchorRoot struct {
GameType uint32
OutputRoot struct {
Root common.Hash
L2BlockNumber *big.Int
}
}
func EncodeStartingAnchorRoots(roots []StartingAnchorRoot) ([]byte, error) {
args := make([]encodingStartingAnchorRoot, len(roots))
for i, root := range roots {
args[i] = encodingStartingAnchorRoot{
GameType: root.GameType,
OutputRoot: struct {
Root common.Hash
L2BlockNumber *big.Int
}{
Root: root.Root,
L2BlockNumber: root.L2BlockNumber,
},
}
}
encoded, err := anchorRootFunc.EncodeArgs(args)
if err != nil {
return nil, fmt.Errorf("error encoding anchor roots: %w", err)
}
// Chop off the function selector since w3 can't serialize structs directly
return encoded[4:], nil
}
package opcm
import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestEncodeStartingAnchorRoots(t *testing.T) {
encoded, err := EncodeStartingAnchorRoots([]StartingAnchorRoot{
DefaultStartingAnchorRoot,
})
require.NoError(t, err)
require.EqualValues(t, PermissionedGameStartingAnchorRoots, encoded)
encoded, err = EncodeStartingAnchorRoots([]StartingAnchorRoot{
{
GameType: 0,
L2BlockNumber: common.Big0,
},
{
GameType: 1,
Root: common.Hash{0xde, 0xad},
L2BlockNumber: big.NewInt(0),
},
})
require.NoError(t, err)
require.EqualValues(t,
common.Hex2Bytes(
"0000000000000000000000000000000000000000000000000000000000000020"+
"0000000000000000000000000000000000000000000000000000000000000002"+
"0000000000000000000000000000000000000000000000000000000000000000"+
"0000000000000000000000000000000000000000000000000000000000000000"+
"0000000000000000000000000000000000000000000000000000000000000000"+
"0000000000000000000000000000000000000000000000000000000000000001"+
"dead000000000000000000000000000000000000000000000000000000000000"+
"0000000000000000000000000000000000000000000000000000000000000000"),
encoded,
)
}
...@@ -8,6 +8,8 @@ import ( ...@@ -8,6 +8,8 @@ import (
type SetDisputeGameImplInput struct { type SetDisputeGameImplInput struct {
Factory common.Address Factory common.Address
Impl common.Address Impl common.Address
Portal common.Address
AnchorStateRegistry common.Address
GameType uint32 GameType uint32
} }
......
...@@ -2,6 +2,7 @@ package opcm ...@@ -2,6 +2,7 @@ package opcm
import ( import (
"fmt" "fmt"
"time"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/script" "github.com/ethereum-optimism/optimism/op-chain-ops/script"
...@@ -32,6 +33,8 @@ func L2Genesis(l2Host *script.Host, input *L2GenesisInput) error { ...@@ -32,6 +33,8 @@ func L2Genesis(l2Host *script.Host, input *L2GenesisInput) error {
l2Host.SetEnvVar("L2GENESIS_L1CrossDomainMessengerProxy", input.L1Deployments.L1CrossDomainMessengerProxy.String()) l2Host.SetEnvVar("L2GENESIS_L1CrossDomainMessengerProxy", input.L1Deployments.L1CrossDomainMessengerProxy.String())
l2Host.SetEnvVar("L2GENESIS_L1StandardBridgeProxy", input.L1Deployments.L1StandardBridgeProxy.String()) l2Host.SetEnvVar("L2GENESIS_L1StandardBridgeProxy", input.L1Deployments.L1StandardBridgeProxy.String())
l2Host.SetEnvVar("L2GENESIS_L1ERC721BridgeProxy", input.L1Deployments.L1ERC721BridgeProxy.String()) l2Host.SetEnvVar("L2GENESIS_L1ERC721BridgeProxy", input.L1Deployments.L1ERC721BridgeProxy.String())
allocsMode := input.L2Config.UpgradeScheduleDeployConfig.AllocMode(uint64(time.Now().Unix()))
l2Host.SetEnvVar("FORK", string(allocsMode))
deployConfig := &genesis.DeployConfig{ deployConfig := &genesis.DeployConfig{
L2InitializationConfig: input.L2Config, L2InitializationConfig: input.L2Config,
......
...@@ -11,18 +11,10 @@ type DeployMIPSInput struct { ...@@ -11,18 +11,10 @@ type DeployMIPSInput struct {
PreimageOracle common.Address PreimageOracle common.Address
} }
func (input *DeployMIPSInput) InputSet() bool {
return true
}
type DeployMIPSOutput struct { type DeployMIPSOutput struct {
MipsSingleton common.Address MipsSingleton common.Address
} }
func (output *DeployMIPSOutput) CheckOutput(input common.Address) error {
return nil
}
type DeployMIPSScript struct { type DeployMIPSScript struct {
Run func(input, output common.Address) error Run func(input, output common.Address) error
} }
......
...@@ -36,6 +36,7 @@ type DeployOPChainInputV160 struct { ...@@ -36,6 +36,7 @@ type DeployOPChainInputV160 struct {
DisputeSplitDepth uint64 DisputeSplitDepth uint64
DisputeClockExtension uint64 DisputeClockExtension uint64
DisputeMaxClockDuration uint64 DisputeMaxClockDuration uint64
StartingAnchorRoots []byte
AllowCustomDisputeParameters bool AllowCustomDisputeParameters bool
} }
...@@ -43,10 +44,6 @@ func (input *DeployOPChainInputV160) InputSet() bool { ...@@ -43,10 +44,6 @@ func (input *DeployOPChainInputV160) InputSet() bool {
return true return true
} }
func (input *DeployOPChainInputV160) StartingAnchorRoots() []byte {
return PermissionedGameStartingAnchorRoots
}
type DeployOPChainInputIsthmus struct { type DeployOPChainInputIsthmus struct {
DeployOPChainInputV160 DeployOPChainInputV160
SystemConfigFeeAdmin common.Address SystemConfigFeeAdmin common.Address
......
...@@ -5,7 +5,6 @@ import ( ...@@ -5,7 +5,6 @@ import (
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state" "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
...@@ -67,8 +66,10 @@ func deployDisputeGame( ...@@ -67,8 +66,10 @@ func deployDisputeGame(
return fmt.Errorf("failed to deploy preimage oracle: %w", err) return fmt.Errorf("failed to deploy preimage oracle: %w", err)
} }
oracleAddr = out.PreimageOracle oracleAddr = out.PreimageOracle
lgr.Info("oracle deployed", "oracleAddr", oracleAddr)
} else { } else {
lgr.Debug("using existing preimage oracle") lgr.Info("using existing preimage oracle")
oracleAddr = st.ImplementationsDeployment.PreimageOracleSingletonAddress
} }
lgr.Info("deploying VM", "vmType", game.VMType) lgr.Info("deploying VM", "vmType", game.VMType)
...@@ -77,12 +78,26 @@ func deployDisputeGame( ...@@ -77,12 +78,26 @@ func deployDisputeGame(
case state.VMTypeAlphabet: case state.VMTypeAlphabet:
out, err := opcm.DeployAlphabetVM(env.L1ScriptHost, opcm.DeployAlphabetVMInput{ out, err := opcm.DeployAlphabetVM(env.L1ScriptHost, opcm.DeployAlphabetVMInput{
AbsolutePrestate: game.DisputeAbsolutePrestate, AbsolutePrestate: game.DisputeAbsolutePrestate,
PreimageOracle: st.ImplementationsDeployment.PreimageOracleSingletonAddress, PreimageOracle: oracleAddr,
}) })
if err != nil { if err != nil {
return fmt.Errorf("failed to deploy Alphabet VM: %w", err) return fmt.Errorf("failed to deploy Alphabet VM: %w", err)
} }
vmAddr = out.AlphabetVM vmAddr = out.AlphabetVM
case state.VMTypeCannon1, state.VMTypeCannon2:
mipsVersion := 1
if game.VMType == state.VMTypeCannon2 {
mipsVersion = 2
}
out, err := opcm.DeployMIPS(env.L1ScriptHost, opcm.DeployMIPSInput{
MipsVersion: uint64(mipsVersion),
PreimageOracle: oracleAddr,
})
if err != nil {
return fmt.Errorf("failed to deploy MIPS VM: %w", err)
}
vmAddr = out.MipsSingleton
default: default:
return fmt.Errorf("unsupported VM type: %v", game.VMType) return fmt.Errorf("unsupported VM type: %v", game.VMType)
} }
...@@ -94,7 +109,7 @@ func deployDisputeGame( ...@@ -94,7 +109,7 @@ func deployDisputeGame(
VmAddress: vmAddr, VmAddress: vmAddr,
GameKind: "FaultDisputeGame", GameKind: "FaultDisputeGame",
GameType: game.DisputeGameType, GameType: game.DisputeGameType,
AbsolutePrestate: standard.DisputeAbsolutePrestate, AbsolutePrestate: game.DisputeAbsolutePrestate,
MaxGameDepth: game.DisputeMaxGameDepth, MaxGameDepth: game.DisputeMaxGameDepth,
SplitDepth: game.DisputeSplitDepth, SplitDepth: game.DisputeSplitDepth,
ClockExtension: game.DisputeClockExtension, ClockExtension: game.DisputeClockExtension,
...@@ -110,13 +125,19 @@ func deployDisputeGame( ...@@ -110,13 +125,19 @@ func deployDisputeGame(
} }
lgr.Info("dispute game deployed", "impl", out.DisputeGameImpl) lgr.Info("dispute game deployed", "impl", out.DisputeGameImpl)
lgr.Info("setting dispute game impl on factory") lgr.Info("setting dispute game impl on factory", "respected", game.MakeRespected)
if err := opcm.SetDisputeGameImpl( sdgiInput := opcm.SetDisputeGameImplInput{
env.L1ScriptHost,
opcm.SetDisputeGameImplInput{
Factory: thisState.DisputeGameFactoryProxyAddress, Factory: thisState.DisputeGameFactoryProxyAddress,
Impl: out.DisputeGameImpl, Impl: out.DisputeGameImpl,
}, GameType: game.DisputeGameType,
AnchorStateRegistry: thisState.AnchorStateRegistryProxyAddress,
}
if game.MakeRespected {
sdgiInput.Portal = thisState.OptimismPortalProxyAddress
}
if err := opcm.SetDisputeGameImpl(
env.L1ScriptHost,
sdgiInput,
); err != nil { ); err != nil {
return fmt.Errorf("failed to set dispute game impl: %w", err) return fmt.Errorf("failed to set dispute game impl: %w", err)
} }
......
...@@ -26,7 +26,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s ...@@ -26,7 +26,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
lgr := env.Logger.New("stage", "init", "strategy", "live") lgr := env.Logger.New("stage", "init", "strategy", "live")
lgr.Info("initializing pipeline") lgr.Info("initializing pipeline")
if err := initCommonChecks(st); err != nil { if err := initCommonChecks(intent, st); err != nil {
return err return err
} }
...@@ -100,7 +100,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s ...@@ -100,7 +100,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
return nil return nil
} }
func initCommonChecks(st *state.State) error { func initCommonChecks(intent *state.Intent, st *state.State) error {
// Ensure the state version is supported. // Ensure the state version is supported.
if !IsSupportedStateVersion(st.Version) { if !IsSupportedStateVersion(st.Version) {
return fmt.Errorf("unsupported state version: %d", st.Version) return fmt.Errorf("unsupported state version: %d", st.Version)
...@@ -112,6 +112,7 @@ func initCommonChecks(st *state.State) error { ...@@ -112,6 +112,7 @@ func initCommonChecks(st *state.State) error {
return fmt.Errorf("failed to generate CREATE2 salt: %w", err) return fmt.Errorf("failed to generate CREATE2 salt: %w", err)
} }
} }
return nil return nil
} }
...@@ -119,7 +120,7 @@ func InitGenesisStrategy(env *Env, intent *state.Intent, st *state.State) error ...@@ -119,7 +120,7 @@ func InitGenesisStrategy(env *Env, intent *state.Intent, st *state.State) error
lgr := env.Logger.New("stage", "init", "strategy", "genesis") lgr := env.Logger.New("stage", "init", "strategy", "genesis")
lgr.Info("initializing pipeline") lgr.Info("initializing pipeline")
if err := initCommonChecks(st); err != nil { if err := initCommonChecks(intent, st); err != nil {
return err return err
} }
......
...@@ -106,6 +106,27 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co ...@@ -106,6 +106,27 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co
return opcm.DeployOPChainInputV160{}, fmt.Errorf("error merging proof params from overrides: %w", err) return opcm.DeployOPChainInputV160{}, fmt.Errorf("error merging proof params from overrides: %w", err)
} }
startingAnchorRoots := opcm.PermissionedGameStartingAnchorRoots
if len(thisIntent.AdditionalDisputeGames) > 0 {
anchorRoots := []opcm.StartingAnchorRoot{
opcm.DefaultStartingAnchorRoot,
}
for _, game := range thisIntent.AdditionalDisputeGames {
anchorRoots = append(anchorRoots, opcm.StartingAnchorRoot{
GameType: game.DisputeGameType,
Root: game.DisputeAbsolutePrestate,
L2BlockNumber: common.Big0,
})
}
encoded, err := opcm.EncodeStartingAnchorRoots(anchorRoots)
if err != nil {
return opcm.DeployOPChainInputV160{}, fmt.Errorf("error encoding starting anchor roots: %w", err)
}
startingAnchorRoots = encoded
}
return opcm.DeployOPChainInputV160{ return opcm.DeployOPChainInputV160{
OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner, OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner,
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner, SystemConfigOwner: thisIntent.Roles.SystemConfigOwner,
...@@ -126,6 +147,7 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co ...@@ -126,6 +147,7 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co
DisputeClockExtension: proofParams.DisputeClockExtension, // 3 hours (input in seconds) DisputeClockExtension: proofParams.DisputeClockExtension, // 3 hours (input in seconds)
DisputeMaxClockDuration: proofParams.DisputeMaxClockDuration, // 3.5 days (input in seconds) DisputeMaxClockDuration: proofParams.DisputeMaxClockDuration, // 3.5 days (input in seconds)
AllowCustomDisputeParameters: proofParams.DangerouslyAllowCustomDisputeParameters, AllowCustomDisputeParameters: proofParams.DangerouslyAllowCustomDisputeParameters,
StartingAnchorRoots: startingAnchorRoots,
}, nil }, nil
} }
......
...@@ -12,6 +12,8 @@ type VMType string ...@@ -12,6 +12,8 @@ type VMType string
const ( const (
VMTypeAlphabet = "ALPHABET" VMTypeAlphabet = "ALPHABET"
VMTypeCannon1 = "CANNON1"
VMTypeCannon2 = "CANNON2"
) )
type ChainProofParams struct { type ChainProofParams struct {
...@@ -30,6 +32,7 @@ type AdditionalDisputeGame struct { ...@@ -30,6 +32,7 @@ type AdditionalDisputeGame struct {
UseCustomOracle bool UseCustomOracle bool
OracleMinProposalSize uint64 OracleMinProposalSize uint64
OracleChallengePeriodSeconds uint64 OracleChallengePeriodSeconds uint64
MakeRespected bool
} }
type ChainIntent struct { type ChainIntent struct {
......
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"math/big" "math/big"
op_service "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/jsonutil" "github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
...@@ -33,6 +35,9 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, ...@@ -33,6 +35,9 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
ProtocolVersionsProxy: state.SuperchainDeployment.ProtocolVersionsProxyAddress, ProtocolVersionsProxy: state.SuperchainDeployment.ProtocolVersionsProxyAddress,
}, },
L2InitializationConfig: genesis.L2InitializationConfig{ L2InitializationConfig: genesis.L2InitializationConfig{
DevDeployConfig: genesis.DevDeployConfig{
FundDevAccounts: intent.FundDevAccounts,
},
L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{ L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{
L2GenesisBlockGasLimit: 60_000_000, L2GenesisBlockGasLimit: 60_000_000,
L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas, L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas,
...@@ -69,12 +74,12 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, ...@@ -69,12 +74,12 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
// In-development hardforks should never be activated here. Instead, they // In-development hardforks should never be activated here. Instead, they
// should be specified as overrides. // should be specified as overrides.
UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{ UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{
L2GenesisRegolithTimeOffset: u64UtilPtr(0), L2GenesisRegolithTimeOffset: op_service.U64UtilPtr(0),
L2GenesisCanyonTimeOffset: u64UtilPtr(0), L2GenesisCanyonTimeOffset: op_service.U64UtilPtr(0),
L2GenesisDeltaTimeOffset: u64UtilPtr(0), L2GenesisDeltaTimeOffset: op_service.U64UtilPtr(0),
L2GenesisEcotoneTimeOffset: u64UtilPtr(0), L2GenesisEcotoneTimeOffset: op_service.U64UtilPtr(0),
L2GenesisFjordTimeOffset: u64UtilPtr(0), L2GenesisFjordTimeOffset: op_service.U64UtilPtr(0),
L2GenesisGraniteTimeOffset: u64UtilPtr(0), L2GenesisGraniteTimeOffset: op_service.U64UtilPtr(0),
UseInterop: intent.UseInterop, UseInterop: intent.UseInterop,
}, },
L2CoreDeployConfig: genesis.L2CoreDeployConfig{ L2CoreDeployConfig: genesis.L2CoreDeployConfig{
...@@ -108,7 +113,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State, ...@@ -108,7 +113,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
} }
if intent.UseInterop { if intent.UseInterop {
cfg.L2InitializationConfig.UpgradeScheduleDeployConfig.L2GenesisInteropTimeOffset = u64UtilPtr(0) cfg.L2InitializationConfig.UpgradeScheduleDeployConfig.L2GenesisInteropTimeOffset = op_service.U64UtilPtr(0)
} }
if chainState.StartBlock == nil { if chainState.StartBlock == nil {
...@@ -177,11 +182,6 @@ func mustHexBigFromHex(hex string) *hexutil.Big { ...@@ -177,11 +182,6 @@ func mustHexBigFromHex(hex string) *hexutil.Big {
return &hexBig return &hexBig
} }
func u64UtilPtr(in uint64) *hexutil.Uint64 {
util := hexutil.Uint64(in)
return &util
}
func calculateBatchInboxAddr(chainID common.Hash) common.Address { func calculateBatchInboxAddr(chainID common.Hash) common.Address {
var out common.Address var out common.Address
copy(out[1:], crypto.Keccak256(chainID[:])[:19]) copy(out[1:], crypto.Keccak256(chainID[:])[:19])
......
...@@ -46,9 +46,9 @@ var emptyAddress common.Address ...@@ -46,9 +46,9 @@ var emptyAddress common.Address
var emptyHash common.Hash var emptyHash common.Hash
type SuperchainProofParams struct { type SuperchainProofParams struct {
WithdrawalDelaySeconds uint64 `json:"withdrawalDelaySeconds" toml:"withdrawalDelaySeconds"` WithdrawalDelaySeconds uint64 `json:"faultGameWithdrawalDelay" toml:"faultGameWithdrawalDelay"`
MinProposalSizeBytes uint64 `json:"minProposalSizeBytes" toml:"minProposalSizeBytes"` MinProposalSizeBytes uint64 `json:"preimageOracleMinProposalSize" toml:"preimageOracleMinProposalSize"`
ChallengePeriodSeconds uint64 `json:"challengePeriodSeconds" toml:"challengePeriodSeconds"` ChallengePeriodSeconds uint64 `json:"preimageOracleChallengePeriod" toml:"preimageOracleChallengePeriod"`
ProofMaturityDelaySeconds uint64 `json:"proofMaturityDelaySeconds" toml:"proofMaturityDelaySeconds"` ProofMaturityDelaySeconds uint64 `json:"proofMaturityDelaySeconds" toml:"proofMaturityDelaySeconds"`
DisputeGameFinalityDelaySeconds uint64 `json:"disputeGameFinalityDelaySeconds" toml:"disputeGameFinalityDelaySeconds"` DisputeGameFinalityDelaySeconds uint64 `json:"disputeGameFinalityDelaySeconds" toml:"disputeGameFinalityDelaySeconds"`
MIPSVersion uint64 `json:"mipsVersion" toml:"mipsVersion"` MIPSVersion uint64 `json:"mipsVersion" toml:"mipsVersion"`
......
...@@ -98,19 +98,19 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -98,19 +98,19 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient()) sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient())
require.NoError(t, err) require.NoError(t, err)
sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.SysCfgOwner, sd.RollupCfg.L1ChainID) sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.Deployer, sd.RollupCfg.L1ChainID)
require.NoError(t, err) require.NoError(t, err)
owner, err := sysCfgContract.Owner(&bind.CallOpts{}) owner, err := sysCfgContract.Owner(&bind.CallOpts{})
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, dp.Addresses.SysCfgOwner, owner, "system config owner mismatch") require.Equal(t, dp.Addresses.Deployer, owner, "system config owner mismatch")
// Change the batch sender key to Bob! // Change the batch sender key to Bob!
tx, err := sysCfgContract.SetBatcherHash(sysCfgOwner, eth.AddressAsLeftPaddedHash(dp.Addresses.Bob)) tx, err := sysCfgContract.SetBatcherHash(sysCfgOwner, eth.AddressAsLeftPaddedHash(dp.Addresses.Bob))
require.NoError(t, err) require.NoError(t, err)
t.Logf("batcher changes in L1 tx %s", tx.Hash()) t.Logf("batcher changes in L1 tx %s", tx.Hash())
miner.ActL1StartBlock(12)(t) miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1IncludeTx(dp.Addresses.Deployer)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), tx.Hash()) receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), tx.Hash())
...@@ -289,7 +289,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -289,7 +289,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient()) sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient())
require.NoError(t, err) require.NoError(t, err)
sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.SysCfgOwner, sd.RollupCfg.L1ChainID) sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.Deployer, sd.RollupCfg.L1ChainID)
require.NoError(t, err) require.NoError(t, err)
// overhead changes from 2100 (default) to 1000 // overhead changes from 2100 (default) to 1000
...@@ -300,7 +300,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -300,7 +300,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
// include the GPO change tx in L1 // include the GPO change tx in L1
miner.ActL1StartBlock(12)(t) miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1IncludeTx(dp.Addresses.Deployer)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
basefeeGPOUpdate := miner.L1Chain().CurrentBlock().BaseFee basefeeGPOUpdate := miner.L1Chain().CurrentBlock().BaseFee
...@@ -384,7 +384,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -384,7 +384,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient()) sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient())
require.NoError(t, err) require.NoError(t, err)
sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.SysCfgOwner, sd.RollupCfg.L1ChainID) sysCfgOwner, err := bind.NewKeyedTransactorWithChainID(dp.Secrets.Deployer, sd.RollupCfg.L1ChainID)
require.NoError(t, err) require.NoError(t, err)
_, err = sysCfgContract.SetGasLimit(sysCfgOwner, oldGasLimit*3) _, err = sysCfgContract.SetGasLimit(sysCfgOwner, oldGasLimit*3)
...@@ -392,7 +392,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { ...@@ -392,7 +392,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
// include the gaslimit update on L1 // include the gaslimit update on L1
miner.ActL1StartBlock(12)(t) miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t) miner.ActL1IncludeTx(dp.Addresses.Deployer)(t)
miner.ActL1EndBlock(t) miner.ActL1EndBlock(t)
// build to latest L1, excluding the block that adopts the L1 block with the gaslimit change // build to latest L1, excluding the block that adopts the L1 block with the gaslimit change
......
...@@ -46,6 +46,7 @@ func TestFjordNetworkUpgradeTransactions(gt *testing.T) { ...@@ -46,6 +46,7 @@ func TestFjordNetworkUpgradeTransactions(gt *testing.T) {
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &fjordOffset dp.DeployConfig.L2GenesisFjordTimeOffset = &fjordOffset
dp.DeployConfig.L2GenesisGraniteTimeOffset = nil dp.DeployConfig.L2GenesisGraniteTimeOffset = nil
dp.DeployConfig.L2GenesisHoloceneTimeOffset = nil
require.NoError(t, dp.DeployConfig.Check(log), "must have valid config") require.NoError(t, dp.DeployConfig.Check(log), "must have valid config")
sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc) sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc)
......
package config package config
import ( import (
"compress/gzip"
"context"
"encoding/json"
"fmt" "fmt"
"log/slog" "log/slog"
"math/big"
"os" "os"
"path/filepath" "path"
"slices" "slices"
"sync"
"time" "time"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/inspect"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"golang.org/x/exp/maps"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
...@@ -15,6 +30,8 @@ import ( ...@@ -15,6 +30,8 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
op_service "github.com/ethereum-optimism/optimism/op-service" op_service "github.com/ethereum-optimism/optimism/op-service"
oplog "github.com/ethereum-optimism/optimism/op-service/log" oplog "github.com/ethereum-optimism/optimism/op-service/log"
_ "embed"
) )
// legacy geth log levels - the geth command line --verbosity flag wasn't // legacy geth log levels - the geth command line --verbosity flag wasn't
...@@ -73,10 +90,15 @@ var ( ...@@ -73,10 +90,15 @@ var (
// DeployConfig represents the deploy config used by the system. // DeployConfig represents the deploy config used by the system.
deployConfigsByType = make(map[AllocType]*genesis.DeployConfig) deployConfigsByType = make(map[AllocType]*genesis.DeployConfig)
// EthNodeVerbosity is the (legacy geth) level of verbosity to output // EthNodeVerbosity is the (legacy geth) level of verbosity to output
EthNodeVerbosity int EthNodeVerbosity int = 3
// mtx is a lock to protect the above variables
mtx sync.RWMutex
) )
func L1Allocs(allocType AllocType) *foundry.ForgeAllocs { func L1Allocs(allocType AllocType) *foundry.ForgeAllocs {
mtx.RLock()
defer mtx.RUnlock()
allocs, ok := l1AllocsByType[allocType] allocs, ok := l1AllocsByType[allocType]
if !ok { if !ok {
panic(fmt.Errorf("unknown L1 alloc type: %q", allocType)) panic(fmt.Errorf("unknown L1 alloc type: %q", allocType))
...@@ -85,6 +107,8 @@ func L1Allocs(allocType AllocType) *foundry.ForgeAllocs { ...@@ -85,6 +107,8 @@ func L1Allocs(allocType AllocType) *foundry.ForgeAllocs {
} }
func L1Deployments(allocType AllocType) *genesis.L1Deployments { func L1Deployments(allocType AllocType) *genesis.L1Deployments {
mtx.RLock()
defer mtx.RUnlock()
deployments, ok := l1DeploymentsByType[allocType] deployments, ok := l1DeploymentsByType[allocType]
if !ok { if !ok {
panic(fmt.Errorf("unknown L1 deployments type: %q", allocType)) panic(fmt.Errorf("unknown L1 deployments type: %q", allocType))
...@@ -93,6 +117,8 @@ func L1Deployments(allocType AllocType) *genesis.L1Deployments { ...@@ -93,6 +117,8 @@ func L1Deployments(allocType AllocType) *genesis.L1Deployments {
} }
func L2Allocs(allocType AllocType, mode genesis.L2AllocsMode) *foundry.ForgeAllocs { func L2Allocs(allocType AllocType, mode genesis.L2AllocsMode) *foundry.ForgeAllocs {
mtx.RLock()
defer mtx.RUnlock()
allocsByType, ok := l2AllocsByType[allocType] allocsByType, ok := l2AllocsByType[allocType]
if !ok { if !ok {
panic(fmt.Errorf("unknown L2 alloc type: %q", allocType)) panic(fmt.Errorf("unknown L2 alloc type: %q", allocType))
...@@ -106,6 +132,8 @@ func L2Allocs(allocType AllocType, mode genesis.L2AllocsMode) *foundry.ForgeAllo ...@@ -106,6 +132,8 @@ func L2Allocs(allocType AllocType, mode genesis.L2AllocsMode) *foundry.ForgeAllo
} }
func DeployConfig(allocType AllocType) *genesis.DeployConfig { func DeployConfig(allocType AllocType) *genesis.DeployConfig {
mtx.RLock()
defer mtx.RUnlock()
dc, ok := deployConfigsByType[allocType] dc, ok := deployConfigsByType[allocType]
if !ok { if !ok {
panic(fmt.Errorf("unknown deploy config type: %q", allocType)) panic(fmt.Errorf("unknown deploy config type: %q", allocType))
...@@ -123,15 +151,13 @@ func init() { ...@@ -123,15 +151,13 @@ func init() {
panic(err) panic(err)
} }
for _, allocType := range allocTypes {
initAllocType(root, allocType)
}
// Setup global logger // Setup global logger
lvl := log.FromLegacyLevel(EthNodeVerbosity) lvl := log.FromLegacyLevel(EthNodeVerbosity)
var handler slog.Handler var handler slog.Handler
var errHandler slog.Handler
if lvl > log.LevelCrit { if lvl > log.LevelCrit {
handler = log.DiscardHandler() handler = log.DiscardHandler()
errHandler = log.DiscardHandler()
} else { } else {
if lvl < log.LevelTrace { // clip to trace level if lvl < log.LevelTrace { // clip to trace level
lvl = log.LevelTrace lvl = log.LevelTrace
...@@ -144,62 +170,172 @@ func init() { ...@@ -144,62 +170,172 @@ func init() {
Color: false, // some CI logs do not handle colors well Color: false, // some CI logs do not handle colors well
Format: oplog.FormatTerminal, Format: oplog.FormatTerminal,
}) })
errHandler = oplog.NewLogHandler(os.Stderr, oplog.CLIConfig{
Level: log.LevelError,
Color: false,
Format: oplog.FormatTerminal,
})
}
// Start at warning level since alloc generation is heavy on the logs,
// which reduces CI performance.
oplog.SetGlobalLogHandler(errHandler)
for _, allocType := range allocTypes {
if allocType == AllocTypeL2OO {
continue
}
initAllocType(root, allocType)
}
configPath := path.Join(root, "op-e2e", "config")
forks := []genesis.L2AllocsMode{
genesis.L2AllocsHolocene,
genesis.L2AllocsGranite,
genesis.L2AllocsFjord,
genesis.L2AllocsEcotone,
genesis.L2AllocsDelta,
}
var l2OOAllocsL1 foundry.ForgeAllocs
decompressGzipJSON(path.Join(configPath, "allocs-l1.json.gz"), &l2OOAllocsL1)
l1AllocsByType[AllocTypeL2OO] = &l2OOAllocsL1
var l2OOAddresses genesis.L1Deployments
decompressGzipJSON(path.Join(configPath, "addresses.json.gz"), &l2OOAddresses)
l1DeploymentsByType[AllocTypeL2OO] = &l2OOAddresses
l2OODC := DeployConfig(AllocTypeStandard)
l2OODC.SetDeployments(&l2OOAddresses)
deployConfigsByType[AllocTypeL2OO] = l2OODC
l2AllocsByType[AllocTypeL2OO] = genesis.L2AllocsModeMap{}
var wg sync.WaitGroup
for _, fork := range forks {
wg.Add(1)
go func(fork genesis.L2AllocsMode) {
defer wg.Done()
var l2OOAllocsL2 foundry.ForgeAllocs
decompressGzipJSON(path.Join(configPath, fmt.Sprintf("allocs-l2-%s.json.gz", fork)), &l2OOAllocsL2)
mtx.Lock()
l2AllocsByType[AllocTypeL2OO][fork] = &l2OOAllocsL2
mtx.Unlock()
}(fork)
} }
wg.Wait()
// Use regular level going forward.
oplog.SetGlobalLogHandler(handler) oplog.SetGlobalLogHandler(handler)
} }
func initAllocType(root string, allocType AllocType) { func initAllocType(root string, allocType AllocType) {
devnetDir := filepath.Join(root, fmt.Sprintf(".devnet-%s", allocType)) artifactsPath := path.Join(root, "packages", "contracts-bedrock", "forge-artifacts")
l1AllocsPath := filepath.Join(devnetDir, "allocs-l1.json") if err := ensureDir(artifactsPath); err != nil {
l2AllocsDir := devnetDir panic(fmt.Errorf("invalid artifacts path: %w", err))
l1DeploymentsPath := filepath.Join(devnetDir, "addresses.json")
deployConfigPath := filepath.Join(root, "packages", "contracts-bedrock", "deploy-config", "devnetL1.json")
var missing bool
for _, fp := range []string{devnetDir, l1AllocsPath, l1DeploymentsPath} {
_, err := os.Stat(fp)
if os.IsNotExist(err) {
missing = true
break
} }
loc, err := artifacts.NewFileLocator(artifactsPath)
if err != nil { if err != nil {
panic(err) panic(fmt.Errorf("failed to create artifacts locator: %w", err))
} }
lgr := log.New()
allocModes := []genesis.L2AllocsMode{
genesis.L2AllocsHolocene,
genesis.L2AllocsGranite,
genesis.L2AllocsFjord,
genesis.L2AllocsEcotone,
genesis.L2AllocsDelta,
} }
if missing {
log.Warn("allocs file not found, skipping", "allocType", allocType)
return
}
l1Allocs, err := foundry.LoadForgeAllocs(l1AllocsPath) l2Alloc := make(map[genesis.L2AllocsMode]*foundry.ForgeAllocs)
var wg sync.WaitGroup
// Corresponds with the Deployer address in cfg.secrets
pk, err := crypto.HexToECDSA("7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6")
if err != nil { if err != nil {
panic(err) panic(fmt.Errorf("failed to parse private key: %w", err))
} }
l1AllocsByType[allocType] = l1Allocs deployerAddr := crypto.PubkeyToAddress(pk.PublicKey)
l2Alloc := make(map[genesis.L2AllocsMode]*foundry.ForgeAllocs) lgr.Info("deployer address", "address", deployerAddr.Hex())
mustL2Allocs := func(mode genesis.L2AllocsMode) {
name := "allocs-l2-" + string(mode) for _, mode := range allocModes {
allocs, err := foundry.LoadForgeAllocs(filepath.Join(l2AllocsDir, name+".json")) wg.Add(1)
go func(mode genesis.L2AllocsMode) {
defer wg.Done()
intent := defaultIntent(root, loc, deployerAddr)
if allocType == AllocTypeAltDA {
intent.Chains[0].DangerousAltDAConfig = genesis.AltDADeployConfig{
UseAltDA: true,
DACommitmentType: "KeccakCommitment",
DAChallengeWindow: 16,
DAResolveWindow: 16,
DABondSize: 1000000,
DAResolverRefundPercentage: 0,
}
}
baseUpgradeSchedule := map[string]any{
"l2GenesisRegolithTimeOffset": nil,
"l2GenesisCanyonTimeOffset": nil,
"l2GenesisDeltaTimeOffset": nil,
"l2GenesisEcotoneTimeOffset": nil,
"l2GenesisFjordTimeOffset": nil,
"l2GenesisGraniteTimeOffset": nil,
"l2GenesisHoloceneTimeOffset": nil,
}
upgradeSchedule := new(genesis.UpgradeScheduleDeployConfig)
upgradeSchedule.ActivateForkAtGenesis(rollup.ForkName(mode))
upgradeOverridesJSON, err := json.Marshal(upgradeSchedule)
if err != nil { if err != nil {
panic(err) panic(fmt.Errorf("failed to marshal upgrade schedule: %w", err))
} }
l2Alloc[mode] = allocs var upgradeOverrides map[string]any
if err := json.Unmarshal(upgradeOverridesJSON, &upgradeOverrides); err != nil {
panic(fmt.Errorf("failed to unmarshal upgrade schedule: %w", err))
} }
mustL2Allocs(genesis.L2AllocsHolocene) maps.Copy(baseUpgradeSchedule, upgradeOverrides)
mustL2Allocs(genesis.L2AllocsGranite) maps.Copy(intent.GlobalDeployOverrides, baseUpgradeSchedule)
mustL2Allocs(genesis.L2AllocsFjord)
mustL2Allocs(genesis.L2AllocsEcotone) st := &state.State{
mustL2Allocs(genesis.L2AllocsDelta) Version: 1,
l2AllocsByType[allocType] = l2Alloc }
l1Deployments, err := genesis.NewL1Deployments(l1DeploymentsPath)
if err := deployer.ApplyPipeline(
context.Background(),
deployer.ApplyPipelineOpts{
L1RPCUrl: "",
DeployerPrivateKey: pk,
Intent: intent,
State: st,
Logger: lgr,
StateWriter: pipeline.NoopStateWriter(),
},
); err != nil {
panic(fmt.Errorf("failed to apply pipeline: %w", err))
}
mtx.Lock()
l2Alloc[mode] = st.Chains[0].Allocs.Data
mtx.Unlock()
// This needs to be updated whenever the latest hardfork is changed.
if mode == genesis.L2AllocsGranite {
dc, err := inspect.DeployConfig(st, intent.Chains[0].ID)
if err != nil { if err != nil {
panic(err) panic(fmt.Errorf("failed to inspect deploy config: %w", err))
} }
l1DeploymentsByType[allocType] = l1Deployments
dc, err := genesis.NewDeployConfig(deployConfigPath) l1Contracts, err := inspect.L1(st, intent.Chains[0].ID)
if err != nil { if err != nil {
panic(err) panic(fmt.Errorf("failed to inspect L1: %w", err))
} }
l1Deployments := l1Contracts.AsL1Deployments()
// Set the L1 genesis block timestamp to now // Set the L1 genesis block timestamp to now
dc.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix()) dc.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
...@@ -208,5 +344,200 @@ func initAllocType(root string, allocType AllocType) { ...@@ -208,5 +344,200 @@ func initAllocType(root string, allocType AllocType) {
dc.L1BlockTime = 2 dc.L1BlockTime = 2
dc.L2BlockTime = 1 dc.L2BlockTime = 1
dc.SetDeployments(l1Deployments) dc.SetDeployments(l1Deployments)
mtx.Lock()
deployConfigsByType[allocType] = dc deployConfigsByType[allocType] = dc
l1AllocsByType[allocType] = st.L1StateDump.Data
l1DeploymentsByType[allocType] = l1Deployments
mtx.Unlock()
}
}(mode)
}
wg.Wait()
l2AllocsByType[allocType] = l2Alloc
}
func defaultIntent(root string, loc *artifacts.Locator, deployer common.Address) *state.Intent {
return &state.Intent{
ConfigType: state.IntentConfigTypeCustom,
DeploymentStrategy: state.DeploymentStrategyGenesis,
L1ChainID: 900,
SuperchainRoles: &state.SuperchainRoles{
ProxyAdminOwner: deployer,
ProtocolVersionsOwner: deployer,
Guardian: deployer,
},
FundDevAccounts: true,
L1ContractsLocator: loc,
L2ContractsLocator: loc,
GlobalDeployOverrides: map[string]any{
"maxSequencerDrift": 300,
"sequencerWindowSize": 200,
"channelTimeout": 120,
"l2OutputOracleSubmissionInterval": 10,
"l2OutputOracleStartingTimestamp": 0,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
"l2GenesisBlockGasLimit": "0x1c9c380",
"l1BlockTime": 6,
"baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000",
"baseFeeVaultWithdrawalNetwork": 0,
"l1FeeVaultWithdrawalNetwork": 0,
"sequencerFeeVaultWithdrawalNetwork": 0,
"finalizationPeriodSeconds": 2,
"l2GenesisBlockBaseFeePerGas": "0x1",
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"gasPriceOracleBaseFeeScalar": 1368,
"gasPriceOracleBlobBaseFeeScalar": 810949,
"l1CancunTimeOffset": "0x0",
"faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98",
"faultGameMaxDepth": 50,
"faultGameClockExtension": 0,
"faultGameMaxClockDuration": 1200,
"faultGameGenesisBlock": 0,
"faultGameGenesisOutputRoot": "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
"faultGameSplitDepth": 14,
"faultGameWithdrawalDelay": 604800,
"preimageOracleMinProposalSize": 10000,
"preimageOracleChallengePeriod": 120,
"proofMaturityDelaySeconds": 12,
"disputeGameFinalityDelaySeconds": 6,
},
Chains: []*state.ChainIntent{
{
ID: common.BigToHash(big.NewInt(901)),
BaseFeeVaultRecipient: common.HexToAddress("0x14dC79964da2C08b23698B3D3cc7Ca32193d9955"),
L1FeeVaultRecipient: common.HexToAddress("0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f"),
SequencerFeeVaultRecipient: common.HexToAddress("0xa0Ee7A142d267C1f36714E4a8F75612F20a79720"),
Eip1559Denominator: 250,
Eip1559DenominatorCanyon: 250,
Eip1559Elasticity: 6,
Roles: state.ChainRoles{
// Use deployer as L1PAO to deploy additional dispute impls
L1ProxyAdminOwner: deployer,
L2ProxyAdminOwner: deployer,
SystemConfigOwner: deployer,
UnsafeBlockSigner: common.HexToAddress("0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"),
Batcher: common.HexToAddress("0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"),
Proposer: common.HexToAddress("0x70997970C51812dc3A010C7d01b50e0d17dc79C8"),
Challenger: common.HexToAddress("0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65"),
},
AdditionalDisputeGames: []state.AdditionalDisputeGame{
{
ChainProofParams: state.ChainProofParams{
// Fast game
DisputeGameType: 254,
DisputeAbsolutePrestate: common.HexToHash("0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98"),
DisputeMaxGameDepth: 14 + 3 + 1,
DisputeSplitDepth: 14,
DisputeClockExtension: 0,
DisputeMaxClockDuration: 0,
},
VMType: state.VMTypeAlphabet,
UseCustomOracle: true,
OracleMinProposalSize: 10000,
OracleChallengePeriodSeconds: 0,
MakeRespected: true,
},
{
ChainProofParams: state.ChainProofParams{
// Alphabet game
DisputeGameType: 255,
DisputeAbsolutePrestate: common.HexToHash("0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98"),
DisputeMaxGameDepth: 14 + 3 + 1,
DisputeSplitDepth: 14,
DisputeClockExtension: 0,
DisputeMaxClockDuration: 1200,
},
VMType: state.VMTypeAlphabet,
},
{
ChainProofParams: state.ChainProofParams{
DisputeGameType: 0,
DisputeAbsolutePrestate: cannonPrestate(root),
DisputeMaxGameDepth: 50,
DisputeSplitDepth: 14,
DisputeClockExtension: 0,
DisputeMaxClockDuration: 1200,
},
VMType: cannonVMType(),
},
},
},
},
}
}
func ensureDir(dirPath string) error {
stat, err := os.Stat(dirPath)
if err != nil {
return fmt.Errorf("failed to stat path: %w", err)
}
if !stat.IsDir() {
return fmt.Errorf("path is not a directory")
}
return nil
}
func decompressGzipJSON(p string, thing any) {
f, err := os.Open(p)
if err != nil {
panic(fmt.Errorf("failed to open file: %w", err))
}
defer f.Close()
gzr, err := gzip.NewReader(f)
if err != nil {
panic(fmt.Errorf("failed to create gzip reader: %w", err))
}
defer gzr.Close()
if err := json.NewDecoder(gzr).Decode(thing); err != nil {
panic(fmt.Errorf("failed to read gzip data: %w", err))
}
}
func cannonVMType() state.VMType {
if os.Getenv("USE_MT_CANNON") == "true" {
return state.VMTypeCannon2
}
return state.VMTypeCannon1
}
type prestateFile struct {
Pre string `json:"pre"`
}
var cannonPrestateCache common.Hash
var cannonPrestateOnce sync.Once
func cannonPrestate(monorepoRoot string) common.Hash {
var filename string
if cannonVMType() == state.VMTypeCannon1 {
filename = "prestate-proof-st.json"
} else {
filename = "prestate-proof-mt.json"
}
cannonPrestateOnce.Do(func() {
f, err := os.Open(path.Join(monorepoRoot, "op-program", "bin", filename))
if err != nil {
log.Warn("error opening prestate file", "err", err)
return
}
defer f.Close()
var prestate prestateFile
dec := json.NewDecoder(f)
if err := dec.Decode(&prestate); err != nil {
log.Warn("error decoding prestate file", "err", err)
return
}
cannonPrestateCache = common.HexToHash(prestate.Pre)
})
return cannonPrestateCache
} }
...@@ -22,7 +22,15 @@ func TestBatcherConcurrentAltDARequests(t *testing.T) { ...@@ -22,7 +22,15 @@ func TestBatcherConcurrentAltDARequests(t *testing.T) {
numL1TxsExpected := int64(10) numL1TxsExpected := int64(10)
cfg := e2esys.DefaultSystemConfig(t) cfg := e2esys.DefaultSystemConfig(t)
// Manually configure these since the alt-DA values aren't
// set at all in the standard config unless UseAltDA is set.
// For some reason this test doesn't use the alt DA allocs.
cfg.DeployConfig.UseAltDA = true cfg.DeployConfig.UseAltDA = true
cfg.DeployConfig.DACommitmentType = "KeccakCommitment"
cfg.DeployConfig.DAChallengeWindow = 16
cfg.DeployConfig.DAResolveWindow = 16
cfg.DeployConfig.DABondSize = 1000000
cfg.DeployConfig.DAResolverRefundPercentage = 0
cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs cfg.BatcherMaxPendingTransactions = 0 // no limit on parallel txs
// ensures that batcher txs are as small as possible // ensures that batcher txs are as small as possible
cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1 cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1
......
...@@ -35,7 +35,7 @@ func TestEIP1559Params(t *testing.T) { ...@@ -35,7 +35,7 @@ func TestEIP1559Params(t *testing.T) {
// Obtain our sequencer, verifier, and transactor keypair. // Obtain our sequencer, verifier, and transactor keypair.
l1Client := sys.NodeClient("l1") l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer") l2Seq := sys.NodeClient("sequencer")
ethPrivKey := cfg.Secrets.SysCfgOwner ethPrivKey := cfg.Secrets.Deployer
_, err = l2Seq.HeaderByNumber(context.Background(), big.NewInt(0)) _, err = l2Seq.HeaderByNumber(context.Background(), big.NewInt(0))
require.NoError(t, err) require.NoError(t, err)
......
...@@ -40,7 +40,7 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) { ...@@ -40,7 +40,7 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
l1Client := sys.NodeClient("l1") l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer") l2Seq := sys.NodeClient("sequencer")
// l2Verif := sys.NodeClient("verifier") // l2Verif := sys.NodeClient("verifier")
ethPrivKey := cfg.Secrets.SysCfgOwner ethPrivKey := cfg.Secrets.Deployer
// Bind to the SystemConfig & GasPriceOracle contracts // Bind to the SystemConfig & GasPriceOracle contracts
sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client) sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client)
......
...@@ -113,14 +113,14 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) { ...@@ -113,14 +113,14 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
op_e2e.InitParallel(t) op_e2e.InitParallel(t)
gto := setup(t) gto := setup(t)
checkDeposit(t, gto, false) checkDeposit(t, gto, false)
setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address) setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address, allocType)
checkDeposit(t, gto, true) checkDeposit(t, gto, true)
}) })
t.Run("withdrawal", func(t *testing.T) { t.Run("withdrawal", func(t *testing.T) {
op_e2e.InitParallel(t) op_e2e.InitParallel(t)
gto := setup(t) gto := setup(t)
setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address) setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address, allocType)
checkDeposit(t, gto, true) checkDeposit(t, gto, true)
checkWithdrawal(t, gto) checkWithdrawal(t, gto)
}) })
...@@ -128,7 +128,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) { ...@@ -128,7 +128,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
t.Run("fee withdrawal", func(t *testing.T) { t.Run("fee withdrawal", func(t *testing.T) {
op_e2e.InitParallel(t) op_e2e.InitParallel(t)
gto := setup(t) gto := setup(t)
setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address) setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address, allocType)
checkDeposit(t, gto, true) checkDeposit(t, gto, true)
checkFeeWithdrawal(t, gto, true) checkFeeWithdrawal(t, gto, true)
}) })
...@@ -139,7 +139,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) { ...@@ -139,7 +139,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
checkL1TokenNameAndSymbol(t, gto, gto.disabledExpectations) checkL1TokenNameAndSymbol(t, gto, gto.disabledExpectations)
checkL2TokenNameAndSymbol(t, gto, gto.disabledExpectations) checkL2TokenNameAndSymbol(t, gto, gto.disabledExpectations)
checkWETHTokenNameAndSymbol(t, gto, gto.disabledExpectations) checkWETHTokenNameAndSymbol(t, gto, gto.disabledExpectations)
setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address) setCustomGasToken(t, gto.cfg, gto.sys, gto.weth9Address, allocType)
checkL1TokenNameAndSymbol(t, gto, gto.enabledExpectations) checkL1TokenNameAndSymbol(t, gto, gto.enabledExpectations)
checkL2TokenNameAndSymbol(t, gto, gto.enabledExpectations) checkL2TokenNameAndSymbol(t, gto, gto.enabledExpectations)
checkWETHTokenNameAndSymbol(t, gto, gto.enabledExpectations) checkWETHTokenNameAndSymbol(t, gto, gto.enabledExpectations)
...@@ -149,7 +149,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) { ...@@ -149,7 +149,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
// setCustomGasToken enables the Custom Gas Token feature on a chain where it wasn't enabled at genesis. // setCustomGasToken enables the Custom Gas Token feature on a chain where it wasn't enabled at genesis.
// It reads existing parameters from the SystemConfig contract, inserts the supplied cgtAddress and reinitializes that contract. // It reads existing parameters from the SystemConfig contract, inserts the supplied cgtAddress and reinitializes that contract.
// To do this it uses the ProxyAdmin and StorageSetter from the supplied cfg. // To do this it uses the ProxyAdmin and StorageSetter from the supplied cfg.
func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System, cgtAddress common.Address) { func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System, cgtAddress common.Address, allocType config.AllocType) {
l1Client := sys.NodeClient("l1") l1Client := sys.NodeClient("l1")
deployerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig()) deployerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
...@@ -203,7 +203,11 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System ...@@ -203,7 +203,11 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System
// Set up a signer which controls the Proxy Admin. // Set up a signer which controls the Proxy Admin.
// The deploy config's finalSystemOwner is the owner of the ProxyAdmin as well as the SystemConfig, // The deploy config's finalSystemOwner is the owner of the ProxyAdmin as well as the SystemConfig,
// so we can use that address for the proxy admin owner. // so we can use that address for the proxy admin owner.
proxyAdminOwnerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) ownerSecret := cfg.Secrets.Deployer
if allocType == config.AllocTypeL2OO {
ownerSecret = cfg.Secrets.SysCfgOwner
}
proxyAdminOwnerOpts, err := bind.NewKeyedTransactorWithChainID(ownerSecret, cfg.L1ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
// Execute the upgrade SystemConfigProxy -> StorageSetter via ProxyAdmin // Execute the upgrade SystemConfigProxy -> StorageSetter via ProxyAdmin
......
...@@ -78,6 +78,7 @@ func applySpanBatchActivation(active bool, dp *genesis.DeployConfig) { ...@@ -78,6 +78,7 @@ func applySpanBatchActivation(active bool, dp *genesis.DeployConfig) {
dp.L2GenesisEcotoneTimeOffset = nil dp.L2GenesisEcotoneTimeOffset = nil
dp.L2GenesisFjordTimeOffset = nil dp.L2GenesisFjordTimeOffset = nil
dp.L2GenesisGraniteTimeOffset = nil dp.L2GenesisGraniteTimeOffset = nil
dp.L2GenesisHoloceneTimeOffset = nil
} }
} }
......
...@@ -40,7 +40,7 @@ func TestRuntimeConfigReload(t *testing.T) { ...@@ -40,7 +40,7 @@ func TestRuntimeConfigReload(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45} newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45}
require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address") require.NotEqual(t, initialRuntimeConfig.P2PSequencerAddress(), newUnsafeBlocksSigner, "changing to a different address")
opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.Nil(t, err) require.Nil(t, err)
// the unsafe signer address is part of the runtime config // the unsafe signer address is part of the runtime config
tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner) tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner)
......
...@@ -49,8 +49,8 @@ func TestRecommendedProtocolVersionChange(t *testing.T) { ...@@ -49,8 +49,8 @@ func TestRecommendedProtocolVersionChange(t *testing.T) {
protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1) protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1)
require.NoError(t, err) require.NoError(t, err)
// ProtocolVersions contract is owned by same key as SystemConfig in devnet // ProtocolVersions contract is owned by the deployer in devnet
opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
// Change recommended protocol version // Change recommended protocol version
...@@ -105,7 +105,7 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) { ...@@ -105,7 +105,7 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
// ProtocolVersions contract is owned by same key as SystemConfig in devnet // ProtocolVersions contract is owned by same key as SystemConfig in devnet
opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig()) opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
// Change required protocol version // Change required protocol version
......
...@@ -12,6 +12,8 @@ import ( ...@@ -12,6 +12,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt" "github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -163,3 +165,8 @@ func Parse256BitChainID(in string) (common.Hash, error) { ...@@ -163,3 +165,8 @@ func Parse256BitChainID(in string) (common.Hash, error) {
return common.BigToHash(chainIDBig), nil return common.BigToHash(chainIDBig), nil
} }
func U64UtilPtr(in uint64) *hexutil.Uint64 {
util := hexutil.Uint64(in)
return &util
}
...@@ -63,32 +63,17 @@ contract DeployMIPSOutput is BaseDeployIO { ...@@ -63,32 +63,17 @@ contract DeployMIPSOutput is BaseDeployIO {
} }
} }
function checkOutput(DeployMIPSInput _mi) public view {
DeployUtils.assertValidContractAddress(address(_mipsSingleton));
assertValidDeploy(_mi);
}
function mipsSingleton() public view returns (IMIPS) { function mipsSingleton() public view returns (IMIPS) {
DeployUtils.assertValidContractAddress(address(_mipsSingleton)); DeployUtils.assertValidContractAddress(address(_mipsSingleton));
return _mipsSingleton; return _mipsSingleton;
} }
function assertValidDeploy(DeployMIPSInput _mi) public view {
assertValidMipsSingleton(_mi);
}
function assertValidMipsSingleton(DeployMIPSInput _mi) internal view {
IMIPS mips = mipsSingleton();
require(address(mips.oracle()) == address(_mi.preimageOracle()), "MIPS-10");
}
} }
/// @title DeployMIPS /// @title DeployMIPS
contract DeployMIPS is Script { contract DeployMIPS is Script {
function run(DeployMIPSInput _mi, DeployMIPSOutput _mo) public { function run(DeployMIPSInput _mi, DeployMIPSOutput _mo) public {
deployMipsSingleton(_mi, _mo); deployMipsSingleton(_mi, _mo);
_mo.checkOutput(_mi); assertValidDeploy(_mi, _mo);
} }
function deployMipsSingleton(DeployMIPSInput _mi, DeployMIPSOutput _mo) internal { function deployMipsSingleton(DeployMIPSInput _mi, DeployMIPSOutput _mo) internal {
...@@ -106,4 +91,14 @@ contract DeployMIPS is Script { ...@@ -106,4 +91,14 @@ contract DeployMIPS is Script {
vm.label(address(singleton), "MIPSSingleton"); vm.label(address(singleton), "MIPSSingleton");
_mo.set(_mo.mipsSingleton.selector, address(singleton)); _mo.set(_mo.mipsSingleton.selector, address(singleton));
} }
function assertValidDeploy(DeployMIPSInput _mi, DeployMIPSOutput _mo) public view {
DeployUtils.assertValidContractAddress(address(_mo.mipsSingleton()));
assertValidMipsSingleton(_mi, _mo);
}
function assertValidMipsSingleton(DeployMIPSInput _mi, DeployMIPSOutput _mo) internal view {
IMIPS mips = _mo.mipsSingleton();
require(address(mips.oracle()) == address(_mi.preimageOracle()), "MIPS-10");
}
} }
...@@ -3,14 +3,16 @@ pragma solidity 0.8.15; ...@@ -3,14 +3,16 @@ pragma solidity 0.8.15;
import { Script } from "forge-std/Script.sol"; import { Script } from "forge-std/Script.sol";
import { IDisputeGame } from "interfaces/dispute/IDisputeGame.sol"; import { IFaultDisputeGame } from "interfaces/dispute/IFaultDisputeGame.sol";
import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol"; import { IDisputeGameFactory } from "interfaces/dispute/IDisputeGameFactory.sol";
import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol"; import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol";
import { GameType } from "src/dispute/lib/Types.sol"; import { GameType } from "src/dispute/lib/Types.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
contract SetDisputeGameImplInput is BaseDeployIO { contract SetDisputeGameImplInput is BaseDeployIO {
IDisputeGameFactory internal _factory; IDisputeGameFactory internal _factory;
IDisputeGame internal _impl; IOptimismPortal2 internal _portal;
IFaultDisputeGame internal _impl;
uint32 internal _gameType; uint32 internal _gameType;
// Setter for address type // Setter for address type
...@@ -18,7 +20,8 @@ contract SetDisputeGameImplInput is BaseDeployIO { ...@@ -18,7 +20,8 @@ contract SetDisputeGameImplInput is BaseDeployIO {
require(_addr != address(0), "SetDisputeGameImplInput: cannot set zero address"); require(_addr != address(0), "SetDisputeGameImplInput: cannot set zero address");
if (_sel == this.factory.selector) _factory = IDisputeGameFactory(_addr); if (_sel == this.factory.selector) _factory = IDisputeGameFactory(_addr);
else if (_sel == this.impl.selector) _impl = IDisputeGame(_addr); else if (_sel == this.portal.selector) _portal = IOptimismPortal2(payable(_addr));
else if (_sel == this.impl.selector) _impl = IFaultDisputeGame(_addr);
else revert("SetDisputeGameImplInput: unknown selector"); else revert("SetDisputeGameImplInput: unknown selector");
} }
...@@ -28,13 +31,16 @@ contract SetDisputeGameImplInput is BaseDeployIO { ...@@ -28,13 +31,16 @@ contract SetDisputeGameImplInput is BaseDeployIO {
else revert("SetDisputeGameImplInput: unknown selector"); else revert("SetDisputeGameImplInput: unknown selector");
} }
// Getters
function factory() public view returns (IDisputeGameFactory) { function factory() public view returns (IDisputeGameFactory) {
require(address(_factory) != address(0), "SetDisputeGameImplInput: not set"); require(address(_factory) != address(0), "SetDisputeGameImplInput: not set");
return _factory; return _factory;
} }
function impl() public view returns (IDisputeGame) { function portal() public view returns (IOptimismPortal2) {
return _portal;
}
function impl() public view returns (IFaultDisputeGame) {
require(address(_impl) != address(0), "SetDisputeGameImplInput: not set"); require(address(_impl) != address(0), "SetDisputeGameImplInput: not set");
return _impl; return _impl;
} }
...@@ -50,14 +56,28 @@ contract SetDisputeGameImpl is Script { ...@@ -50,14 +56,28 @@ contract SetDisputeGameImpl is Script {
GameType gameType = GameType.wrap(_input.gameType()); GameType gameType = GameType.wrap(_input.gameType());
require(address(factory.gameImpls(gameType)) == address(0), "SDGI-10"); require(address(factory.gameImpls(gameType)) == address(0), "SDGI-10");
IDisputeGame impl = _input.impl(); IFaultDisputeGame impl = _input.impl();
IOptimismPortal2 portal = _input.portal();
vm.broadcast(msg.sender); vm.broadcast(msg.sender);
factory.setImplementation(gameType, impl); factory.setImplementation(gameType, impl);
if (address(portal) != address(0)) {
require(address(portal.disputeGameFactory()) == address(factory), "SDGI-20");
vm.broadcast(msg.sender);
portal.setRespectedGameType(gameType);
}
assertValid(_input); assertValid(_input);
} }
function assertValid(SetDisputeGameImplInput _input) public view { function assertValid(SetDisputeGameImplInput _input) public view {
GameType gameType = GameType.wrap(_input.gameType()); GameType gameType = GameType.wrap(_input.gameType());
require(address(_input.factory().gameImpls(gameType)) == address(_input.impl()), "SDGI-20"); require(address(_input.factory().gameImpls(gameType)) == address(_input.impl()), "SDGI-30");
if (address(_input.portal()) != address(0)) {
require(address(_input.portal().disputeGameFactory()) == address(_input.factory()), "SDGI-40");
require(GameType.unwrap(_input.portal().respectedGameType()) == GameType.unwrap(gameType), "SDGI-50");
}
} }
} }
...@@ -8,6 +8,11 @@ import { GameType } from "src/dispute/lib/Types.sol"; ...@@ -8,6 +8,11 @@ import { GameType } from "src/dispute/lib/Types.sol";
import { SetDisputeGameImpl, SetDisputeGameImplInput } from "scripts/deploy/SetDisputeGameImpl.s.sol"; import { SetDisputeGameImpl, SetDisputeGameImplInput } from "scripts/deploy/SetDisputeGameImpl.s.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol"; import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { Proxy } from "src/universal/Proxy.sol"; import { Proxy } from "src/universal/Proxy.sol";
import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
contract SetDisputeGameImplInput_Test is Test { contract SetDisputeGameImplInput_Test is Test {
SetDisputeGameImplInput input; SetDisputeGameImplInput input;
...@@ -65,19 +70,43 @@ contract SetDisputeGameImpl_Test is Test { ...@@ -65,19 +70,43 @@ contract SetDisputeGameImpl_Test is Test {
SetDisputeGameImpl script; SetDisputeGameImpl script;
SetDisputeGameImplInput input; SetDisputeGameImplInput input;
IDisputeGameFactory factory; IDisputeGameFactory factory;
IOptimismPortal2 portal;
address mockImpl; address mockImpl;
uint32 gameType; uint32 gameType;
function setUp() public { function setUp() public {
script = new SetDisputeGameImpl(); script = new SetDisputeGameImpl();
input = new SetDisputeGameImplInput(); input = new SetDisputeGameImplInput();
DisputeGameFactory impl = new DisputeGameFactory(); DisputeGameFactory dgfImpl = new DisputeGameFactory();
OptimismPortal2 portalImpl = new OptimismPortal2(0, 0);
SuperchainConfig supConfigImpl = new SuperchainConfig();
// Needs to be a proxy to properly initialize Proxy supConfigProxy = new Proxy(address(1));
Proxy proxy = new Proxy(address(1));
vm.prank(address(1)); vm.prank(address(1));
proxy.upgradeToAndCall(address(impl), abi.encodeCall(impl.initialize, address(this))); supConfigProxy.upgradeToAndCall(
factory = IDisputeGameFactory(address(proxy)); address(supConfigImpl), abi.encodeCall(supConfigImpl.initialize, (address(this), false))
);
Proxy factoryProxy = new Proxy(address(1));
vm.prank(address(1));
factoryProxy.upgradeToAndCall(address(dgfImpl), abi.encodeCall(dgfImpl.initialize, (address(this))));
factory = IDisputeGameFactory(address(factoryProxy));
Proxy portalProxy = new Proxy(address(1));
vm.prank(address(1));
portalProxy.upgradeToAndCall(
address(portalImpl),
abi.encodeCall(
portalImpl.initialize,
(
factory,
ISystemConfig(makeAddr("sysConfig")),
ISuperchainConfig(address(supConfigProxy)),
GameType.wrap(100)
)
)
);
portal = IOptimismPortal2(payable(address(portalProxy)));
mockImpl = makeAddr("impl"); mockImpl = makeAddr("impl");
gameType = 999; gameType = 999;
...@@ -86,6 +115,7 @@ contract SetDisputeGameImpl_Test is Test { ...@@ -86,6 +115,7 @@ contract SetDisputeGameImpl_Test is Test {
function test_run_succeeds() public { function test_run_succeeds() public {
input.set(input.factory.selector, address(factory)); input.set(input.factory.selector, address(factory));
input.set(input.impl.selector, mockImpl); input.set(input.impl.selector, mockImpl);
input.set(input.portal.selector, address(portal));
input.set(input.gameType.selector, gameType); input.set(input.gameType.selector, gameType);
script.run(input); script.run(input);
...@@ -94,6 +124,7 @@ contract SetDisputeGameImpl_Test is Test { ...@@ -94,6 +124,7 @@ contract SetDisputeGameImpl_Test is Test {
function test_run_whenImplAlreadySet_reverts() public { function test_run_whenImplAlreadySet_reverts() public {
input.set(input.factory.selector, address(factory)); input.set(input.factory.selector, address(factory));
input.set(input.impl.selector, mockImpl); input.set(input.impl.selector, mockImpl);
input.set(input.portal.selector, address(portal));
input.set(input.gameType.selector, gameType); input.set(input.gameType.selector, gameType);
// First run should succeed // First run should succeed
...@@ -115,7 +146,7 @@ contract SetDisputeGameImpl_Test is Test { ...@@ -115,7 +146,7 @@ contract SetDisputeGameImpl_Test is Test {
vm.broadcast(address(this)); vm.broadcast(address(this));
factory.setImplementation(GameType.wrap(gameType), IDisputeGame(address(0))); factory.setImplementation(GameType.wrap(gameType), IDisputeGame(address(0)));
vm.expectRevert("SDGI-20"); vm.expectRevert("SDGI-30");
script.assertValid(input); script.assertValid(input);
} }
} }
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