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 (
github.com/libp2p/go-libp2p-mplex v0.9.0
github.com/libp2p/go-libp2p-pubsub 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/minio/minio-go/v7 v7.0.81
github.com/multiformats/go-base32 v0.1.0
......@@ -157,7 +158,7 @@ require (
github.com/libp2p/go-yamux/v4 v4.0.1 // 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-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/miekg/dns v1.1.62 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
......@@ -208,7 +209,7 @@ require (
github.com/quic-go/quic-go v0.46.0 // indirect
github.com/quic-go/webtransport-go v0.8.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/rs/cors v1.11.0 // indirect
github.com/rs/xid v1.6.0 // indirect
......
......@@ -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-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ=
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/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/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
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.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.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
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/mholt/archiver v3.1.1+incompatible h1:1dCVxuqs0dJseYEhi5pl7MYPH9zDa1wBi7mF09cbNkU=
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
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/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.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
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.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
......
package foundry
import (
"bytes"
"encoding/json"
"fmt"
"maps"
......@@ -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 {
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}
}
......
......@@ -218,6 +218,7 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
DisputeSplitDepth: cfg.DisputeSplitDepth,
DisputeClockExtension: cfg.DisputeClockExtension,
DisputeMaxClockDuration: cfg.DisputeMaxClockDuration,
StartingAnchorRoots: opcm.PermissionedGameStartingAnchorRoots,
})
if err != nil {
return nil, fmt.Errorf("failed to deploy L2 OP chain: %w", err)
......
......@@ -45,6 +45,15 @@ type Locator struct {
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 {
str := string(text)
......
......@@ -3,6 +3,8 @@ package inspect
import (
"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/state"
......@@ -18,6 +20,33 @@ type L1Contracts struct {
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 {
ProxyAdminAddress common.Address `json:"proxyAdminAddress"`
SuperchainConfigProxyAddress common.Address `json:"superchainConfigProxyAddress"`
......@@ -42,6 +71,8 @@ type OpChainDeployment struct {
PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"`
DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"`
// DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"`
DataAvailabilityChallengeProxyAddress common.Address `json:"dataAvailabilityChallengeProxyAddress"`
DataAvailabilityChallengeImplAddress common.Address `json:"dataAvailabilityChallengeImplAddress"`
}
type ImplementationsDeployment struct {
......@@ -110,6 +141,8 @@ func L1(globalState *state.State, chainID common.Hash) (*L1Contracts, error) {
FaultDisputeGameAddress: chainState.FaultDisputeGameAddress,
PermissionedDisputeGameAddress: chainState.PermissionedDisputeGameAddress,
DelayedWETHPermissionedGameProxyAddress: chainState.DelayedWETHPermissionedGameProxyAddress,
DataAvailabilityChallengeProxyAddress: chainState.DataAvailabilityChallengeProxyAddress,
DataAvailabilityChallengeImplAddress: chainState.DataAvailabilityChallengeImplAddress,
// DelayedWETHPermissionlessGameProxyAddress: chainState.DelayedWETHPermissionlessGameProxyAddress,
},
ImplementationsDeployment: ImplementationsDeployment{
......
......@@ -182,11 +182,7 @@ func TestApplyExistingOPCM(t *testing.T) {
func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, versions standard.L1Versions) {
op_e2e.InitParallel(t)
anvil.Test(t)
if forkRPCUrl == "" {
t.Skip("no fork RPC URL provided")
}
require.NotEmpty(t, forkRPCUrl, "no fork RPC URL provided")
lgr := testlog.Logger(t, slog.LevelDebug)
......@@ -406,7 +402,6 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve
//Use a custom equality function to compare the genesis allocs
//because the reflect-based one is really slow
actAllocs := st.Chains[0].Allocs.Data.Accounts
require.Equal(t, len(expAllocs), len(actAllocs))
for addr, expAcc := range expAllocs {
actAcc, ok := actAllocs[addr]
require.True(t, ok)
......@@ -420,11 +415,17 @@ func testApplyExistingOPCM(t *testing.T, l1ChainID uint64, forkRPCUrl string, ve
}
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) {
op_e2e.InitParallel(t)
kurtosisutil.Test(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
......@@ -499,9 +500,9 @@ func TestProofParamOverrides(t *testing.T) {
opts, intent, st := setupGenesisChain(t, defaultL1ChainID)
intent.GlobalDeployOverrides = map[string]any{
"withdrawalDelaySeconds": standard.WithdrawalDelaySeconds + 1,
"minProposalSizeBytes": standard.MinProposalSizeBytes + 1,
"challengePeriodSeconds": standard.ChallengePeriodSeconds + 1,
"faultGameWithdrawalDelay": standard.WithdrawalDelaySeconds + 1,
"preimageOracleMinProposalSize": standard.MinProposalSizeBytes + 1,
"preimageOracleChallengePeriod": standard.ChallengePeriodSeconds + 1,
"proofMaturityDelaySeconds": standard.ProofMaturityDelaySeconds + 1,
"disputeGameFinalityDelaySeconds": standard.DisputeGameFinalityDelaySeconds + 1,
"mipsVersion": standard.MIPSVersion + 1,
......@@ -529,17 +530,17 @@ func TestProofParamOverrides(t *testing.T) {
address common.Address
}{
{
"withdrawalDelaySeconds",
"faultGameWithdrawalDelay",
uint64Caster,
st.ImplementationsDeployment.DelayedWETHImplAddress,
},
{
"minProposalSizeBytes",
"preimageOracleMinProposalSize",
uint64Caster,
st.ImplementationsDeployment.PreimageOracleSingletonAddress,
},
{
"challengePeriodSeconds",
"preimageOracleChallengePeriod",
uint64Caster,
st.ImplementationsDeployment.PreimageOracleSingletonAddress,
},
......@@ -708,7 +709,9 @@ func TestAdditionalDisputeGames(t *testing.T) {
defer cancel()
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{
"challengePeriodSeconds": 1,
}
......@@ -726,6 +729,7 @@ func TestAdditionalDisputeGames(t *testing.T) {
UseCustomOracle: true,
OracleMinProposalSize: 10000,
OracleChallengePeriodSeconds: 120,
MakeRespected: true,
VMType: state.VMTypeAlphabet,
},
}
......@@ -848,7 +852,7 @@ func newIntent(
ProtocolVersionsOwner: addrFor(t, dk, devkeys.SuperchainDeployerKey.Key(l1ChainID)),
Guardian: addrFor(t, dk, devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)),
},
FundDevAccounts: true,
FundDevAccounts: false,
L1ContractsLocator: l1Loc,
L2ContractsLocator: l2Loc,
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 (
type SetDisputeGameImplInput struct {
Factory common.Address
Impl common.Address
Portal common.Address
AnchorStateRegistry common.Address
GameType uint32
}
......
......@@ -2,6 +2,7 @@ package opcm
import (
"fmt"
"time"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
......@@ -32,6 +33,8 @@ func L2Genesis(l2Host *script.Host, input *L2GenesisInput) error {
l2Host.SetEnvVar("L2GENESIS_L1CrossDomainMessengerProxy", input.L1Deployments.L1CrossDomainMessengerProxy.String())
l2Host.SetEnvVar("L2GENESIS_L1StandardBridgeProxy", input.L1Deployments.L1StandardBridgeProxy.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{
L2InitializationConfig: input.L2Config,
......
......@@ -11,18 +11,10 @@ type DeployMIPSInput struct {
PreimageOracle common.Address
}
func (input *DeployMIPSInput) InputSet() bool {
return true
}
type DeployMIPSOutput struct {
MipsSingleton common.Address
}
func (output *DeployMIPSOutput) CheckOutput(input common.Address) error {
return nil
}
type DeployMIPSScript struct {
Run func(input, output common.Address) error
}
......
......@@ -36,6 +36,7 @@ type DeployOPChainInputV160 struct {
DisputeSplitDepth uint64
DisputeClockExtension uint64
DisputeMaxClockDuration uint64
StartingAnchorRoots []byte
AllowCustomDisputeParameters bool
}
......@@ -43,10 +44,6 @@ func (input *DeployOPChainInputV160) InputSet() bool {
return true
}
func (input *DeployOPChainInputV160) StartingAnchorRoots() []byte {
return PermissionedGameStartingAnchorRoots
}
type DeployOPChainInputIsthmus struct {
DeployOPChainInputV160
SystemConfigFeeAdmin common.Address
......
......@@ -5,7 +5,6 @@ import (
"math/big"
"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/go-ethereum/common"
)
......@@ -67,8 +66,10 @@ func deployDisputeGame(
return fmt.Errorf("failed to deploy preimage oracle: %w", err)
}
oracleAddr = out.PreimageOracle
lgr.Info("oracle deployed", "oracleAddr", oracleAddr)
} else {
lgr.Debug("using existing preimage oracle")
lgr.Info("using existing preimage oracle")
oracleAddr = st.ImplementationsDeployment.PreimageOracleSingletonAddress
}
lgr.Info("deploying VM", "vmType", game.VMType)
......@@ -77,12 +78,26 @@ func deployDisputeGame(
case state.VMTypeAlphabet:
out, err := opcm.DeployAlphabetVM(env.L1ScriptHost, opcm.DeployAlphabetVMInput{
AbsolutePrestate: game.DisputeAbsolutePrestate,
PreimageOracle: st.ImplementationsDeployment.PreimageOracleSingletonAddress,
PreimageOracle: oracleAddr,
})
if err != nil {
return fmt.Errorf("failed to deploy Alphabet VM: %w", err)
}
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:
return fmt.Errorf("unsupported VM type: %v", game.VMType)
}
......@@ -94,7 +109,7 @@ func deployDisputeGame(
VmAddress: vmAddr,
GameKind: "FaultDisputeGame",
GameType: game.DisputeGameType,
AbsolutePrestate: standard.DisputeAbsolutePrestate,
AbsolutePrestate: game.DisputeAbsolutePrestate,
MaxGameDepth: game.DisputeMaxGameDepth,
SplitDepth: game.DisputeSplitDepth,
ClockExtension: game.DisputeClockExtension,
......@@ -110,13 +125,19 @@ func deployDisputeGame(
}
lgr.Info("dispute game deployed", "impl", out.DisputeGameImpl)
lgr.Info("setting dispute game impl on factory")
if err := opcm.SetDisputeGameImpl(
env.L1ScriptHost,
opcm.SetDisputeGameImplInput{
lgr.Info("setting dispute game impl on factory", "respected", game.MakeRespected)
sdgiInput := opcm.SetDisputeGameImplInput{
Factory: thisState.DisputeGameFactoryProxyAddress,
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 {
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
lgr := env.Logger.New("stage", "init", "strategy", "live")
lgr.Info("initializing pipeline")
if err := initCommonChecks(st); err != nil {
if err := initCommonChecks(intent, st); err != nil {
return err
}
......@@ -100,7 +100,7 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
return nil
}
func initCommonChecks(st *state.State) error {
func initCommonChecks(intent *state.Intent, st *state.State) error {
// Ensure the state version is supported.
if !IsSupportedStateVersion(st.Version) {
return fmt.Errorf("unsupported state version: %d", st.Version)
......@@ -112,6 +112,7 @@ func initCommonChecks(st *state.State) error {
return fmt.Errorf("failed to generate CREATE2 salt: %w", err)
}
}
return nil
}
......@@ -119,7 +120,7 @@ func InitGenesisStrategy(env *Env, intent *state.Intent, st *state.State) error
lgr := env.Logger.New("stage", "init", "strategy", "genesis")
lgr.Info("initializing pipeline")
if err := initCommonChecks(st); err != nil {
if err := initCommonChecks(intent, st); err != nil {
return err
}
......
......@@ -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)
}
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{
OpChainProxyAdminOwner: thisIntent.Roles.L1ProxyAdminOwner,
SystemConfigOwner: thisIntent.Roles.SystemConfigOwner,
......@@ -126,6 +147,7 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co
DisputeClockExtension: proofParams.DisputeClockExtension, // 3 hours (input in seconds)
DisputeMaxClockDuration: proofParams.DisputeMaxClockDuration, // 3.5 days (input in seconds)
AllowCustomDisputeParameters: proofParams.DangerouslyAllowCustomDisputeParameters,
StartingAnchorRoots: startingAnchorRoots,
}, nil
}
......
......@@ -12,6 +12,8 @@ type VMType string
const (
VMTypeAlphabet = "ALPHABET"
VMTypeCannon1 = "CANNON1"
VMTypeCannon2 = "CANNON2"
)
type ChainProofParams struct {
......@@ -30,6 +32,7 @@ type AdditionalDisputeGame struct {
UseCustomOracle bool
OracleMinProposalSize uint64
OracleChallengePeriodSeconds uint64
MakeRespected bool
}
type ChainIntent struct {
......
......@@ -4,6 +4,8 @@ import (
"fmt"
"math/big"
op_service "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/rpc"
......@@ -33,6 +35,9 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
ProtocolVersionsProxy: state.SuperchainDeployment.ProtocolVersionsProxyAddress,
},
L2InitializationConfig: genesis.L2InitializationConfig{
DevDeployConfig: genesis.DevDeployConfig{
FundDevAccounts: intent.FundDevAccounts,
},
L2GenesisBlockDeployConfig: genesis.L2GenesisBlockDeployConfig{
L2GenesisBlockGasLimit: 60_000_000,
L2GenesisBlockBaseFeePerGas: &l2GenesisBlockBaseFeePerGas,
......@@ -69,12 +74,12 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
// In-development hardforks should never be activated here. Instead, they
// should be specified as overrides.
UpgradeScheduleDeployConfig: genesis.UpgradeScheduleDeployConfig{
L2GenesisRegolithTimeOffset: u64UtilPtr(0),
L2GenesisCanyonTimeOffset: u64UtilPtr(0),
L2GenesisDeltaTimeOffset: u64UtilPtr(0),
L2GenesisEcotoneTimeOffset: u64UtilPtr(0),
L2GenesisFjordTimeOffset: u64UtilPtr(0),
L2GenesisGraniteTimeOffset: u64UtilPtr(0),
L2GenesisRegolithTimeOffset: op_service.U64UtilPtr(0),
L2GenesisCanyonTimeOffset: op_service.U64UtilPtr(0),
L2GenesisDeltaTimeOffset: op_service.U64UtilPtr(0),
L2GenesisEcotoneTimeOffset: op_service.U64UtilPtr(0),
L2GenesisFjordTimeOffset: op_service.U64UtilPtr(0),
L2GenesisGraniteTimeOffset: op_service.U64UtilPtr(0),
UseInterop: intent.UseInterop,
},
L2CoreDeployConfig: genesis.L2CoreDeployConfig{
......@@ -108,7 +113,7 @@ func CombineDeployConfig(intent *Intent, chainIntent *ChainIntent, state *State,
}
if intent.UseInterop {
cfg.L2InitializationConfig.UpgradeScheduleDeployConfig.L2GenesisInteropTimeOffset = u64UtilPtr(0)
cfg.L2InitializationConfig.UpgradeScheduleDeployConfig.L2GenesisInteropTimeOffset = op_service.U64UtilPtr(0)
}
if chainState.StartBlock == nil {
......@@ -177,11 +182,6 @@ func mustHexBigFromHex(hex string) *hexutil.Big {
return &hexBig
}
func u64UtilPtr(in uint64) *hexutil.Uint64 {
util := hexutil.Uint64(in)
return &util
}
func calculateBatchInboxAddr(chainID common.Hash) common.Address {
var out common.Address
copy(out[1:], crypto.Keccak256(chainID[:])[:19])
......
......@@ -46,9 +46,9 @@ var emptyAddress common.Address
var emptyHash common.Hash
type SuperchainProofParams struct {
WithdrawalDelaySeconds uint64 `json:"withdrawalDelaySeconds" toml:"withdrawalDelaySeconds"`
MinProposalSizeBytes uint64 `json:"minProposalSizeBytes" toml:"minProposalSizeBytes"`
ChallengePeriodSeconds uint64 `json:"challengePeriodSeconds" toml:"challengePeriodSeconds"`
WithdrawalDelaySeconds uint64 `json:"faultGameWithdrawalDelay" toml:"faultGameWithdrawalDelay"`
MinProposalSizeBytes uint64 `json:"preimageOracleMinProposalSize" toml:"preimageOracleMinProposalSize"`
ChallengePeriodSeconds uint64 `json:"preimageOracleChallengePeriod" toml:"preimageOracleChallengePeriod"`
ProofMaturityDelaySeconds uint64 `json:"proofMaturityDelaySeconds" toml:"proofMaturityDelaySeconds"`
DisputeGameFinalityDelaySeconds uint64 `json:"disputeGameFinalityDelaySeconds" toml:"disputeGameFinalityDelaySeconds"`
MIPSVersion uint64 `json:"mipsVersion" toml:"mipsVersion"`
......
......@@ -98,19 +98,19 @@ func BatcherKeyRotation(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient())
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)
owner, err := sysCfgContract.Owner(&bind.CallOpts{})
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!
tx, err := sysCfgContract.SetBatcherHash(sysCfgOwner, eth.AddressAsLeftPaddedHash(dp.Addresses.Bob))
require.NoError(t, err)
t.Logf("batcher changes in L1 tx %s", tx.Hash())
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t)
miner.ActL1IncludeTx(dp.Addresses.Deployer)(t)
miner.ActL1EndBlock(t)
receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), tx.Hash())
......@@ -289,7 +289,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient())
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)
// overhead changes from 2100 (default) to 1000
......@@ -300,7 +300,7 @@ func GPOParamsChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
// include the GPO change tx in L1
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t)
miner.ActL1IncludeTx(dp.Addresses.Deployer)(t)
miner.ActL1EndBlock(t)
basefeeGPOUpdate := miner.L1Chain().CurrentBlock().BaseFee
......@@ -384,7 +384,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
sysCfgContract, err := bindings.NewSystemConfig(sd.RollupCfg.L1SystemConfigAddress, miner.EthClient())
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)
_, err = sysCfgContract.SetGasLimit(sysCfgOwner, oldGasLimit*3)
......@@ -392,7 +392,7 @@ func GasLimitChange(gt *testing.T, deltaTimeOffset *hexutil.Uint64) {
// include the gaslimit update on L1
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.SysCfgOwner)(t)
miner.ActL1IncludeTx(dp.Addresses.Deployer)(t)
miner.ActL1EndBlock(t)
// 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) {
dp.DeployConfig.L2GenesisEcotoneTimeOffset = &genesisBlock
dp.DeployConfig.L2GenesisFjordTimeOffset = &fjordOffset
dp.DeployConfig.L2GenesisGraniteTimeOffset = nil
dp.DeployConfig.L2GenesisHoloceneTimeOffset = nil
require.NoError(t, dp.DeployConfig.Check(log), "must have valid config")
sd := e2eutils.Setup(t, dp, helpers.DefaultAlloc)
......
package config
import (
"compress/gzip"
"context"
"encoding/json"
"fmt"
"log/slog"
"math/big"
"os"
"path/filepath"
"path"
"slices"
"sync"
"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/log"
......@@ -15,6 +30,8 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
op_service "github.com/ethereum-optimism/optimism/op-service"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
_ "embed"
)
// legacy geth log levels - the geth command line --verbosity flag wasn't
......@@ -73,10 +90,15 @@ var (
// DeployConfig represents the deploy config used by the system.
deployConfigsByType = make(map[AllocType]*genesis.DeployConfig)
// 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 {
mtx.RLock()
defer mtx.RUnlock()
allocs, ok := l1AllocsByType[allocType]
if !ok {
panic(fmt.Errorf("unknown L1 alloc type: %q", allocType))
......@@ -85,6 +107,8 @@ func L1Allocs(allocType AllocType) *foundry.ForgeAllocs {
}
func L1Deployments(allocType AllocType) *genesis.L1Deployments {
mtx.RLock()
defer mtx.RUnlock()
deployments, ok := l1DeploymentsByType[allocType]
if !ok {
panic(fmt.Errorf("unknown L1 deployments type: %q", allocType))
......@@ -93,6 +117,8 @@ func L1Deployments(allocType AllocType) *genesis.L1Deployments {
}
func L2Allocs(allocType AllocType, mode genesis.L2AllocsMode) *foundry.ForgeAllocs {
mtx.RLock()
defer mtx.RUnlock()
allocsByType, ok := l2AllocsByType[allocType]
if !ok {
panic(fmt.Errorf("unknown L2 alloc type: %q", allocType))
......@@ -106,6 +132,8 @@ func L2Allocs(allocType AllocType, mode genesis.L2AllocsMode) *foundry.ForgeAllo
}
func DeployConfig(allocType AllocType) *genesis.DeployConfig {
mtx.RLock()
defer mtx.RUnlock()
dc, ok := deployConfigsByType[allocType]
if !ok {
panic(fmt.Errorf("unknown deploy config type: %q", allocType))
......@@ -123,15 +151,13 @@ func init() {
panic(err)
}
for _, allocType := range allocTypes {
initAllocType(root, allocType)
}
// Setup global logger
lvl := log.FromLegacyLevel(EthNodeVerbosity)
var handler slog.Handler
var errHandler slog.Handler
if lvl > log.LevelCrit {
handler = log.DiscardHandler()
errHandler = log.DiscardHandler()
} else {
if lvl < log.LevelTrace { // clip to trace level
lvl = log.LevelTrace
......@@ -144,62 +170,172 @@ func init() {
Color: false, // some CI logs do not handle colors well
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)
}
func initAllocType(root string, allocType AllocType) {
devnetDir := filepath.Join(root, fmt.Sprintf(".devnet-%s", allocType))
l1AllocsPath := filepath.Join(devnetDir, "allocs-l1.json")
l2AllocsDir := devnetDir
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
artifactsPath := path.Join(root, "packages", "contracts-bedrock", "forge-artifacts")
if err := ensureDir(artifactsPath); err != nil {
panic(fmt.Errorf("invalid artifacts path: %w", err))
}
loc, err := artifacts.NewFileLocator(artifactsPath)
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 {
panic(err)
panic(fmt.Errorf("failed to parse private key: %w", err))
}
l1AllocsByType[allocType] = l1Allocs
l2Alloc := make(map[genesis.L2AllocsMode]*foundry.ForgeAllocs)
mustL2Allocs := func(mode genesis.L2AllocsMode) {
name := "allocs-l2-" + string(mode)
allocs, err := foundry.LoadForgeAllocs(filepath.Join(l2AllocsDir, name+".json"))
deployerAddr := crypto.PubkeyToAddress(pk.PublicKey)
lgr.Info("deployer address", "address", deployerAddr.Hex())
for _, mode := range allocModes {
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 {
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)
mustL2Allocs(genesis.L2AllocsGranite)
mustL2Allocs(genesis.L2AllocsFjord)
mustL2Allocs(genesis.L2AllocsEcotone)
mustL2Allocs(genesis.L2AllocsDelta)
l2AllocsByType[allocType] = l2Alloc
l1Deployments, err := genesis.NewL1Deployments(l1DeploymentsPath)
maps.Copy(baseUpgradeSchedule, upgradeOverrides)
maps.Copy(intent.GlobalDeployOverrides, baseUpgradeSchedule)
st := &state.State{
Version: 1,
}
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 {
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 {
panic(err)
panic(fmt.Errorf("failed to inspect L1: %w", err))
}
l1Deployments := l1Contracts.AsL1Deployments()
// Set the L1 genesis block timestamp to now
dc.L1GenesisBlockTimestamp = hexutil.Uint64(time.Now().Unix())
......@@ -208,5 +344,200 @@ func initAllocType(root string, allocType AllocType) {
dc.L1BlockTime = 2
dc.L2BlockTime = 1
dc.SetDeployments(l1Deployments)
mtx.Lock()
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) {
numL1TxsExpected := int64(10)
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.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
// ensures that batcher txs are as small as possible
cfg.BatcherMaxL1TxSizeBytes = derive.FrameV0OverHeadSize + 1 /*version bytes*/ + 1
......
......@@ -35,7 +35,7 @@ func TestEIP1559Params(t *testing.T) {
// Obtain our sequencer, verifier, and transactor keypair.
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
ethPrivKey := cfg.Secrets.SysCfgOwner
ethPrivKey := cfg.Secrets.Deployer
_, err = l2Seq.HeaderByNumber(context.Background(), big.NewInt(0))
require.NoError(t, err)
......
......@@ -40,7 +40,7 @@ func TestGasPriceOracleFeeUpdates(t *testing.T) {
l1Client := sys.NodeClient("l1")
l2Seq := sys.NodeClient("sequencer")
// l2Verif := sys.NodeClient("verifier")
ethPrivKey := cfg.Secrets.SysCfgOwner
ethPrivKey := cfg.Secrets.Deployer
// Bind to the SystemConfig & GasPriceOracle contracts
sysconfig, err := legacybindings.NewSystemConfig(cfg.L1Deployments.SystemConfigProxy, l1Client)
......
......@@ -113,14 +113,14 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
op_e2e.InitParallel(t)
gto := setup(t)
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)
})
t.Run("withdrawal", func(t *testing.T) {
op_e2e.InitParallel(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)
checkWithdrawal(t, gto)
})
......@@ -128,7 +128,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
t.Run("fee withdrawal", func(t *testing.T) {
op_e2e.InitParallel(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)
checkFeeWithdrawal(t, gto, true)
})
......@@ -139,7 +139,7 @@ func testCustomGasToken(t *testing.T, allocType config.AllocType) {
checkL1TokenNameAndSymbol(t, gto, gto.disabledExpectations)
checkL2TokenNameAndSymbol(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)
checkL2TokenNameAndSymbol(t, gto, gto.enabledExpectations)
checkWETHTokenNameAndSymbol(t, gto, gto.enabledExpectations)
......@@ -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.
// 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.
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")
deployerOpts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err)
......@@ -203,7 +203,11 @@ func setCustomGasToken(t *testing.T, cfg e2esys.SystemConfig, sys *e2esys.System
// 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,
// 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)
// Execute the upgrade SystemConfigProxy -> StorageSetter via ProxyAdmin
......
......@@ -78,6 +78,7 @@ func applySpanBatchActivation(active bool, dp *genesis.DeployConfig) {
dp.L2GenesisEcotoneTimeOffset = nil
dp.L2GenesisFjordTimeOffset = nil
dp.L2GenesisGraniteTimeOffset = nil
dp.L2GenesisHoloceneTimeOffset = nil
}
}
......
......@@ -40,7 +40,7 @@ func TestRuntimeConfigReload(t *testing.T) {
require.NoError(t, err)
newUnsafeBlocksSigner := common.Address{0x12, 0x23, 0x45}
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)
// the unsafe signer address is part of the runtime config
tx, err := sysCfgContract.SetUnsafeBlockSigner(opts, newUnsafeBlocksSigner)
......
......@@ -49,8 +49,8 @@ func TestRecommendedProtocolVersionChange(t *testing.T) {
protVersions, err := bindings.NewProtocolVersions(cfg.L1Deployments.ProtocolVersionsProxy, l1)
require.NoError(t, err)
// ProtocolVersions contract is owned by same key as SystemConfig in devnet
opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.SysCfgOwner, cfg.L1ChainIDBig())
// ProtocolVersions contract is owned by the deployer in devnet
opts, err := bind.NewKeyedTransactorWithChainID(cfg.Secrets.Deployer, cfg.L1ChainIDBig())
require.NoError(t, err)
// Change recommended protocol version
......@@ -105,7 +105,7 @@ func TestRequiredProtocolVersionChangeAndHalt(t *testing.T) {
require.NoError(t, err)
// 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)
// Change required protocol version
......
......@@ -12,6 +12,8 @@ import (
"strings"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
"github.com/ethereum/go-ethereum/common"
......@@ -163,3 +165,8 @@ func Parse256BitChainID(in string) (common.Hash, error) {
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 {
}
}
function checkOutput(DeployMIPSInput _mi) public view {
DeployUtils.assertValidContractAddress(address(_mipsSingleton));
assertValidDeploy(_mi);
}
function mipsSingleton() public view returns (IMIPS) {
DeployUtils.assertValidContractAddress(address(_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
contract DeployMIPS is Script {
function run(DeployMIPSInput _mi, DeployMIPSOutput _mo) public {
deployMipsSingleton(_mi, _mo);
_mo.checkOutput(_mi);
assertValidDeploy(_mi, _mo);
}
function deployMipsSingleton(DeployMIPSInput _mi, DeployMIPSOutput _mo) internal {
......@@ -106,4 +91,14 @@ contract DeployMIPS is Script {
vm.label(address(singleton), "MIPSSingleton");
_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;
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 { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol";
import { GameType } from "src/dispute/lib/Types.sol";
import { IOptimismPortal2 } from "interfaces/L1/IOptimismPortal2.sol";
contract SetDisputeGameImplInput is BaseDeployIO {
IDisputeGameFactory internal _factory;
IDisputeGame internal _impl;
IOptimismPortal2 internal _portal;
IFaultDisputeGame internal _impl;
uint32 internal _gameType;
// Setter for address type
......@@ -18,7 +20,8 @@ contract SetDisputeGameImplInput is BaseDeployIO {
require(_addr != address(0), "SetDisputeGameImplInput: cannot set zero address");
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");
}
......@@ -28,13 +31,16 @@ contract SetDisputeGameImplInput is BaseDeployIO {
else revert("SetDisputeGameImplInput: unknown selector");
}
// Getters
function factory() public view returns (IDisputeGameFactory) {
require(address(_factory) != address(0), "SetDisputeGameImplInput: not set");
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");
return _impl;
}
......@@ -50,14 +56,28 @@ contract SetDisputeGameImpl is Script {
GameType gameType = GameType.wrap(_input.gameType());
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);
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);
}
function assertValid(SetDisputeGameImplInput _input) public view {
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";
import { SetDisputeGameImpl, SetDisputeGameImplInput } from "scripts/deploy/SetDisputeGameImpl.s.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.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 {
SetDisputeGameImplInput input;
......@@ -65,19 +70,43 @@ contract SetDisputeGameImpl_Test is Test {
SetDisputeGameImpl script;
SetDisputeGameImplInput input;
IDisputeGameFactory factory;
IOptimismPortal2 portal;
address mockImpl;
uint32 gameType;
function setUp() public {
script = new SetDisputeGameImpl();
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 proxy = new Proxy(address(1));
Proxy supConfigProxy = new Proxy(address(1));
vm.prank(address(1));
proxy.upgradeToAndCall(address(impl), abi.encodeCall(impl.initialize, address(this)));
factory = IDisputeGameFactory(address(proxy));
supConfigProxy.upgradeToAndCall(
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");
gameType = 999;
......@@ -86,6 +115,7 @@ contract SetDisputeGameImpl_Test is Test {
function test_run_succeeds() public {
input.set(input.factory.selector, address(factory));
input.set(input.impl.selector, mockImpl);
input.set(input.portal.selector, address(portal));
input.set(input.gameType.selector, gameType);
script.run(input);
......@@ -94,6 +124,7 @@ contract SetDisputeGameImpl_Test is Test {
function test_run_whenImplAlreadySet_reverts() public {
input.set(input.factory.selector, address(factory));
input.set(input.impl.selector, mockImpl);
input.set(input.portal.selector, address(portal));
input.set(input.gameType.selector, gameType);
// First run should succeed
......@@ -115,7 +146,7 @@ contract SetDisputeGameImpl_Test is Test {
vm.broadcast(address(this));
factory.setImplementation(GameType.wrap(gameType), IDisputeGame(address(0)));
vm.expectRevert("SDGI-20");
vm.expectRevert("SDGI-30");
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