Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 25 additions & 16 deletions op-deployer/pkg/deployer/pipeline/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,34 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
return fmt.Errorf("unsupported L2 version: %s", intent.L2ContractsLocator.Tag)
}

if isL1Tag && hasPredeployedOPCM {
superCfg, err := standard.SuperchainFor(intent.L1ChainID)
isStandardIntent := intent.ConfigType == state.IntentTypeStandard ||
intent.ConfigType == state.IntentTypeStandardOverrides
if isL1Tag && hasPredeployedOPCM && isStandardIntent {
stdRoles, err := state.GetStandardSuperchainRoles(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting superchain config: %w", err)
return fmt.Errorf("error getting superchain roles: %w", err)
}

proxyAdmin, err := standard.SuperchainProxyAdminAddrFor(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting superchain proxy admin address: %w", err)
}

st.SuperchainDeployment = &state.SuperchainDeployment{
ProxyAdminAddress: proxyAdmin,
ProtocolVersionsProxyAddress: superCfg.ProtocolVersionsAddr,
SuperchainConfigProxyAddress: superCfg.SuperchainConfigAddr,
}

st.ImplementationsDeployment = &state.ImplementationsDeployment{
OpcmAddress: opcmAddress,
if *intent.SuperchainRoles == *stdRoles {
superCfg, err := standard.SuperchainFor(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting superchain config: %w", err)
}

proxyAdmin, err := standard.SuperchainProxyAdminAddrFor(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting superchain proxy admin address: %w", err)
}

st.SuperchainDeployment = &state.SuperchainDeployment{
ProxyAdminAddress: proxyAdmin,
ProtocolVersionsProxyAddress: superCfg.ProtocolVersionsAddr,
SuperchainConfigProxyAddress: superCfg.SuperchainConfigAddr,
}

st.ImplementationsDeployment = &state.ImplementationsDeployment{
OpcmAddress: opcmAddress,
}
}
}

Expand Down
171 changes: 171 additions & 0 deletions op-deployer/pkg/deployer/pipeline/init_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package pipeline

import (
"context"
"log/slog"
"os"
"testing"
"time"

"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-deployer/pkg/deployer/state"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/testutils/devnet"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)

func TestInitLiveStrategy_OPCMReuseLogicSepolia(t *testing.T) {
rpcURL := os.Getenv("SEPOLIA_RPC_URL")
require.NotEmpty(t, rpcURL, "SEPOLIA_RPC_URL must be set")

lgr := testlog.Logger(t, slog.LevelInfo)
retryProxy := devnet.NewRetryProxy(lgr, rpcURL)
require.NoError(t, retryProxy.Start())
t.Cleanup(func() {
require.NoError(t, retryProxy.Stop())
})

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

client, err := ethclient.Dial(retryProxy.Endpoint())
require.NoError(t, err)

l1ChainID := uint64(11155111)
t.Run("untagged L1 locator", func(t *testing.T) {
st := &state.State{
Version: 1,
}
require.NoError(t, InitLiveStrategy(
ctx,
&Env{
L1Client: client,
Logger: lgr,
},
&state.Intent{
L1ChainID: l1ChainID,
L1ContractsLocator: artifacts.MustNewLocatorFromURL("file:///not-a-path"),
L2ContractsLocator: artifacts.MustNewLocatorFromURL("file:///not-a-path"),
},
st,
))

// Defining a file locator will always deploy a new superchain and OPCM
require.Nil(t, st.SuperchainDeployment)
require.Nil(t, st.ImplementationsDeployment)
})

t.Run("tagged L1 locator with standard intent types and standard roles", func(t *testing.T) {
runTest := func(configType state.IntentType) {
stdSuperchainRoles, err := state.GetStandardSuperchainRoles(l1ChainID)
require.NoError(t, err)

intent := &state.Intent{
ConfigType: configType,
L1ChainID: l1ChainID,
L1ContractsLocator: artifacts.DefaultL1ContractsLocator,
L2ContractsLocator: artifacts.DefaultL2ContractsLocator,
SuperchainRoles: stdSuperchainRoles,
}
st := &state.State{
Version: 1,
}
require.NoError(t, InitLiveStrategy(
ctx,
&Env{
L1Client: client,
Logger: lgr,
},
intent,
st,
))

// Defining a file locator will always deploy a new superchain and OPCM
superCfg, err := standard.SuperchainFor(l1ChainID)
require.NoError(t, err)
proxyAdmin, err := standard.SuperchainProxyAdminAddrFor(l1ChainID)
require.NoError(t, err)
opcmAddr, err := standard.ManagerImplementationAddrFor(l1ChainID, intent.L1ContractsLocator.Tag)
require.NoError(t, err)

expDeployment := &state.SuperchainDeployment{
ProxyAdminAddress: proxyAdmin,
ProtocolVersionsProxyAddress: superCfg.ProtocolVersionsAddr,
SuperchainConfigProxyAddress: superCfg.SuperchainConfigAddr,
}

// Tagged locator will reuse the existing superchain and OPCM
require.NotNil(t, st.SuperchainDeployment)
require.NotNil(t, st.ImplementationsDeployment)
require.Equal(t, *expDeployment, *st.SuperchainDeployment)
require.Equal(t, opcmAddr, st.ImplementationsDeployment.OpcmAddress)
}

runTest(state.IntentTypeStandard)
runTest(state.IntentTypeStandardOverrides)
})

t.Run("tagged L1 locator with standard intent types and modified roles", func(t *testing.T) {
runTest := func(configType state.IntentType) {
intent := &state.Intent{
ConfigType: configType,
L1ChainID: l1ChainID,
L1ContractsLocator: artifacts.DefaultL1ContractsLocator,
L2ContractsLocator: artifacts.DefaultL2ContractsLocator,
SuperchainRoles: &state.SuperchainRoles{
Guardian: common.Address{0: 99},
},
}
st := &state.State{
Version: 1,
}
require.NoError(t, InitLiveStrategy(
ctx,
&Env{
L1Client: client,
Logger: lgr,
},
intent,
st,
))

// Modified roles will cause a new superchain and OPCM to be deployed
require.Nil(t, st.SuperchainDeployment)
require.Nil(t, st.ImplementationsDeployment)
}

runTest(state.IntentTypeStandard)
runTest(state.IntentTypeStandardOverrides)
})

t.Run("tagged locator with custom intent type", func(t *testing.T) {
intent := &state.Intent{
ConfigType: state.IntentTypeCustom,
L1ChainID: l1ChainID,
L1ContractsLocator: artifacts.DefaultL1ContractsLocator,
L2ContractsLocator: artifacts.DefaultL2ContractsLocator,
SuperchainRoles: &state.SuperchainRoles{
Guardian: common.Address{0: 99},
},
}
st := &state.State{
Version: 1,
}
require.NoError(t, InitLiveStrategy(
ctx,
&Env{
L1Client: client,
Logger: lgr,
},
intent,
st,
))

// Custom intent types always deploy a new superchain and OPCM
require.Nil(t, st.SuperchainDeployment)
require.Nil(t, st.ImplementationsDeployment)
})
}
11 changes: 11 additions & 0 deletions op-deployer/pkg/deployer/standard/standard.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,17 @@ func L1ProxyAdminOwner(chainID uint64) (common.Address, error) {
}
}

func L2ProxyAdminOwner(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
return common.Address(validation.StandardConfigRolesMainnet.L2ProxyAdminOwner), nil
case 11155111:
return common.Address(validation.StandardConfigRolesSepolia.L2ProxyAdminOwner), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
}

func ProtocolVersionsOwner(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
Expand Down
23 changes: 23 additions & 0 deletions op-deployer/pkg/deployer/standard/standard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"strings"
"testing"

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

"github.com/ethereum/go-ethereum/common"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -62,3 +64,24 @@ func TestStandardAddresses(t *testing.T) {
})
}
}

