Skip to content

Commit

Permalink
op-deployer: add 'inspect superchain-registry' subcommand (#12736)
Browse files Browse the repository at this point in the history
* op-deployer: add 'inspect superchain-registry' subcommand

* op-deployer: generate artifacts at runtime of superchain-registry cmd

* op-deployer: add missing err handler

* op-deployer: add Printf to prompt user to populate .env vals

* op-deployer: reformat addresses to superchain.AddressList
  • Loading branch information
bitwiseguy authored Oct 31, 2024
1 parent 72c11da commit caf63ce
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 24 deletions.
35 changes: 24 additions & 11 deletions op-deployer/pkg/deployer/inspect/deploy_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ 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"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
)

Expand All @@ -18,29 +20,40 @@ func DeployConfigCLI(cliCtx *cli.Context) error {

globalState, err := pipeline.ReadState(cliCfg.Workdir)
if err != nil {
return fmt.Errorf("failed to read intent: %w", err)
return fmt.Errorf("failed to read globalState: %w", err)
}
chainState, err := globalState.Chain(cliCfg.ChainID)

config, err := DeployConfig(globalState, cliCfg.ChainID)
if err != nil {
return fmt.Errorf("failed to find chain state: %w", err)
return fmt.Errorf("failed to generate deploy config: %w", err)
}

if err := jsonutil.WriteJSON(config, ioutil.ToStdOutOrFileOrNoop(cliCfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write deploy config: %w", err)
}

return nil
}

func DeployConfig(globalState *state.State, chainID common.Hash) (*genesis.DeployConfig, error) {
chainState, err := globalState.Chain(chainID)
if err != nil {
return nil, fmt.Errorf("failed to find chain state: %w", err)
}

intent := globalState.AppliedIntent
if intent == nil {
return fmt.Errorf("can only run this command following a full apply")
return nil, fmt.Errorf("can only run this command following a full apply")
}
chainIntent, err := intent.Chain(cliCfg.ChainID)
chainIntent, err := intent.Chain(chainID)
if err != nil {
return fmt.Errorf("failed to find chain intent: %w", err)
return nil, fmt.Errorf("failed to find chain intent: %w", err)
}

config, err := state.CombineDeployConfig(intent, chainIntent, globalState, chainState)
if err != nil {
return fmt.Errorf("failed to generate deploy config: %w", err)
}
if err := jsonutil.WriteJSON(config, ioutil.ToStdOutOrFileOrNoop(cliCfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write deploy config: %w", err)
return nil, fmt.Errorf("failed to generate deploy config: %w", err)
}

return nil
return &config, nil
}
8 changes: 8 additions & 0 deletions op-deployer/pkg/deployer/inspect/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ var Commands = []*cli.Command{
Action: L2SemversCLI,
Flags: Flags,
},
{
Name: "superchain-registry",
Usage: "outputs the .env file expected by superchain-registry add-chain tool",
Args: true,
ArgsUsage: "<l2-chain-id>",
Action: SuperchainRegistryCLI,
Flags: Flags,
},
}

type cliConfig struct {
Expand Down
36 changes: 23 additions & 13 deletions op-deployer/pkg/deployer/inspect/l1.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"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-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
Expand Down Expand Up @@ -37,9 +38,9 @@ type OpChainDeployment struct {
DisputeGameFactoryProxyAddress common.Address `json:"disputeGameFactoryProxyAddress"`
AnchorStateRegistryProxyAddress common.Address `json:"anchorStateRegistryProxyAddress"`
AnchorStateRegistryImplAddress common.Address `json:"anchorStateRegistryImplAddress"`
// FaultDisputeGameAddress common.Address `json:"faultDisputeGameAddress"`
PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"`
DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"`
FaultDisputeGameAddress common.Address `json:"faultDisputeGameAddress"`
PermissionedDisputeGameAddress common.Address `json:"permissionedDisputeGameAddress"`
DelayedWETHPermissionedGameProxyAddress common.Address `json:"delayedWETHPermissionedGameProxyAddress"`
// DelayedWETHPermissionlessGameProxyAddress common.Address `json:"delayedWETHPermissionlessGameProxyAddress"`
}

Expand Down Expand Up @@ -68,9 +69,22 @@ func L1CLI(cliCtx *cli.Context) error {
return fmt.Errorf("failed to read intent: %w", err)
}

chainState, err := globalState.Chain(cfg.ChainID)
l1Contracts, err := L1(globalState, cfg.ChainID)
if err != nil {
return fmt.Errorf("failed to get chain state for ID %s: %w", cfg.ChainID.String(), err)
return fmt.Errorf("failed to generate l1Contracts: %w", err)
}

if err := jsonutil.WriteJSON(l1Contracts, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write L1 contract addresses: %w", err)
}

return nil
}

func L1(globalState *state.State, chainID common.Hash) (*L1Contracts, error) {
chainState, err := globalState.Chain(chainID)
if err != nil {
return nil, fmt.Errorf("failed to get chain state for ID %s: %w", chainID.String(), err)
}

l1Contracts := L1Contracts{
Expand All @@ -93,9 +107,9 @@ func L1CLI(cliCtx *cli.Context) error {
DisputeGameFactoryProxyAddress: chainState.DisputeGameFactoryProxyAddress,
AnchorStateRegistryProxyAddress: chainState.AnchorStateRegistryProxyAddress,
AnchorStateRegistryImplAddress: chainState.AnchorStateRegistryImplAddress,
// FaultDisputeGameAddress: chainState.FaultDisputeGameAddress,
PermissionedDisputeGameAddress: chainState.PermissionedDisputeGameAddress,
DelayedWETHPermissionedGameProxyAddress: chainState.DelayedWETHPermissionedGameProxyAddress,
FaultDisputeGameAddress: chainState.FaultDisputeGameAddress,
PermissionedDisputeGameAddress: chainState.PermissionedDisputeGameAddress,
DelayedWETHPermissionedGameProxyAddress: chainState.DelayedWETHPermissionedGameProxyAddress,
// DelayedWETHPermissionlessGameProxyAddress: chainState.DelayedWETHPermissionlessGameProxyAddress,
},
ImplementationsDeployment: ImplementationsDeployment{
Expand All @@ -113,9 +127,5 @@ func L1CLI(cliCtx *cli.Context) error {
},
}

if err := jsonutil.WriteJSON(l1Contracts, ioutil.ToStdOutOrFileOrNoop(cfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write L1 contract addresses: %w", err)
}

return nil
return &l1Contracts, nil
}
173 changes: 173 additions & 0 deletions op-deployer/pkg/deployer/inspect/superchain_registry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
package inspect

import (
"fmt"
"os"
"path/filepath"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum-optimism/optimism/op-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
"github.com/ethereum/go-ethereum/common"

"github.com/ethereum-optimism/superchain-registry/superchain"

"github.com/urfave/cli/v2"
)

func SuperchainRegistryCLI(cliCtx *cli.Context) error {
cfg, err := readConfig(cliCtx)
if err != nil {
return err
}

globalIntent, err := pipeline.ReadIntent(cfg.Workdir)
if err != nil {
return fmt.Errorf("failed to read intent: %w", err)
}

envVars := map[string]string{}
envVars["SCR_CHAIN_NAME"] = ""
envVars["SCR_CHAIN_SHORT_NAME"] = ""
envVars["SCR_PUBLIC_RPC"] = ""
envVars["SCR_SEQUENCER_RPC"] = ""
envVars["SCR_EXPLORER"] = ""
envVars["SCR_STANDARD_CHAIN_CANDIDATE"] = "false"

creationCommit, err := standard.CommitForDeployTag(globalIntent.L2ContractsLocator.Tag)
if err != nil {
return fmt.Errorf("failed to get commit for deploy tag: %w", err)
}
envVars["SCR_GENESIS_CREATION_COMMIT"] = creationCommit

l1ChainName, err := standard.ChainNameFor(globalIntent.L1ChainID)
if err != nil {
return fmt.Errorf("failed to get l1 chain name: %w", err)
}
envVars["SCR_SUPERCHAIN_TARGET"] = l1ChainName

globalState, err := pipeline.ReadState(cfg.Workdir)
if err != nil {
return fmt.Errorf("failed to read state: %w", err)
}

genesis, rollup, err := GenesisAndRollup(globalState, cfg.ChainID)
if err != nil {
return fmt.Errorf("failed to generate genesis and rollup: %w", err)
}
genesisFilepath := filepath.Join(cfg.Workdir, "genesis.json")
if err := jsonutil.WriteJSON(genesis, ioutil.ToStdOutOrFileOrNoop(genesisFilepath, 0o666)); err != nil {
return fmt.Errorf("failed to write genesis: %w", err)
}
rollupFilepath := filepath.Join(cfg.Workdir, "rollup.json")
if err := jsonutil.WriteJSON(rollup, ioutil.ToStdOutOrFileOrNoop(rollupFilepath, 0o666)); err != nil {
return fmt.Errorf("failed to write rollup: %w", err)
}

deployConfig, err := DeployConfig(globalState, cfg.ChainID)
if err != nil {
return fmt.Errorf("failed to generate deploy config: %w", err)
}
deployConfigFilepath := filepath.Join(cfg.Workdir, "deploy-config.json")
if err := jsonutil.WriteJSON(deployConfig, ioutil.ToStdOutOrFileOrNoop(deployConfigFilepath, 0o666)); err != nil {
return fmt.Errorf("failed to write rollup: %w", err)
}

l1Contracts, err := L1(globalState, cfg.ChainID)
if err != nil {
return fmt.Errorf("failed to generate l1 contracts: %w", err)
}

addressList, err := createAddressList(l1Contracts, globalState.AppliedIntent, cfg.ChainID)
if err != nil {
return fmt.Errorf("failed to create address list: %w", err)
}

addressListFilepath := filepath.Join(cfg.Workdir, "addresses.json")
if err := jsonutil.WriteJSON(addressList, ioutil.ToStdOutOrFileOrNoop(addressListFilepath, 0o666)); err != nil {
return fmt.Errorf("failed to write address list: %w", err)
}

envVars["SCR_GENESIS"] = genesisFilepath
envVars["SCR_ROLLUP_CONFIG"] = rollupFilepath
envVars["SCR_DEPLOY_CONFIG"] = deployConfigFilepath
envVars["SCR_DEPLOYMENTS_DIR"] = addressListFilepath

envFilepath := filepath.Join(cfg.Workdir, "superchain-registry.env")
err = writeEnvFile(envFilepath, envVars)
if err != nil {
return fmt.Errorf("failed to write .env file: %w", err)
}

fmt.Printf("---------------------------------------------------\n"+
"Please populate any empty values in your .env file\n"+
"before creating your pull-request to add this chain\n"+
"to the superchain-registry repo.\n\n"+
" * %s\n"+
"---------------------------------------------------\n", envFilepath,
)

return nil
}

func writeEnvFile(filepath string, envVars map[string]string) error {
file, err := os.Create(filepath)
if err != nil {
return err
}
defer file.Close()

for key, value := range envVars {
_, err := file.WriteString(fmt.Sprintf("%s=\"%s\"\n", key, value))
if err != nil {
return err
}
}

return nil
}

func createAddressList(l1Contracts *L1Contracts, appliedIntent *state.Intent, chainId common.Hash) (*superchain.AddressList, error) {
chainIntent, err := appliedIntent.Chain(chainId)
if err != nil {
return nil, fmt.Errorf("failed to get applied chain intent: %w", err)
}

addressList := superchain.AddressList{
// Roles
Roles: superchain.Roles{
Guardian: superchain.Address(appliedIntent.SuperchainRoles.Guardian),
SystemConfigOwner: superchain.Address(chainIntent.Roles.SystemConfigOwner),
ProxyAdminOwner: superchain.Address(chainIntent.Roles.L1ProxyAdminOwner),
Challenger: superchain.Address(chainIntent.Roles.Challenger),
Proposer: superchain.Address(chainIntent.Roles.Proposer),
UnsafeBlockSigner: superchain.Address(chainIntent.Roles.UnsafeBlockSigner),
BatchSubmitter: superchain.Address(chainIntent.Roles.Batcher),
},

// Contracts
AddressManager: superchain.Address(l1Contracts.OpChainDeployment.AddressManagerAddress),
L1CrossDomainMessengerProxy: superchain.Address(l1Contracts.OpChainDeployment.L1CrossDomainMessengerProxyAddress),
L1ERC721BridgeProxy: superchain.Address(l1Contracts.OpChainDeployment.L1ERC721BridgeProxyAddress),
L1StandardBridgeProxy: superchain.Address(l1Contracts.OpChainDeployment.L1StandardBridgeProxyAddress),
OptimismMintableERC20FactoryProxy: superchain.Address(l1Contracts.OpChainDeployment.OptimismMintableERC20FactoryProxyAddress),
OptimismPortalProxy: superchain.Address(l1Contracts.OpChainDeployment.OptimismPortalProxyAddress),
SystemConfigProxy: superchain.Address(l1Contracts.OpChainDeployment.SystemConfigProxyAddress),

ProxyAdmin: superchain.Address(l1Contracts.OpChainDeployment.ProxyAdminAddress),
SuperchainConfig: superchain.Address(l1Contracts.SuperchainDeployment.SuperchainConfigProxyAddress),

// Fault proof contracts
AnchorStateRegistryProxy: superchain.Address(l1Contracts.OpChainDeployment.AnchorStateRegistryProxyAddress),
DelayedWETHProxy: superchain.Address(l1Contracts.OpChainDeployment.L1CrossDomainMessengerProxyAddress),
DisputeGameFactoryProxy: superchain.Address(l1Contracts.OpChainDeployment.DisputeGameFactoryProxyAddress),
FaultDisputeGame: superchain.Address(l1Contracts.OpChainDeployment.FaultDisputeGameAddress),
MIPS: superchain.Address(l1Contracts.ImplementationsDeployment.MipsSingletonAddress),
PermissionedDisputeGame: superchain.Address(l1Contracts.OpChainDeployment.PermissionedDisputeGameAddress),
PreimageOracle: superchain.Address(l1Contracts.ImplementationsDeployment.PreimageOracleSingletonAddress),
}

return &addressList, nil
}
22 changes: 22 additions & 0 deletions op-deployer/pkg/deployer/standard/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,28 @@ func SuperchainFor(chainID uint64) (*superchain.Superchain, error) {
}
}

func ChainNameFor(chainID uint64) (string, error) {
switch chainID {
case 1:
return "mainnet", nil
case 11155111:
return "sepolia", nil
default:
return "", fmt.Errorf("unrecognized chain ID: %d", chainID)
}
}

func CommitForDeployTag(tag string) (string, error) {
switch tag {
case "op-contracts/v1.6.0":
return "33f06d2d5e4034125df02264a5ffe84571bd0359", nil
case "op-contracts/v1.7.0-beta.1+l2-contracts":
return "5e14a61547a45eef2ebeba677aee4a049f106ed8", nil
default:
return "", fmt.Errorf("unsupported tag: %s", tag)
}
}

func ManagerImplementationAddrFor(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
Expand Down

0 comments on commit caf63ce

Please sign in to comment.