Commit 4e8d5274 authored by Mark Tyneway's avatar Mark Tyneway

op-upgrade: extended pause

Create a one off script that can be used to generate the upgrade JSON
files. This still needs to have the addresses for each network
added in the `addresses` mapping at the top of the script. It uses
a subset of the `op-upgrade` code.
parent 658d4df5
# op-upgrade-extended-pause
One off CLI tooling for the extended pause upgrade
package main
import (
"encoding/json"
"errors"
"fmt"
"os"
"github.com/ethereum/go-ethereum/log"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
"github.com/ethereum-optimism/optimism/op-chain-ops/clients"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/safe"
"github.com/ethereum-optimism/optimism/op-chain-ops/upgrades"
"github.com/ethereum-optimism/superchain-registry/superchain"
)
// addresses contains the L1 addresses of the contracts that are being upgraded to.
// Note that the key is the L2 chain id. This is because the L1 contracts must be specific
// for a particular OP Stack chain and cannot currently be used by multiple chains.
var addresses = map[uint64]superchain.ImplementationList{
10: {
L1CrossDomainMessenger: superchain.VersionedContract{
Version: "",
Address: superchain.Address{},
},
L1ERC721Bridge: superchain.VersionedContract{
Version: "",
Address: superchain.Address{},
},
L1StandardBridge: superchain.VersionedContract{
Version: "",
Address: superchain.Address{},
},
OptimismPortal: superchain.VersionedContract{
Version: "",
Address: superchain.Address{},
},
SystemConfig: superchain.VersionedContract{
Version: "",
Address: superchain.Address{},
},
},
}
func main() {
log.Root().SetHandler(log.StreamHandler(os.Stderr, log.TerminalFormat(isatty.IsTerminal(os.Stderr.Fd()))))
app := &cli.App{
Name: "op-upgrade",
Usage: "Build transactions useful for upgrading the Superchain",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "l1-rpc-url",
Value: "http://127.0.0.1:8545",
Usage: "L1 RPC URL, the chain ID will be used to determine the superchain",
EnvVars: []string{"L1_RPC_URL"},
},
&cli.StringFlag{
Name: "l2-rpc-url",
Value: "http://127.0.0.1:9545",
Usage: "L2 RPC URL",
EnvVars: []string{"L2_RPC_URL"},
},
&cli.PathFlag{
Name: "deploy-config",
Usage: "The path to the deploy config file",
Required: true,
EnvVars: []string{"DEPLOY_CONFIG"},
},
&cli.PathFlag{
Name: "outfile",
Usage: "The file to write the output to. If not specified, output is written to stdout",
EnvVars: []string{"OUTFILE"},
},
},
Action: entrypoint,
}
if err := app.Run(os.Args); err != nil {
log.Crit("error op-upgrade", "err", err)
}
}
// entrypoint contains the main logic of the script
func entrypoint(ctx *cli.Context) error {
config, err := genesis.NewDeployConfig(ctx.Path("deploy-config"))
if err != nil {
return err
}
if err := config.Check(); err != nil {
return fmt.Errorf("error checking deploy config: %w", err)
}
clients, err := clients.NewClients(ctx.String("l1-rpc-url"), ctx.String("l2-rpc-url"))
if err != nil {
return fmt.Errorf("cannot create RPC clients: %w", err)
}
if clients.L1Client == nil {
return errors.New("Cannot create L1 client")
}
if clients.L2Client == nil {
return errors.New("Cannot create L1 client")
}
l1ChainID, err := clients.L1Client.ChainID(ctx.Context)
if err != nil {
return fmt.Errorf("cannot fetch L1 chain ID: %w", err)
}
l2ChainID, err := clients.L2Client.ChainID(ctx.Context)
if err != nil {
return fmt.Errorf("cannot fetch L2 chain ID: %w", err)
}
log.Info("connected to chains", "l1-chain-id", l1ChainID, "l2-chain-id", l2ChainID)
// Create a batch of transactions
batch := safe.Batch{}
list, ok := addresses[l2ChainID.Uint64()]
if !ok {
return fmt.Errorf("no implementations for chain ID %d", l2ChainID)
}
addresses, ok := superchain.Addresses[l2ChainID.Uint64()]
if !ok {
return fmt.Errorf("no proxy addresses for chain ID %d", l2ChainID)
}
chainConfig, ok := superchain.OPChains[l2ChainID.Uint64()]
if !ok {
return fmt.Errorf("no chain config for chain ID %d", l2ChainID)
}
log.Info("Upgrading to the following versions")
log.Info("L1CrossDomainMessenger", "version", list.L1CrossDomainMessenger.Version, "address", list.L1CrossDomainMessenger.Address)
log.Info("L1ERC721Bridge", "version", list.L1ERC721Bridge.Version, "address", list.L1ERC721Bridge.Address)
log.Info("L1StandardBridge", "version", list.L1StandardBridge.Version, "address", list.L1StandardBridge.Address)
log.Info("L2OutputOracle", "version", list.L2OutputOracle.Version, "address", list.L2OutputOracle.Address)
log.Info("OptimismMintableERC20Factory", "version", list.OptimismMintableERC20Factory.Version, "address", list.OptimismMintableERC20Factory.Address)
log.Info("OptimismPortal", "version", list.OptimismPortal.Version, "address", list.OptimismPortal.Address)
log.Info("SystemConfig", "version", list.SystemConfig.Version, "address", list.SystemConfig.Address)
// Check just the versions that we care about
if err := upgrades.CheckVersionedContract(ctx.Context, list.L1CrossDomainMessenger, clients.L1Client); err != nil {
return fmt.Errorf("L1CrossDomainMessenger: %w", err)
}
if err := upgrades.CheckVersionedContract(ctx.Context, list.L1ERC721Bridge, clients.L1Client); err != nil {
return fmt.Errorf("L1ERC721Bridge: %w", err)
}
if err := upgrades.CheckVersionedContract(ctx.Context, list.L1StandardBridge, clients.L1Client); err != nil {
return fmt.Errorf("L1StandardBridge: %w", err)
}
if err := upgrades.CheckVersionedContract(ctx.Context, list.OptimismPortal, clients.L1Client); err != nil {
return fmt.Errorf("OptimismPortal: %w", err)
}
if err := upgrades.CheckVersionedContract(ctx.Context, list.SystemConfig, clients.L1Client); err != nil {
return fmt.Errorf("SystemConfig: %w", err)
}
// Build the batch
if err := upgrades.L1CrossDomainMessenger(&batch, list, *addresses, config, chainConfig, clients.L1Client); err != nil {
return fmt.Errorf("upgrading L1CrossDomainMessenger: %w", err)
}
if err := upgrades.L1ERC721Bridge(&batch, list, *addresses, config, chainConfig, clients.L1Client); err != nil {
return fmt.Errorf("upgrading L1ERC721Bridge: %w", err)
}
if err := upgrades.L1StandardBridge(&batch, list, *addresses, config, chainConfig, clients.L1Client); err != nil {
return fmt.Errorf("upgrading L1StandardBridge: %w", err)
}
if err := upgrades.OptimismPortal(&batch, list, *addresses, config, chainConfig, clients.L1Client); err != nil {
return fmt.Errorf("upgrading OptimismPortal: %w", err)
}
if err := upgrades.SystemConfig(&batch, list, *addresses, config, chainConfig, clients.L1Client); err != nil {
return fmt.Errorf("upgrading SystemConfig: %w", err)
}
// Write the batch to disk or stdout
if outfile := ctx.Path("outfile"); outfile != "" {
if err := writeJSON(outfile, batch); err != nil {
return err
}
} else {
data, err := json.MarshalIndent(batch, "", " ")
if err != nil {
return err
}
fmt.Println(string(data))
}
return nil
}
func writeJSON(outfile string, input interface{}) error {
f, err := os.OpenFile(outfile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o666)
if err != nil {
return err
}
defer f.Close()
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
return enc.Encode(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