func TestL2ProxyAdminOwner(t *testing.T) {
tests := []struct {
chainID uint64
expAddr validation.Address
}{
{
1,
validation.StandardConfigRolesMainnet.L2ProxyAdminOwner,
},
{
11155111,
validation.StandardConfigRolesSepolia.L2ProxyAdminOwner,
},
}
for _, test := range tests {
addr, err := L2ProxyAdminOwner(test.chainID)
require.NoError(t, err)
require.Equal(t, common.Address(test.expAddr), addr)
}
}
21 changes: 16 additions & 5 deletions op-deployer/pkg/deployer/state/intent.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (c *Intent) validateStandardValues() error {
return err
}

standardSuperchainRoles, err := getStandardSuperchainRoles(c.L1ChainID)
standardSuperchainRoles, err := GetStandardSuperchainRoles(c.L1ChainID)
if err != nil {
return fmt.Errorf("error getting standard superchain roles: %w", err)
}
Expand Down Expand Up @@ -157,7 +157,7 @@ func (c *Intent) validateStandardValues() error {
return nil
}

func getStandardSuperchainRoles(l1ChainId uint64) (*SuperchainRoles, error) {
func GetStandardSuperchainRoles(l1ChainId uint64) (*SuperchainRoles, error) {
proxyAdminOwner, err := standard.L1ProxyAdminOwner(l1ChainId)
if err != nil {
return nil, fmt.Errorf("error getting L1ProxyAdminOwner: %w", err)
Expand Down Expand Up @@ -286,14 +286,24 @@ func NewIntentStandard(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, erro
L2ContractsLocator: artifacts.DefaultL2ContractsLocator,
}

superchainRoles, err := getStandardSuperchainRoles(l1ChainId)
superchainRoles, err := GetStandardSuperchainRoles(l1ChainId)
if err != nil {
return Intent{}, fmt.Errorf("error getting standard superchain roles: %w", err)
}
intent.SuperchainRoles = superchainRoles

challenger, _ := standard.ChallengerAddressFor(l1ChainId)
l1ProxyAdminOwner, _ := standard.L1ProxyAdminOwner(l1ChainId)
challenger, err := standard.ChallengerAddressFor(l1ChainId)
if err != nil {
return Intent{}, fmt.Errorf("error getting challenger address: %w", err)
}
l1ProxyAdminOwner, err := standard.L1ProxyAdminOwner(l1ChainId)
if err != nil {
return Intent{}, fmt.Errorf("error getting L1ProxyAdminOwner: %w", err)
}
l2ProxyAdminOwner, err := standard.L2ProxyAdminOwner(l1ChainId)
if err != nil {
return Intent{}, fmt.Errorf("error getting L2ProxyAdminOwner: %w", err)
}

for _, l2ChainID := range l2ChainIds {
intent.Chains = append(intent.Chains, &ChainIntent{
Expand All @@ -304,6 +314,7 @@ func NewIntentStandard(l1ChainId uint64, l2ChainIds []common.Hash) (Intent, erro
Roles: ChainRoles{
Challenger: challenger,
L1ProxyAdminOwner: l1ProxyAdminOwner,
L2ProxyAdminOwner: l2ProxyAdminOwner,
},
})
}
Expand Down