Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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
3 changes: 3 additions & 0 deletions op-deployer/pkg/deployer/devfeatures.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ var (

// DeployV2DisputeGamesDevFlag enables deployment of V2 dispute game contracts.
DeployV2DisputeGamesDevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000100")

// OPCMDevFlag enables deployment of OPCM v2 contracts.
OPCMV2DevFlag = common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000010000")
)

// IsDevFeatureEnabled checks if a specific development feature is enabled in a feature bitmap.
Expand Down
20 changes: 11 additions & 9 deletions op-deployer/pkg/deployer/opcm/read_superchain_deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,23 @@ import (
)

type ReadSuperchainDeploymentInput struct {
OPCMAddress common.Address `abi:"opcmAddress"`
OPCMAddress common.Address `abi:"opcmAddress"` // TODO: Remove OPCMAddress field when OPCMv1 gets deprecated
Comment thread
0xniha marked this conversation as resolved.
Outdated
SuperchainConfigProxy common.Address `abi:"superchainConfigProxy"`
}

type ReadSuperchainDeploymentOutput struct {
ProtocolVersionsImpl common.Address
ProtocolVersionsProxy common.Address
SuperchainConfigImpl common.Address
SuperchainConfigProxy common.Address
SuperchainProxyAdmin common.Address

Guardian common.Address
// TODO: Remove ProtocolVersions fields when OPCMv1 gets deprecated
ProtocolVersionsImpl common.Address
ProtocolVersionsProxy common.Address
ProtocolVersionsOwner common.Address
SuperchainProxyAdminOwner common.Address
RecommendedProtocolVersion [32]byte
RequiredProtocolVersion [32]byte

SuperchainConfigImpl common.Address
SuperchainConfigProxy common.Address
SuperchainProxyAdmin common.Address
Guardian common.Address
SuperchainProxyAdminOwner common.Address
}

type ReadSuperchainDeploymentScript script.DeployScriptWithOutput[ReadSuperchainDeploymentInput, ReadSuperchainDeploymentOutput]
Expand Down
58 changes: 54 additions & 4 deletions op-deployer/pkg/deployer/pipeline/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"crypto/rand"
"fmt"
"math/big"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/opcm"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
Expand All @@ -28,7 +29,13 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s

hasPredeployedOPCM := intent.OPCMAddress != nil

if hasPredeployedOPCM {
var opcmV2Enabled bool
if devFeatureBitmap, ok := intent.GlobalDeployOverrides["devFeatureBitmap"].(common.Hash); ok {
opcmV2Flag := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000010000")
opcmV2Enabled = isDevFeatureEnabled(devFeatureBitmap, opcmV2Flag)
}

if hasPredeployedOPCM && !opcmV2Enabled {
if intent.SuperchainConfigProxy != nil {
Comment thread
0xniha marked this conversation as resolved.
Outdated
return fmt.Errorf("cannot set superchain config proxy for predeployed OPCM")
}
Expand All @@ -37,7 +44,14 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
return fmt.Errorf("cannot set superchain roles for predeployed OPCM")
}

superDeployment, superRoles, err := PopulateSuperchainState(env.L1ScriptHost, *intent.OPCMAddress)
// Use OPCMv1 to populate superchain state.
// When using OPCMv1, we only provide the OPCM address (superchainConfigProxy is zero).
// The ReadSuperchainDeployment script (packages/contracts-bedrock/scripts/deploy/ReadSuperchainDeployment.s.sol)
// detects OPCM v1 mode when superchainConfigProxy is zero, then queries the OPCM contract to discover:
// - ProtocolVersions contract address via opcm.protocolVersions()
// - SuperchainConfig contract address via opcm.superchainConfig()
// - All related proxy admin addresses, implementations, and role addresses
superDeployment, superRoles, err := PopulateSuperchainState(env.L1ScriptHost, *intent.OPCMAddress, common.Address{})
if err != nil {
return fmt.Errorf("error populating superchain state: %w", err)
}
Expand All @@ -50,6 +64,28 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
}
}

hasSuperchainConfigProxy := intent.SuperchainConfigProxy != nil
if hasSuperchainConfigProxy && opcmV2Enabled {
if intent.SuperchainRoles != nil {
return fmt.Errorf("cannot set superchain roles for superchain config proxy")
}

// Use OPCMv2 to populate superchain state.
// When using OPCMv2, we provide the SuperchainConfigProxy address while the OPCM address is zero.
// The ReadSuperchainDeployment script (packages/contracts-bedrock/scripts/deploy/ReadSuperchainDeployment.s.sol)
// detects OPCM v2 mode when superchainConfigProxy is non-zero, then queries the SuperchainConfig contract
// to discover the implementation address, proxy admin, guardian, and proxy admin owner.
// In OPCMv2, ProtocolVersions is being removed. Therefore, the ProtocolVersions-related fields
// (protocolVersionsImpl, protocolVersionsProxy, protocolVersionsOwner, recommendedProtocolVersion,
// requiredProtocolVersion) are intentionally left uninitialized.
superDeployment, superRoles, err := PopulateSuperchainState(env.L1ScriptHost, common.Address{}, *intent.SuperchainConfigProxy)
if err != nil {
return fmt.Errorf("error populating superchain state: %w", err)
}
st.SuperchainDeployment = superDeployment
st.SuperchainRoles = superRoles
}

l1ChainID, err := env.L1Client.ChainID(ctx)
if err != nil {
return fmt.Errorf("failed to get L1 chain ID: %w", err)
Expand Down Expand Up @@ -125,14 +161,17 @@ func immutableErr(field string, was, is any) error {
return fmt.Errorf("%s is immutable: was %v, is %v", field, was, is)
}

func PopulateSuperchainState(host *script.Host, opcmAddr common.Address) (*addresses.SuperchainContracts, *addresses.SuperchainRoles, error) {
// TODO: Remove OPCMAddress field when OPCMv1 gets deprecated
// TODO: Remove ProtocolVersions fields when OPCMv1 gets deprecated
func PopulateSuperchainState(host *script.Host, opcmAddr common.Address, superchainConfigProxy common.Address) (*addresses.SuperchainContracts, *addresses.SuperchainRoles, error) {
readScript, err := opcm.NewReadSuperchainDeploymentScript(host)
if err != nil {
return nil, nil, fmt.Errorf("error generating read superchain deployment script: %w", err)
}

out, err := readScript.Run(opcm.ReadSuperchainDeploymentInput{
OPCMAddress: opcmAddr,
OPCMAddress: opcmAddr,
SuperchainConfigProxy: superchainConfigProxy,
})
if err != nil {
return nil, nil, fmt.Errorf("error reading superchain deployment: %w", err)
Expand All @@ -152,3 +191,14 @@ func PopulateSuperchainState(host *script.Host, opcmAddr common.Address) (*addre
}
return deployment, roles, nil
}

// isDevFeatureEnabled checks if a specific development feature is enabled in a feature bitmap.
// This mirrors the function in devfeatures.go to avoid import cycles.
func isDevFeatureEnabled(bitmap, flag common.Hash) bool {
b := new(big.Int).SetBytes(bitmap[:])
f := new(big.Int).SetBytes(flag[:])

featuresIsNonZero := f.Cmp(big.NewInt(0)) != 0
bitmapContainsFeatures := new(big.Int).And(b, f).Cmp(f) == 0
return featuresIsNonZero && bitmapContainsFeatures
}
Loading