Commit d3fbc576 authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

op-deployer: Update OPCM bootstrap command (#13238)

* op-deployer: Update OPCM bootstrap command

Updates the OPCM bootstrap command to allow bootstrapping Holocene.

* fix merge artifact
parent a5556262
build:
go build -o bin/op-deployer cmd/op-deployer/main.go
download-artifacts checksum outfile:
curl -o {{outfile}} -L https://storage.googleapis.com/oplabs-contract-artifacts/artifacts-v1-{{checksum}}.tar.gz
calculate-artifacts-hash checksum:
just download-artifacts {{checksum}} /tmp/artifact.tgz
sha256sum /tmp/artifact.tgz
rm /tmp/artifact.tgz
\ No newline at end of file
......@@ -6,8 +6,6 @@ import (
"fmt"
"strings"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum-optimism/optimism/op-chain-ops/script/forking"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum/go-ethereum/common"
......@@ -145,35 +143,18 @@ func Asterisc(ctx context.Context, cfg AsteriscConfig) error {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
l1Host, err := env.DefaultScriptHost(
l1Host, err := env.DefaultForkedScriptHost(
ctx,
bcaster,
lgr,
chainDeployer,
artifactsFS,
script.WithForkHook(func(cfg *script.ForkConfig) (forking.ForkSource, error) {
src, err := forking.RPCSourceByNumber(cfg.URLOrAlias, l1RPC, *cfg.BlockNumber)
if err != nil {
return nil, fmt.Errorf("failed to create RPC fork source: %w", err)
}
return forking.Cache(src), nil
}),
l1RPC,
)
if err != nil {
return fmt.Errorf("failed to create script host: %w", err)
}
latest, err := l1Client.HeaderByNumber(ctx, nil)
if err != nil {
return fmt.Errorf("failed to get latest block: %w", err)
}
if _, err := l1Host.CreateSelectFork(
script.ForkWithURLOrAlias("main"),
script.ForkWithBlockNumberU256(latest.Number),
); err != nil {
return fmt.Errorf("failed to select fork: %w", err)
}
dgo, err := opcm.DeployAsterisc(
l1Host,
opcm.DeployAsteriscInput{
......
package bootstrap
import (
"errors"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
......@@ -30,6 +32,7 @@ const (
ProposerFlagName = "proposer"
ChallengerFlagName = "challenger"
PreimageOracleFlagName = "preimage-oracle"
ReleaseFlagName = "release"
)
var (
......@@ -153,18 +156,26 @@ var (
EnvVars: deployer.PrefixEnvVar("PREIMAGE_ORACLE"),
Value: common.Address{}.Hex(),
}
ReleaseFlag = &cli.StringFlag{
Name: ReleaseFlagName,
Usage: "Release to deploy.",
EnvVars: deployer.PrefixEnvVar("RELEASE"),
}
)
var OPCMFlags = []cli.Flag{
deployer.L1RPCURLFlag,
deployer.PrivateKeyFlag,
ArtifactsLocatorFlag,
ReleaseFlag,
}
var ImplementationsFlags = []cli.Flag{
MIPSVersionFlag,
WithdrawalDelaySecondsFlag,
MinProposalSizeBytesFlag,
ChallengePeriodSecondsFlag,
ProofMaturityDelaySecondsFlag,
DisputeGameFinalityDelaySecondsFlag,
MIPSVersionFlag,
}
var DelayedWETHFlags = []cli.Flag{
......@@ -212,6 +223,15 @@ var Commands = []*cli.Command{
Flags: cliapp.ProtectFlags(OPCMFlags),
Action: OPCMCLI,
},
{
Name: "implementations",
Usage: "Bootstraps implementations.",
Flags: cliapp.ProtectFlags(ImplementationsFlags),
Action: func(context *cli.Context) error {
return errors.New("not implemented yet")
},
Hidden: true,
},
{
Name: "delayedweth",
Usage: "Bootstrap an instance of DelayedWETH.",
......
......@@ -3,12 +3,12 @@ package bootstrap
import (
"context"
"crypto/ecdsa"
"crypto/rand"
"fmt"
"math/big"
"strings"
artifacts2 "github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
......@@ -18,7 +18,6 @@ import (
"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"
opcrypto "github.com/ethereum-optimism/optimism/op-service/crypto"
"github.com/ethereum-optimism/optimism/op-service/ctxinterrupt"
......@@ -26,7 +25,6 @@ import (
"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"
......@@ -34,12 +32,10 @@ import (
)
type OPCMConfig struct {
pipeline.SuperchainProofParams
L1RPCUrl string
PrivateKey string
Release string
Logger log.Logger
ArtifactsLocator *artifacts2.Locator
privateKeyECDSA *ecdsa.PrivateKey
}
......@@ -53,6 +49,10 @@ func (c *OPCMConfig) Check() error {
return fmt.Errorf("private key must be specified")
}
if c.Release == "" {
return fmt.Errorf("release 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)
......@@ -63,34 +63,6 @@ func (c *OPCMConfig) Check() error {
return fmt.Errorf("logger must be specified")
}
if c.ArtifactsLocator == nil {
return fmt.Errorf("artifacts locator must be specified")
}
if c.WithdrawalDelaySeconds == 0 {
c.WithdrawalDelaySeconds = standard.WithdrawalDelaySeconds
}
if c.MinProposalSizeBytes == 0 {
c.MinProposalSizeBytes = standard.MinProposalSizeBytes
}
if c.ChallengePeriodSeconds == 0 {
c.ChallengePeriodSeconds = standard.ChallengePeriodSeconds
}
if c.ProofMaturityDelaySeconds == 0 {
c.ProofMaturityDelaySeconds = standard.ProofMaturityDelaySeconds
}
if c.DisputeGameFinalityDelaySeconds == 0 {
c.DisputeGameFinalityDelaySeconds = standard.DisputeGameFinalityDelaySeconds
}
if c.MIPSVersion == 0 {
c.MIPSVersion = standard.MIPSVersion
}
return nil
}
......@@ -101,33 +73,30 @@ func OPCMCLI(cliCtx *cli.Context) error {
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)
}
release := cliCtx.String(ReleaseFlagName)
ctx := ctxinterrupt.WithCancelOnInterrupt(cliCtx.Context)
return OPCM(ctx, OPCMConfig{
out, err := OPCM(ctx, OPCMConfig{
L1RPCUrl: l1RPCUrl,
PrivateKey: privateKey,
Release: release,
Logger: l,
ArtifactsLocator: artifactsLocator,
SuperchainProofParams: pipeline.SuperchainProofParams{
WithdrawalDelaySeconds: cliCtx.Uint64(WithdrawalDelaySecondsFlagName),
MinProposalSizeBytes: cliCtx.Uint64(MinProposalSizeBytesFlagName),
ChallengePeriodSeconds: cliCtx.Uint64(ChallengePeriodSecondsFlagName),
ProofMaturityDelaySeconds: cliCtx.Uint64(ProofMaturityDelaySecondsFlagName),
DisputeGameFinalityDelaySeconds: cliCtx.Uint64(DisputeGameFinalityDelaySecondsFlagName),
MIPSVersion: cliCtx.Uint64(MIPSVersionFlagName),
},
})
if err != nil {
return fmt.Errorf("failed to deploy OPCM: %w", err)
}
if err := jsonutil.WriteJSON(out, ioutil.ToStdOut()); err != nil {
return fmt.Errorf("failed to write output: %w", err)
}
return nil
}
func OPCM(ctx context.Context, cfg OPCMConfig) error {
func OPCM(ctx context.Context, cfg OPCMConfig) (opcm.DeployOPCMOutput, error) {
var out opcm.DeployOPCMOutput
if err := cfg.Check(); err != nil {
return fmt.Errorf("invalid config for OPCM: %w", err)
return out, fmt.Errorf("invalid config for OPCM: %w", err)
}
lgr := cfg.Logger
......@@ -135,35 +104,33 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
lgr.Info("artifacts download progress", "current", curr, "total", total)
}
artifactsFS, cleanup, err := artifacts2.Download(ctx, cfg.ArtifactsLocator, progressor)
l1RPC, err := rpc.Dial(cfg.L1RPCUrl)
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)
return out, fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
}()
l1Client, err := ethclient.Dial(cfg.L1RPCUrl)
if err != nil {
return fmt.Errorf("failed to connect to L1 RPC: %w", err)
}
l1Client := ethclient.NewClient(l1RPC)
chainID, err := l1Client.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get chain ID: %w", err)
return out, fmt.Errorf("failed to get chain ID: %w", err)
}
chainIDU64 := chainID.Uint64()
superCfg, err := standard.SuperchainFor(chainIDU64)
loc, err := artifacts.NewLocatorFromTag(cfg.Release)
if err != nil {
return fmt.Errorf("error getting superchain config: %w", err)
return out, fmt.Errorf("failed to create artifacts locator: %w", err)
}
standardVersionsTOML, err := standard.L1VersionsDataFor(chainIDU64)
artifactsFS, cleanup, err := artifacts.Download(ctx, loc, progressor)
if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err)
return out, fmt.Errorf("failed to download artifacts: %w", err)
}
defer func() {
if err := cleanup(); err != nil {
lgr.Warn("failed to clean up artifacts", "err", err)
}
}()
signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID))
chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey)
......@@ -176,83 +143,87 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
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)
return out, fmt.Errorf("failed to create broadcaster: %w", err)
}
host, err := env.DefaultScriptHost(
host, err := env.DefaultForkedScriptHost(
ctx,
bcaster,
lgr,
chainDeployer,
artifactsFS,
l1RPC,
)
if err != nil {
return fmt.Errorf("failed to create script host: %w", err)
return out, fmt.Errorf("failed to create script host: %w", err)
}
host.SetNonce(chainDeployer, nonce)
var l1ContractsRelease string
if cfg.ArtifactsLocator.IsTag() {
l1ContractsRelease = cfg.ArtifactsLocator.Tag
} else {
l1ContractsRelease = "dev"
}
lgr.Info("deploying OPCM", "l1ContractsRelease", l1ContractsRelease)
lgr.Info("deploying OPCM", "l1ContractsRelease", cfg.Release)
// 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[:])
input, err := DeployOPCMInputForChain(cfg.Release, chainIDU64)
if err != nil {
return fmt.Errorf("failed to generate CREATE2 salt: %w", err)
return out, fmt.Errorf("error creating OPCM input: %w", err)
}
dio, err := opcm.DeployImplementations(
out, err = opcm.DeployOPCM(
host,
opcm.DeployImplementationsInput{
Salt: salt,
WithdrawalDelaySeconds: new(big.Int).SetUint64(cfg.WithdrawalDelaySeconds),
MinProposalSizeBytes: new(big.Int).SetUint64(cfg.MinProposalSizeBytes),
ChallengePeriodSeconds: new(big.Int).SetUint64(cfg.ChallengePeriodSeconds),
ProofMaturityDelaySeconds: new(big.Int).SetUint64(cfg.ProofMaturityDelaySeconds),
DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(cfg.DisputeGameFinalityDelaySeconds),
MipsVersion: new(big.Int).SetUint64(cfg.MIPSVersion),
L1ContractsRelease: l1ContractsRelease,
SuperchainConfigProxy: superchainConfigAddr,
ProtocolVersionsProxy: protocolVersionsAddr,
StandardVersionsToml: standardVersionsTOML,
UseInterop: false,
},
input,
)
if err != nil {
return fmt.Errorf("error deploying implementations: %w", err)
return out, fmt.Errorf("error deploying implementations: %w", err)
}
if _, err := bcaster.Broadcast(ctx); err != nil {
return fmt.Errorf("failed to broadcast: %w", err)
return out, fmt.Errorf("failed to broadcast: %w", err)
}
lgr.Info("deployed implementations")
lgr.Info("deployed OPCM")
if err := jsonutil.WriteJSON(dio, ioutil.ToStdOut()); err != nil {
return fmt.Errorf("failed to write output: %w", err)
return out, nil
}
func DeployOPCMInputForChain(release string, chainID uint64) (opcm.DeployOPCMInput, error) {
superchain, err := standard.SuperchainFor(chainID)
if err != nil {
return opcm.DeployOPCMInput{}, fmt.Errorf("error getting superchain config: %w", err)
}
return nil
l1VersionsData, err := standard.L1VersionsFor(chainID)
if err != nil {
return opcm.DeployOPCMInput{}, fmt.Errorf("error getting L1 versions: %w", err)
}
releases, ok := l1VersionsData.Releases[release]
if !ok {
return opcm.DeployOPCMInput{}, fmt.Errorf("release not found: %s", release)
}
blueprints, err := standard.OPCMBlueprintsFor(chainID)
if err != nil {
return opcm.DeployOPCMInput{}, fmt.Errorf("error getting OPCM blueprints: %w", err)
}
return opcm.DeployOPCMInput{
SuperchainConfig: common.Address(*superchain.Config.SuperchainConfigAddr),
ProtocolVersions: common.Address(*superchain.Config.ProtocolVersionsAddr),
L1ContractsRelease: strings.TrimPrefix(release, "op-contracts/"),
AddressManagerBlueprint: blueprints.AddressManager,
ProxyBlueprint: blueprints.Proxy,
ProxyAdminBlueprint: blueprints.ProxyAdmin,
L1ChugSplashProxyBlueprint: blueprints.L1ChugSplashProxy,
ResolvedDelegateProxyBlueprint: blueprints.ResolvedDelegateProxy,
AnchorStateRegistryBlueprint: blueprints.AnchorStateRegistry,
PermissionedDisputeGame1Blueprint: blueprints.PermissionedDisputeGame1,
PermissionedDisputeGame2Blueprint: blueprints.PermissionedDisputeGame2,
L1ERC721BridgeImpl: releases.L1ERC721Bridge.ImplementationAddress,
OptimismPortalImpl: releases.OptimismPortal.ImplementationAddress,
SystemConfigImpl: releases.SystemConfig.ImplementationAddress,
OptimismMintableERC20FactoryImpl: releases.OptimismMintableERC20Factory.ImplementationAddress,
L1CrossDomainMessengerImpl: releases.L1CrossDomainMessenger.ImplementationAddress,
L1StandardBridgeImpl: releases.L1StandardBridge.ImplementationAddress,
DisputeGameFactoryImpl: releases.DisputeGameFactory.ImplementationAddress,
DelayedWETHImpl: releases.DelayedWETH.ImplementationAddress,
MipsImpl: releases.MIPS.Address,
}, nil
}
package bootstrap
import (
"context"
"log/slog"
"os"
"strings"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/retryproxy"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/testutils/anvil"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
var networks = []string{"mainnet", "sepolia"}
var versions = []string{"v1.8.0-rc.3"}
func TestOPCMLiveChain(t *testing.T) {
for _, network := range networks {
for _, version := range versions {
t.Run(network+"-"+version, func(t *testing.T) {
if version == "v1.8.0-rc.3" && network == "mainnet" {
t.Skip("v1.8.0-rc.3 not supported on mainnet yet")
}
envVar := strings.ToUpper(network) + "_RPC_URL"
rpcURL := os.Getenv(envVar)
require.NotEmpty(t, rpcURL, "must specify RPC url via %s env var", envVar)
testOPCMLiveChain(t, "op-contracts/"+version, rpcURL)
})
}
}
}
func testOPCMLiveChain(t *testing.T, version string, forkRPCURL string) {
t.Parallel()
if forkRPCURL == "" {
t.Skip("forkRPCURL not set")
}
lgr := testlog.Logger(t, slog.LevelDebug)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
defer cancel()
retryProxy := retryproxy.New(lgr, forkRPCURL)
require.NoError(t, retryProxy.Start())
t.Cleanup(func() {
require.NoError(t, retryProxy.Stop())
})
runner, err := anvil.New(
retryProxy.Endpoint(),
lgr,
)
require.NoError(t, err)
require.NoError(t, runner.Start(ctx))
t.Cleanup(func() {
require.NoError(t, runner.Stop())
})
out, err := OPCM(ctx, OPCMConfig{
L1RPCUrl: runner.RPCUrl(),
PrivateKey: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
Release: version,
Logger: lgr,
})
require.NoError(t, err)
require.NotEmpty(t, out.Opcm)
client, err := ethclient.Dial(runner.RPCUrl())
require.NoError(t, err)
code, err := client.CodeAt(ctx, out.Opcm, nil)
require.NoError(t, err)
require.NotEmpty(t, code)
}
package opcm
import (
"fmt"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum/go-ethereum/common"
)
type DeployOPCMInput struct {
SuperchainConfig common.Address
ProtocolVersions common.Address
L1ContractsRelease string
AddressManagerBlueprint common.Address
ProxyBlueprint common.Address
ProxyAdminBlueprint common.Address
L1ChugSplashProxyBlueprint common.Address
ResolvedDelegateProxyBlueprint common.Address
AnchorStateRegistryBlueprint common.Address
PermissionedDisputeGame1Blueprint common.Address
PermissionedDisputeGame2Blueprint common.Address
L1ERC721BridgeImpl common.Address
OptimismPortalImpl common.Address
SystemConfigImpl common.Address
OptimismMintableERC20FactoryImpl common.Address
L1CrossDomainMessengerImpl common.Address
L1StandardBridgeImpl common.Address
DisputeGameFactoryImpl common.Address
DelayedWETHImpl common.Address
MipsImpl common.Address
}
type DeployOPCMOutput struct {
Opcm common.Address
}
func DeployOPCM(
host *script.Host,
input DeployOPCMInput,
) (DeployOPCMOutput, error) {
scriptFile := "DeployOPCM.s.sol"
contractName := "DeployOPCM"
out, err := RunBasicScript[DeployOPCMInput, DeployOPCMOutput](host, input, scriptFile, contractName)
if err != nil {
return DeployOPCMOutput{}, fmt.Errorf("failed to deploy OPCM: %w", err)
}
if err := host.RememberOnLabel("OPContractsManager", "OPContractsManager.sol", "OPContractsManager"); err != nil {
return DeployOPCMOutput{}, fmt.Errorf("failed to link OPContractsManager label: %w", err)
}
return out, nil
}
package opcm
import (
"fmt"
"github.com/ethereum-optimism/optimism/op-chain-ops/script"
"github.com/ethereum/go-ethereum/common"
)
type BasicScriptIO struct {
Run func(input, output common.Address) error
}
func RunBasicScript[I any, O any](
host *script.Host,
input I,
scriptFile string,
contractName string,
) (O, error) {
var output O
inputAddr := host.NewScriptAddress()
outputAddr := host.NewScriptAddress()
cleanupInput, err := script.WithPrecompileAtAddress[*I](host, inputAddr, &input)
if err != nil {
return output, fmt.Errorf("failed to insert input precompile: %w", err)
}
defer cleanupInput()
cleanupOutput, err := script.WithPrecompileAtAddress[*O](host, outputAddr, &output,
script.WithFieldSetter[*O])
if err != nil {
return output, fmt.Errorf("failed to insert output precompile: %w", err)
}
defer cleanupOutput()
deployScript, cleanupDeploy, err := script.WithScript[BasicScriptIO](host, scriptFile, contractName)
if err != nil {
return output, fmt.Errorf("failed to load %s script: %w", scriptFile, err)
}
defer cleanupDeploy()
if err := deployScript.Run(inputAddr, outputAddr); err != nil {
return output, fmt.Errorf("failed to run %s script: %w", scriptFile, err)
}
return output, nil
}
......@@ -5,6 +5,25 @@
# * proxied : specify a standard "implementation_address"
# * neither : specify neither a standard "address" nor "implementation_address"
# Holocene https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.8.0-rc.3
[releases."op-contracts/v1.8.0-rc.3"]
# Updated in this release
system_config = { version = "2.3.0", implementation_address = "0x33b83E4C305c908B2Fc181dDa36e230213058d7d" } # UPDATED IN THIS RELEASE
fault_dispute_game = { version = "1.3.1" } # UPDATED IN THIS RELEASE
permissioned_dispute_game = { version = "1.3.1" } # UPDATED IN THIS RELEASE
mips = { version = "1.2.1", address = "0x69470D6970Cd2A006b84B1d4d70179c892cFCE01" } # UPDATED IN THIS RELEASE
# Unchanged in this release
optimism_portal = { version = "3.10.0", implementation_address = "0x35028bae87d71cbc192d545d38f960ba30b4b233" }
anchor_state_registry = { version = "2.0.0" }
delayed_weth = { version = "1.1.0", implementation_address = "0x07f69b19532476c6cd03056d6bc3f1b110ab7538" }
dispute_game_factory = { version = "1.0.0", implementation_address = "0xa51bea7e4d34206c0bcb04a776292f2f19f0beec" }
preimage_oracle = { version = "1.1.2", address = "0x92240135b46fc1142dA181f550aE8f595B858854" }
l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" }
l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xae2af01232a6c4a4d3012c5ec5b1b35059caf10d" }
l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64b5a5ed26dcb17370ff4d33a8d503f0fbd06cff" }
# l2_output_oracle -- This contract not used in fault proofs
optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xe01efbeb1089d1d1db9c6c8b135c934c0734c846" }
# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0
[releases."op-contracts/v1.6.0"]
optimism_portal = { version = "3.10.0", implementation_address = "0x35028bae87d71cbc192d545d38f960ba30b4b233" }
......
......@@ -78,6 +78,50 @@ type VersionRelease struct {
var _ embed.FS
type OPCMBlueprints struct {
AddressManager common.Address
Proxy common.Address
ProxyAdmin common.Address
L1ChugSplashProxy common.Address
ResolvedDelegateProxy common.Address
AnchorStateRegistry common.Address
PermissionedDisputeGame1 common.Address
PermissionedDisputeGame2 common.Address
}
var sepoliaBlueprints = OPCMBlueprints{
AddressManager: common.HexToAddress("0x3125a4cB2179E04203D3Eb2b5784aaef9FD64216"),
Proxy: common.HexToAddress("0xe650ADb86a0de96e2c434D0a52E7D5B70980D6f1"),
ProxyAdmin: common.HexToAddress("0x3AC6b88F6bC4A5038DB7718dE47a5ab1a9609319"),
L1ChugSplashProxy: common.HexToAddress("0x58770FC7ed304c43D2B70248914eb34A741cF411"),
ResolvedDelegateProxy: common.HexToAddress("0x0449adB72D489a137d476aB49c6b812161754fD3"),
AnchorStateRegistry: common.HexToAddress("0xB98095199437883b7661E0D58256060f3bc730a4"),
PermissionedDisputeGame1: common.HexToAddress("0xf72Ac5f164cC024DE09a2c249441715b69a16eAb"),
PermissionedDisputeGame2: common.HexToAddress("0x713dAC5A23728477547b484f9e0D751077E300a2"),
}
var mainnetBlueprints = OPCMBlueprints{
AddressManager: common.HexToAddress("0x29aA24714c06914d9689e933cae2293C569AfeEa"),
Proxy: common.HexToAddress("0x3626ebD458c7f34FD98789A373593fF2fc227bA0"),
ProxyAdmin: common.HexToAddress("0x7170678A5CFFb6872606d251B3CcdB27De962631"),
L1ChugSplashProxy: common.HexToAddress("0x538906C8B000D621fd11B7e8642f504dD8730837"),
ResolvedDelegateProxy: common.HexToAddress("0xF12bD34d6a1d26d230240ECEA761f77e2013926E"),
AnchorStateRegistry: common.HexToAddress("0xbA7Be2bEE016568274a4D1E6c852Bb9a99FaAB8B"),
PermissionedDisputeGame1: common.HexToAddress("0xb94bF6130Df8BD9a9eA45D8dD8C18957002d1986"),
PermissionedDisputeGame2: common.HexToAddress("0xe0a642B249CF6cbF0fF7b4dDf41443Ea7a5C8Cc8"),
}
func OPCMBlueprintsFor(chainID uint64) (OPCMBlueprints, error) {
switch chainID {
case 1:
return mainnetBlueprints, nil
case 11155111:
return sepoliaBlueprints, nil
default:
return OPCMBlueprints{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}
func L1VersionsDataFor(chainID uint64) (string, error) {
switch chainID {
case 1:
......@@ -215,6 +259,8 @@ func ArtifactsURLForTag(tag string) (*url.URL, error) {
return url.Parse(standardArtifactsURL("e1f0c4020618c4a98972e7124c39686cab2e31d5d7846f9ce5e0d5eed0f5ff32"))
case "op-contracts/v1.7.0-beta.1+l2-contracts":
return url.Parse(standardArtifactsURL("b0fb1f6f674519d637cff39a22187a5993d7f81a6d7b7be6507a0b50a5e38597"))
case "op-contracts/v1.8.0-rc.3":
return url.Parse(standardArtifactsURL("3bcff2944953862596d5fd0125d166a04af2ba6426dc693983291d3cb86b2e2e"))
default:
return nil, fmt.Errorf("unsupported tag: %s", tag)
}
......@@ -226,6 +272,8 @@ func ArtifactsHashForTag(tag string) (common.Hash, error) {
return common.HexToHash("d20a930cc0ff204c2d93b7aa60755ec7859ba4f328b881f5090c6a6a2a86dcba"), nil
case "op-contracts/v1.7.0-beta.1+l2-contracts":
return common.HexToHash("9e3ad322ec9b2775d59143ce6874892f9b04781742c603ad59165159e90b00b9"), nil
case "op-contracts/v1.8.0-rc.3":
return common.HexToHash("7c133142165fbbdba28ced5d9a04af8bea68baf58b19a07cdd8ae531b01fbe9d"), nil
default:
return common.Hash{}, fmt.Errorf("unsupported tag: %s", tag)
}
......
package env
import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-chain-ops/script/forking"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/broadcaster"
"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
......@@ -39,3 +44,48 @@ func DefaultScriptHost(
return h, nil
}
func DefaultForkedScriptHost(
ctx context.Context,
bcaster broadcaster.Broadcaster,
lgr log.Logger,
deployer common.Address,
artifacts foundry.StatDirFs,
forkRPC *rpc.Client,
additionalOpts ...script.HostOption,
) (*script.Host, error) {
h, err := DefaultScriptHost(
bcaster,
lgr,
deployer,
artifacts,
append([]script.HostOption{
script.WithForkHook(func(cfg *script.ForkConfig) (forking.ForkSource, error) {
src, err := forking.RPCSourceByNumber(cfg.URLOrAlias, forkRPC, *cfg.BlockNumber)
if err != nil {
return nil, fmt.Errorf("failed to create RPC fork source: %w", err)
}
return forking.Cache(src), nil
}),
}, additionalOpts...)...,
)
if err != nil {
return nil, fmt.Errorf("failed to create default script host: %w", err)
}
client := ethclient.NewClient(forkRPC)
latest, err := client.HeaderByNumber(ctx, nil)
if err != nil {
return nil, fmt.Errorf("failed to get latest block: %w", err)
}
if _, err := h.CreateSelectFork(
script.ForkWithURLOrAlias("main"),
script.ForkWithBlockNumberU256(latest.Number),
); err != nil {
return nil, fmt.Errorf("failed to select fork: %w", err)
}
return h, nil
}
......@@ -3,6 +3,7 @@ package retryproxy
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net"
......@@ -13,6 +14,10 @@ import (
"github.com/ethereum/go-ethereum/log"
)
type jsonRPCReq struct {
Method string `json:"method"`
}
var copyHeaders = []string{
"Content-Type",
}
......@@ -92,6 +97,8 @@ func (p *RetryProxy) Endpoint() string {
}
func (p *RetryProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
start := time.Now()
if r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
......@@ -138,7 +145,16 @@ func (p *RetryProxy) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if _, err := io.Copy(w, bytes.NewReader(resBody)); err != nil {
p.lgr.Error("failed to copy response", "err", err)
http.Error(w, "failed to copy response", http.StatusInternalServerError)
return
}
var jReq jsonRPCReq
if err := json.Unmarshal(reqBody, &jReq); err != nil {
p.lgr.Warn("failed to unmarshal request", "err", err)
return
}
p.lgr.Debug("proxied request", "method", jReq.Method, "dur", time.Since(start))
}
func (p *RetryProxy) doProxyReq(ctx context.Context, body []byte) (*http.Response, error) {
......
......@@ -33,6 +33,10 @@ type Runner struct {
}
func New(l1RPCURL string, logger log.Logger) (*Runner, error) {
if _, err := exec.LookPath("anvil"); err != nil {
return nil, fmt.Errorf("anvil not found in PATH: %w", err)
}
proc := exec.Command(
"anvil",
"--fork-url", l1RPCURL,
......@@ -106,7 +110,7 @@ func (r *Runner) outputStream(stream io.ReadCloser) {
}
}
r.logger.Debug("[ANVIL] " + scanner.Text())
r.logger.Debug("[ANVIL] " + line)
}
}
......
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