Commit 2c5f6ed3 authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat(ct): DeployDelayedWETH script (#12662)

* feat(ct): DeployDelayedWETH script

Adds a new deployment script for deploying a new DelayedWETH
proxy contract.

* fix tests

* lint

* delete letter o

* move testdata

---------
Co-authored-by: default avatarMatthew Slipper <me@matthewslipper.com>
parent 1f335f15
......@@ -7,6 +7,10 @@ import (
"math/big"
"strings"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum/go-ethereum/common"
......@@ -146,7 +150,7 @@ func Apply(ctx context.Context, cfg ApplyConfig) error {
cfg.Logger.Info("artifacts download progress", "current", curr, "total", total)
}
l1ArtifactsFS, cleanupL1, err := pipeline.DownloadArtifacts(ctx, intent.L1ContractsLocator, progressor)
l1ArtifactsFS, cleanupL1, err := artifacts.Download(ctx, intent.L1ContractsLocator, progressor)
if err != nil {
return fmt.Errorf("failed to download L1 artifacts: %w", err)
}
......@@ -156,7 +160,7 @@ func Apply(ctx context.Context, cfg ApplyConfig) error {
}
}()
l2ArtifactsFS, cleanupL2, err := pipeline.DownloadArtifacts(ctx, intent.L2ContractsLocator, progressor)
l2ArtifactsFS, cleanupL2, err := artifacts.Download(ctx, intent.L2ContractsLocator, progressor)
if err != nil {
return fmt.Errorf("failed to download L2 artifacts: %w", err)
}
......@@ -171,7 +175,7 @@ func Apply(ctx context.Context, cfg ApplyConfig) error {
L2: l2ArtifactsFS,
}
l1Host, err := pipeline.DefaultScriptHost(bcaster, cfg.Logger, deployer, bundle.L1, startingNonce)
l1Host, err := env.DefaultScriptHost(bcaster, cfg.Logger, deployer, bundle.L1, startingNonce)
if err != nil {
return fmt.Errorf("failed to create L1 script host: %w", err)
}
......
package pipeline
package artifacts
import (
"archive/tar"
......@@ -19,8 +19,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
)
......@@ -40,7 +38,7 @@ func LogProgressor(lgr log.Logger) DownloadProgressor {
}
}
func DownloadArtifacts(ctx context.Context, loc *opcm.ArtifactsLocator, progress DownloadProgressor) (foundry.StatDirFs, CleanupFunc, error) {
func Download(ctx context.Context, loc *Locator, progress DownloadProgressor) (foundry.StatDirFs, CleanupFunc, error) {
var u *url.URL
var err error
if loc.IsTag() {
......
package pipeline
package artifacts
import (
"context"
......@@ -9,8 +9,6 @@ import (
"os"
"testing"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/stretchr/testify/require"
)
......@@ -29,11 +27,11 @@ func TestDownloadArtifacts(t *testing.T) {
ctx := context.Background()
artifactsURL, err := url.Parse(ts.URL)
require.NoError(t, err)
loc := &opcm.ArtifactsLocator{
loc := &Locator{
URL: artifactsURL,
}
fs, cleanup, err := DownloadArtifacts(ctx, loc, nil)
fs, cleanup, err := Download(ctx, loc, nil)
require.NoError(t, err)
require.NotNil(t, fs)
defer func() {
......
package opcm
package artifacts
import (
"fmt"
......@@ -8,7 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
)
type schemeUnmarshaler func(string) (*ArtifactsLocator, error)
type schemeUnmarshaler func(string) (*Locator, error)
var schemeUnmarshalerDispatch = map[string]schemeUnmarshaler{
"tag": unmarshalTag,
......@@ -16,20 +16,20 @@ var schemeUnmarshalerDispatch = map[string]schemeUnmarshaler{
"https": unmarshalURL,
}
var DefaultL1ContractsLocator = &ArtifactsLocator{
var DefaultL1ContractsLocator = &Locator{
Tag: standard.DefaultL1ContractsTag,
}
var DefaultL2ContractsLocator = &ArtifactsLocator{
var DefaultL2ContractsLocator = &Locator{
Tag: standard.DefaultL2ContractsTag,
}
type ArtifactsLocator struct {
type Locator struct {
URL *url.URL
Tag string
}
func (a *ArtifactsLocator) UnmarshalText(text []byte) error {
func (a *Locator) UnmarshalText(text []byte) error {
str := string(text)
for scheme, unmarshaler := range schemeUnmarshalerDispatch {
......@@ -49,7 +49,7 @@ func (a *ArtifactsLocator) UnmarshalText(text []byte) error {
return fmt.Errorf("unsupported scheme")
}
func (a *ArtifactsLocator) MarshalText() ([]byte, error) {
func (a *Locator) MarshalText() ([]byte, error) {
if a.URL != nil {
return []byte(a.URL.String()), nil
}
......@@ -61,11 +61,11 @@ func (a *ArtifactsLocator) MarshalText() ([]byte, error) {
return nil, fmt.Errorf("no URL, path or tag set")
}
func (a *ArtifactsLocator) IsTag() bool {
func (a *Locator) IsTag() bool {
return a.Tag != ""
}
func unmarshalTag(tag string) (*ArtifactsLocator, error) {
func unmarshalTag(tag string) (*Locator, error) {
tag = strings.TrimPrefix(tag, "tag://")
if !strings.HasPrefix(tag, "op-contracts/") {
return nil, fmt.Errorf("invalid tag: %s", tag)
......@@ -75,14 +75,14 @@ func unmarshalTag(tag string) (*ArtifactsLocator, error) {
return nil, err
}
return &ArtifactsLocator{Tag: tag}, nil
return &Locator{Tag: tag}, nil
}
func unmarshalURL(text string) (*ArtifactsLocator, error) {
func unmarshalURL(text string) (*Locator, error) {
u, err := url.Parse(text)
if err != nil {
return nil, err
}
return &ArtifactsLocator{URL: u}, nil
return &Locator{URL: u}, nil
}
package opcm
package artifacts
import (
"net/url"
......@@ -7,17 +7,17 @@ import (
"github.com/stretchr/testify/require"
)
func TestArtifactsLocator_Marshaling(t *testing.T) {
func TestLocator_Marshaling(t *testing.T) {
tests := []struct {
name string
in string
out *ArtifactsLocator
out *Locator
err bool
}{
{
name: "valid tag",
in: "tag://op-contracts/v1.6.0",
out: &ArtifactsLocator{
out: &Locator{
Tag: "op-contracts/v1.6.0",
},
err: false,
......@@ -37,7 +37,7 @@ func TestArtifactsLocator_Marshaling(t *testing.T) {
{
name: "valid HTTPS URL",
in: "https://example.com",
out: &ArtifactsLocator{
out: &Locator{
URL: parseUrl(t, "https://example.com"),
},
err: false,
......@@ -45,7 +45,7 @@ func TestArtifactsLocator_Marshaling(t *testing.T) {
{
name: "valid file URL",
in: "file:///tmp/artifacts",
out: &ArtifactsLocator{
out: &Locator{
URL: parseUrl(t, "file:///tmp/artifacts"),
},
err: false,
......@@ -71,7 +71,7 @@ func TestArtifactsLocator_Marshaling(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
var a ArtifactsLocator
var a Locator
err := a.UnmarshalText([]byte(tt.in))
if tt.err {
require.Error(t, err)
......
package bootstrap
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"strings"
artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
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/crypto"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
)
type DelayedWETHConfig struct {
L1RPCUrl string
PrivateKey string
Logger log.Logger
ArtifactsLocator *artifacts2.Locator
privateKeyECDSA *ecdsa.PrivateKey
}
func (c *DelayedWETHConfig) 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.ArtifactsLocator == nil {
return fmt.Errorf("artifacts locator must be specified")
}
return nil
}
func DelayedWETHCLI(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(ArtifactsLocatorFlagName)
artifactsLocator := new(artifacts2.Locator)
if err := artifactsLocator.UnmarshalText([]byte(artifactsURLStr)); err != nil {
return fmt.Errorf("failed to parse artifacts URL: %w", err)
}
ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context)
return DelayedWETH(ctx, DelayedWETHConfig{
L1RPCUrl: l1RPCUrl,
PrivateKey: privateKey,
Logger: l,
ArtifactsLocator: artifactsLocator,
})
}
func DelayedWETH(ctx context.Context, cfg DelayedWETHConfig) error {
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid config for DelayedWETH: %w", err)
}
lgr := cfg.Logger
progressor := func(curr, total int64) {
lgr.Info("artifacts download progress", "current", curr, "total", total)
}
artifactsFS, cleanup, err := artifacts2.Download(ctx, cfg.ArtifactsLocator, 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 := standard.SuperchainFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting superchain config: %w", err)
}
standardVersionsTOML, err := standard.L1VersionsDataFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err)
}
proxyAdmin, err := standard.ManagerOwnerAddrFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting superchain proxy admin: %w", err)
}
delayedWethOwner, err := standard.SystemOwnerAddrFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting superchain system owner: %w", err)
}
signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID))
chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey)
bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: lgr,
ChainID: chainID,
Client: l1Client,
Signer: signer,
From: chainDeployer,
})
if err != nil {
return fmt.Errorf("failed to create broadcaster: %w", err)
}
nonce, err := l1Client.NonceAt(ctx, chainDeployer, nil)
if err != nil {
return fmt.Errorf("failed to get starting nonce: %w", err)
}
host, err := env.DefaultScriptHost(
bcaster,
lgr,
chainDeployer,
artifactsFS,
nonce,
)
if err != nil {
return fmt.Errorf("failed to create script host: %w", err)
}
var release string
if cfg.ArtifactsLocator.IsTag() {
release = cfg.ArtifactsLocator.Tag
} else {
release = "dev"
}
lgr.Info("deploying DelayedWETH", "release", release)
superchainConfigAddr := common.Address(*superCfg.Config.SuperchainConfigAddr)
dwo, err := opcm.DeployDelayedWETH(
host,
opcm.DeployDelayedWETHInput{
Release: release,
StandardVersionsToml: standardVersionsTOML,
ProxyAdmin: proxyAdmin,
SuperchainConfigProxy: superchainConfigAddr,
DelayedWethOwner: delayedWethOwner,
DelayedWethDelay: big.NewInt(604800),
},
)
if err != nil {
return fmt.Errorf("error deploying implementations: %w", err)
}
if _, err := bcaster.Broadcast(ctx); err != nil {
return fmt.Errorf("failed to broadcast: %w", err)
}
lgr.Info("deployed DelayedWETH")
if err := jsonutil.WriteJSON(dwo, ioutil.ToStdOut()); err != nil {
return fmt.Errorf("failed to write output: %w", err)
}
return nil
}
......@@ -73,6 +73,12 @@ var OPCMFlags = []cli.Flag{
MIPSVersionFlag,
}
var DelayedWETHFlags = []cli.Flag{
deployer.L1RPCURLFlag,
deployer.PrivateKeyFlag,
ArtifactsLocatorFlag,
}
var Commands = []*cli.Command{
{
Name: "opcm",
......@@ -80,4 +86,10 @@ var Commands = []*cli.Command{
Flags: cliapp.ProtectFlags(OPCMFlags),
Action: OPCMCLI,
},
{
Name: "delayedweth",
Usage: "Bootstrap an instance of DelayedWETH.",
Flags: cliapp.ProtectFlags(DelayedWETHFlags),
Action: DelayedWETHCLI,
},
}
......@@ -8,6 +8,10 @@ import (
"math/big"
"strings"
artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
......@@ -35,7 +39,7 @@ type OPCMConfig struct {
L1RPCUrl string
PrivateKey string
Logger log.Logger
ArtifactsLocator *opcm.ArtifactsLocator
ArtifactsLocator *artifacts2.Locator
privateKeyECDSA *ecdsa.PrivateKey
}
......@@ -98,7 +102,7 @@ func OPCMCLI(cliCtx *cli.Context) error {
l1RPCUrl := cliCtx.String(deployer.L1RPCURLFlagName)
privateKey := cliCtx.String(deployer.PrivateKeyFlagName)
artifactsURLStr := cliCtx.String(ArtifactsLocatorFlagName)
artifactsLocator := new(opcm.ArtifactsLocator)
artifactsLocator := new(artifacts2.Locator)
if err := artifactsLocator.UnmarshalText([]byte(artifactsURLStr)); err != nil {
return fmt.Errorf("failed to parse artifacts URL: %w", err)
}
......@@ -131,7 +135,7 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
lgr.Info("artifacts download progress", "current", curr, "total", total)
}
artifactsFS, cleanup, err := pipeline.DownloadArtifacts(ctx, cfg.ArtifactsLocator, progressor)
artifactsFS, cleanup, err := artifacts2.Download(ctx, cfg.ArtifactsLocator, progressor)
if err != nil {
return fmt.Errorf("failed to download artifacts: %w", err)
}
......@@ -184,7 +188,7 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
return fmt.Errorf("failed to get starting nonce: %w", err)
}
host, err := pipeline.DefaultScriptHost(
host, err := env.DefaultScriptHost(
bcaster,
lgr,
chainDeployer,
......
......@@ -7,7 +7,7 @@ import (
"path"
"strings"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
......@@ -90,8 +90,8 @@ func Init(cfg InitConfig) error {
DeploymentStrategy: cfg.DeploymentStrategy,
L1ChainID: cfg.L1ChainID,
FundDevAccounts: true,
L1ContractsLocator: opcm.DefaultL1ContractsLocator,
L2ContractsLocator: opcm.DefaultL2ContractsLocator,
L1ContractsLocator: artifacts.DefaultL1ContractsLocator,
L2ContractsLocator: artifacts.DefaultL2ContractsLocator,
}
l1ChainIDBig := intent.L1ChainIDBig()
......
......@@ -8,6 +8,10 @@ import (
"regexp"
"time"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
......@@ -53,7 +57,7 @@ func L2SemversCLI(cliCtx *cli.Context) error {
return fmt.Errorf("chain state does not have allocs")
}
artifactsFS, cleanup, err := pipeline.DownloadArtifacts(ctx, intent.L2ContractsLocator, pipeline.LogProgressor(l))
artifactsFS, cleanup, err := artifacts.Download(ctx, intent.L2ContractsLocator, artifacts.LogProgressor(l))
if err != nil {
return fmt.Errorf("failed to download L2 artifacts: %w", err)
}
......@@ -63,7 +67,7 @@ func L2SemversCLI(cliCtx *cli.Context) error {
}
}()
host, err := pipeline.DefaultScriptHost(
host, err := env.DefaultScriptHost(
broadcaster.NoopBroadcaster(),
l,
common.Address{19: 0x01},
......
......@@ -7,14 +7,16 @@ import (
"fmt"
"log/slog"
"math/big"
"net/url"
"os"
"path"
"runtime"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/testutil"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/testutils/anvil"
......@@ -22,7 +24,6 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/pipeline"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
......@@ -109,7 +110,7 @@ func TestEndToEndApply(t *testing.T) {
deployerAddr, err := dk.Address(depKey)
require.NoError(t, err)
loc := localArtifactsLocator(t)
loc, _ := testutil.LocalArtifacts(t)
bcaster, err := broadcaster.NewKeyedBroadcaster(broadcaster.KeyedBroadcasterOpts{
Logger: log.NewLogger(log.DiscardHandler()),
......@@ -120,7 +121,7 @@ func TestEndToEndApply(t *testing.T) {
})
require.NoError(t, err)
env, bundle, _ := createEnv(t, ctx, lgr, l1Client, bcaster, deployerAddr)
env, bundle, _ := createEnv(t, lgr, l1Client, bcaster, deployerAddr)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
cg := ethClientCodeGetter(ctx, l1Client)
......@@ -140,7 +141,7 @@ func TestEndToEndApply(t *testing.T) {
t.Run("subsequent chain", func(t *testing.T) {
// create a new environment with wiped state to ensure we can continue using the
// state from the previous deployment
env, bundle, _ = createEnv(t, ctx, lgr, l1Client, bcaster, deployerAddr)
env, bundle, _ = createEnv(t, lgr, l1Client, bcaster, deployerAddr)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID2))
require.NoError(t, deployer.ApplyPipeline(
......@@ -202,15 +203,15 @@ func TestApplyExistingOPCM(t *testing.T) {
})
require.NoError(t, err)
env, bundle, _ := createEnv(t, ctx, lgr, l1Client, bcaster, deployerAddr)
env, bundle, _ := createEnv(t, lgr, l1Client, bcaster, deployerAddr)
intent, st := newIntent(
t,
l1ChainID,
dk,
l2ChainID,
opcm.DefaultL1ContractsLocator,
opcm.DefaultL2ContractsLocator,
artifacts.DefaultL1ContractsLocator,
artifacts.DefaultL2ContractsLocator,
)
require.NoError(t, deployer.ApplyPipeline(
......@@ -421,7 +422,7 @@ func TestInvalidL2Genesis(t *testing.T) {
deployerAddr, err := dk.Address(depKey)
require.NoError(t, err)
loc := localArtifactsLocator(t)
loc, _ := testutil.LocalArtifacts(t)
// these tests were generated by grepping all usages of the deploy
// config in L2Genesis.s.sol.
......@@ -468,7 +469,7 @@ func TestInvalidL2Genesis(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
env, bundle, _ := createEnv(t, ctx, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
env, bundle, _ := createEnv(t, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
......@@ -490,9 +491,6 @@ func TestInvalidL2Genesis(t *testing.T) {
func setupGenesisChain(t *testing.T) (*pipeline.Env, pipeline.ArtifactsBundle, *state.Intent, *state.State) {
lgr := testlog.Logger(t, slog.LevelDebug)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
depKey := new(deployerKey)
l1ChainID := big.NewInt(77799777)
dk, err := devkeys.NewMnemonicDevKeys(devkeys.TestMnemonic)
......@@ -503,53 +501,25 @@ func setupGenesisChain(t *testing.T) (*pipeline.Env, pipeline.ArtifactsBundle, *
deployerAddr, err := dk.Address(depKey)
require.NoError(t, err)
loc := localArtifactsLocator(t)
loc, _ := testutil.LocalArtifacts(t)
env, bundle, _ := createEnv(t, ctx, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
env, bundle, _ := createEnv(t, lgr, nil, broadcaster.NoopBroadcaster(), deployerAddr)
intent, st := newIntent(t, l1ChainID, dk, l2ChainID1, loc, loc)
intent.Chains = append(intent.Chains, newChainIntent(t, dk, l1ChainID, l2ChainID1))
intent.DeploymentStrategy = state.DeploymentStrategyGenesis
return env, bundle, intent, st
}
func localArtifactsLocator(t *testing.T) *opcm.ArtifactsLocator {
_, testFilename, _, ok := runtime.Caller(0)
require.Truef(t, ok, "failed to get test filename")
monorepoDir := path.Join(path.Dir(testFilename), "..", "..", "..", "..")
artifactsDir := path.Join(monorepoDir, "packages", "contracts-bedrock", "forge-artifacts")
artifactsURL, err := url.Parse(fmt.Sprintf("file://%s", artifactsDir))
require.NoError(t, err)
loc := &opcm.ArtifactsLocator{
URL: artifactsURL,
}
return loc
}
func createEnv(
t *testing.T,
ctx context.Context,
lgr log.Logger,
l1Client *ethclient.Client,
bcaster broadcaster.Broadcaster,
deployerAddr common.Address,
) (*pipeline.Env, pipeline.ArtifactsBundle, *script.Host) {
_, testFilename, _, ok := runtime.Caller(0)
require.Truef(t, ok, "failed to get test filename")
monorepoDir := path.Join(path.Dir(testFilename), "..", "..", "..", "..")
artifactsDir := path.Join(monorepoDir, "packages", "contracts-bedrock", "forge-artifacts")
artifactsURL, err := url.Parse(fmt.Sprintf("file://%s", artifactsDir))
require.NoError(t, err)
artifactsLocator := &opcm.ArtifactsLocator{
URL: artifactsURL,
}
artifactsFS, cleanupArtifacts, err := pipeline.DownloadArtifacts(ctx, artifactsLocator, pipeline.NoopDownloadProgressor)
require.NoError(t, err)
defer func() {
require.NoError(t, cleanupArtifacts())
}()
_, artifactsFS := testutil.LocalArtifacts(t)
host, err := pipeline.DefaultScriptHost(
host, err := env.DefaultScriptHost(
bcaster,
lgr,
deployerAddr,
......@@ -586,8 +556,8 @@ func newIntent(
l1ChainID *big.Int,
dk *devkeys.MnemonicDevKeys,
l2ChainID *uint256.Int,
l1Loc *opcm.ArtifactsLocator,
l2Loc *opcm.ArtifactsLocator,
l1Loc *artifacts.Locator,
l2Loc *artifacts.Locator,
) (*state.Intent, *state.State) {
intent := &state.Intent{
DeploymentStrategy: state.DeploymentStrategyLive,
......
package opcm
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
)
type DeployDelayedWETHInput struct {
Release string
StandardVersionsToml string
ProxyAdmin common.Address
SuperchainConfigProxy common.Address
DelayedWethOwner common.Address
DelayedWethDelay *big.Int
}
func (input *DeployDelayedWETHInput) InputSet() bool {
return true
}
type DeployDelayedWETHOutput struct {
DelayedWethImpl common.Address
DelayedWethProxy common.Address
}
func (output *DeployDelayedWETHOutput) CheckOutput(input common.Address) error {
return nil
}
type DeployDelayedWETHScript struct {
Run func(input, output common.Address) error
}
func DeployDelayedWETH(
host *script.Host,
input DeployDelayedWETHInput,
) (DeployDelayedWETHOutput, error) {
var output DeployDelayedWETHOutput
inputAddr := host.NewScriptAddress()
outputAddr := host.NewScriptAddress()
cleanupInput, err := script.WithPrecompileAtAddress[*DeployDelayedWETHInput](host, inputAddr, &input)
if err != nil {
return output, fmt.Errorf("failed to insert DeployDelayedWETHInput precompile: %w", err)
}
defer cleanupInput()
cleanupOutput, err := script.WithPrecompileAtAddress[*DeployDelayedWETHOutput](host, outputAddr, &output,
script.WithFieldSetter[*DeployDelayedWETHOutput])
if err != nil {
return output, fmt.Errorf("failed to insert DeployDelayedWETHOutput precompile: %w", err)
}
defer cleanupOutput()
implContract := "DeployDelayedWETH"
deployScript, cleanupDeploy, err := script.WithScript[DeployDelayedWETHScript](host, "DeployDelayedWETH.s.sol", implContract)
if err != nil {
return output, fmt.Errorf("failed to load %s script: %w", implContract, err)
}
defer cleanupDeploy()
if err := deployScript.Run(inputAddr, outputAddr); err != nil {
return output, fmt.Errorf("failed to run %s script: %w", implContract, err)
}
return output, nil
}
package opcm
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/testutil"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
func TestDeployDelayedWETH(t *testing.T) {
_, artifacts := testutil.LocalArtifacts(t)
host, err := env.DefaultScriptHost(
broadcaster.NoopBroadcaster(),
testlog.Logger(t, log.LevelInfo),
common.Address{'D'},
artifacts,
0,
)
require.NoError(t, err)
standardVersionsTOML, err := standard.L1VersionsDataFor(11155111)
require.NoError(t, err)
input := DeployDelayedWETHInput{
Release: "dev",
StandardVersionsToml: standardVersionsTOML,
ProxyAdmin: common.Address{'P'},
SuperchainConfigProxy: common.Address{'S'},
DelayedWethOwner: common.Address{'O'},
DelayedWethDelay: big.NewInt(100),
}
output, err := DeployDelayedWETH(host, input)
require.NoError(t, err)
require.NotEmpty(t, output.DelayedWethImpl)
require.NotEmpty(t, output.DelayedWethProxy)
}
......@@ -3,6 +3,8 @@ package pipeline
import (
"fmt"
env2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
......@@ -36,7 +38,7 @@ func GenerateL2Genesis(env *Env, intent *state.Intent, bundle ArtifactsBundle, s
return fmt.Errorf("failed to combine L2 init config: %w", err)
}
host, err := DefaultScriptHost(
host, err := env2.DefaultScriptHost(
broadcaster.NoopBroadcaster(),
env.Logger,
env.Deployer,
......
......@@ -6,6 +6,8 @@ import (
"errors"
"fmt"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
......@@ -144,7 +146,7 @@ func conditionallySetImplementationAddresses(ctx context.Context, client *ethcli
return nil
}
func setMipsSingletonAddress(ctx context.Context, client *ethclient.Client, l1ArtifactsLocator *opcm.ArtifactsLocator, errCh chan error, opcmProxyAddress common.Address, singletonAddress *common.Address) {
func setMipsSingletonAddress(ctx context.Context, client *ethclient.Client, l1ArtifactsLocator *artifacts.Locator, errCh chan error, opcmProxyAddress common.Address, singletonAddress *common.Address) {
if !l1ArtifactsLocator.IsTag() {
errCh <- errors.New("L1 contracts locator is not a tag, cannot set MIPS singleton address")
return
......
......@@ -156,6 +156,19 @@ func ManagerOwnerAddrFor(chainID uint64) (common.Address, error) {
}
}
func SystemOwnerAddrFor(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
// Set to owner of superchain proxy admin
return common.HexToAddress("0x5a0Aae59D09fccBdDb6C6CcEB07B7279367C3d2A"), nil
case 11155111:
// Set to development multisig
return common.HexToAddress("0xDEe57160aAfCF04c34C887B5962D0a69676d3C8B"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func ArtifactsURLForTag(tag string) (*url.URL, error) {
switch tag {
case "op-contracts/v1.6.0":
......
......@@ -4,9 +4,9 @@ import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"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-service/ioutil"
"github.com/ethereum-optimism/optimism/op-service/jsonutil"
......@@ -42,9 +42,9 @@ type Intent struct {
UseInterop bool `json:"useInterop" toml:"useInterop"`
L1ContractsLocator *opcm.ArtifactsLocator `json:"l1ContractsLocator" toml:"l1ContractsLocator"`
L1ContractsLocator *artifacts.Locator `json:"l1ContractsLocator" toml:"l1ContractsLocator"`
L2ContractsLocator *opcm.ArtifactsLocator `json:"l2ContractsLocator" toml:"l2ContractsLocator"`
L2ContractsLocator *artifacts.Locator `json:"l2ContractsLocator" toml:"l2ContractsLocator"`
Chains []*ChainIntent `json:"chains" toml:"chains"`
......@@ -65,11 +65,11 @@ func (c *Intent) Check() error {
}
if c.L1ContractsLocator == nil {
c.L1ContractsLocator = opcm.DefaultL1ContractsLocator
c.L1ContractsLocator = artifacts.DefaultL1ContractsLocator
}
if c.L2ContractsLocator == nil {
c.L2ContractsLocator = opcm.DefaultL2ContractsLocator
c.L2ContractsLocator = artifacts.DefaultL2ContractsLocator
}
var err error
......
package testutil
import (
"context"
"fmt"
"net/url"
"path"
"runtime"
"testing"
artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
op_service "github.com/ethereum-optimism/optimism/op-service"
"github.com/stretchr/testify/require"
)
func LocalArtifacts(t *testing.T) (*artifacts2.Locator, foundry.StatDirFs) {
_, testFilename, _, ok := runtime.Caller(0)
require.Truef(t, ok, "failed to get test filename")
monorepoDir, err := op_service.FindMonorepoRoot(testFilename)
require.NoError(t, err)
artifactsDir := path.Join(monorepoDir, "packages", "contracts-bedrock", "forge-artifacts")
artifactsURL, err := url.Parse(fmt.Sprintf("file://%s", artifactsDir))
require.NoError(t, err)
loc := &artifacts2.Locator{
URL: artifactsURL,
}
artifactsFS, cleanupArtifacts, err := artifacts2.Download(context.Background(), loc, artifacts2.NoopDownloadProgressor)
require.NoError(t, err)
t.Cleanup(func() {
_ = cleanupArtifacts()
})
return loc, artifactsFS
}
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