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

contracts-bedrock: fix deploy config for mainnet MCP upgrade #9865

Merged
merged 20 commits into from
Apr 4, 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
15 changes: 8 additions & 7 deletions op-chain-ops/cmd/ecotone-scalar/main.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package main

import (
"encoding/binary"
"flag"
"fmt"
"math"
"math/big"
"os"

"github.com/ethereum-optimism/optimism/op-service/eth"
)

func main() {
Expand All @@ -26,15 +27,15 @@ func main() {
os.Exit(2)
}

var n [32]byte
n[0] = 1 // version
binary.BigEndian.PutUint32(n[32-4:], uint32(scalar))
binary.BigEndian.PutUint32(n[32-8:], uint32(blobScalar))
i := new(big.Int).SetBytes(n[:])
encoded := eth.EncodeScalar(eth.EcostoneScalars{
BlobBaseFeeScalar: uint32(blobScalar),
BaseFeeScalar: uint32(scalar),
})
i := new(big.Int).SetBytes(encoded[:])

fmt.Println("# base fee scalar :", scalar)
fmt.Println("# blob base fee scalar:", blobScalar)
fmt.Printf("# v1 hex encoding : 0x%x\n", n[:])
fmt.Printf("# v1 hex encoding : 0x%x\n", encoded[:])
fmt.Println("# uint value for the 'scalar' parameter in SystemConfigProxy.setGasConfig():")
fmt.Println(i)
}
9 changes: 7 additions & 2 deletions op-chain-ops/cmd/op-upgrade-mcp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func main() {
oplog.SetGlobalLogHandler(log.NewTerminalHandler(os.Stderr, color))

app := &cli.App{
Name: "op-upgrade",
Name: "op-upgrade-mcp",
protolambda marked this conversation as resolved.
Show resolved Hide resolved
Usage: "Build transactions useful for upgrading the Superchain",
Flags: []cli.Flag{
&cli.StringFlag{
Expand Down Expand Up @@ -179,6 +179,11 @@ func entrypoint(ctx *cli.Context) error {
return fmt.Errorf("no chain config for chain ID %d", l2ChainID)
}

superchainConfig, ok := superchain.Superchains[chainConfig.Superchain]
if !ok {
return fmt.Errorf("no superchain config for superchain %s", chainConfig.Superchain)
}

log.Info("Upgrading to the following versions")
log.Info("L1CrossDomainMessenger", "version", list.L1CrossDomainMessenger.Version, "address", list.L1CrossDomainMessenger.Address)
log.Info("L1ERC721Bridge", "version", list.L1ERC721Bridge.Version, "address", list.L1ERC721Bridge.Address)
Expand All @@ -193,7 +198,7 @@ func entrypoint(ctx *cli.Context) error {
}

// Build the batch
if err := upgrades.L1(&batch, list, *proxyAddresses, config, chainConfig, clients.L1Client); err != nil {
if err := upgrades.L1(&batch, list, *proxyAddresses, config, chainConfig, superchainConfig, clients.L1Client); err != nil {
return fmt.Errorf("cannot build L1 upgrade batch: %w", err)
}

Expand Down
4 changes: 3 additions & 1 deletion op-chain-ops/cmd/op-upgrade/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ func entrypoint(ctx *cli.Context) error {
}

// Build the batch
if err := upgrades.L1(&batch, list, *addresses, config, chainConfig, clients.L1Client); err != nil {
// op-upgrade assumes a superchain config for L1 contract-implementations set.
// The nil superchainConfig here is a placeholder, until op-upgrade and op-upgrade-mcp are consolidated.
if err := upgrades.L1(&batch, list, *addresses, config, chainConfig, nil, clients.L1Client); err != nil {
protolambda marked this conversation as resolved.
Show resolved Hide resolved
return err
}
}
Expand Down
56 changes: 45 additions & 11 deletions op-chain-ops/genesis/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
gstate "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
Expand Down Expand Up @@ -169,9 +170,15 @@ type DeployConfig struct {
// as part of the derivation pipeline.
OptimismPortalProxy common.Address `json:"optimismPortalProxy"`
// GasPriceOracleOverhead represents the initial value of the gas overhead in the GasPriceOracle predeploy.
// Deprecated: Since Ecotone, this field is superseded by GasPriceOracleBaseFeeScalar and GasPriceOracleBlobBaseFeeScalar.
GasPriceOracleOverhead uint64 `json:"gasPriceOracleOverhead"`
// GasPriceOracleScalar represents the initial value of the gas scalar in the GasPriceOracle predeploy.
// Deprecated: Since Ecotone, this field is superseded by GasPriceOracleBaseFeeScalar and GasPriceOracleBlobBaseFeeScalar.
GasPriceOracleScalar uint64 `json:"gasPriceOracleScalar"`
// GasPriceOracleBaseFeeScalar represents the value of the base fee scalar used for fee calculations.
GasPriceOracleBaseFeeScalar uint32 `json:"gasPriceOracleBaseFeeScalar"`
// GasPriceOracleBlobBaseFeeScalar represents the value of the blob base fee scalar used for fee calculations.
GasPriceOracleBlobBaseFeeScalar uint32 `json:"gasPriceOracleBlobBaseFeeScalar"`
// EnableGovernance configures whether or not include governance token predeploy.
EnableGovernance bool `json:"enableGovernance"`
// GovernanceTokenSymbol represents the ERC20 symbol of the GovernanceToken.
Expand Down Expand Up @@ -356,7 +363,13 @@ func (d *DeployConfig) Check() error {
log.Warn("GasPriceOracleOverhead is 0")
}
if d.GasPriceOracleScalar == 0 {
return fmt.Errorf("%w: GasPriceOracleScalar cannot be 0", ErrInvalidDeployConfig)
log.Warn("GasPriceOracleScalar is 0")
}
if d.GasPriceOracleBaseFeeScalar == 0 {
log.Warn("GasPriceOracleBaseFeeScalar is 0")
}
if d.GasPriceOracleBlobBaseFeeScalar == 0 {
log.Warn("GasPriceOracleBlobBaseFeeScalar is 0")
protolambda marked this conversation as resolved.
Show resolved Hide resolved
}
protolambda marked this conversation as resolved.
Show resolved Hide resolved
if d.EIP1559Denominator == 0 {
return fmt.Errorf("%w: EIP1559Denominator cannot be 0", ErrInvalidDeployConfig)
Expand Down Expand Up @@ -447,6 +460,18 @@ func (d *DeployConfig) Check() error {
return nil
}

// FeeScalar returns the raw serialized fee scalar. Uses pre-Ecotone if legacy config is present,
// otherwise uses the post-Ecotone scalar serialization.
func (d *DeployConfig) FeeScalar() [32]byte {
if d.GasPriceOracleScalar != 0 {
return common.BigToHash(big.NewInt(int64(d.GasPriceOracleScalar)))
}
return eth.EncodeScalar(eth.EcostoneScalars{
BlobBaseFeeScalar: d.GasPriceOracleBlobBaseFeeScalar,
BaseFeeScalar: d.GasPriceOracleBaseFeeScalar,
})
}

// CheckAddresses will return an error if the addresses are not set.
// These values are required to create the L2 genesis state and are present in the deploy config
// even though the deploy config is required to deploy the contracts on L1. This creates a
Expand Down Expand Up @@ -573,7 +598,7 @@ func (d *DeployConfig) RollupConfig(l1StartBlock *types.Block, l2GenesisBlockHas
SystemConfig: eth.SystemConfig{
BatcherAddr: d.BatchSenderAddress,
Overhead: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleOverhead))),
Scalar: eth.Bytes32(common.BigToHash(new(big.Int).SetUint64(d.GasPriceOracleScalar))),
Scalar: eth.Bytes32(d.FeeScalar()),
GasLimit: uint64(d.L2GenesisBlockGasLimit),
},
},
Expand Down Expand Up @@ -874,7 +899,7 @@ func NewL2ImmutableConfig(config *DeployConfig, block *types.Block) (*immutables
return &cfg, nil
}

// NewL2StorageConfig will create a StorageConfig given an instance of a DeployConfig and genesis block.
// NewL2StorageConfig will create a StorageConfig given an instance of a DeployConfig and genesis L1 anchor block.
func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.StorageConfig, error) {
storage := make(state.StorageConfig)

Expand Down Expand Up @@ -912,15 +937,24 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"_initializing": false,
"bridge": predeploys.L2StandardBridgeAddr,
}

excessBlobGas := block.ExcessBlobGas()
if excessBlobGas == nil {
excessBlobGas = u64ptr(0)
}
protolambda marked this conversation as resolved.
Show resolved Hide resolved

storage["L1Block"] = state.StorageValues{
"number": block.Number(),
"timestamp": block.Time(),
"basefee": block.BaseFee(),
"hash": block.Hash(),
"sequenceNumber": 0,
"batcherHash": eth.AddressAsLeftPaddedHash(config.BatchSenderAddress),
"l1FeeOverhead": config.GasPriceOracleOverhead,
"l1FeeScalar": config.GasPriceOracleScalar,
"number": block.Number(),
"timestamp": block.Time(),
"basefee": block.BaseFee(),
"hash": block.Hash(),
"sequenceNumber": 0,
"blobBaseFeeScalar": config.GasPriceOracleBlobBaseFeeScalar,
"baseFeeScalar": config.GasPriceOracleBaseFeeScalar,
"batcherHash": eth.AddressAsLeftPaddedHash(config.BatchSenderAddress),
"l1FeeOverhead": config.GasPriceOracleOverhead,
"l1FeeScalar": config.GasPriceOracleScalar,
"blobBaseFee": eip4844.CalcBlobFee(*excessBlobGas),
}
storage["LegacyERC20ETH"] = state.StorageValues{
"_name": "Ether",
Expand Down
100 changes: 100 additions & 0 deletions op-chain-ops/genesis/layer_two_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ import (

"github.com/stretchr/testify/require"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"

"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-service/eth"
"github.com/ethereum/go-ethereum/eth/ethconfig"
)

var writeFile bool
Expand Down Expand Up @@ -47,9 +51,52 @@ func testBuildL2Genesis(t *testing.T, config *genesis.DeployConfig) *core.Genesi
proxyBytecode, err := bindings.GetDeployedBytecode("Proxy")
require.NoError(t, err)

// for simulation we need a regular EVM, not with system-deposit information.
chainConfig := params.ChainConfig{
ChainID: big.NewInt(1337),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: false,
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(0),
ArrowGlacierBlock: big.NewInt(0),
GrayGlacierBlock: big.NewInt(0),
// Activated proof of stake. We manually build/commit blocks in the simulator anyway,
// and the timestamp verification of PoS is not against the wallclock,
// preventing blocks from getting stuck temporarily in the future-blocks queue, decreasing setup time a lot.
MergeNetsplitBlock: big.NewInt(0),
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
ShanghaiTime: new(uint64),
}

// Apply the genesis to the backend
cfg := ethconfig.Defaults
cfg.Preimages = true
cfg.Genesis = &core.Genesis{
Config: &chainConfig,
Timestamp: 1234567,
Difficulty: big.NewInt(0),
Alloc: gen.Alloc,
GasLimit: 30_000_000,
}
backend = backends.NewSimulatedBackendFromConfig(cfg)

for name, predeploy := range predeploys.Predeploys {
addr := predeploy.Address

if addr == predeploys.L1BlockAddr {
testL1Block(t, backend, config, block)
}

account, ok := gen.Alloc[addr]
require.Equal(t, true, ok, name)
require.Greater(t, len(account.Code), 0)
Expand Down Expand Up @@ -84,6 +131,59 @@ func testBuildL2Genesis(t *testing.T, config *genesis.DeployConfig) *core.Genesi
return gen
}

// testL1Block tests that the state is set correctly in the L1Block predeploy
func testL1Block(t *testing.T, caller bind.ContractCaller, config *genesis.DeployConfig, block *types.Block) {
contract, err := bindings.NewL1BlockCaller(predeploys.L1BlockAddr, caller)
require.NoError(t, err)

number, err := contract.Number(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, block.Number().Uint64(), number)

timestamp, err := contract.Timestamp(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, block.Time(), timestamp)

basefee, err := contract.Basefee(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, block.BaseFee(), basefee)

hash, err := contract.Hash(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, block.Hash(), common.Hash(hash))

sequenceNumber, err := contract.SequenceNumber(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, uint64(0), sequenceNumber)

blobBaseFeeScalar, err := contract.BlobBaseFeeScalar(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, config.GasPriceOracleBlobBaseFeeScalar, blobBaseFeeScalar)

baseFeeScalar, err := contract.BaseFeeScalar(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, config.GasPriceOracleBaseFeeScalar, baseFeeScalar)

batcherHeader, err := contract.BatcherHash(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, eth.AddressAsLeftPaddedHash(config.BatchSenderAddress), common.Hash(batcherHeader))

l1FeeOverhead, err := contract.L1FeeOverhead(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, config.GasPriceOracleOverhead, l1FeeOverhead.Uint64())

l1FeeScalar, err := contract.L1FeeScalar(&bind.CallOpts{})
require.NoError(t, err)
require.Equal(t, config.GasPriceOracleScalar, l1FeeScalar.Uint64())

blobBaseFee, err := contract.BlobBaseFee(&bind.CallOpts{})
require.NoError(t, err)
if excessBlobGas := block.ExcessBlobGas(); excessBlobGas != nil {
require.Equal(t, uint64(0), *excessBlobGas)
}
require.Equal(t, big.NewInt(1), blobBaseFee)
}

func TestBuildL2MainnetGenesis(t *testing.T) {
config, err := genesis.NewDeployConfig("./testdata/test-deploy-config-devnet-l1.json")
require.Nil(t, err)
Expand Down
2 changes: 2 additions & 0 deletions op-chain-ops/genesis/testdata/test-deploy-config-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
"systemConfigProxy": "0x4200000000000000000000000000000000000061",
"optimismPortalProxy": "0x4200000000000000000000000000000000000062",
"proxyAdminOwner": "0x0000000000000000000000000000000000000222",
"gasPriceOracleBaseFeeScalar": 0,
"gasPriceOracleBlobBaseFeeScalar": 0,
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"enableGovernance": true,
Expand Down
Loading