Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op-deployer: Refactor semver inspector, add L2 genesis test #12946

Merged
merged 1 commit into from
Nov 18, 2024
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
16 changes: 16 additions & 0 deletions op-deployer/pkg/deployer/artifacts/locator.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ var DefaultL2ContractsLocator = &Locator{
Tag: standard.DefaultL2ContractsTag,
}

func NewLocatorFromTag(tag string) (*Locator, error) {
loc := new(Locator)
if err := loc.UnmarshalText([]byte("tag://" + tag)); err != nil {
return nil, fmt.Errorf("failed to unmarshal tag: %w", err)
}
return loc, nil
}

func MustNewLocatorFromTag(tag string) *Locator {
loc, err := NewLocatorFromTag(tag)
if err != nil {
panic(err)
}
return loc
}

type Locator struct {
URL *url.URL
Tag string
Expand Down
164 changes: 112 additions & 52 deletions op-deployer/pkg/deployer/inspect/semvers.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import (
"regexp"
"time"

"github.com/ethereum-optimism/optimism/op-chain-ops/foundry"
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/state"
"github.com/ethereum/go-ethereum/log"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/artifacts"

"github.com/ethereum-optimism/optimism/op-deployer/pkg/env"
Expand All @@ -25,8 +29,6 @@ import (
"github.com/urfave/cli/v2"
)

var versionSelector = []byte{0x54, 0xfd, 0x4d, 0x50}

func L2SemversCLI(cliCtx *cli.Context) error {
cliCfg, err := readConfig(cliCtx)
if err != nil {
Expand Down Expand Up @@ -67,92 +69,150 @@ func L2SemversCLI(cliCtx *cli.Context) error {
}
}()

ps, err := L2Semvers(L2SemversConfig{
Lgr: l,
Artifacts: artifactsFS,
ChainState: chainState,
})
if err != nil {
return fmt.Errorf("failed to get L2 semvers: %w", err)
}

if err := jsonutil.WriteJSON(ps, ioutil.ToStdOutOrFileOrNoop(cliCfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write rollup config: %w", err)
}

return nil
}

type L2SemversConfig struct {
Lgr log.Logger
Artifacts foundry.StatDirFs
ChainState *state.ChainState
}

type L2PredeploySemvers struct {
L2ToL1MessagePasser string
DeployerWhitelist string
WETH string
L2CrossDomainMessenger string
L2StandardBridge string
SequencerFeeVault string
OptimismMintableERC20Factory string
L1BlockNumber string
GasPriceOracle string
L1Block string
LegacyMessagePasser string
L2ERC721Bridge string
OptimismMintableERC721Factory string
BaseFeeVault string
L1FeeVault string
SchemaRegistry string
EAS string
CrossL2Inbox string
L2toL2CrossDomainMessenger string
SuperchainWETH string
ETHLiquidity string
SuperchainTokenBridge string
OptimismMintableERC20 string
OptimismMintableERC721 string
}

func L2Semvers(cfg L2SemversConfig) (*L2PredeploySemvers, error) {
l := cfg.Lgr
artifactsFS := cfg.Artifacts
chainState := cfg.ChainState

host, err := env.DefaultScriptHost(
broadcaster.NoopBroadcaster(),
l,
common.Address{19: 0x01},
artifactsFS,
)
if err != nil {
return fmt.Errorf("failed to create script host: %w", err)
return nil, fmt.Errorf("failed to create script host: %w", err)
}
host.ImportState(chainState.Allocs.Data)

addr := common.Address{19: 0x01}

type contractToCheck struct {
Address common.Address
Name string
Address common.Address
FieldPtr *string
Name string
}

contractsOutput := make(map[string]string)
var ps L2PredeploySemvers

// The gov token and the proxy admin do not have semvers.
contracts := []contractToCheck{
{predeploys.L2ToL1MessagePasserAddr, "L2ToL1MessagePasser"},
{predeploys.DeployerWhitelistAddr, "DeployerWhitelist"},
{predeploys.WETHAddr, "WETH"},
{predeploys.L2CrossDomainMessengerAddr, "L2CrossDomainMessenger"},
{predeploys.L2StandardBridgeAddr, "L2StandardBridge"},
{predeploys.SequencerFeeVaultAddr, "SequencerFeeVault"},
{predeploys.OptimismMintableERC20FactoryAddr, "OptimismMintableERC20Factory"},
{predeploys.L1BlockNumberAddr, "L1BlockNumber"},
{predeploys.GasPriceOracleAddr, "GasPriceOracle"},
{predeploys.L1BlockAddr, "L1Block"},
{predeploys.LegacyMessagePasserAddr, "LegacyMessagePasser"},
{predeploys.L2ERC721BridgeAddr, "L2ERC721Bridge"},
{predeploys.OptimismMintableERC721FactoryAddr, "OptimismMintableERC721Factory"},
{predeploys.BaseFeeVaultAddr, "BaseFeeVault"},
{predeploys.L1FeeVaultAddr, "L1FeeVault"},
{predeploys.SchemaRegistryAddr, "SchemaRegistry"},
{predeploys.EASAddr, "EAS"},
{predeploys.WETHAddr, "WETH"},
{predeploys.L2ToL1MessagePasserAddr, &ps.L2ToL1MessagePasser, "L2ToL1MessagePasser"},
{predeploys.DeployerWhitelistAddr, &ps.DeployerWhitelist, "DeployerWhitelist"},
{predeploys.WETHAddr, &ps.WETH, "WETH"},
{predeploys.L2CrossDomainMessengerAddr, &ps.L2CrossDomainMessenger, "L2CrossDomainMessenger"},
{predeploys.L2StandardBridgeAddr, &ps.L2StandardBridge, "L2StandardBridge"},
{predeploys.SequencerFeeVaultAddr, &ps.SequencerFeeVault, "SequencerFeeVault"},
{predeploys.OptimismMintableERC20FactoryAddr, &ps.OptimismMintableERC20Factory, "OptimismMintableERC20Factory"},
{predeploys.L1BlockNumberAddr, &ps.L1BlockNumber, "L1BlockNumber"},
{predeploys.GasPriceOracleAddr, &ps.GasPriceOracle, "GasPriceOracle"},
{predeploys.L1BlockAddr, &ps.L1Block, "L1Block"},
{predeploys.LegacyMessagePasserAddr, &ps.LegacyMessagePasser, "LegacyMessagePasser"},
{predeploys.L2ERC721BridgeAddr, &ps.L2ERC721Bridge, "L2ERC721Bridge"},
{predeploys.OptimismMintableERC721FactoryAddr, &ps.OptimismMintableERC721Factory, "OptimismMintableERC721Factory"},
{predeploys.BaseFeeVaultAddr, &ps.BaseFeeVault, "BaseFeeVault"},
{predeploys.L1FeeVaultAddr, &ps.L1FeeVault, "L1FeeVault"},
{predeploys.SchemaRegistryAddr, &ps.SchemaRegistry, "SchemaRegistry"},
{predeploys.EASAddr, &ps.EAS, "EAS"},
}
for _, contract := range contracts {
data, _, err := host.Call(
addr,
contract.Address,
bytes.Clone(versionSelector),
1_000_000_000,
uint256.NewInt(0),
)
semver, err := ReadSemver(host, contract.Address)
if err != nil {
return fmt.Errorf("failed to call version on %s: %w", contract.Name, err)
}

// The second 32 bytes contain the length of the string
length := new(big.Int).SetBytes(data[32:64]).Int64()
// Start of the string data (after offset and length)
stringStart := 64
stringEnd := int64(stringStart) + length

// Bounds check
if stringEnd > int64(len(data)) {
return fmt.Errorf("string data out of bounds")
return nil, fmt.Errorf("failed to read semver for %s: %w", contract.Name, err)
}

contractsOutput[contract.Name] = string(data[stringStart:stringEnd])
*contract.FieldPtr = semver
}

erc20Semver, err := findSemverBytecode(host, predeploys.OptimismMintableERC20FactoryAddr)
if err == nil {
contractsOutput["OptimismMintableERC20"] = erc20Semver
ps.OptimismMintableERC20 = erc20Semver
} else {
l.Warn("failed to find semver for OptimismMintableERC20", "err", err)
}

erc721Semver, err := findSemverBytecode(host, predeploys.OptimismMintableERC721FactoryAddr)
if err == nil {
contractsOutput["OptimismMintableERC721"] = erc721Semver
ps.OptimismMintableERC721 = erc721Semver
} else {
l.Warn("failed to find semver for OptimismMintableERC721", "err", err)
}

if err := jsonutil.WriteJSON(contractsOutput, ioutil.ToStdOutOrFileOrNoop(cliCfg.Outfile, 0o666)); err != nil {
return fmt.Errorf("failed to write rollup config: %w", err)
return &ps, nil
}

var versionSelector = []byte{0x54, 0xfd, 0x4d, 0x50}

func ReadSemver(host *script.Host, addr common.Address) (string, error) {
data, _, err := host.Call(
common.Address{19: 0x01},
addr,
bytes.Clone(versionSelector),
1_000_000_000,
uint256.NewInt(0),
)
if err != nil {
return "", fmt.Errorf("failed to call version on %s: %w", addr, err)
}

return nil
// The second 32 bytes contain the length of the string
length := new(big.Int).SetBytes(data[32:64]).Int64()
// Start of the string data (after offset and length)
stringStart := 64
stringEnd := int64(stringStart) + length

// Bounds check
if stringEnd > int64(len(data)) {
return "", fmt.Errorf("string data out of bounds")
}

return string(data[stringStart:stringEnd]), nil
}

const patternLen = 24
Expand Down
Loading