Commit 644dc2b5 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

Cleanups for production, add standard addresses (#12169)

* Cleanups for production, add standard addresses

This PR:

- Cleans up the intent file to be more suitable for production deployments
- Fixes various bugs encountered while preparing `op-deployer` for use against predeployed OPCM contracts
- Adds a new CLI command to bootstrap a new OPCM deployment against an existing set of implementation contracts

Note on Solidity changes:

- Since the code for custom gas tokens is in the monorepo but isn't included in an official contracts release yet, we had to add interfaces for the pre-CGT contracts to the Solidity codebase.
- The `DeployImplementations` script looks at the release identifier to determine whether or not it should use the pre- or post-CGT interfaces.

* goimports

* lints

* fix tests

* revert tx manger changes

* Update packages/contracts-bedrock/src/L1/interfaces/IL1StandardBridgeV160.sol
Co-authored-by: default avatarMaurelian <john@oplabs.co>

* Update packages/contracts-bedrock/src/L1/interfaces/IL1CrossDomainMessengerV160.sol
Co-authored-by: default avatarMaurelian <john@oplabs.co>

* use new opcm

* fix test

* semver

* semver

* bump semver

* update manager deployment

* natspec

* SEMVER

---------
Co-authored-by: default avatarMaurelian <john@oplabs.co>
parent a96b2282
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"fmt" "fmt"
"os" "os"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/bootstrap"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/version"
opservice "github.com/ethereum-optimism/optimism/op-service" opservice "github.com/ethereum-optimism/optimism/op-service"
...@@ -41,6 +43,11 @@ func main() { ...@@ -41,6 +43,11 @@ func main() {
Flags: cliapp.ProtectFlags(deployer.ApplyFlags), Flags: cliapp.ProtectFlags(deployer.ApplyFlags),
Action: deployer.ApplyCLI(), Action: deployer.ApplyCLI(),
}, },
{
Name: "bootstrap",
Usage: "bootstraps global contract instances",
Subcommands: bootstrap.Commands,
},
{ {
Name: "inspect", Name: "inspect",
Usage: "inspects the state of a deployment", Usage: "inspects the state of a deployment",
......
package bootstrap
import (
"context"
"crypto/ecdsa"
"crypto/rand"
"fmt"
"math/big"
"strings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto"
"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
)
type OPCMConfig struct {
L1RPCUrl string
PrivateKey string
Logger log.Logger
ArtifactsURL *state.ArtifactsURL
ContractsRelease string
privateKeyECDSA *ecdsa.PrivateKey
}
func (c *OPCMConfig) Check() error {
if c.L1RPCUrl == "" {
return fmt.Errorf("l1RPCUrl must be specified")
}
if c.PrivateKey == "" {
return fmt.Errorf("private key must be specified")
}
privECDSA, err := crypto.HexToECDSA(strings.TrimPrefix(c.PrivateKey, "0x"))
if err != nil {
return fmt.Errorf("failed to parse private key: %w", err)
}
c.privateKeyECDSA = privECDSA
if c.Logger == nil {
return fmt.Errorf("logger must be specified")
}
if c.ArtifactsURL == nil {
return fmt.Errorf("artifacts URL must be specified")
}
if c.ContractsRelease == "" {
return fmt.Errorf("contracts release must be specified")
}
return nil
}
func OPCMCLI(cliCtx *cli.Context) error {
logCfg := oplog.ReadCLIConfig(cliCtx)
l := oplog.NewLogger(oplog.AppOut(cliCtx), logCfg)
oplog.SetGlobalLogHandler(l.Handler())
l1RPCUrl := cliCtx.String(deployer.L1RPCURLFlagName)
privateKey := cliCtx.String(deployer.PrivateKeyFlagName)
artifactsURLStr := cliCtx.String(ArtifactsURLFlagName)
artifactsURL := new(state.ArtifactsURL)
if err := artifactsURL.UnmarshalText([]byte(artifactsURLStr)); err != nil {
return fmt.Errorf("failed to parse artifacts URL: %w", err)
}
contractsRelease := cliCtx.String(ContractsReleaseFlagName)
ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context)
return OPCM(ctx, OPCMConfig{
L1RPCUrl: l1RPCUrl,
PrivateKey: privateKey,
Logger: l,
ArtifactsURL: artifactsURL,
ContractsRelease: contractsRelease,
})
}
func OPCM(ctx context.Context, cfg OPCMConfig) error {
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid config for OPCM: %w", err)
}
lgr := cfg.Logger
progressor := func(curr, total int64) {
lgr.Info("artifacts download progress", "current", curr, "total", total)
}
artifactsFS, cleanup, err := pipeline.DownloadArtifacts(ctx, cfg.ArtifactsURL, progressor)
if err != nil {
return fmt.Errorf("failed to download artifacts: %w", err)
}
defer func() {
if err := cleanup(); err != nil {
lgr.Warn("failed to clean up artifacts", "err", err)
}
}()
l1Client, err := ethclient.Dial(cfg.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
chainID, err := l1Client.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get chain ID: %w", err)
}
chainIDU64 := chainID.Uint64()
superCfg, err := opcm.SuperchainFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting superchain config: %w", err)
}
standardVersionsTOML, err := opcm.StandardVersionsFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err)
}
opcmProxyOwnerAddr, err := opcm.ManagerOwnerAddrFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting superchain proxy admin: %w", err)
}
signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID))
chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey)
lgr.Info("deploying OPCM", "release", cfg.ContractsRelease)
var dio opcm.DeployImplementationsOutput
err = pipeline.CallScriptBroadcast(
ctx,
pipeline.CallScriptBroadcastOpts{
L1ChainID: chainID,
Logger: lgr,
ArtifactsFS: artifactsFS,
Deployer: chainDeployer,
Signer: signer,
Client: l1Client,
Broadcaster: pipeline.KeyedBroadcaster,
Handler: func(host *script.Host) error {
// We need to etch the Superchain addresses so that they have nonzero code
// and the checks in the OPCM constructor pass.
superchainConfigAddr := common.Address(*superCfg.Config.SuperchainConfigAddr)
protocolVersionsAddr := common.Address(*superCfg.Config.ProtocolVersionsAddr)
addresses := []common.Address{
superchainConfigAddr,
protocolVersionsAddr,
}
for _, addr := range addresses {
host.ImportAccount(addr, types.Account{
Code: []byte{0x00},
})
}
var salt common.Hash
_, err = rand.Read(salt[:])
if err != nil {
return fmt.Errorf("failed to generate CREATE2 salt: %w", err)
}
dio, err = opcm.DeployImplementations(
host,
opcm.DeployImplementationsInput{
Salt: salt,
WithdrawalDelaySeconds: big.NewInt(604800),
MinProposalSizeBytes: big.NewInt(126000),
ChallengePeriodSeconds: big.NewInt(86400),
ProofMaturityDelaySeconds: big.NewInt(604800),
DisputeGameFinalityDelaySeconds: big.NewInt(302400),
Release: cfg.ContractsRelease,
SuperchainConfigProxy: superchainConfigAddr,
ProtocolVersionsProxy: protocolVersionsAddr,
OpcmProxyOwner: opcmProxyOwnerAddr,
StandardVersionsToml: standardVersionsTOML,
UseInterop: false,
},
)
return err
},
},
)
if err != nil {
return fmt.Errorf("error deploying implementations: %w", err)
}
lgr.Info("deployed implementations")
if err := jsonutil.WriteJSON(dio, ioutil.ToStdOut()); err != nil {
return fmt.Errorf("failed to write output: %w", err)
}
return nil
}
package bootstrap
import (
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/urfave/cli/v2"
)
const (
ArtifactsURLFlagName = "artifacts-url"
ContractsReleaseFlagName = "contracts-release"
)
var (
ArtifactsURLFlag = &cli.StringFlag{
Name: ArtifactsURLFlagName,
Usage: "URL to the artifacts directory.",
EnvVars: deployer.PrefixEnvVar("ARTIFACTS_URL"),
}
ContractsReleaseFlag = &cli.StringFlag{
Name: ContractsReleaseFlagName,
Usage: "Release of the contracts to deploy.",
EnvVars: deployer.PrefixEnvVar("CONTRACTS_RELEASE"),
}
)
var OPCMFlags = []cli.Flag{
deployer.L1RPCURLFlag,
deployer.PrivateKeyFlag,
ArtifactsURLFlag,
ContractsReleaseFlag,
}
var Commands = []*cli.Command{
{
Name: "opcm",
Usage: "Bootstrap an instance of OPCM.",
Flags: cliapp.ProtectFlags(OPCMFlags),
Action: OPCMCLI,
},
}
...@@ -66,7 +66,7 @@ func NewKeyedBroadcaster(cfg KeyedBroadcasterOpts) (*KeyedBroadcaster, error) { ...@@ -66,7 +66,7 @@ func NewKeyedBroadcaster(cfg KeyedBroadcasterOpts) (*KeyedBroadcaster, error) {
mgrCfg.FeeLimitMultiplier.Store(5) mgrCfg.FeeLimitMultiplier.Store(5)
mgrCfg.FeeLimitThreshold.Store(big.NewInt(100)) mgrCfg.FeeLimitThreshold.Store(big.NewInt(100))
mgrCfg.MinTipCap.Store(minTipCap) mgrCfg.MinTipCap.Store(minTipCap)
mgrCfg.MinTipCap.Store(minBaseFee) mgrCfg.MinBaseFee.Store(minBaseFee)
txmLogger := log.NewLogger(log.DiscardHandler()) txmLogger := log.NewLogger(log.DiscardHandler())
if cfg.TXManagerLogger != nil { if cfg.TXManagerLogger != nil {
......
...@@ -30,28 +30,27 @@ var ( ...@@ -30,28 +30,27 @@ var (
L1ChainIDFlag = &cli.Uint64Flag{ L1ChainIDFlag = &cli.Uint64Flag{
Name: L1ChainIDFlagName, Name: L1ChainIDFlagName,
Usage: "Chain ID of the L1 chain.", Usage: "Chain ID of the L1 chain.",
EnvVars: prefixEnvVar("L1_CHAIN_ID"), EnvVars: PrefixEnvVar("L1_CHAIN_ID"),
Value: 900, Value: 900,
} }
L2ChainIDsFlag = &cli.StringFlag{ L2ChainIDsFlag = &cli.StringFlag{
Name: L2ChainIDsFlagName, Name: L2ChainIDsFlagName,
Usage: "Comma-separated list of L2 chain IDs to deploy.", Usage: "Comma-separated list of L2 chain IDs to deploy.",
EnvVars: prefixEnvVar("L2_CHAIN_IDS"), EnvVars: PrefixEnvVar("L2_CHAIN_IDS"),
} }
WorkdirFlag = &cli.StringFlag{ WorkdirFlag = &cli.StringFlag{
Name: WorkdirFlagName, Name: WorkdirFlagName,
Usage: "Directory storing intent and stage. Defaults to the current directory.", Usage: "Directory storing intent and stage. Defaults to the current directory.",
EnvVars: prefixEnvVar("WORKDIR"), EnvVars: PrefixEnvVar("WORKDIR"),
Value: cwd(), Value: cwd(),
Aliases: []string{ Aliases: []string{
OutdirFlagName, OutdirFlagName,
}, },
} }
PrivateKeyFlag = &cli.StringFlag{ PrivateKeyFlag = &cli.StringFlag{
Name: PrivateKeyFlagName, Name: PrivateKeyFlagName,
Usage: "Private key of the deployer account.", Usage: "Private key of the deployer account.",
EnvVars: prefixEnvVar("PRIVATE_KEY"), EnvVars: PrefixEnvVar("PRIVATE_KEY"),
} }
) )
...@@ -69,7 +68,7 @@ var ApplyFlags = []cli.Flag{ ...@@ -69,7 +68,7 @@ var ApplyFlags = []cli.Flag{
PrivateKeyFlag, PrivateKeyFlag,
} }
func prefixEnvVar(name string) []string { func PrefixEnvVar(name string) []string {
return op_service.PrefixEnvVar(EnvVarPrefix, name) return op_service.PrefixEnvVar(EnvVarPrefix, name)
} }
......
...@@ -41,8 +41,8 @@ func InitCLI() func(ctx *cli.Context) error { ...@@ -41,8 +41,8 @@ func InitCLI() func(ctx *cli.Context) error {
outdir := ctx.String(OutdirFlagName) outdir := ctx.String(OutdirFlagName)
l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName) l2ChainIDsRaw := ctx.String(L2ChainIDsFlagName)
l2ChainIDsStr := strings.Split(l2ChainIDsRaw, ",") l2ChainIDsStr := strings.Split(strings.TrimSpace(l2ChainIDsRaw), ",")
l2ChainIDs := make([]common.Hash, 0, len(l2ChainIDsStr)) l2ChainIDs := make([]common.Hash, len(l2ChainIDsStr))
for _, idStr := range l2ChainIDsStr { for _, idStr := range l2ChainIDsStr {
id, err := op_service.Parse256BitChainID(idStr) id, err := op_service.Parse256BitChainID(idStr)
if err != nil { if err != nil {
...@@ -66,7 +66,6 @@ func Init(cfg InitConfig) error { ...@@ -66,7 +66,6 @@ func Init(cfg InitConfig) error {
intent := &state.Intent{ intent := &state.Intent{
L1ChainID: cfg.L1ChainID, L1ChainID: cfg.L1ChainID,
UseFaultProofs: true,
FundDevAccounts: true, FundDevAccounts: true,
ContractsRelease: "dev", ContractsRelease: "dev",
} }
......
...@@ -198,7 +198,6 @@ func makeIntent( ...@@ -198,7 +198,6 @@ func makeIntent(
ProtocolVersionsOwner: addrFor(devkeys.SuperchainDeployerKey.Key(l1ChainID)), ProtocolVersionsOwner: addrFor(devkeys.SuperchainDeployerKey.Key(l1ChainID)),
Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)), Guardian: addrFor(devkeys.SuperchainConfigGuardianKey.Key(l1ChainID)),
}, },
UseFaultProofs: true,
FundDevAccounts: true, FundDevAccounts: true,
ContractArtifactsURL: (*state.ArtifactsURL)(artifactsURL), ContractArtifactsURL: (*state.ArtifactsURL)(artifactsURL),
ContractsRelease: "dev", ContractsRelease: "dev",
...@@ -239,7 +238,6 @@ func validateOPChainDeployment(t *testing.T, ctx context.Context, l1Client *ethc ...@@ -239,7 +238,6 @@ func validateOPChainDeployment(t *testing.T, ctx context.Context, l1Client *ethc
{"OptimismPortalProxyAddress", chainState.OptimismPortalProxyAddress}, {"OptimismPortalProxyAddress", chainState.OptimismPortalProxyAddress},
{"DisputeGameFactoryProxyAddress", chainState.DisputeGameFactoryProxyAddress}, {"DisputeGameFactoryProxyAddress", chainState.DisputeGameFactoryProxyAddress},
{"AnchorStateRegistryProxyAddress", chainState.AnchorStateRegistryProxyAddress}, {"AnchorStateRegistryProxyAddress", chainState.AnchorStateRegistryProxyAddress},
{"AnchorStateRegistryImplAddress", chainState.AnchorStateRegistryImplAddress},
{"FaultDisputeGameAddress", chainState.FaultDisputeGameAddress}, {"FaultDisputeGameAddress", chainState.FaultDisputeGameAddress},
{"PermissionedDisputeGameAddress", chainState.PermissionedDisputeGameAddress}, {"PermissionedDisputeGameAddress", chainState.PermissionedDisputeGameAddress},
{"DelayedWETHPermissionedGameProxyAddress", chainState.DelayedWETHPermissionedGameProxyAddress}, {"DelayedWETHPermissionedGameProxyAddress", chainState.DelayedWETHPermissionedGameProxyAddress},
......
...@@ -22,7 +22,7 @@ type DeployImplementationsInput struct { ...@@ -22,7 +22,7 @@ type DeployImplementationsInput struct {
ProtocolVersionsProxy common.Address ProtocolVersionsProxy common.Address
UseInterop bool // if true, deploy Interop implementations UseInterop bool // if true, deploy Interop implementations
SuperchainProxyAdmin common.Address OpcmProxyOwner common.Address
StandardVersionsToml string // contents of 'standard-versions-mainnet.toml' or 'standard-versions-sepolia.toml' file StandardVersionsToml string // contents of 'standard-versions-mainnet.toml' or 'standard-versions-sepolia.toml' file
} }
......
...@@ -123,6 +123,7 @@ type opcmDeployInput struct { ...@@ -123,6 +123,7 @@ type opcmDeployInput struct {
BlobBasefeeScalar uint32 BlobBasefeeScalar uint32
L2ChainId *big.Int L2ChainId *big.Int
StartingAnchorRoots []byte StartingAnchorRoots []byte
SaltMixer string
} }
// decodeOutputABIJSON defines an ABI for a fake method called "decodeOutput" that returns the // decodeOutputABIJSON defines an ABI for a fake method called "decodeOutput" that returns the
...@@ -241,6 +242,7 @@ func DeployOPChainRaw( ...@@ -241,6 +242,7 @@ func DeployOPChainRaw(
BlobBasefeeScalar: input.BlobBaseFeeScalar, BlobBasefeeScalar: input.BlobBaseFeeScalar,
L2ChainId: input.L2ChainId, L2ChainId: input.L2ChainId,
StartingAnchorRoots: input.StartingAnchorRoots(), StartingAnchorRoots: input.StartingAnchorRoots(),
SaltMixer: input.SaltMixer,
}) })
if err != nil { if err != nil {
return out, fmt.Errorf("failed to pack deploy input: %w", err) return out, fmt.Errorf("failed to pack deploy input: %w", err)
......
package opcm package opcm
import "embed" import (
"embed"
"fmt"
"github.com/ethereum-optimism/superchain-registry/superchain"
"github.com/ethereum/go-ethereum/common"
)
//go:embed standard-versions-mainnet.toml //go:embed standard-versions-mainnet.toml
var StandardVersionsMainnetData string var StandardVersionsMainnetData string
...@@ -9,3 +15,48 @@ var StandardVersionsMainnetData string ...@@ -9,3 +15,48 @@ var StandardVersionsMainnetData string
var StandardVersionsSepoliaData string var StandardVersionsSepoliaData string
var _ embed.FS var _ embed.FS
func StandardVersionsFor(chainID uint64) (string, error) {
switch chainID {
case 1:
return StandardVersionsMainnetData, nil
case 11155111:
return StandardVersionsSepoliaData, nil
default:
return "", fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func SuperchainFor(chainID uint64) (*superchain.Superchain, error) {
switch chainID {
case 1:
return superchain.Superchains["mainnet"], nil
case 11155111:
return superchain.Superchains["sepolia"], nil
default:
return nil, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func ManagerImplementationAddrFor(chainID uint64) (common.Address, error) {
switch chainID {
case 11155111:
// Generated using the bootstrap command on 09/26/2024.
return common.HexToAddress("0x0dc727671d5c08e4e41e8909983ebfa6f57aa0bf"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func ManagerOwnerAddrFor(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
// Set to superchain proxy admin
return common.HexToAddress("0x543bA4AADBAb8f9025686Bd03993043599c6fB04"), nil
case 11155111:
// Set to development multisig
return common.HexToAddress("0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"math/big" "math/big"
"strings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state"
...@@ -21,9 +22,17 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St ...@@ -21,9 +22,17 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St
lgr.Info("deploying implementations") lgr.Info("deploying implementations")
var standardVersionsTOML string
var err error
if strings.HasPrefix(intent.ContractsRelease, "op-contracts") {
standardVersionsTOML, err = opcm.StandardVersionsFor(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err)
}
}
var dump *foundry.ForgeAllocs var dump *foundry.ForgeAllocs
var dio opcm.DeployImplementationsOutput var dio opcm.DeployImplementationsOutput
var err error
err = CallScriptBroadcast( err = CallScriptBroadcast(
ctx, ctx,
CallScriptBroadcastOpts{ CallScriptBroadcastOpts{
...@@ -35,8 +44,8 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St ...@@ -35,8 +44,8 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St
Client: env.L1Client, Client: env.L1Client,
Broadcaster: KeyedBroadcaster, Broadcaster: KeyedBroadcaster,
Handler: func(host *script.Host) error { Handler: func(host *script.Host) error {
host.SetEnvVar("IMPL_SALT", st.Create2Salt.Hex()[2:])
host.ImportState(st.SuperchainDeployment.StateDump) host.ImportState(st.SuperchainDeployment.StateDump)
dio, err = opcm.DeployImplementations( dio, err = opcm.DeployImplementations(
host, host,
opcm.DeployImplementationsInput{ opcm.DeployImplementationsInput{
...@@ -49,8 +58,8 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St ...@@ -49,8 +58,8 @@ func DeployImplementations(ctx context.Context, env *Env, artifactsFS foundry.St
Release: intent.ContractsRelease, Release: intent.ContractsRelease,
SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress, SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress,
ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress, ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress,
SuperchainProxyAdmin: st.SuperchainDeployment.ProxyAdminAddress, OpcmProxyOwner: st.SuperchainDeployment.ProxyAdminAddress,
StandardVersionsToml: opcm.StandardVersionsMainnetData, StandardVersionsToml: standardVersionsTOML,
UseInterop: false, UseInterop: false,
}, },
) )
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"strings"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry" "github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
...@@ -19,7 +20,7 @@ func IsSupportedStateVersion(version int) bool { ...@@ -19,7 +20,7 @@ func IsSupportedStateVersion(version int) bool {
return version == 1 return version == 1
} }
func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *state.Intent, st *state.State) error { func Init(ctx context.Context, env *Env, _ foundry.StatDirFs, intent *state.Intent, st *state.State) error {
lgr := env.Logger.New("stage", "init") lgr := env.Logger.New("stage", "init")
lgr.Info("initializing pipeline") lgr.Info("initializing pipeline")
...@@ -35,37 +36,31 @@ func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent * ...@@ -35,37 +36,31 @@ func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *
} }
} }
if intent.OPCMAddress != (common.Address{}) { if strings.HasPrefix(intent.ContractsRelease, "op-contracts") {
env.Logger.Info("using provided OPCM address, populating state", "address", intent.OPCMAddress.Hex()) superCfg, err := opcm.SuperchainFor(intent.L1ChainID)
if intent.ContractsRelease == "dev" {
env.Logger.Warn("using dev release with existing OPCM, this field will be ignored")
}
opcmContract := opcm.NewContract(intent.OPCMAddress, env.L1Client)
protocolVersions, err := opcmContract.ProtocolVersions(ctx)
if err != nil { if err != nil {
return fmt.Errorf("error getting protocol versions address: %w", err) return fmt.Errorf("error getting superchain config: %w", err)
} }
superchainConfig, err := opcmContract.SuperchainConfig(ctx)
proxyAdmin, err := opcm.ManagerOwnerAddrFor(intent.L1ChainID)
if err != nil { if err != nil {
return fmt.Errorf("error getting superchain config address: %w", err) return fmt.Errorf("error getting superchain proxy admin address: %w", err)
} }
env.Logger.Debug(
"populating protocol versions and superchain config addresses",
"protocolVersions", protocolVersions.Hex(),
"superchainConfig", superchainConfig.Hex(),
)
// The below fields are the only ones required to perform an OP Chain // Have to do this weird pointer thing below because the Superchain Registry defines its
// deployment via an existing OPCM contract. All the others are used // own Address type.
// for deploying the OPCM itself, which isn't necessary in this case.
st.SuperchainDeployment = &state.SuperchainDeployment{ st.SuperchainDeployment = &state.SuperchainDeployment{
ProtocolVersionsProxyAddress: protocolVersions, ProxyAdminAddress: proxyAdmin,
SuperchainConfigProxyAddress: superchainConfig, ProtocolVersionsProxyAddress: common.Address(*superCfg.Config.ProtocolVersionsAddr),
SuperchainConfigProxyAddress: common.Address(*superCfg.Config.SuperchainConfigAddr),
}
opcmProxy, err := opcm.ManagerImplementationAddrFor(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting OPCM proxy address: %w", err)
} }
st.ImplementationsDeployment = &state.ImplementationsDeployment{ st.ImplementationsDeployment = &state.ImplementationsDeployment{
OpcmProxyAddress: intent.OPCMAddress, OpcmProxyAddress: opcmProxy,
} }
} }
...@@ -81,14 +76,6 @@ func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent * ...@@ -81,14 +76,6 @@ func Init(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, intent *
return immutableErr("L1ChainID", st.AppliedIntent.L1ChainID, intent.L1ChainID) return immutableErr("L1ChainID", st.AppliedIntent.L1ChainID, intent.L1ChainID)
} }
if st.AppliedIntent.UseFaultProofs != intent.UseFaultProofs {
return immutableErr("useFaultProofs", st.AppliedIntent.UseFaultProofs, intent.UseFaultProofs)
}
if st.AppliedIntent.UseAltDA != intent.UseAltDA {
return immutableErr("useAltDA", st.AppliedIntent.UseAltDA, intent.UseAltDA)
}
if st.AppliedIntent.FundDevAccounts != intent.FundDevAccounts { if st.AppliedIntent.FundDevAccounts != intent.FundDevAccounts {
return immutableErr("fundDevAccounts", st.AppliedIntent.FundDevAccounts, intent.FundDevAccounts) return immutableErr("fundDevAccounts", st.AppliedIntent.FundDevAccounts, intent.FundDevAccounts)
} }
......
...@@ -10,7 +10,6 @@ import ( ...@@ -10,7 +10,6 @@ import (
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state" "github.com/ethereum-optimism/optimism/op-chain-ops/deployer/state"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry" "github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
...@@ -44,34 +43,7 @@ func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, ...@@ -44,34 +43,7 @@ func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs,
} }
var dco opcm.DeployOPChainOutput var dco opcm.DeployOPChainOutput
if intent.OPCMAddress == (common.Address{}) { lgr.Info("deploying using existing OPCM", "address", st.ImplementationsDeployment.OpcmProxyAddress.Hex())
err = CallScriptBroadcast(
ctx,
CallScriptBroadcastOpts{
L1ChainID: big.NewInt(int64(intent.L1ChainID)),
Logger: lgr,
ArtifactsFS: artifactsFS,
Deployer: env.Deployer,
Signer: env.Signer,
Client: env.L1Client,
Broadcaster: KeyedBroadcaster,
Handler: func(host *script.Host) error {
host.ImportState(st.ImplementationsDeployment.StateDump)
dco, err = opcm.DeployOPChain(
host,
input,
)
return err
},
},
)
if err != nil {
return fmt.Errorf("error deploying OP chain: %w", err)
}
} else {
lgr.Info("deploying using existing OPCM", "address", intent.OPCMAddress.Hex())
bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{ bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: lgr, Logger: lgr,
ChainID: big.NewInt(int64(intent.L1ChainID)), ChainID: big.NewInt(int64(intent.L1ChainID)),
...@@ -93,7 +65,6 @@ func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs, ...@@ -93,7 +65,6 @@ func DeployOPChain(ctx context.Context, env *Env, artifactsFS foundry.StatDirFs,
if err != nil { if err != nil {
return fmt.Errorf("error deploying OP chain: %w", err) return fmt.Errorf("error deploying OP chain: %w", err)
} }
}
st.Chains = append(st.Chains, &state.ChainState{ st.Chains = append(st.Chains, &state.ChainState{
ID: chainID, ID: chainID,
......
...@@ -65,6 +65,13 @@ func DefaultDeployConfig() genesis.DeployConfig { ...@@ -65,6 +65,13 @@ func DefaultDeployConfig() genesis.DeployConfig {
SystemConfigStartBlock: 0, SystemConfigStartBlock: 0,
}, },
}, },
FaultProofDeployConfig: genesis.FaultProofDeployConfig{
FaultGameWithdrawalDelay: 604800,
PreimageOracleMinProposalSize: 126000,
PreimageOracleChallengePeriod: 86400,
ProofMaturityDelaySeconds: 604800,
DisputeGameFinalityDelaySeconds: 302400,
},
} }
} }
......
...@@ -17,17 +17,11 @@ type Intent struct { ...@@ -17,17 +17,11 @@ type Intent struct {
SuperchainRoles SuperchainRoles `json:"superchainRoles" toml:"superchainRoles"` SuperchainRoles SuperchainRoles `json:"superchainRoles" toml:"superchainRoles"`
UseFaultProofs bool `json:"useFaultProofs" toml:"useFaultProofs"`
UseAltDA bool `json:"useAltDA" toml:"useAltDA"`
FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"` FundDevAccounts bool `json:"fundDevAccounts" toml:"fundDevAccounts"`
ContractArtifactsURL *ArtifactsURL `json:"contractArtifactsURL" toml:"contractArtifactsURL"` ContractArtifactsURL *ArtifactsURL `json:"contractArtifactsURL" toml:"contractArtifactsURL"`
ContractsRelease string `json:"contractsVersion" toml:"contractsVersion"` ContractsRelease string `json:"contractsRelease" toml:"contractsRelease"`
OPCMAddress common.Address `json:"opcmAddress" toml:"opcmAddress"`
Chains []*ChainIntent `json:"chains" toml:"chains"` Chains []*ChainIntent `json:"chains" toml:"chains"`
...@@ -43,10 +37,28 @@ func (c *Intent) Check() error { ...@@ -43,10 +37,28 @@ func (c *Intent) Check() error {
return fmt.Errorf("l1ChainID must be set") return fmt.Errorf("l1ChainID must be set")
} }
if c.UseFaultProofs && c.UseAltDA { if c.ContractsRelease == "dev" {
return fmt.Errorf("cannot use both fault proofs and alt-DA") return c.checkDev()
} }
return c.checkProd()
}
func (c *Intent) Chain(id common.Hash) (*ChainIntent, error) {
for i := range c.Chains {
if c.Chains[i].ID == id {
return c.Chains[i], nil
}
}
return nil, fmt.Errorf("chain %d not found", id)
}
func (c *Intent) WriteToFile(path string) error {
return jsonutil.WriteTOML(c, ioutil.ToAtomicFile(path, 0o755))
}
func (c *Intent) checkDev() error {
if c.SuperchainRoles.ProxyAdminOwner == emptyAddress { if c.SuperchainRoles.ProxyAdminOwner == emptyAddress {
return fmt.Errorf("proxyAdminOwner must be set") return fmt.Errorf("proxyAdminOwner must be set")
} }
...@@ -60,28 +72,18 @@ func (c *Intent) Check() error { ...@@ -60,28 +72,18 @@ func (c *Intent) Check() error {
} }
if c.ContractArtifactsURL == nil { if c.ContractArtifactsURL == nil {
return fmt.Errorf("contractArtifactsURL must be set") return fmt.Errorf("contractArtifactsURL must be set in dev mode")
}
if c.ContractsRelease != "dev" && !strings.HasPrefix(c.ContractsRelease, "op-contracts/") {
return fmt.Errorf("contractsVersion must be either the literal \"dev\" or start with \"op-contracts/\"")
} }
return nil return nil
} }
func (c *Intent) Chain(id common.Hash) (*ChainIntent, error) { func (c *Intent) checkProd() error {
for i := range c.Chains { if !strings.HasPrefix(c.ContractsRelease, "op-contracts/") {
if c.Chains[i].ID == id { return fmt.Errorf("contractsVersion must be either the literal \"dev\" or start with \"op-contracts/\"")
return c.Chains[i], nil
}
} }
return nil, fmt.Errorf("chain %d not found", id) return nil
}
func (c *Intent) WriteToFile(path string) error {
return jsonutil.WriteTOML(c, ioutil.ToAtomicFile(path, 0o755))
} }
type SuperchainRoles struct { type SuperchainRoles struct {
......
...@@ -61,7 +61,7 @@ type SuperchainDeployment struct { ...@@ -61,7 +61,7 @@ type SuperchainDeployment struct {
SuperchainConfigImplAddress common.Address `json:"superchainConfigImplAddress"` SuperchainConfigImplAddress common.Address `json:"superchainConfigImplAddress"`
ProtocolVersionsProxyAddress common.Address `json:"protocolVersionsProxyAddress"` ProtocolVersionsProxyAddress common.Address `json:"protocolVersionsProxyAddress"`
ProtocolVersionsImplAddress common.Address `json:"protocolVersionsImplAddress"` ProtocolVersionsImplAddress common.Address `json:"protocolVersionsImplAddress"`
StateDump *foundry.ForgeAllocs `json:"stateDump"` StateDump *foundry.ForgeAllocs `json:"-"`
} }
type ImplementationsDeployment struct { type ImplementationsDeployment struct {
...@@ -76,7 +76,7 @@ type ImplementationsDeployment struct { ...@@ -76,7 +76,7 @@ type ImplementationsDeployment struct {
L1StandardBridgeImplAddress common.Address `json:"l1StandardBridgeImplAddress"` L1StandardBridgeImplAddress common.Address `json:"l1StandardBridgeImplAddress"`
OptimismMintableERC20FactoryImplAddress common.Address `json:"optimismMintableERC20FactoryImplAddress"` OptimismMintableERC20FactoryImplAddress common.Address `json:"optimismMintableERC20FactoryImplAddress"`
DisputeGameFactoryImplAddress common.Address `json:"disputeGameFactoryImplAddress"` DisputeGameFactoryImplAddress common.Address `json:"disputeGameFactoryImplAddress"`
StateDump *foundry.ForgeAllocs `json:"stateDump"` StateDump *foundry.ForgeAllocs `json:"-"`
} }
type ChainState struct { type ChainState struct {
......
...@@ -169,7 +169,7 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup ...@@ -169,7 +169,7 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup
Release: superCfg.Implementations.Release, Release: superCfg.Implementations.Release,
SuperchainConfigProxy: superDeployment.SuperchainConfigProxy, SuperchainConfigProxy: superDeployment.SuperchainConfigProxy,
ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy, ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy,
SuperchainProxyAdmin: superDeployment.SuperchainProxyAdmin, OpcmProxyOwner: superDeployment.SuperchainProxyAdmin,
UseInterop: superCfg.Implementations.UseInterop, UseInterop: superCfg.Implementations.UseInterop,
StandardVersionsToml: opcm.StandardVersionsMainnetData, StandardVersionsToml: opcm.StandardVersionsMainnetData,
}) })
......
...@@ -391,12 +391,22 @@ func (h *Host) GetNonce(addr common.Address) uint64 { ...@@ -391,12 +391,22 @@ func (h *Host) GetNonce(addr common.Address) uint64 {
// when importing. // when importing.
func (h *Host) ImportState(allocs *foundry.ForgeAllocs) { func (h *Host) ImportState(allocs *foundry.ForgeAllocs) {
for addr, alloc := range allocs.Accounts { for addr, alloc := range allocs.Accounts {
h.state.SetBalance(addr, uint256.MustFromBig(alloc.Balance), tracing.BalanceChangeUnspecified) h.ImportAccount(addr, alloc)
h.state.SetNonce(addr, alloc.Nonce) }
h.state.SetCode(addr, alloc.Code) }
for key, value := range alloc.Storage {
h.state.SetState(addr, key, value) func (h *Host) ImportAccount(addr common.Address, account types.Account) {
var balance *uint256.Int
if account.Balance == nil {
balance = uint256.NewInt(0)
} else {
balance = uint256.MustFromBig(account.Balance)
} }
h.state.SetBalance(addr, balance, tracing.BalanceChangeUnspecified)
h.state.SetNonce(addr, account.Nonce)
h.state.SetCode(addr, account.Code)
for key, value := range account.Storage {
h.state.SetState(addr, key, value)
} }
} }
......
...@@ -819,6 +819,12 @@ func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transa ...@@ -819,6 +819,12 @@ func (m *SimpleTxManager) increaseGasPrice(ctx context.Context, tx *types.Transa
"gasFeeCap", bumpedFee, "gasTipCap", bumpedTip) "gasFeeCap", bumpedFee, "gasTipCap", bumpedTip)
} }
if tx.Gas() > gas {
// Don't bump the gas limit down if the passed-in gas limit is higher than
// what was originally specified.
gas = tx.Gas()
}
var newTx *types.Transaction var newTx *types.Transaction
if tx.Type() == types.BlobTxType { if tx.Type() == types.BlobTxType {
// Blob transactions have an additional blob gas price we must specify, so we must make sure it is // Blob transactions have an additional blob gas price we must specify, so we must make sure it is
......
...@@ -8,6 +8,8 @@ import { LibString } from "@solady/utils/LibString.sol"; ...@@ -8,6 +8,8 @@ import { LibString } from "@solady/utils/LibString.sol";
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol"; import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol"; import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol"; import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol";
import { IL1CrossDomainMessengerV160 } from "src/L1/interfaces/IL1CrossDomainMessengerV160.sol";
import { IL1StandardBridgeV160 } from "src/L1/interfaces/IL1StandardBridgeV160.sol";
import { Constants } from "src/libraries/Constants.sol"; import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
...@@ -65,6 +67,8 @@ contract DeployImplementationsInput is BaseDeployIO { ...@@ -65,6 +67,8 @@ contract DeployImplementationsInput is BaseDeployIO {
string internal _standardVersionsToml; string internal _standardVersionsToml;
address internal _opcmProxyOwner;
function set(bytes4 _sel, uint256 _value) public { function set(bytes4 _sel, uint256 _value) public {
require(_value != 0, "DeployImplementationsInput: cannot set zero value"); require(_value != 0, "DeployImplementationsInput: cannot set zero value");
...@@ -95,6 +99,7 @@ contract DeployImplementationsInput is BaseDeployIO { ...@@ -95,6 +99,7 @@ contract DeployImplementationsInput is BaseDeployIO {
require(_addr != address(0), "DeployImplementationsInput: cannot set zero address"); require(_addr != address(0), "DeployImplementationsInput: cannot set zero address");
if (_sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_addr); if (_sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_addr);
else if (_sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = ProtocolVersions(_addr); else if (_sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = ProtocolVersions(_addr);
else if (_sel == this.opcmProxyOwner.selector) _opcmProxyOwner = _addr;
else revert("DeployImplementationsInput: unknown selector"); else revert("DeployImplementationsInput: unknown selector");
} }
...@@ -156,13 +161,9 @@ contract DeployImplementationsInput is BaseDeployIO { ...@@ -156,13 +161,9 @@ contract DeployImplementationsInput is BaseDeployIO {
return _protocolVersionsProxy; return _protocolVersionsProxy;
} }
function superchainProxyAdmin() public returns (ProxyAdmin) { function opcmProxyOwner() public view returns (address) {
SuperchainConfig proxy = this.superchainConfigProxy(); require(address(_opcmProxyOwner) != address(0), "DeployImplementationsInput: not set");
// Can infer the superchainProxyAdmin from the superchainConfigProxy. return _opcmProxyOwner;
vm.prank(address(0));
ProxyAdmin proxyAdmin = ProxyAdmin(Proxy(payable(address(proxy))).admin());
require(address(proxyAdmin) != address(0), "DeployImplementationsInput: not set");
return proxyAdmin;
} }
} }
...@@ -308,7 +309,7 @@ contract DeployImplementationsOutput is BaseDeployIO { ...@@ -308,7 +309,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
Proxy proxy = Proxy(payable(address(opcmProxy()))); Proxy proxy = Proxy(payable(address(opcmProxy())));
vm.prank(address(0)); vm.prank(address(0));
address admin = proxy.admin(); address admin = proxy.admin();
require(admin == address(_dii.superchainProxyAdmin()), "OPCMP-10"); require(admin == address(_dii.opcmProxyOwner()), "OPCMP-10");
// Then we check the proxy as OPCM. // Then we check the proxy as OPCM.
DeployUtils.assertInitialized({ _contractAddress: address(opcmProxy()), _slot: 0, _offset: 0 }); DeployUtils.assertInitialized({ _contractAddress: address(opcmProxy()), _slot: 0, _offset: 0 });
...@@ -504,6 +505,42 @@ contract DeployImplementations is Script { ...@@ -504,6 +505,42 @@ contract DeployImplementations is Script {
}); });
} }
function l1CrossDomainMessengerConfigSetter(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
internal
view
virtual
returns (OPContractsManager.ImplementationSetter memory)
{
bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0")
? IL1CrossDomainMessengerV160.initialize.selector
: L1CrossDomainMessenger.initialize.selector;
return OPContractsManager.ImplementationSetter({
name: "L1CrossDomainMessenger",
info: OPContractsManager.Implementation(address(_dio.l1CrossDomainMessengerImpl()), selector)
});
}
function l1StandardBridgeConfigSetter(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
internal
view
virtual
returns (OPContractsManager.ImplementationSetter memory)
{
bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0")
? IL1StandardBridgeV160.initialize.selector
: L1StandardBridge.initialize.selector;
return OPContractsManager.ImplementationSetter({
name: "L1StandardBridge",
info: OPContractsManager.Implementation(address(_dio.l1StandardBridgeImpl()), selector)
});
}
// Deploy and initialize a proxied OPContractsManager. // Deploy and initialize a proxied OPContractsManager.
function createOPCMContract( function createOPCMContract(
DeployImplementationsInput _dii, DeployImplementationsInput _dii,
...@@ -516,7 +553,7 @@ contract DeployImplementations is Script { ...@@ -516,7 +553,7 @@ contract DeployImplementations is Script {
virtual virtual
returns (OPContractsManager opcmProxy_) returns (OPContractsManager opcmProxy_)
{ {
ProxyAdmin proxyAdmin = _dii.superchainProxyAdmin(); address opcmProxyOwner = _dii.opcmProxyOwner();
vm.broadcast(msg.sender); vm.broadcast(msg.sender);
Proxy proxy = new Proxy(address(msg.sender)); Proxy proxy = new Proxy(address(msg.sender));
...@@ -532,7 +569,7 @@ contract DeployImplementations is Script { ...@@ -532,7 +569,7 @@ contract DeployImplementations is Script {
address(opcmImpl), abi.encodeWithSelector(opcmImpl.initialize.selector, initializerInputs) address(opcmImpl), abi.encodeWithSelector(opcmImpl.initialize.selector, initializerInputs)
); );
proxy.changeAdmin(address(proxyAdmin)); // transfer ownership of Proxy contract to the ProxyAdmin contract proxy.changeAdmin(address(opcmProxyOwner)); // transfer ownership of Proxy contract to the ProxyAdmin contract
vm.stopBroadcast(); vm.stopBroadcast();
opcmProxy_ = OPContractsManager(address(proxy)); opcmProxy_ = OPContractsManager(address(proxy));
...@@ -579,18 +616,8 @@ contract DeployImplementations is Script { ...@@ -579,18 +616,8 @@ contract DeployImplementations is Script {
address(_dio.optimismMintableERC20FactoryImpl()), OptimismMintableERC20Factory.initialize.selector address(_dio.optimismMintableERC20FactoryImpl()), OptimismMintableERC20Factory.initialize.selector
) )
}); });
setters[4] = OPContractsManager.ImplementationSetter({ setters[4] = l1CrossDomainMessengerConfigSetter(_dii, _dio);
name: "L1CrossDomainMessenger", setters[5] = l1StandardBridgeConfigSetter(_dii, _dio);
info: OPContractsManager.Implementation(
address(_dio.l1CrossDomainMessengerImpl()), L1CrossDomainMessenger.initialize.selector
)
});
setters[5] = OPContractsManager.ImplementationSetter({
name: "L1StandardBridge",
info: OPContractsManager.Implementation(
address(_dio.l1StandardBridgeImpl()), L1StandardBridge.initialize.selector
)
});
setters[6] = OPContractsManager.ImplementationSetter({ setters[6] = OPContractsManager.ImplementationSetter({
name: "DisputeGameFactory", name: "DisputeGameFactory",
info: OPContractsManager.Implementation( info: OPContractsManager.Implementation(
...@@ -1036,7 +1063,7 @@ contract DeployImplementationsInterop is DeployImplementations { ...@@ -1036,7 +1063,7 @@ contract DeployImplementationsInterop is DeployImplementations {
override override
returns (OPContractsManager opcmProxy_) returns (OPContractsManager opcmProxy_)
{ {
ProxyAdmin proxyAdmin = _dii.superchainProxyAdmin(); address opcmProxyOwner = _dii.opcmProxyOwner();
vm.broadcast(msg.sender); vm.broadcast(msg.sender);
Proxy proxy = new Proxy(address(msg.sender)); Proxy proxy = new Proxy(address(msg.sender));
...@@ -1052,7 +1079,7 @@ contract DeployImplementationsInterop is DeployImplementations { ...@@ -1052,7 +1079,7 @@ contract DeployImplementationsInterop is DeployImplementations {
address(opcmImpl), abi.encodeWithSelector(opcmImpl.initialize.selector, initializerInputs) address(opcmImpl), abi.encodeWithSelector(opcmImpl.initialize.selector, initializerInputs)
); );
proxy.changeAdmin(address(proxyAdmin)); // transfer ownership of Proxy contract to the ProxyAdmin contract proxy.changeAdmin(opcmProxyOwner); // transfer ownership of Proxy contract to the ProxyAdmin contract
vm.stopBroadcast(); vm.stopBroadcast();
opcmProxy_ = OPContractsManagerInterop(address(proxy)); opcmProxy_ = OPContractsManagerInterop(address(proxy));
......
...@@ -471,7 +471,7 @@ contract DeployOPChainOutput is BaseDeployIO { ...@@ -471,7 +471,7 @@ contract DeployOPChainOutput is BaseDeployIO {
require(vm.load(address(portal), bytes32(uint256(61))) == bytes32(0)); require(vm.load(address(portal), bytes32(uint256(61))) == bytes32(0));
} }
function assertValidDisputeGameFactory(DeployOPChainInput) internal view { function assertValidDisputeGameFactory(DeployOPChainInput _doi) internal view {
DisputeGameFactory factory = disputeGameFactoryProxy(); DisputeGameFactory factory = disputeGameFactoryProxy();
DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 }); DeployUtils.assertInitialized({ _contractAddress: address(factory), _slot: 0, _offset: 0 });
...@@ -479,7 +479,7 @@ contract DeployOPChainOutput is BaseDeployIO { ...@@ -479,7 +479,7 @@ contract DeployOPChainOutput is BaseDeployIO {
require( require(
address(factory.gameImpls(GameTypes.PERMISSIONED_CANNON)) == address(permissionedDisputeGame()), "DF-10" address(factory.gameImpls(GameTypes.PERMISSIONED_CANNON)) == address(permissionedDisputeGame()), "DF-10"
); );
require(factory.owner() == address(opChainProxyAdmin()), "DF-20"); require(factory.owner() == address(_doi.opChainProxyAdminOwner()), "DF-20");
} }
function assertValidDelayedWETHs(DeployOPChainInput) internal view { function assertValidDelayedWETHs(DeployOPChainInput) internal view {
......
...@@ -32,8 +32,8 @@ ...@@ -32,8 +32,8 @@
"sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649" "sourceCodeHash": "0xde4df0f9633dc0cdb1c9f634003ea5b0f7c5c1aebc407bc1b2f44c0ecf938649"
}, },
"src/L1/OPContractsManager.sol": { "src/L1/OPContractsManager.sol": {
"initCodeHash": "0x944deadee322fdbae8a8fffd16deceb3766509cfb54da06adb8aa84473f79f53", "initCodeHash": "0x7c5d90928ce882ed5360939722271e9af36e81c394e4110ba32864b14c3d78be",
"sourceCodeHash": "0x1a48119cbc0b778a4dd3454179060b71361ba44b61af1ac6398cc9274bb5e89f" "sourceCodeHash": "0x25372ad554eaeb64d7512e19642210bb3736e4047ea97518b2992b3ab67e1a5d"
}, },
"src/L1/OptimismPortal.sol": { "src/L1/OptimismPortal.sol": {
"initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190", "initCodeHash": "0xbe2c0c81b3459014f287d8c89cdc0d27dde5d1f44e5d024fa1e4773ddc47c190",
......
...@@ -128,8 +128,8 @@ contract OPContractsManager is ISemver, Initializable { ...@@ -128,8 +128,8 @@ contract OPContractsManager is ISemver, Initializable {
// -------- Constants and Variables -------- // -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.14 /// @custom:semver 1.0.0-beta.15
string public constant version = "1.0.0-beta.14"; string public constant version = "1.0.0-beta.15";
/// @notice Represents the interface version so consumers know how to decode the DeployOutput struct /// @notice Represents the interface version so consumers know how to decode the DeployOutput struct
/// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used. /// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used.
...@@ -342,7 +342,7 @@ contract OPContractsManager is ISemver, Initializable { ...@@ -342,7 +342,7 @@ contract OPContractsManager is ISemver, Initializable {
output.disputeGameFactoryProxy.setImplementation( output.disputeGameFactoryProxy.setImplementation(
GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(output.permissionedDisputeGame)) GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(output.permissionedDisputeGame))
); );
output.disputeGameFactoryProxy.transferOwnership(address(output.opChainProxyAdmin)); output.disputeGameFactoryProxy.transferOwnership(address(_input.roles.opChainProxyAdminOwner));
impl.logic = address(output.anchorStateRegistryImpl); impl.logic = address(output.anchorStateRegistryImpl);
impl.initializer = AnchorStateRegistry.initialize.selector; impl.initializer = AnchorStateRegistry.initialize.selector;
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
/// @notice This interface corresponds to the op-contracts/v1.6.0 release of the L1CrossDomainMessenger
/// contract, which has a semver of 2.3.0 as specified in
/// https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0
interface IL1CrossDomainMessengerV160 is ICrossDomainMessenger {
function PORTAL() external view returns (address);
function initialize(ISuperchainConfig _superchainConfig, IOptimismPortal _portal) external;
function portal() external view returns (address);
function superchainConfig() external view returns (address);
function systemConfig() external view returns (address);
function version() external view returns (string memory);
function __constructor__() external;
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IStandardBridge } from "src/universal/interfaces/IStandardBridge.sol";
import { ICrossDomainMessenger } from "src/universal/interfaces/ICrossDomainMessenger.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
/// @notice This interface corresponds to the op-contracts/v1.6.0 release of the L1StandardBridge
/// contract, which has a semver of 2.1.0 as specified in
/// https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0
interface IL1StandardBridgeV160 is IStandardBridge {
event ERC20DepositInitiated(
address indexed l1Token,
address indexed l2Token,
address indexed from,
address to,
uint256 amount,
bytes extraData
);
event ERC20WithdrawalFinalized(
address indexed l1Token,
address indexed l2Token,
address indexed from,
address to,
uint256 amount,
bytes extraData
);
event ETHDepositInitiated(address indexed from, address indexed to, uint256 amount, bytes extraData);
event ETHWithdrawalFinalized(address indexed from, address indexed to, uint256 amount, bytes extraData);
function depositERC20(
address _l1Token,
address _l2Token,
uint256 _amount,
uint32 _minGasLimit,
bytes memory _extraData
)
external;
function depositERC20To(
address _l1Token,
address _l2Token,
address _to,
uint256 _amount,
uint32 _minGasLimit,
bytes memory _extraData
)
external;
function depositETH(uint32 _minGasLimit, bytes memory _extraData) external payable;
function depositETHTo(address _to, uint32 _minGasLimit, bytes memory _extraData) external payable;
function finalizeERC20Withdrawal(
address _l1Token,
address _l2Token,
address _from,
address _to,
uint256 _amount,
bytes memory _extraData
)
external;
function finalizeETHWithdrawal(
address _from,
address _to,
uint256 _amount,
bytes memory _extraData
)
external
payable;
function initialize(ICrossDomainMessenger _messenger, ISuperchainConfig _superchainConfig) external;
function l2TokenBridge() external view returns (address);
function superchainConfig() external view returns (ISuperchainConfig);
function systemConfig() external view returns (ISystemConfig);
function version() external view returns (string memory);
function __constructor__() external;
}
...@@ -48,8 +48,8 @@ interface ISystemConfigV160 { ...@@ -48,8 +48,8 @@ interface ISystemConfigV160 {
function gasPayingTokenSymbol() external view returns (string memory symbol_); function gasPayingTokenSymbol() external view returns (string memory symbol_);
function initialize( function initialize(
address _owner, address _owner,
uint32 _basefeeScalar, uint256 _basefeeScalar,
uint32 _blobbasefeeScalar, uint256 _blobbasefeeScalar,
bytes32 _batcherHash, bytes32 _batcherHash,
uint64 _gasLimit, uint64 _gasLimit,
address _unsafeBlockSigner, address _unsafeBlockSigner,
......
...@@ -69,31 +69,21 @@ contract DeployImplementationsInput_Test is Test { ...@@ -69,31 +69,21 @@ contract DeployImplementationsInput_Test is Test {
dii.protocolVersionsProxy(); dii.protocolVersionsProxy();
vm.expectRevert("DeployImplementationsInput: not set"); vm.expectRevert("DeployImplementationsInput: not set");
dii.superchainProxyAdmin(); dii.opcmProxyOwner();
vm.expectRevert("DeployImplementationsInput: not set"); vm.expectRevert("DeployImplementationsInput: not set");
dii.standardVersionsToml(); dii.standardVersionsToml();
} }
function test_superchainProxyAdmin_whenNotSet_reverts() public { function test_opcmProxyOwner_whenNotSet_reverts() public {
vm.expectRevert("DeployImplementationsInput: not set"); vm.expectRevert("DeployImplementationsInput: not set");
dii.superchainProxyAdmin(); dii.opcmProxyOwner();
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
vm.expectRevert();
dii.superchainProxyAdmin();
Proxy noAdminProxy = new Proxy(address(0));
dii.set(dii.superchainConfigProxy.selector, address(noAdminProxy));
vm.expectRevert("DeployImplementationsInput: not set");
dii.superchainProxyAdmin();
} }
function test_superchainProxyAdmin_succeeds() public { function test_opcmProxyOwner_succeeds() public {
Proxy proxyWithAdminSet = new Proxy(msg.sender); dii.set(dii.opcmProxyOwner.selector, address(msg.sender));
dii.set(dii.superchainConfigProxy.selector, address(proxyWithAdminSet)); address opcmProxyOwner = dii.opcmProxyOwner();
ProxyAdmin proxyAdmin = dii.superchainProxyAdmin(); assertEq(address(msg.sender), address(opcmProxyOwner), "100");
assertEq(address(msg.sender), address(proxyAdmin), "100");
} }
} }
...@@ -433,6 +423,7 @@ contract DeployImplementations_Test is Test { ...@@ -433,6 +423,7 @@ contract DeployImplementations_Test is Test {
dii.set(dii.release.selector, release); dii.set(dii.release.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
dii.set(dii.opcmProxyOwner.selector, msg.sender);
deployImplementations.run(dii, dio); deployImplementations.run(dii, dio);
...@@ -445,7 +436,7 @@ contract DeployImplementations_Test is Test { ...@@ -445,7 +436,7 @@ contract DeployImplementations_Test is Test {
assertEq(release, dii.release(), "525"); assertEq(release, dii.release(), "525");
assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550"); assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550");
assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575"); assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575");
assertEq(address(superchainProxyAdmin), address(dii.superchainProxyAdmin()), "580"); assertEq(msg.sender, dii.opcmProxyOwner(), "580");
// Architecture assertions. // Architecture assertions.
assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600"); assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600");
......
...@@ -417,6 +417,7 @@ contract DeployOPChain_TestBase is Test { ...@@ -417,6 +417,7 @@ contract DeployOPChain_TestBase is Test {
string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml"); string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml");
string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath); string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath);
dii.set(dii.standardVersionsToml.selector, standardVersionsToml); dii.set(dii.standardVersionsToml.selector, standardVersionsToml);
dii.set(dii.opcmProxyOwner.selector, address(1));
deployImplementations.run(dii, dio); deployImplementations.run(dii, dio);
// Deploy DeployOpChain, but defer populating the input values to the test suites inheriting this contract. // Deploy DeployOpChain, but defer populating the input values to the test suites inheriting this contract.
......
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