Commit a5d10181 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into more-audits

parents a5bc5df9 d6e1f3b2
---
'@eth-optimism/contracts-bedrock': patch
---
Cleans up remaining lint warnings
---
'@eth-optimism/hardhat-node': patch
---
Upgrade dependencies, add fork chain ID support
comment: false
comment: true
ignore:
- "l2geth"
- "**/*.t.sol"
......@@ -10,6 +10,11 @@ flag_management:
individual_flags:
- name: bedrock-go-tests
- name: contracts-bedrock-tests
paths:
- packages/contracts-bedrock/contracts
statuses:
- type: patch
target: 100%
- name: common-ts-tests
- name: contracts-tests
- name: core-utils-tests
......@@ -22,3 +27,20 @@ flag_management:
- name: message-relayer-tests
- name: replica-healthcheck-tests
- name: sdk-tests
coverage:
status:
patch:
default:
# basic
target: auto
threshold: 0%
base: auto
# advanced
branches:
- master
if_ci_failed: error #success, error
only_pulls: false
flags:
- "unit"
paths:
- "src"
package op_batcher
import (
"bytes"
"io"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/core/types"
)
type txID struct {
chID derive.ChannelID
frameNumber uint16
}
type taggedData struct {
data []byte
id txID
}
type channelManager struct {
// All blocks since the last request for new tx data
blocks []*types.Block
datas []taggedData
}
// func (s *channelManager) TxConfirmed(id txID, inclusionBlock eth.BlockID) {
// // todo: implement
// }
// TxData returns the next tx.data that should be submitted to L1.
// It is very simple & currently ignores the l1Head provided (this will change).
// It may buffer very large channels as well.
func (s *channelManager) TxData(l1Head eth.L1BlockRef) ([]byte, txID, error) {
// Note: l1Head is not actually used in this function.
// Return a pre-existing frame if we have it.
if len(s.datas) != 0 {
r := s.datas[0]
s.datas = s.datas[1:]
return r.data, r.id, nil
}
// Also return io.EOF if we cannot create a channel
if len(s.blocks) == 0 {
return nil, txID{}, io.EOF
}
// Add all pending blocks to a channel
ch, err := derive.NewChannelOut()
if err != nil {
return nil, txID{}, err
}
// TODO: use peek/pop paradigm here instead of manually slicing
i := 0
// Cap length at 100 blocks
l := len(s.blocks)
if l > 100 {
l = 100
}
for ; i < l; i++ {
if err := ch.AddBlock(s.blocks[i]); err == derive.ErrTooManyRLPBytes {
break
} else if err != nil {
return nil, txID{}, err
}
// TODO: limit the RLP size of the channel to be lower than the limit to enable
// channels to be fully submitted on time.
}
if err := ch.Close(); err != nil {
return nil, txID{}, err
}
var t []taggedData
frameNumber := uint16(0)
for {
var buf bytes.Buffer
buf.WriteByte(derive.DerivationVersion0)
err := ch.OutputFrame(&buf, 120_000)
if err != io.EOF && err != nil {
return nil, txID{}, err
}
t = append(t, taggedData{
data: buf.Bytes(),
id: txID{ch.ID(), frameNumber},
})
frameNumber += 1
if err == io.EOF {
break
}
}
s.datas = append(s.datas, t...)
// Say i = 0, 1 are added to the channel, but i = 2 returns ErrTooManyRLPBytes. i remains 2 & is inclusive, so this works.
// Say all blocks are added, i will be len(blocks) after exiting the loop (but never inside the loop).
s.blocks = s.blocks[i:]
if len(s.datas) == 0 {
return nil, txID{}, io.EOF // TODO: not enough data error instead
}
r := s.datas[0]
s.datas = s.datas[1:]
return r.data, r.id, nil
}
// TODO: Continuity check here?
// Invariants about what's on L1?
func (s *channelManager) AddL2Block(block *types.Block) error {
s.blocks = append(s.blocks, block)
return nil
}
package op_batcher
import (
"bytes"
"context"
"crypto/ecdsa"
"errors"
......@@ -13,11 +12,9 @@ import (
"github.com/ethereum-optimism/optimism/op-batcher/sequencer"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-proposer/txmgr"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
hdwallet "github.com/miguelmota/go-ethereum-hdwallet"
......@@ -26,7 +23,7 @@ import (
// BatchSubmitter encapsulates a service responsible for submitting L2 tx
// batches to L1 for availability.
type BatchSubmitter struct {
txMgr txmgr.TxManager
txMgr *TransactionManager
addr common.Address
cfg sequencer.Config
wg sync.WaitGroup
......@@ -38,7 +35,7 @@ type BatchSubmitter struct {
lastSubmittedBlock eth.BlockID
ch *derive.ChannelOut
state *channelManager
}
// NewBatchSubmitter initializes the BatchSubmitter, gathering any resources
......@@ -148,9 +145,10 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
return &BatchSubmitter{
cfg: batcherCfg,
addr: addr,
txMgr: txmgr.NewSimpleTxManager("batcher", txManagerConfig, l1Client),
txMgr: NewTransactionManger(l, txManagerConfig, batchInboxAddress, chainID, sequencerPrivKey, l1Client),
done: make(chan struct{}),
log: l,
state: new(channelManager),
// TODO: this context only exists because the even loop doesn't reach done
// if the tx manager is blocking forever due to e.g. insufficient balance.
ctx: ctx,
......@@ -170,33 +168,25 @@ func (l *BatchSubmitter) Stop() {
l.wg.Wait()
}
func (l *BatchSubmitter) loop() {
defer l.wg.Done()
ticker := time.NewTicker(l.cfg.PollInterval)
defer ticker.Stop()
mainLoop:
for {
select {
case <-ticker.C:
// Do the simplest thing of one channel per range of blocks since the iteration of this loop.
// The channel is closed at the end of this loop (to avoid lifecycle management of the channel).
ctx, cancel := context.WithTimeout(l.ctx, time.Second*10)
// loadBlocksIntoState loads all blocks since the previous submitted block
func (l *BatchSubmitter) loadBlocksIntoState(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
syncStatus, err := l.cfg.RollupNode.SyncStatus(ctx)
cancel()
if err != nil {
l.log.Warn("issue fetching L2 head", "err", err)
continue
return
}
if syncStatus.HeadL1 == (eth.L1BlockRef{}) {
l.log.Info("Rollup node has no L1 head info yet")
continue
return
}
l.log.Info("Got new L2 sync status", "safe_head", syncStatus.SafeL2, "unsafe_head", syncStatus.UnsafeL2, "last_submitted", l.lastSubmittedBlock, "l1_head", syncStatus.HeadL1)
if syncStatus.SafeL2.Number >= syncStatus.UnsafeL2.Number {
l.log.Trace("No unsubmitted blocks from sequencer")
continue
return
}
// If we just started, start at safe-head
if l.lastSubmittedBlock == (eth.BlockID{}) {
l.log.Info("Starting batch-submitter work at safe-head", "safe", syncStatus.SafeL2)
......@@ -207,110 +197,57 @@ mainLoop:
l.log.Warn("last submitted block lagged behind L2 safe head: batch submission will continue from the safe head now", "last", l.lastSubmittedBlock, "safe", syncStatus.SafeL2)
l.lastSubmittedBlock = syncStatus.SafeL2.ID()
}
if ch, err := derive.NewChannelOut(); err != nil {
l.log.Error("Error creating channel", "err", err)
continue
} else {
l.ch = ch
}
prevID := l.lastSubmittedBlock
maxBlocksPerChannel := uint64(100)
// Hacky min() here to ensure that we don't batch submit more than 100 blocks per channel.
// TODO: use proper channel size here instead.
upToBlockNumber := syncStatus.UnsafeL2.Number
if l.lastSubmittedBlock.Number+1+maxBlocksPerChannel < upToBlockNumber {
upToBlockNumber = l.lastSubmittedBlock.Number + 1 + maxBlocksPerChannel
}
for i := l.lastSubmittedBlock.Number + 1; i <= upToBlockNumber; i++ {
// Add all blocks to "state"
for i := l.lastSubmittedBlock.Number + 1; i <= syncStatus.UnsafeL2.Number; i++ {
ctx, cancel := context.WithTimeout(l.ctx, time.Second*10)
block, err := l.cfg.L2Client.BlockByNumber(ctx, new(big.Int).SetUint64(i))
cancel()
if err != nil {
l.log.Error("issue fetching L2 block", "err", err)
continue mainLoop
return
}
if block.ParentHash() != prevID.Hash {
l.log.Error("detected a reorg in L2 chain vs previous submitted information, resetting to safe head now", "safe_head", syncStatus.SafeL2)
l.lastSubmittedBlock = syncStatus.SafeL2.ID()
continue mainLoop
}
if err := l.ch.AddBlock(block); err != nil {
l.log.Error("issue adding L2 Block to the channel", "err", err, "channel_id", l.ch.ID())
continue mainLoop
}
prevID = eth.BlockID{Hash: block.Hash(), Number: block.NumberU64()}
l.log.Info("added L2 block to channel", "block", prevID, "channel_id", l.ch.ID(), "tx_count", len(block.Transactions()), "time", block.Time())
}
if err := l.ch.Close(); err != nil {
l.log.Error("issue getting adding L2 Block", "err", err)
continue
return
}
// Hand role do-while loop to fully pull all frames out of the channel
for {
// Collect the output frame
data := new(bytes.Buffer)
data.WriteByte(derive.DerivationVersion0)
done := false
// subtract one, to account for the version byte
if err := l.ch.OutputFrame(data, l.cfg.MaxL1TxSize-1); err == io.EOF {
done = true
} else if err != nil {
l.log.Error("error outputting frame", "err", err)
continue mainLoop
if err := l.state.AddL2Block(block); err != nil {
return
}
// Query for the submitter's current nonce.
walletAddr := crypto.PubkeyToAddress(l.cfg.PrivKey.PublicKey)
ctx, cancel = context.WithTimeout(l.ctx, time.Second*10)
nonce, err := l.cfg.L1Client.NonceAt(ctx, walletAddr, nil)
cancel()
if err != nil {
l.log.Error("unable to get current nonce", "err", err)
continue mainLoop
prevID = eth.ToBlockID(block)
l.lastSubmittedBlock = prevID
l.log.Info("added L2 block to local state", "block", prevID, "tx_count", len(block.Transactions()), "time", block.Time())
}
}
// Create the transaction
ctx, cancel = context.WithTimeout(l.ctx, time.Second*10)
tx, err := l.CraftTx(ctx, data.Bytes(), nonce)
cancel()
if err != nil {
l.log.Error("unable to craft tx", "err", err)
continue mainLoop
}
func (l *BatchSubmitter) loop() {
defer l.wg.Done()
// Construct the a closure that will update the txn with the current gas prices.
updateGasPrice := func(ctx context.Context) (*types.Transaction, error) {
l.log.Debug("updating batch tx gas price")
return l.UpdateGasPrice(ctx, tx)
}
ticker := time.NewTicker(l.cfg.PollInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
l.loadBlocksIntoState(l.ctx)
// Wait until one of our submitted transactions confirms. If no
// receipt is received it's likely our gas price was too low.
// TODO: does the tx manager nicely replace the tx?
// (submit a new one, that's within the channel timeout, but higher fee than previously submitted tx? Or use a cheap cancel tx?)
ctx, cancel = context.WithTimeout(l.ctx, time.Second*time.Duration(l.cfg.ChannelTimeout))
receipt, err := l.txMgr.Send(ctx, updateGasPrice, l.cfg.L1Client.SendTransaction)
cancel()
if err != nil {
l.log.Warn("unable to publish tx", "err", err)
continue mainLoop
// Empty the state after loading into it on every iteration.
for {
// Collect the output frame
data, _, err := l.state.TxData(eth.L1BlockRef{})
if err == io.EOF {
break // local for loop
} else if err != nil {
l.log.Error("unable to get tx data", "err", err)
break
}
// The transaction was successfully submitted.
l.log.Info("tx successfully published", "tx_hash", receipt.TxHash, "channel_id", l.ch.ID())
// If `ch.OutputFrame` returned io.EOF we don't need to submit any more frames for this channel.
if done {
break // local do-while loop
// Drop receipt + error for now
if _, err := l.txMgr.SendTransaction(l.ctx, data); err != nil {
l.log.Error("Failed to send transaction", "err", err)
}
}
// TODO: if we exit to the mainLoop early on an error,
// it would be nice if we can determine which blocks are still readable from the partially submitted data.
// We can open a channel-in-reader, parse the data up to which we managed to submit it,
// and then take the block hash (if we remember which blocks we put in the channel)
//
// Now we just continue batch submission from the end of the channel.
l.lastSubmittedBlock = prevID
case <-l.done:
return
......
......@@ -2,65 +2,144 @@ package op_batcher
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-proposer/txmgr"
"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/ethclient"
"github.com/ethereum/go-ethereum/log"
)
// NOTE: This method SHOULD NOT publish the resulting transaction.
func (l *BatchSubmitter) CraftTx(ctx context.Context, data []byte, nonce uint64) (*types.Transaction, error) {
gasTipCap, err := l.cfg.L1Client.SuggestGasTipCap(ctx)
const networkTimeout = 2 * time.Second // How long a single network request can take. TODO: put in a config somewhere
// TransactionManager wraps the simple txmgr package to make it easy to send & wait for transactions
type TransactionManager struct {
// Config
batchInboxAddress common.Address
senderAddress common.Address
chainID *big.Int
// Outside world
txMgr txmgr.TxManager
l1Client *ethclient.Client
signerFn func(types.TxData) (*types.Transaction, error)
log log.Logger
}
func NewTransactionManger(log log.Logger, txMgrConfg txmgr.Config, batchInboxAddress common.Address, chainID *big.Int, privKey *ecdsa.PrivateKey, l1Client *ethclient.Client) *TransactionManager {
signerFn := func(rawTx types.TxData) (*types.Transaction, error) {
return types.SignNewTx(privKey, types.LatestSignerForChainID(chainID), rawTx)
}
t := &TransactionManager{
batchInboxAddress: batchInboxAddress,
senderAddress: crypto.PubkeyToAddress(privKey.PublicKey),
chainID: chainID,
txMgr: txmgr.NewSimpleTxManager("batcher", txMgrConfg, l1Client),
l1Client: l1Client,
signerFn: signerFn,
log: log,
}
return t
}
// SendTransaction creates & submits a transaction to the batch inbox address with the given `data`.
// It currently uses the underlying `txmgr` to handle transaction sending & price management.
// This is a blocking method. It should not be called concurrently.
// TODO: where to put concurrent transaction handling logic.
func (t *TransactionManager) SendTransaction(ctx context.Context, data []byte) (*types.Receipt, error) {
tx, err := t.CraftTx(ctx, data)
if err != nil {
return nil, fmt.Errorf("failed to create tx: %w", err)
}
// Construct a closure that will update the txn with the current gas prices.
updateGasPrice := func(ctx context.Context) (*types.Transaction, error) {
return t.UpdateGasPrice(ctx, tx)
}
ctx, cancel := context.WithTimeout(ctx, 100*time.Second) // TODO: Select a timeout that makes sense here.
defer cancel()
if receipt, err := t.txMgr.Send(ctx, updateGasPrice, t.l1Client.SendTransaction); err != nil {
t.log.Warn("unable to publish tx", "err", err)
return nil, err
} else {
t.log.Info("tx successfully published", "tx_hash", receipt.TxHash)
return receipt, nil
}
}
// calcGasTipAndFeeCap queries L1 to determine what a suitable miner tip & basefee limit would be for timely inclusion
func (t *TransactionManager) calcGasTipAndFeeCap(ctx context.Context) (gasTipCap *big.Int, gasFeeCap *big.Int, err error) {
childCtx, cancel := context.WithTimeout(ctx, networkTimeout)
gasTipCap, err = t.l1Client.SuggestGasTipCap(childCtx)
cancel()
if err != nil {
return nil, nil, fmt.Errorf("failed to get suggested gas tip cap: %w", err)
}
head, err := l.cfg.L1Client.HeaderByNumber(ctx, nil)
childCtx, cancel = context.WithTimeout(ctx, networkTimeout)
head, err := t.l1Client.HeaderByNumber(childCtx, nil)
cancel()
if err != nil {
return nil, nil, fmt.Errorf("failed to get L1 head block for fee cap: %w", err)
}
gasFeeCap = txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap)
return gasTipCap, gasFeeCap, nil
}
// CraftTx creates the signed transaction to the batchInboxAddress.
// It queries L1 for the current fee market conditions as well as for the nonce.
// NOTE: This method SHOULD NOT publish the resulting transaction.
func (t *TransactionManager) CraftTx(ctx context.Context, data []byte) (*types.Transaction, error) {
gasTipCap, gasFeeCap, err := t.calcGasTipAndFeeCap(ctx)
if err != nil {
return nil, err
}
gasFeeCap := txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap)
ctx, cancel := context.WithTimeout(ctx, networkTimeout)
nonce, err := t.l1Client.NonceAt(ctx, t.senderAddress, nil)
cancel()
if err != nil {
return nil, fmt.Errorf("failed to get nonce: %w", err)
}
rawTx := &types.DynamicFeeTx{
ChainID: l.cfg.ChainID,
ChainID: t.chainID,
Nonce: nonce,
To: &l.cfg.BatchInboxAddress,
To: &t.batchInboxAddress,
GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap,
Data: data,
}
l.log.Debug("creating tx", "to", rawTx.To, "from", crypto.PubkeyToAddress(l.cfg.PrivKey.PublicKey))
t.log.Info("creating tx", "to", rawTx.To, "from", t.senderAddress)
gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to calculate intrinsic gas: %w", err)
}
rawTx.Gas = gas
return types.SignNewTx(l.cfg.PrivKey, types.LatestSignerForChainID(l.cfg.ChainID), rawTx)
return t.signerFn(rawTx)
}
// UpdateGasPrice signs an otherwise identical txn to the one provided but with
// updated gas prices sampled from the existing network conditions.
//
// NOTE: Thie method SHOULD NOT publish the resulting transaction.
func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) {
gasTipCap, err := l.cfg.L1Client.SuggestGasTipCap(ctx)
if err != nil {
return nil, err
}
head, err := l.cfg.L1Client.HeaderByNumber(ctx, nil)
// NOTE: This method SHOULD NOT publish the resulting transaction.
func (t *TransactionManager) UpdateGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) {
gasTipCap, gasFeeCap, err := t.calcGasTipAndFeeCap(ctx)
if err != nil {
return nil, err
}
gasFeeCap := txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap)
rawTx := &types.DynamicFeeTx{
ChainID: l.cfg.ChainID,
ChainID: t.chainID,
Nonce: tx.Nonce(),
To: tx.To(),
GasTipCap: gasTipCap,
......@@ -68,12 +147,8 @@ func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transacti
Gas: tx.Gas(),
Data: tx.Data(),
}
// Only log the new tip/fee cap because the updateGasPrice closure reuses the same initial transaction
t.log.Trace("updating gas price", "tip_cap", gasTipCap, "fee_cap", gasFeeCap)
return types.SignNewTx(l.cfg.PrivKey, types.LatestSignerForChainID(l.cfg.ChainID), rawTx)
}
// SendTransaction injects a signed transaction into the pending pool for
// execution.
func (l *BatchSubmitter) SendTransaction(ctx context.Context, tx *types.Transaction) error {
return l.cfg.L1Client.SendTransaction(ctx, tx)
return t.signerFn(rawTx)
}
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const DeployerWhitelistStorageLayoutJSON = "{\"storage\":[{\"astId\":4098,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":4103,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"whitelist\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}"
const DeployerWhitelistStorageLayoutJSON = "{\"storage\":[{\"astId\":4092,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":4097,\"contract\":\"contracts/legacy/DeployerWhitelist.sol:DeployerWhitelist\",\"label\":\"whitelist\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}"
var DeployerWhitelistStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const GasPriceOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":29370,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1958,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_1_0_32\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1961,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_2_0_32\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1964,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint256\"},{\"astId\":1967,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_uint256\"},{\"astId\":1970,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"decimals\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_uint256\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
const GasPriceOracleStorageLayoutJSON = "{\"storage\":[{\"astId\":29364,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1958,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_1_0_32\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_uint256\"},{\"astId\":1961,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"spacer_2_0_32\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":1964,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"overhead\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_uint256\"},{\"astId\":1967,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"scalar\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_uint256\"},{\"astId\":1970,\"contract\":\"contracts/L2/GasPriceOracle.sol:GasPriceOracle\",\"label\":\"decimals\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_uint256\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var GasPriceOracleStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const GovernanceTokenStorageLayoutJSON = "{\"storage\":[{\"astId\":29720,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":29726,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":29728,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":29730,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":29732,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":31097,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_nonces\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_mapping(t_address,t_struct(Counter)33283_storage)\"},{\"astId\":31105,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_PERMIT_TYPEHASH_DEPRECATED_SLOT\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_bytes32\"},{\"astId\":30438,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_delegates\",\"offset\":0,\"slot\":\"7\",\"type\":\"t_mapping(t_address,t_address)\"},{\"astId\":30444,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_checkpoints\",\"offset\":0,\"slot\":\"8\",\"type\":\"t_mapping(t_address,t_array(t_struct(Checkpoint)30429_storage)dyn_storage)\"},{\"astId\":30448,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupplyCheckpoints\",\"offset\":0,\"slot\":\"9\",\"type\":\"t_array(t_struct(Checkpoint)30429_storage)dyn_storage\"},{\"astId\":29370,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"10\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_struct(Checkpoint)30429_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct ERC20Votes.Checkpoint[]\",\"numberOfBytes\":\"32\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_address)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e address)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_address\"},\"t_mapping(t_address,t_array(t_struct(Checkpoint)30429_storage)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct ERC20Votes.Checkpoint[])\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_array(t_struct(Checkpoint)30429_storage)dyn_storage\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_struct(Counter)33283_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct Counters.Counter)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_struct(Counter)33283_storage\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_struct(Checkpoint)30429_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ERC20Votes.Checkpoint\",\"numberOfBytes\":\"32\"},\"t_struct(Counter)33283_storage\":{\"encoding\":\"inplace\",\"label\":\"struct Counters.Counter\",\"numberOfBytes\":\"32\"},\"t_uint224\":{\"encoding\":\"inplace\",\"label\":\"uint224\",\"numberOfBytes\":\"28\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"}}}"
const GovernanceTokenStorageLayoutJSON = "{\"storage\":[{\"astId\":29714,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":29720,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":29722,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":29724,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":29726,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":31091,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_nonces\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_mapping(t_address,t_struct(Counter)33277_storage)\"},{\"astId\":31099,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_PERMIT_TYPEHASH_DEPRECATED_SLOT\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_bytes32\"},{\"astId\":30432,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_delegates\",\"offset\":0,\"slot\":\"7\",\"type\":\"t_mapping(t_address,t_address)\"},{\"astId\":30438,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_checkpoints\",\"offset\":0,\"slot\":\"8\",\"type\":\"t_mapping(t_address,t_array(t_struct(Checkpoint)30423_storage)dyn_storage)\"},{\"astId\":30442,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_totalSupplyCheckpoints\",\"offset\":0,\"slot\":\"9\",\"type\":\"t_array(t_struct(Checkpoint)30423_storage)dyn_storage\"},{\"astId\":29364,\"contract\":\"contracts/L2/GovernanceToken.sol:GovernanceToken\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"10\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_struct(Checkpoint)30423_storage)dyn_storage\":{\"encoding\":\"dynamic_array\",\"label\":\"struct ERC20Votes.Checkpoint[]\",\"numberOfBytes\":\"32\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_address,t_address)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e address)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_address\"},\"t_mapping(t_address,t_array(t_struct(Checkpoint)30423_storage)dyn_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct ERC20Votes.Checkpoint[])\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_array(t_struct(Checkpoint)30423_storage)dyn_storage\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_struct(Counter)33277_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e struct Counters.Counter)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_struct(Counter)33277_storage\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_struct(Checkpoint)30423_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ERC20Votes.Checkpoint\",\"numberOfBytes\":\"32\"},\"t_struct(Counter)33277_storage\":{\"encoding\":\"inplace\",\"label\":\"struct Counters.Counter\",\"numberOfBytes\":\"32\"},\"t_uint224\":{\"encoding\":\"inplace\",\"label\":\"uint224\",\"numberOfBytes\":\"28\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint32\":{\"encoding\":\"inplace\",\"label\":\"uint32\",\"numberOfBytes\":\"4\"}}}"
var GovernanceTokenStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const L1CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":25754,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":28747,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":28750,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":29361,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":28619,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":28739,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":28912,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":29017,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":29032,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":29076,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":25806,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25811,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25816,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25819,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":25822,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":25827,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25832,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint240\":{\"encoding\":\"inplace\",\"label\":\"uint240\",\"numberOfBytes\":\"30\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
const L1CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":25748,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":28741,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":28744,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":29355,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":28613,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":28733,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":28906,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":29011,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":29026,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":29070,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":25800,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25805,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25810,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25813,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":25816,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":25821,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25826,\"contract\":\"contracts/L1/L1CrossDomainMessenger.sol:L1CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint240\":{\"encoding\":\"inplace\",\"label\":\"uint240\",\"numberOfBytes\":\"30\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var L1CrossDomainMessengerStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const L2CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":25754,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":28747,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":28750,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":29361,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":28619,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":28739,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":28912,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":29017,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":29032,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":29076,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":25806,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25811,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25816,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25819,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":25822,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":25827,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25832,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint240\":{\"encoding\":\"inplace\",\"label\":\"uint240\",\"numberOfBytes\":\"30\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
const L2CrossDomainMessengerStorageLayoutJSON = "{\"storage\":[{\"astId\":25748,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":28741,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initialized\",\"offset\":20,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":28744,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_initializing\",\"offset\":21,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":29355,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_array(t_uint256)50_storage\"},{\"astId\":28613,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_owner\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_address\"},{\"astId\":28733,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"52\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":28906,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_paused\",\"offset\":0,\"slot\":\"101\",\"type\":\"t_bool\"},{\"astId\":29011,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"102\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":29026,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"_status\",\"offset\":0,\"slot\":\"151\",\"type\":\"t_uint256\"},{\"astId\":29070,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"152\",\"type\":\"t_array(t_uint256)49_storage\"},{\"astId\":25800,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_201_0_32\",\"offset\":0,\"slot\":\"201\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25805,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"spacer_202_0_32\",\"offset\":0,\"slot\":\"202\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25810,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"successfulMessages\",\"offset\":0,\"slot\":\"203\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25813,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"xDomainMsgSender\",\"offset\":0,\"slot\":\"204\",\"type\":\"t_address\"},{\"astId\":25816,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"msgNonce\",\"offset\":0,\"slot\":\"205\",\"type\":\"t_uint240\"},{\"astId\":25821,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"receivedMessages\",\"offset\":0,\"slot\":\"206\",\"type\":\"t_mapping(t_bytes32,t_bool)\"},{\"astId\":25826,\"contract\":\"contracts/L2/L2CrossDomainMessenger.sol:L2CrossDomainMessenger\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"207\",\"type\":\"t_array(t_uint256)42_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)42_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[42]\",\"numberOfBytes\":\"1344\"},\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_array(t_uint256)50_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[50]\",\"numberOfBytes\":\"1600\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_uint240\":{\"encoding\":\"inplace\",\"label\":\"uint240\",\"numberOfBytes\":\"30\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var L2CrossDomainMessengerStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const L2ERC721BridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":26267,\"contract\":\"contracts/L2/L2ERC721Bridge.sol:L2ERC721Bridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_array(t_uint256)49_storage\"}],\"types\":{\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
const L2ERC721BridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":26231,\"contract\":\"contracts/L2/L2ERC721Bridge.sol:L2ERC721Bridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_array(t_uint256)49_storage\"}],\"types\":{\"t_array(t_uint256)49_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[49]\",\"numberOfBytes\":\"1568\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var L2ERC721BridgeStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const L2StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":27920,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27923,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":27930,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":27935,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
const L2StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":27914,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27917,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":27924,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":27929,\"contract\":\"contracts/L2/L2StandardBridge.sol:L2StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var L2StandardBridgeStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":29720,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":29726,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":29728,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":29730,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":29732,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":26496,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"remoteToken\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_address\"},{\"astId\":26499,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"bridge\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
const LegacyERC20ETHStorageLayoutJSON = "{\"storage\":[{\"astId\":29714,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_balances\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_uint256)\"},{\"astId\":29720,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_allowances\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":29722,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_totalSupply\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_uint256\"},{\"astId\":29724,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_name\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_string_storage\"},{\"astId\":29726,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"_symbol\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_string_storage\"},{\"astId\":26490,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"remoteToken\",\"offset\":0,\"slot\":\"5\",\"type\":\"t_address\"},{\"astId\":26493,\"contract\":\"contracts/legacy/LegacyERC20ETH.sol:LegacyERC20ETH\",\"label\":\"bridge\",\"offset\":0,\"slot\":\"6\",\"type\":\"t_address\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
var LegacyERC20ETHStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const LegacyMessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":4741,\"contract\":\"contracts/legacy/LegacyMessagePasser.sol:LegacyMessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"}}}"
const LegacyMessagePasserStorageLayoutJSON = "{\"storage\":[{\"astId\":4735,\"contract\":\"contracts/legacy/LegacyMessagePasser.sol:LegacyMessagePasser\",\"label\":\"sentMessages\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"}}}"
var LegacyMessagePasserStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const OptimismMintableERC721FactoryStorageLayoutJSON = "{\"storage\":[{\"astId\":27019,\"contract\":\"contracts/universal/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory\",\"label\":\"isOptimismMintableERC721\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}"
const OptimismMintableERC721FactoryStorageLayoutJSON = "{\"storage\":[{\"astId\":27004,\"contract\":\"contracts/universal/OptimismMintableERC721Factory.sol:OptimismMintableERC721Factory\",\"label\":\"isOptimismMintableERC721\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_mapping(t_address,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_bool\"}}}"
var OptimismMintableERC721FactoryStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":29560,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":29563,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1608,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1578_storage\"},{\"astId\":1613,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)48_storage\"},{\"astId\":1179,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":1192,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1578_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
const OptimismPortalStorageLayoutJSON = "{\"storage\":[{\"astId\":29554,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":29557,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1608,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"params\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_struct(ResourceParams)1578_storage\"},{\"astId\":1613,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_array(t_uint256)48_storage\"},{\"astId\":1179,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"l2Sender\",\"offset\":0,\"slot\":\"50\",\"type\":\"t_address\"},{\"astId\":1192,\"contract\":\"contracts/L1/OptimismPortal.sol:OptimismPortal\",\"label\":\"finalizedWithdrawals\",\"offset\":0,\"slot\":\"51\",\"type\":\"t_mapping(t_bytes32,t_bool)\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)48_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[48]\",\"numberOfBytes\":\"1536\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_bytes32\":{\"encoding\":\"inplace\",\"label\":\"bytes32\",\"numberOfBytes\":\"32\"},\"t_mapping(t_bytes32,t_bool)\":{\"encoding\":\"mapping\",\"label\":\"mapping(bytes32 =\u003e bool)\",\"numberOfBytes\":\"32\",\"key\":\"t_bytes32\",\"value\":\"t_bool\"},\"t_struct(ResourceParams)1578_storage\":{\"encoding\":\"inplace\",\"label\":\"struct ResourceMetering.ResourceParams\",\"numberOfBytes\":\"32\"},\"t_uint128\":{\"encoding\":\"inplace\",\"label\":\"uint128\",\"numberOfBytes\":\"16\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint64\":{\"encoding\":\"inplace\",\"label\":\"uint64\",\"numberOfBytes\":\"8\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var OptimismPortalStorageLayout = new(solc.StorageLayout)
......
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const ProxyAdminStorageLayoutJSON = "{\"storage\":[{\"astId\":36820,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27392,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"proxyType\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_enum(ProxyType)27386)\"},{\"astId\":27397,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"implementationName\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_string_storage)\"},{\"astId\":27401,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"addressManager\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_contract(AddressManager)4088\"},{\"astId\":27405,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"upgrading\",\"offset\":20,\"slot\":\"3\",\"type\":\"t_bool\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(AddressManager)4088\":{\"encoding\":\"inplace\",\"label\":\"contract AddressManager\",\"numberOfBytes\":\"20\"},\"t_enum(ProxyType)27386\":{\"encoding\":\"inplace\",\"label\":\"enum ProxyAdmin.ProxyType\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_enum(ProxyType)27386)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e enum ProxyAdmin.ProxyType)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_enum(ProxyType)27386\"},\"t_mapping(t_address,t_string_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e string)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_string_storage\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"}}}"
const ProxyAdminStorageLayoutJSON = "{\"storage\":[{\"astId\":36814,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"owner\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":27386,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"proxyType\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_mapping(t_address,t_enum(ProxyType)27380)\"},{\"astId\":27391,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"implementationName\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_string_storage)\"},{\"astId\":27395,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"addressManager\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_contract(AddressManager)4082\"},{\"astId\":27399,\"contract\":\"contracts/universal/ProxyAdmin.sol:ProxyAdmin\",\"label\":\"upgrading\",\"offset\":20,\"slot\":\"3\",\"type\":\"t_bool\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(AddressManager)4082\":{\"encoding\":\"inplace\",\"label\":\"contract AddressManager\",\"numberOfBytes\":\"20\"},\"t_enum(ProxyType)27380\":{\"encoding\":\"inplace\",\"label\":\"enum ProxyAdmin.ProxyType\",\"numberOfBytes\":\"1\"},\"t_mapping(t_address,t_enum(ProxyType)27380)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e enum ProxyAdmin.ProxyType)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_enum(ProxyType)27380\"},\"t_mapping(t_address,t_string_storage)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e string)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_string_storage\"},\"t_string_storage\":{\"encoding\":\"bytes\",\"label\":\"string\",\"numberOfBytes\":\"32\"}}}"
var ProxyAdminStorageLayout = new(solc.StorageLayout)
......
......@@ -8,12 +8,12 @@ import (
"strings"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/mattn/go-isatty"
......@@ -84,28 +84,28 @@ func main() {
return err
}
ovmAddresses, err := genesis.NewAddresses(ctx.String("ovm-addresses"))
ovmAddresses, err := migration.NewAddresses(ctx.String("ovm-addresses"))
if err != nil {
return err
}
evmAddresess, err := genesis.NewAddresses(ctx.String("evm-addresses"))
evmAddresess, err := migration.NewAddresses(ctx.String("evm-addresses"))
if err != nil {
return err
}
ovmAllowances, err := genesis.NewAllowances(ctx.String("ovm-allowances"))
ovmAllowances, err := migration.NewAllowances(ctx.String("ovm-allowances"))
if err != nil {
return err
}
ovmMessages, err := genesis.NewSentMessage(ctx.String("ovm-messages"))
ovmMessages, err := migration.NewSentMessage(ctx.String("ovm-messages"))
if err != nil {
return err
}
evmMessages, err := genesis.NewSentMessage(ctx.String("evm-messages"))
evmMessages, err := migration.NewSentMessage(ctx.String("evm-messages"))
if err != nil {
return err
}
migrationData := genesis.MigrationData{
migrationData := migration.MigrationData{
OvmAddresses: ovmAddresses,
EvmAddresses: evmAddresess,
OvmAllowances: ovmAllowances,
......@@ -143,18 +143,6 @@ func main() {
return err
}
hash := rawdb.ReadHeadHeaderHash(ldb)
if err != nil {
return err
}
num := rawdb.ReadHeaderNumber(ldb, hash)
header := rawdb.ReadHeader(ldb, hash, *num)
sdb, err := state.New(header.Root, state.NewDatabase(ldb), nil)
if err != nil {
return err
}
// Get the addresses from the hardhat deploy artifacts
l1StandardBridgeProxyDeployment, err := hh.GetDeployment("Proxy__OVM_L1StandardBridge")
if err != nil {
......@@ -176,20 +164,10 @@ func main() {
L1ERC721BridgeProxy: l1ERC721BridgeProxyDeployment.Address,
}
if err := genesis.MigrateDB(sdb, config, block, &l2Addrs, &migrationData); err != nil {
return err
}
if ctx.Bool("dry-run") {
log.Info("Dry run complete")
return nil
}
root, err := sdb.Commit(true)
if err != nil {
dryRun := ctx.Bool("dry-run")
if err := genesis.MigrateDB(ldb, config, block, &l2Addrs, &migrationData, !dryRun); err != nil {
return err
}
log.Info("Migration complete", "root", root)
return nil
},
......
......@@ -8,8 +8,8 @@ import (
"io"
"strings"
l2grawdb "github.com/ethereum-optimism/optimism/l2geth/core/rawdb"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
)
......@@ -31,8 +31,8 @@ type AllowanceCB func(owner, spender common.Address) error
// IterateDBAddresses iterates over each address in Geth's address
// preimage database, calling the callback with the address.
func IterateDBAddresses(inDB ethdb.Database, cb AddressCB) error {
iter := inDB.NewIterator(AddressPreimagePrefix, nil)
func IterateDBAddresses(db ethdb.Database, cb AddressCB) error {
iter := db.NewIterator(AddressPreimagePrefix, nil)
for iter.Next() {
if iter.Error() != nil {
return iter.Error()
......@@ -98,10 +98,10 @@ func IterateAllowanceList(r io.Reader, cb AllowanceCB) error {
// IterateMintEvents iterates over each mint event in the database starting
// from head and stopping at genesis.
func IterateMintEvents(inDB ethdb.Database, headNum uint64, cb AddressCB) error {
func IterateMintEvents(db ethdb.Database, headNum uint64, cb AddressCB) error {
for headNum > 0 {
hash := l2grawdb.ReadCanonicalHash(inDB, headNum)
receipts := l2grawdb.ReadRawReceipts(inDB, hash, headNum)
hash := rawdb.ReadCanonicalHash(db, headNum)
receipts := rawdb.ReadRawReceipts(db, hash, headNum)
for _, receipt := range receipts {
for _, l := range receipt.Logs {
if common.BytesToHash(l.Topics[0].Bytes()) != MintTopic {
......
This diff is collapsed.
package ether
import (
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
func MigrateLegacyETH(db ethdb.Database, addresses []common.Address, allowances []*migration.Allowance, chainID int) error {
// Set of addresses that we will be migrating.
addressesToMigrate := make(map[common.Address]bool)
// Set of storage slots that we expect to see in the OVM ETH contract.
storageSlotsToMigrate := make(map[common.Hash]int)
// Chain params to use for integrity checking.
params := ParamsByChainID[chainID]
// Iterate over each address list, and read the addresses they
// contain into memory. Also calculate the storage slots for each
// address.
for _, addr := range addresses {
addressesToMigrate[addr] = true
storageSlotsToMigrate[CalcOVMETHStorageKey(addr)] = 1
}
for _, allowance := range allowances {
addressesToMigrate[allowance.From] = true
// TODO: double check ordering here
storageSlotsToMigrate[CalcAllowanceStorageKey(allowance.From, allowance.To)] = 2
}
headBlock := rawdb.ReadHeadBlock(db)
root := headBlock.Root()
// Read mint events from the database. Even though Geth's balance methods
// are instrumented, mints from the bridge happen in the EVM and so do
// not execute that code path. As a result, we parse mint events in order
// to not miss any balances.
log.Info("reading mint events from DB")
logProgress := ProgressLogger(100, "read mint event")
err := IterateMintEvents(db, headBlock.NumberU64(), func(address common.Address) error {
addressesToMigrate[address] = true
storageSlotsToMigrate[CalcOVMETHStorageKey(address)] = 1
logProgress()
return nil
})
if err != nil {
return wrapErr(err, "error reading mint events")
}
// Make sure all addresses are accounted for by iterating over
// the OVM ETH contract's state, and panicking if we miss
// any storage keys. We also keep track of the total amount of
// OVM ETH found, and diff that against the total supply of
// OVM ETH specified in the contract.
backingStateDB := state.NewDatabase(db)
stateDB, err := state.New(root, backingStateDB, nil)
if err != nil {
return wrapErr(err, "error opening state DB")
}
storageTrie := stateDB.StorageTrie(OVMETHAddress)
storageIt := trie.NewIterator(storageTrie.NodeIterator(nil))
logProgress = ProgressLogger(10000, "iterating storage keys")
totalFound := new(big.Int)
totalSupply := getOVMETHTotalSupply(stateDB)
for storageIt.Next() {
_, content, _, err := rlp.Split(storageIt.Value)
if err != nil {
panic(err)
}
k := common.BytesToHash(storageTrie.GetKey(storageIt.Key))
v := common.BytesToHash(content)
sType := storageSlotsToMigrate[k]
switch sType {
case 1:
// This slot is a balance, increment totalFound.
totalFound = totalFound.Add(totalFound, v.Big())
case 2:
// This slot is an allowance, ignore it.
continue
default:
slot := new(big.Int).SetBytes(k.Bytes())
// Check if this slot is a variable. If it isn't, and it isn't a
// known missing key, abort
if slot.Cmp(maxSlot) == 1 && !params.KnownMissingKeys[k] {
log.Crit("missed storage key", "k", k.String(), "v", v.String())
}
}
logProgress()
}
// Verify that the total supply is what we expect. We allow a hardcoded
// delta to be specified in the chain params since older regenesis events
// had supply bugs.
delta := new(big.Int).Set(totalSupply)
delta = delta.Sub(delta, totalFound)
if delta.Cmp(params.ExpectedSupplyDelta) != 0 {
log.Crit(
"supply mismatch",
"migrated", totalFound,
"supply", totalSupply,
"delta", delta,
"exp_delta", params.ExpectedSupplyDelta,
)
}
log.Info(
"supply verified OK",
"migrated", totalFound.String(),
"supply", totalSupply.String(),
"delta", delta.String(),
"exp_delta", params.ExpectedSupplyDelta,
)
log.Info("performing migration")
log.Info("trie dumping started", "root", root)
tr, err := backingStateDB.OpenTrie(root)
if err != nil {
return err
}
it := trie.NewIterator(tr.NodeIterator(nil))
totalMigrated := new(big.Int)
logAccountProgress := ProgressLogger(1000, "imported accounts")
migratedAccounts := make(map[common.Address]bool)
for it.Next() {
// It's up to us to decode trie data.
var data types.StateAccount
if err := rlp.DecodeBytes(it.Value, &data); err != nil {
panic(err)
}
addrBytes := tr.GetKey(it.Key)
addr := common.BytesToAddress(addrBytes)
migratedAccounts[addr] = true
// Get the OVM ETH balance based on the address's storage key.
ovmBalance := getOVMETHBalance(stateDB, addr)
// No accounts should have a balance in state. If they do, bail.
if data.Balance.Sign() > 0 {
log.Crit("account has non-zero balance in state - should never happen", "addr", addr)
}
// Actually perform the migration by setting the appropriate values in state.
stateDB.SetBalance(addr, ovmBalance)
stateDB.SetState(predeploys.LegacyERC20ETHAddr, CalcOVMETHStorageKey(addr), common.Hash{})
// Bump the total OVM balance.
totalMigrated = totalMigrated.Add(totalMigrated, ovmBalance)
logAccountProgress()
}
// Take care of nonce zero accounts with balances. These are accounts
// that received OVM ETH as part of the regenesis, but never actually
// transacted on-chain.
logNonceZeroProgress := ProgressLogger(1000, "imported zero nonce accounts")
log.Info("importing accounts with zero-nonce balances")
for addr := range addressesToMigrate {
if migratedAccounts[addr] {
continue
}
ovmBalance := getOVMETHBalance(stateDB, addr)
totalMigrated = totalMigrated.Add(totalMigrated, ovmBalance)
stateDB.AddBalance(addr, ovmBalance)
stateDB.SetState(predeploys.LegacyERC20ETHAddr, CalcOVMETHStorageKey(addr), common.Hash{})
logNonceZeroProgress()
}
// Make sure that the amount we migrated matches the amount in
// our original state.
if totalMigrated.Cmp(totalFound) != 0 {
log.Crit(
"total migrated does not equal total OVM eth found",
"migrated", totalMigrated,
"found", totalFound,
)
}
// Set the total supply to 0
stateDB.SetState(predeploys.LegacyERC20ETHAddr, getOVMETHTotalSupplySlot(), common.Hash{})
return nil
}
......@@ -30,7 +30,6 @@ type DeployConfig struct {
SequencerWindowSize uint64 `json:"sequencerWindowSize"`
ChannelTimeout uint64 `json:"channelTimeout"`
P2PSequencerAddress common.Address `json:"p2pSequencerAddress"`
OptimismL2FeeRecipient common.Address `json:"optimismL2FeeRecipient"`
BatchInboxAddress common.Address `json:"batchInboxAddress"`
BatchSenderAddress common.Address `json:"batchSenderAddress"`
......
package genesis
import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum-optimism/optimism/op-chain-ops/ether"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/trie"
)
var abiTrue = common.Hash{31: 0x01}
// MigrateDB will migrate an old l2geth database to the new bedrock style system
func MigrateDB(db vm.StateDB, config *DeployConfig, l1Block *types.Block, l2Addrs *L2Addresses, migrationData *MigrationData) error {
func MigrateDB(ldb ethdb.Database, config *DeployConfig, l1Block *types.Block, l2Addrs *L2Addresses, migrationData *migration.MigrationData, commit bool) error {
hash := rawdb.ReadHeadHeaderHash(ldb)
num := rawdb.ReadHeaderNumber(ldb, hash)
header := rawdb.ReadHeader(ldb, hash, *num)
db, err := state.New(header.Root, state.NewDatabase(ldb), nil)
if err != nil {
return err
}
// Convert all of the messages into legacy withdrawals
withdrawals, err := migrationData.ToWithdrawals()
if err != nil {
return err
}
if err := CheckWithdrawals(db, withdrawals); err != nil {
return err
}
// Now start the migration
if err := SetL2Proxies(db); err != nil {
return err
}
......@@ -26,28 +59,97 @@ func MigrateDB(db vm.StateDB, config *DeployConfig, l1Block *types.Block, l2Addr
return err
}
// Convert all of the messages into legacy withdrawals
messages := make([]*crossdomain.LegacyWithdrawal, 0)
for _, msg := range migrationData.OvmMessages {
wd, err := msg.ToLegacyWithdrawal()
err = crossdomain.MigrateWithdrawals(withdrawals, db, &l2Addrs.L1CrossDomainMessengerProxy, &l2Addrs.L1StandardBridgeProxy)
if err != nil {
return err
}
messages = append(messages, wd)
addrs := migrationData.Addresses()
if err := ether.MigrateLegacyETH(ldb, addrs, migrationData.OvmAllowances, int(config.L1ChainID)); err != nil {
return err
}
if !commit {
return nil
}
for _, msg := range migrationData.EvmMessages {
wd, err := msg.ToLegacyWithdrawal()
root, err := db.Commit(true)
if err != nil {
return err
}
messages = append(messages, wd)
// Create the bedrock transition block
bedrockHeader := &types.Header{
ParentHash: header.Hash(),
UncleHash: types.EmptyUncleHash,
Coinbase: config.L2GenesisBlockCoinbase,
Root: root,
TxHash: types.EmptyRootHash,
ReceiptHash: types.EmptyRootHash,
Bloom: types.Bloom{},
Difficulty: (*big.Int)(config.L2GenesisBlockDifficulty),
Number: new(big.Int).Add(header.Number, common.Big1),
GasLimit: (uint64)(config.L2GenesisBlockGasLimit),
GasUsed: (uint64)(config.L2GenesisBlockGasUsed),
Time: uint64(config.L2OutputOracleStartingTimestamp),
Extra: config.L2GenesisBlockExtraData,
MixDigest: config.L2GenesisBlockMixHash,
Nonce: types.EncodeNonce((uint64)(config.L1GenesisBlockNonce)),
BaseFee: (*big.Int)(config.L2GenesisBlockBaseFeePerGas),
}
if err := crossdomain.MigrateWithdrawals(messages, db, &l2Addrs.L1CrossDomainMessengerProxy, &l2Addrs.L1StandardBridgeProxy); err != nil {
block := types.NewBlock(bedrockHeader, nil, nil, nil, trie.NewStackTrie(nil))
rawdb.WriteTd(ldb, block.Hash(), block.NumberU64(), block.Difficulty())
rawdb.WriteBlock(ldb, block)
rawdb.WriteReceipts(ldb, block.Hash(), block.NumberU64(), nil)
rawdb.WriteCanonicalHash(ldb, block.Hash(), block.NumberU64())
rawdb.WriteHeadBlockHash(ldb, block.Hash())
rawdb.WriteHeadFastBlockHash(ldb, block.Hash())
rawdb.WriteHeadHeaderHash(ldb, block.Hash())
return nil
}
// CheckWithdrawals will ensure that the entire list of withdrawals is being
// operated on during the database migration.
func CheckWithdrawals(db vm.StateDB, withdrawals []*crossdomain.LegacyWithdrawal) error {
// Create a mapping of all of their storage slots
knownSlots := make(map[common.Hash]bool)
for _, wd := range withdrawals {
slot, err := wd.StorageSlot()
if err != nil {
return err
}
knownSlots[slot] = true
}
// Build a map of all the slots in the LegacyMessagePasser
slots := make(map[common.Hash]bool)
err := db.ForEachStorage(predeploys.LegacyMessagePasserAddr, func(key, value common.Hash) bool {
if value != abiTrue {
return false
}
slots[key] = true
return true
})
if err != nil {
return err
}
// TODO: use migration data to double check things
// Check that all of the slots from storage correspond to a known message
for slot := range slots {
_, ok := knownSlots[slot]
if !ok {
return fmt.Errorf("Unknown storage slot in state: %s", slot)
}
}
// Check that all of the input messages are legit
for slot := range knownSlots {
_, ok := slots[slot]
if !ok {
return fmt.Errorf("Unknown input message: %s", slot)
}
}
return nil
}
......@@ -52,8 +52,8 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true,
Optimism: &params.OptimismConfig{
L1FeeRecipient: config.OptimismL1FeeRecipient,
BaseFeeRecipient: config.OptimismBaseFeeRecipient,
L1FeeRecipient: config.OptimismL2FeeRecipient,
EIP1559Denominator: eip1559Denom,
EIP1559Elasticity: eip1559Elasticity,
},
......
package genesis
package migration
import (
"encoding/json"
......@@ -116,3 +116,36 @@ type MigrationData struct {
// L2CrossDomainMessenger from after the evm equivalence upgrade
EvmMessages []*SentMessage
}
func (m *MigrationData) ToWithdrawals() ([]*crossdomain.LegacyWithdrawal, error) {
messages := make([]*crossdomain.LegacyWithdrawal, 0)
for _, msg := range m.OvmMessages {
wd, err := msg.ToLegacyWithdrawal()
if err != nil {
return nil, err
}
messages = append(messages, wd)
if err != nil {
return nil, err
}
}
for _, msg := range m.EvmMessages {
wd, err := msg.ToLegacyWithdrawal()
if err != nil {
return nil, err
}
messages = append(messages, wd)
}
return messages, nil
}
func (m *MigrationData) Addresses() []common.Address {
addresses := make([]common.Address, 0)
for addr := range m.EvmAddresses {
addresses = append(addresses, addr)
}
for addr := range m.EvmAddresses {
addresses = append(addresses, addr)
}
return addresses
}
......@@ -8,7 +8,6 @@
"sequencerWindowSize": 4,
"channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
......
......@@ -7,7 +7,6 @@
"sequencerWindowSize": 100,
"channelTimeout": 30,
"p2pSequencerAddress": "0x0000000000000000000000000000000000000000",
"optimismL2FeeRecipient": "0x42000000000000000000000000000000000000f0",
"batchInboxAddress": "0x42000000000000000000000000000000000000ff",
"batchSenderAddress": "0x0000000000000000000000000000000000000000",
"l2OutputOracleSubmissionInterval": 6,
......
......@@ -3,7 +3,6 @@ module github.com/ethereum-optimism/optimism/op-chain-ops
go 1.18
require (
github.com/ethereum-optimism/optimism/l2geth v0.0.0-20220820030939-de38b6f6f77e
github.com/ethereum-optimism/optimism/op-bindings v0.8.10
github.com/ethereum/go-ethereum v1.10.23
github.com/holiman/uint256 v1.2.0
......@@ -16,45 +15,35 @@ require (
require (
github.com/VictoriaMetrics/fastcache v1.9.0 // indirect
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 // indirect
github.com/btcsuite/btcd v0.22.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect
github.com/elastic/gosigar v0.12.0 // indirect
github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/hashicorp/go-bexpr v0.1.11 // indirect
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/tsdb v0.10.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/rjeczalik/notify v0.9.2 // indirect
github.com/rogpeppe/go-internal v1.8.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // indirect
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 // indirect
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 // indirect
github.com/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect
golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1 // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
......
This diff is collapsed.
......@@ -177,8 +177,16 @@ func (s *L1Replica) L1Client(t Testing, cfg *rollup.Config) *sources.L1Client {
// ActL1FinalizeNext finalizes the next block, which must be marked as safe before doing so (see ActL1SafeNext).
func (s *L1Replica) ActL1FinalizeNext(t Testing) {
safe := s.l1Chain.CurrentSafeBlock()
finalizedNum := s.l1Chain.CurrentFinalizedBlock().NumberU64()
if safe.NumberU64() <= finalizedNum {
safeNum := uint64(0)
if safe != nil {
safeNum = safe.NumberU64()
}
finalized := s.l1Chain.CurrentFinalizedBlock()
finalizedNum := uint64(0)
if finalized != nil {
finalizedNum = finalized.NumberU64()
}
if safeNum <= finalizedNum {
t.InvalidAction("need to move forward safe block before moving finalized block")
return
}
......@@ -192,7 +200,11 @@ func (s *L1Replica) ActL1FinalizeNext(t Testing) {
// ActL1SafeNext marks the next unsafe block as safe.
func (s *L1Replica) ActL1SafeNext(t Testing) {
safe := s.l1Chain.CurrentSafeBlock()
next := s.l1Chain.GetBlockByNumber(safe.NumberU64() + 1)
safeNum := uint64(0)
if safe != nil {
safeNum = safe.NumberU64()
}
next := s.l1Chain.GetBlockByNumber(safeNum + 1)
if next == nil {
t.InvalidAction("if head of chain is marked as safe then there's no next block")
return
......
......@@ -7,15 +7,16 @@ import (
"io"
"math/big"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
)
type SyncStatusAPI interface {
......@@ -149,8 +150,8 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing) {
data.WriteByte(derive.DerivationVersion0)
// subtract one, to account for the version byte
if err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF {
s.l2ChannelOut = nil
s.l2Submitting = false
// there may still be some data to submit
} else if err != nil {
s.l2Submitting = false
t.Fatalf("failed to output channel data to frame: %v", err)
......
......@@ -4,12 +4,14 @@ import (
"math/big"
"testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testlog"
)
......@@ -87,3 +89,108 @@ func TestBatcher(gt *testing.T) {
require.False(t, isPending)
require.NotNil(t, vTx)
}
func TestL2Finalization(gt *testing.T) {
t := NewDefaultTesting(gt)
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams)
sd := e2eutils.Setup(t, dp, defaultAlloc)
log := testlog.Logger(t, log.LvlDebug)
miner, engine, sequencer := setupSequencerTest(t, sd, log)
sequencer.ActL2PipelineFull(t)
// build an empty L1 block (#1), mark it as justified
miner.ActEmptyBlock(t)
miner.ActL1SafeNext(t) // #0 -> #1
// sequencer builds L2 chain, up to and including a block that has the new L1 block as origin
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
sequencer.ActL2PipelineFull(t)
sequencer.ActL1SafeSignal(t)
require.Equal(t, uint64(1), sequencer.SyncStatus().SafeL1.Number)
// build another L1 block (#2), mark it as justified. And mark previous justified as finalized.
miner.ActEmptyBlock(t)
miner.ActL1SafeNext(t) // #1 -> #2
miner.ActL1FinalizeNext(t) // #0 -> #1
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
// continue to build L2 chain referencing the new L1 blocks
sequencer.ActL2PipelineFull(t)
sequencer.ActL1FinalizedSignal(t)
sequencer.ActL1SafeSignal(t)
require.Equal(t, uint64(2), sequencer.SyncStatus().SafeL1.Number)
require.Equal(t, uint64(1), sequencer.SyncStatus().FinalizedL1.Number)
require.Equal(t, uint64(0), sequencer.SyncStatus().FinalizedL2.Number, "L2 block has to be included on L1 before it can be finalized")
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{
MinL1TxSize: 0,
MaxL1TxSize: 128_000,
BatcherKey: dp.Secrets.Batcher,
}, sequencer.RollupClient(), miner.EthClient(), engine.EthClient())
heightToSubmit := sequencer.SyncStatus().UnsafeL2.Number
batcher.ActSubmitAll(t)
// confirm batch on L1, block #3
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.Batcher)(t)
miner.ActL1EndBlock(t)
// read the batch
sequencer.ActL2PipelineFull(t)
require.Equal(t, uint64(0), sequencer.SyncStatus().FinalizedL2.Number, "Batch must be included in finalized part of L1 chain for L2 block to finalize")
// build some more L2 blocks, so there is an unsafe part again that hasn't been submitted yet
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
// submit those blocks too, block #4
batcher.ActSubmitAll(t)
miner.ActL1StartBlock(12)(t)
miner.ActL1IncludeTx(dp.Addresses.Batcher)(t)
miner.ActL1EndBlock(t)
// add some more L1 blocks #5, #6
miner.ActEmptyBlock(t)
miner.ActEmptyBlock(t)
// and more unsafe L2 blocks
sequencer.ActL1HeadSignal(t)
sequencer.ActBuildToL1Head(t)
// move safe/finalize markers: finalize the L1 chain block with the first batch, but not the second
miner.ActL1SafeNext(t) // #2 -> #3
miner.ActL1SafeNext(t) // #3 -> #4
miner.ActL1FinalizeNext(t) // #1 -> #2
miner.ActL1FinalizeNext(t) // #2 -> #3
sequencer.ActL2PipelineFull(t)
sequencer.ActL1FinalizedSignal(t)
sequencer.ActL1SafeSignal(t)
sequencer.ActL1HeadSignal(t)
require.Equal(t, uint64(6), sequencer.SyncStatus().HeadL1.Number)
require.Equal(t, uint64(4), sequencer.SyncStatus().SafeL1.Number)
require.Equal(t, uint64(3), sequencer.SyncStatus().FinalizedL1.Number)
require.Equal(t, heightToSubmit, sequencer.SyncStatus().FinalizedL2.Number, "finalized L2 blocks in first batch")
// need to act with the engine on the signals still
sequencer.ActL2PipelineFull(t)
engCl := engine.EngineClient(t, sd.RollupCfg)
engBlock, err := engCl.L2BlockRefByLabel(t.Ctx(), eth.Finalized)
require.NoError(t, err)
require.Equal(t, heightToSubmit, engBlock.Number, "engine finalizes what rollup node finalizes")
// Now try to finalize block 4, but with a bad/malicious alternative hash.
// If we get this false signal, we shouldn't finalize the L2 chain.
altBlock4 := sequencer.SyncStatus().SafeL1
altBlock4.Hash = common.HexToHash("0xdead")
sequencer.derivation.Finalize(altBlock4)
sequencer.ActL2PipelineFull(t)
require.Equal(t, uint64(3), sequencer.SyncStatus().FinalizedL1.Number)
require.Equal(t, heightToSubmit, sequencer.SyncStatus().FinalizedL2.Number, "unknown/bad finalized L1 blocks are ignored")
}
......@@ -175,7 +175,7 @@ func (e *L2Engine) ActL2IncludeTx(from common.Address) Action {
e.l2GasPool, e.l2BuildingState, e.l2BuildingHeader, tx, &e.l2BuildingHeader.GasUsed, *e.l2Chain.GetVMConfig())
if err != nil {
e.l2TxFailed = append(e.l2TxFailed, tx)
t.Fatalf("failed to apply transaction to L1 block (tx %d): %v", len(e.l2Transactions), err)
t.Fatalf("failed to apply transaction to L2 block (tx %d): %v", len(e.l2Transactions), err)
}
e.l2Receipts = append(e.l2Receipts, receipt)
e.l2Transactions = append(e.l2Transactions, tx)
......
......@@ -119,6 +119,7 @@ func (s *L2Verifier) L2Unsafe() eth.L2BlockRef {
func (s *L2Verifier) SyncStatus() *eth.SyncStatus {
return &eth.SyncStatus{
CurrentL1: s.derivation.Origin(),
CurrentL1Finalized: s.derivation.FinalizedL1(),
HeadL1: s.l1State.L1Head(),
SafeL1: s.l1State.L1Safe(),
FinalizedL1: s.l1State.L1Finalized(),
......@@ -160,15 +161,16 @@ func (s *L2Verifier) ActL1HeadSignal(t Testing) {
}
func (s *L2Verifier) ActL1SafeSignal(t Testing) {
head, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Safe)
safe, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Safe)
require.NoError(t, err)
s.l1State.HandleNewL1SafeBlock(head)
s.l1State.HandleNewL1SafeBlock(safe)
}
func (s *L2Verifier) ActL1FinalizedSignal(t Testing) {
head, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Finalized)
finalized, err := s.l1.L1BlockRefByLabel(t.Ctx(), eth.Finalized)
require.NoError(t, err)
s.l1State.HandleNewL1FinalizedBlock(head)
s.l1State.HandleNewL1FinalizedBlock(finalized)
s.derivation.Finalize(finalized)
}
// ActL2PipelineStep runs one iteration of the L2 derivation pipeline
......
......@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
)
......@@ -41,7 +42,7 @@ func CollectAddresses(sd *SetupData, dp *DeployParams) (out []common.Address) {
sd.L1Cfg.Coinbase,
sd.L2Cfg.Coinbase,
sd.RollupCfg.P2PSequencerAddress,
sd.RollupCfg.FeeRecipientAddress,
predeploys.SequencerFeeVaultAddr,
sd.RollupCfg.BatchInboxAddress,
sd.RollupCfg.BatchSenderAddress,
sd.RollupCfg.DepositContractAddress,
......
......@@ -62,7 +62,6 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
SequencerWindowSize: tp.SequencerWindowSize,
ChannelTimeout: tp.ChannelTimeout,
P2PSequencerAddress: addresses.SequencerP2P,
OptimismL2FeeRecipient: common.Address{0: 0x42, 19: 0xf0}, // tbd
BatchInboxAddress: common.Address{0: 0x42, 19: 0xff}, // tbd
BatchSenderAddress: addresses.Batcher,
......@@ -89,7 +88,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
L2GenesisBlockGasLimit: 15_000_000,
L2GenesisBlockDifficulty: uint64ToBig(0),
L2GenesisBlockMixHash: common.Hash{},
L2GenesisBlockCoinbase: common.Address{0: 0x42, 19: 0xf0}, // matching OptimismL2FeeRecipient
L2GenesisBlockCoinbase: predeploys.SequencerFeeVaultAddr,
L2GenesisBlockNumber: 0,
L2GenesisBlockGasUsed: 0,
L2GenesisBlockParentHash: common.Hash{},
......@@ -201,7 +200,6 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
L1ChainID: new(big.Int).SetUint64(deployConf.L1ChainID),
L2ChainID: new(big.Int).SetUint64(deployConf.L2ChainID),
P2PSequencerAddress: deployConf.P2PSequencerAddress,
FeeRecipientAddress: deployConf.OptimismL2FeeRecipient,
BatchInboxAddress: deployConf.BatchInboxAddress,
BatchSenderAddress: deployConf.BatchSenderAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr,
......
......@@ -94,7 +94,6 @@ func DefaultSystemConfig(t *testing.T) SystemConfig {
OptimismBaseFeeRecipient: common.Address{0: 0x52, 19: 0xf0}, // tbd
OptimismL1FeeRecipient: common.Address{0: 0x52, 19: 0xf1},
OptimismL2FeeRecipient: common.Address{0: 0x52, 19: 0xf2}, // tbd
L2CrossDomainMessengerOwner: common.Address{0: 0x52, 19: 0xf3}, // tbd
GasPriceOracleOwner: addresses.Alice, // tbd
GasPriceOracleOverhead: 0,
......@@ -283,7 +282,6 @@ func (cfg SystemConfig) Start() (*System, error) {
L1ChainID: cfg.L1ChainIDBig(),
L2ChainID: cfg.L2ChainIDBig(),
P2PSequencerAddress: cfg.DeployConfig.P2PSequencerAddress,
FeeRecipientAddress: l2Genesis.Coinbase,
BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress,
BatchSenderAddress: cfg.DeployConfig.BatchSenderAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr,
......
......@@ -915,7 +915,7 @@ func TestFees(t *testing.T) {
// L1Fee Recipient
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil)
l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL1FeeRecipient, nil)
require.Nil(t, err)
// Simple transfer from signer to random account
......@@ -976,7 +976,7 @@ func TestFees(t *testing.T) {
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil)
l1FeeRecipientEndBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL1FeeRecipient, header.Number)
require.Nil(t, err)
// Diff fee recipient + coinbase balances
......
......@@ -193,7 +193,6 @@ func makeRollupConfig(
L1ChainID: new(big.Int).SetUint64(config.L1ChainID),
L2ChainID: new(big.Int).SetUint64(config.L2ChainID),
P2PSequencerAddress: config.P2PSequencerAddress,
FeeRecipientAddress: config.OptimismL2FeeRecipient,
BatchInboxAddress: config.BatchInboxAddress,
BatchSenderAddress: config.BatchSenderAddress,
DepositContractAddress: portalAddr,
......
......@@ -3,10 +3,18 @@ package eth
// SyncStatus is a snapshot of the driver.
// Values may be zeroed if not yet initialized.
type SyncStatus struct {
// CurrentL1 is the block that the derivation process is currently at,
// this may not be fully derived into L2 data yet.
// CurrentL1 is the L1 block that the derivation process is currently at in the inner-most stage.
// This may not be fully derived into L2 data yet.
// The safe L2 blocks were produced/included fully from the L1 chain up to and including this L1 block.
// If the node is synced, this matches the HeadL1, minus the verifier confirmation distance.
CurrentL1 L1BlockRef `json:"current_l1"`
// CurrentL1Finalized is the L1 block that the derivation process is currently accepting as finalized
// in the inner-most stage,
// This may not be fully derived into L2 data yet.
// The finalized L2 blocks were produced/included fully from the L1 chain up to and including this L1 block.
// This may lag behind the FinalizedL1 when the FinalizedL1 could not yet be verified
// to be canonical w.r.t. the currently derived L2 chain. It may be zeroed if no block could be verified yet.
CurrentL1Finalized L1BlockRef `json:"current_l1_finalized"`
// HeadL1 is the perceived head of the L1 chain, no confirmation distance.
// The head is not guaranteed to build on the other L1 sync status fields,
// as the node may be in progress of resetting to adapt to a L1 reorg.
......
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common"
......@@ -74,7 +75,7 @@ func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1Rece
return &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(timestamp),
PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: cfg.FeeRecipientAddress,
SuggestedFeeRecipient: predeploys.SequencerFeeVaultAddr,
Transactions: txs,
NoTxPool: true,
}, nil
......
......@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testlog"
......@@ -25,7 +26,6 @@ func TestAttributesQueue(t *testing.T) {
BlockTime: 2,
L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb},
}
rng := rand.New(rand.NewSource(1234))
......@@ -52,7 +52,7 @@ func TestAttributesQueue(t *testing.T) {
attrs := eth.PayloadAttributes{
Timestamp: eth.Uint64Quantity(safeHead.Time + cfg.BlockTime),
PrevRandao: eth.Bytes32(l1Info.InfoMixDigest),
SuggestedFeeRecipient: cfg.FeeRecipientAddress,
SuggestedFeeRecipient: predeploys.SequencerFeeVaultAddr,
Transactions: []eth.Data{l1InfoTx, eth.Data("foobar"), eth.Data("example")},
NoTxPool: true,
}
......
......@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testutils"
......@@ -23,7 +24,6 @@ func TestPreparePayloadAttributes(t *testing.T) {
BlockTime: 2,
L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb},
}
......@@ -99,7 +99,7 @@ func TestPreparePayloadAttributes(t *testing.T) {
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient)
require.Equal(t, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool)
......@@ -136,7 +136,7 @@ func TestPreparePayloadAttributes(t *testing.T) {
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient)
require.Equal(t, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs")
require.Equal(t, l2Txs, attrs.Transactions)
require.True(t, attrs.NoTxPool)
......@@ -161,7 +161,7 @@ func TestPreparePayloadAttributes(t *testing.T) {
require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao)
require.Equal(t, cfg.FeeRecipientAddress, attrs.SuggestedFeeRecipient)
require.Equal(t, predeploys.SequencerFeeVaultAddr, attrs.SuggestedFeeRecipient)
require.Equal(t, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool)
......
......@@ -72,7 +72,7 @@ type EngineQueue struct {
// This update may repeat if the engine returns a temporary error.
needForkchoiceUpdate bool
finalizedL1 eth.BlockID
finalizedL1 eth.L1BlockRef
safeAttributes []*eth.PayloadAttributes
unsafePayloads PayloadsQueue // queue of unsafe payloads, ordered by ascending block number, may have gaps
......@@ -83,7 +83,7 @@ type EngineQueue struct {
engine Engine
prev NextAttributesProvider
origin eth.L1BlockRef // only used for pipeline resets
origin eth.L1BlockRef // updated on resets, and whenever we read from the previous stage.
metrics Metrics
l1Fetcher L1Fetcher
......@@ -106,6 +106,7 @@ func NewEngineQueue(log log.Logger, cfg *rollup.Config, engine Engine, metrics M
}
}
// Origin identifies the L1 chain (incl.) that included and/or produced all the safe L2 blocks.
func (eq *EngineQueue) Origin() eth.L1BlockRef {
return eq.origin
}
......@@ -134,9 +135,28 @@ func (eq *EngineQueue) AddSafeAttributes(attributes *eth.PayloadAttributes) {
eq.safeAttributes = append(eq.safeAttributes, attributes)
}
func (eq *EngineQueue) Finalize(l1Origin eth.BlockID) {
func (eq *EngineQueue) Finalize(l1Origin eth.L1BlockRef) {
if l1Origin.Number < eq.finalizedL1.Number {
eq.log.Error("ignoring old L1 finalized block signal! Is the L1 provider corrupted?", "prev_finalized_l1", eq.finalizedL1, "signaled_finalized_l1", l1Origin)
return
}
// Perform a safety check: the L1 finalization signal is only accepted if we previously processed the L1 block.
// This prevents a corrupt L1 provider from tricking us in recognizing a L1 block inconsistent with the L1 chain we are on.
// Missing a finality signal due to empty buffer is fine, it will finalize when the buffer is filled again.
for _, fd := range eq.finalityData {
if fd.L1Block == l1Origin.ID() {
eq.finalizedL1 = l1Origin
eq.tryFinalizeL2()
return
}
}
eq.log.Warn("ignoring finalization signal for unknown L1 block, waiting for new L1 blocks in buffer", "prev_finalized_l1", eq.finalizedL1, "signaled_finalized_l1", l1Origin)
}
// FinalizedL1 identifies the L1 chain (incl.) that included and/or produced all the finalized L2 blocks.
// This may return a zeroed ID if no finalization signals have been seen yet.
func (eq *EngineQueue) FinalizedL1() eth.L1BlockRef {
return eq.finalizedL1
}
func (eq *EngineQueue) Finalized() eth.L2BlockRef {
......@@ -167,6 +187,7 @@ func (eq *EngineQueue) Step(ctx context.Context) error {
}
outOfData := false
if len(eq.safeAttributes) == 0 {
eq.origin = eq.prev.Origin()
if next, err := eq.prev.NextAttributes(ctx, eq.safeHead); err == io.EOF {
outOfData = true
} else if err != nil {
......@@ -191,7 +212,7 @@ func (eq *EngineQueue) Step(ctx context.Context) error {
// and then marks the latest fully derived L2 block from this as finalized,
// or defaults to the current finalized L2 block.
func (eq *EngineQueue) tryFinalizeL2() {
if eq.finalizedL1 == (eth.BlockID{}) {
if eq.finalizedL1 == (eth.L1BlockRef{}) {
return // if no L1 information is finalized yet, then skip this
}
// default to keep the same finalized block
......@@ -200,6 +221,7 @@ func (eq *EngineQueue) tryFinalizeL2() {
for _, fd := range eq.finalityData {
if fd.L2Block.Number > finalizedL2.Number && fd.L1Block.Number <= eq.finalizedL1.Number {
finalizedL2 = fd.L2Block
eq.needForkchoiceUpdate = true
}
}
eq.finalized = finalizedL2
......@@ -214,11 +236,11 @@ func (eq *EngineQueue) postProcessSafeL2() {
eq.finalityData = append(eq.finalityData[:0], eq.finalityData[1:finalityLookback]...)
}
// remember the last L2 block that we fully derived from the given finality data
if len(eq.finalityData) == 0 || eq.finalityData[len(eq.finalityData)-1].L1Block.Number < eq.prev.Origin().Number {
if len(eq.finalityData) == 0 || eq.finalityData[len(eq.finalityData)-1].L1Block.Number < eq.origin.Number {
// append entry for new L1 block
eq.finalityData = append(eq.finalityData, FinalityData{
L2Block: eq.safeHead,
L1Block: eq.prev.Origin().ID(),
L1Block: eq.origin.ID(),
})
} else {
// if it's a now L2 block that was derived from the same latest L1 block, then just update the entry
......@@ -233,7 +255,7 @@ func (eq *EngineQueue) logSyncProgress(reason string) {
"l2_safe", eq.safeHead,
"l2_unsafe", eq.unsafeHead,
"l2_time", eq.unsafeHead.Time,
"l1_derived", eq.prev.Origin(),
"l1_derived", eq.origin,
)
}
......
......@@ -250,7 +250,7 @@ func TestEngineQueue_Finalize(t *testing.T) {
eq.postProcessSafeL2()
// let's finalize D (current L1), from which we fully derived C1 (it was safe head), but not D0 (included in E)
eq.Finalize(refD.ID())
eq.Finalize(refD)
require.Equal(t, refC1, eq.Finalized(), "C1 was included in finalized D, and should now be finalized")
......
......@@ -5,9 +5,10 @@ import (
"fmt"
"io"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/log"
)
type Metrics interface {
......@@ -30,13 +31,14 @@ type ResetableStage interface {
}
type EngineQueueStage interface {
FinalizedL1() eth.L1BlockRef
Finalized() eth.L2BlockRef
UnsafeL2Head() eth.L2BlockRef
SafeL2Head() eth.L2BlockRef
Origin() eth.L1BlockRef
SetUnsafeHead(head eth.L2BlockRef)
Finalize(l1Origin eth.BlockID)
Finalize(l1Origin eth.L1BlockRef)
AddSafeAttributes(attributes *eth.PayloadAttributes)
AddUnsafePayload(payload *eth.ExecutionPayload)
Step(context.Context) error
......@@ -97,14 +99,22 @@ func (dp *DerivationPipeline) Reset() {
dp.resetting = 0
}
// Origin is the L1 block of the inner-most stage of the derivation pipeline,
// i.e. the L1 chain up to and including this point included and/or produced all the safe L2 blocks.
func (dp *DerivationPipeline) Origin() eth.L1BlockRef {
return dp.eng.Origin()
}
func (dp *DerivationPipeline) Finalize(l1Origin eth.BlockID) {
func (dp *DerivationPipeline) Finalize(l1Origin eth.L1BlockRef) {
dp.eng.Finalize(l1Origin)
}
// FinalizedL1 is the L1 finalization of the inner-most stage of the derivation pipeline,
// i.e. the L1 chain up to and including this point included and/or produced all the finalized L2 blocks.
func (dp *DerivationPipeline) FinalizedL1() eth.L1BlockRef {
return dp.eng.FinalizedL1()
}
func (dp *DerivationPipeline) Finalized() eth.L2BlockRef {
return dp.eng.Finalized()
}
......
......@@ -39,6 +39,7 @@ type L2Chain interface {
derive.Engine
L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error)
L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (eth.L2BlockRef, error)
L2BlockRefByNumber(ctx context.Context, num uint64) (eth.L2BlockRef, error)
}
type DerivationPipeline interface {
......@@ -46,7 +47,8 @@ type DerivationPipeline interface {
Step(ctx context.Context) error
SetUnsafeHead(head eth.L2BlockRef)
AddUnsafePayload(payload *eth.ExecutionPayload)
Finalize(ref eth.BlockID)
Finalize(ref eth.L1BlockRef)
FinalizedL1() eth.L1BlockRef
Finalized() eth.L2BlockRef
SafeL2Head() eth.L2BlockRef
UnsafeL2Head() eth.L2BlockRef
......@@ -92,7 +94,7 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, ne
l1State: l1State,
derivation: derivationPipeline,
idleDerivation: false,
syncStatusReq: make(chan chan eth.SyncStatus, 10),
stateReq: make(chan chan struct{}),
forceReset: make(chan chan struct{}, 10),
config: cfg,
driverConfig: driverCfg,
......
......@@ -30,8 +30,8 @@ type Driver struct {
// When the derivation pipeline is waiting for new data to do anything
idleDerivation bool
// Requests for sync status. Synchronized with event loop to avoid reading an inconsistent sync status.
syncStatusReq chan chan eth.SyncStatus
// Requests to block the event loop for synchronous execution to avoid reading an inconsistent state
stateReq chan chan struct{}
// Upon receiving a channel in this channel, the derivation pipeline is forced to be reset.
// It tells the caller that the reset occurred by closing the passed in channel.
......@@ -300,7 +300,7 @@ func (s *Driver) eventLoop() {
// no step, justified L1 information does not do anything for L2 derivation or status
case newL1Finalized := <-s.l1FinalizedSig:
s.l1State.HandleNewL1FinalizedBlock(newL1Finalized)
s.derivation.Finalize(newL1Finalized.ID())
s.derivation.Finalize(newL1Finalized)
reqStep() // we may be able to mark more L2 data as finalized now
case <-delayedStepReq:
delayedStepReq = nil
......@@ -342,16 +342,8 @@ func (s *Driver) eventLoop() {
stepAttempts = 0
reqStep() // continue with the next step if we can
}
case respCh := <-s.syncStatusReq:
respCh <- eth.SyncStatus{
CurrentL1: s.derivation.Origin(),
HeadL1: s.l1State.L1Head(),
SafeL1: s.l1State.L1Safe(),
FinalizedL1: s.l1State.L1Finalized(),
UnsafeL2: s.derivation.UnsafeL2Head(),
SafeL2: s.derivation.SafeL2Head(),
FinalizedL2: s.derivation.Finalized(),
}
case respCh := <-s.stateReq:
respCh <- struct{}{}
case respCh := <-s.forceReset:
s.log.Warn("Derivation pipeline is manually reset")
s.derivation.Reset()
......@@ -381,18 +373,48 @@ func (s *Driver) ResetDerivationPipeline(ctx context.Context) error {
}
}
// syncStatus returns the current sync status, and should only be called synchronously with
// the driver event loop to avoid retrieval of an inconsistent status.
func (s *Driver) syncStatus() *eth.SyncStatus {
return &eth.SyncStatus{
CurrentL1: s.derivation.Origin(),
CurrentL1Finalized: s.derivation.FinalizedL1(),
HeadL1: s.l1State.L1Head(),
SafeL1: s.l1State.L1Safe(),
FinalizedL1: s.l1State.L1Finalized(),
UnsafeL2: s.derivation.UnsafeL2Head(),
SafeL2: s.derivation.SafeL2Head(),
FinalizedL2: s.derivation.Finalized(),
}
}
// SyncStatus blocks the driver event loop and captures the syncing status.
// If the event loop is too busy and the context expires, a context error is returned.
func (s *Driver) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) {
respCh := make(chan eth.SyncStatus, 1)
wait := make(chan struct{})
select {
case s.stateReq <- wait:
resp := s.syncStatus()
<-wait
return resp, nil
case <-ctx.Done():
return nil, ctx.Err()
case s.syncStatusReq <- respCh:
}
}
// BlockRefWithStatus blocks the driver event loop and captures the syncing status,
// along with an L2 block reference by number consistent with that same status.
// If the event loop is too busy and the context expires, a context error is returned.
func (s *Driver) BlockRefWithStatus(ctx context.Context, num uint64) (eth.L2BlockRef, *eth.SyncStatus, error) {
wait := make(chan struct{})
select {
case s.stateReq <- wait:
resp := s.syncStatus()
ref, err := s.l2.L2BlockRefByNumber(ctx, num)
<-wait
return ref, resp, err
case <-ctx.Done():
return nil, ctx.Err()
case resp := <-respCh:
return &resp, nil
}
return eth.L2BlockRef{}, nil, ctx.Err()
}
}
......
......@@ -45,8 +45,6 @@ type Config struct {
// Note: below addresses are part of the block-derivation process,
// and required to be the same network-wide to stay in consensus.
// L2 address used to send all priority fees to, also known as the coinbase address in the block.
FeeRecipientAddress common.Address `json:"fee_recipient_address"`
// L1 address that batches are sent to.
BatchInboxAddress common.Address `json:"batch_inbox_address"`
// Acceptable batch-sender address
......@@ -81,9 +79,6 @@ func (cfg *Config) Check() error {
if cfg.P2PSequencerAddress == (common.Address{}) {
return errors.New("missing p2p sequencer address")
}
if cfg.FeeRecipientAddress == (common.Address{}) {
return errors.New("missing fee recipient address")
}
if cfg.BatchInboxAddress == (common.Address{}) {
return errors.New("missing batch inbox address")
}
......
......@@ -32,7 +32,6 @@ func randConfig() *Config {
MaxSequencerDrift: 100,
SeqWindowSize: 2,
L1ChainID: big.NewInt(900),
FeeRecipientAddress: randAddr(),
BatchInboxAddress: randAddr(),
BatchSenderAddress: randAddr(),
}
......
......@@ -11,6 +11,7 @@ const config = {
hardhat: {
gasPrice,
initialBaseFeePerGas: 0,
chainId: process.env.FORK_CHAIN_ID ? Number(process.env.FORK_CHAIN_ID) : 31337
},
},
analytics: { enabled: false },
......
......@@ -16,6 +16,7 @@
"event-name-camelcase": "off",
"reason-string": "off",
"avoid-tx-origin": "off",
"var-name-mixedcase": "off",
"func-visibility": ["warn", { "ignoreConstructors": true }]
}
}
......@@ -19,31 +19,26 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
/**
* @notice The interval in L2 blocks at which checkpoints must be submitted.
*/
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable SUBMISSION_INTERVAL;
/**
* @notice The number of blocks in the chain before the first block in this contract.
*/
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable HISTORICAL_TOTAL_BLOCKS;
/**
* @notice The number of the first L2 block recorded in this contract.
*/
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable STARTING_BLOCK_NUMBER;
/**
* @notice The timestamp of the first L2 block recorded in this contract.
*/
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable STARTING_TIMESTAMP;
/**
* @notice The time between L2 blocks in seconds.
*/
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable L2_BLOCK_TIME;
/**
......@@ -170,6 +165,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
*
* @param _proposal Represents the output proposal to delete
*/
// solhint-disable-next-line ordering
function deleteL2Output(Types.OutputProposal memory _proposal) external onlyOwner {
Types.OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber];
......
......@@ -32,13 +32,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
/**
* @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized.
*/
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable FINALIZATION_PERIOD_SECONDS;
/**
* @notice Address of the L2OutputOracle.
*/
// solhint-disable-next-line var-name-mixedcase
L2OutputOracle public immutable L2_ORACLE;
/**
......@@ -113,6 +111,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
* function for EOAs. Contracts should call the depositTransaction() function directly
* otherwise any deposited funds will be lost due to address aliasing.
*/
// solhint-disable-next-line ordering
receive() external payable {
depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(""));
}
......
......@@ -19,14 +19,6 @@ contract BaseSystemDictator is Ownable {
*/
uint256 public currentStep = 1;
/**
* @param _config System configuration.
*/
constructor(SystemConfig memory _config) Ownable() {
config = _config;
_transferOwnership(config.globalConfig.controller);
}
/**
* @notice Checks that the current step is the expected step, then bumps the current step.
*
......@@ -37,4 +29,12 @@ contract BaseSystemDictator is Ownable {
_;
currentStep++;
}
/**
* @param _config System configuration.
*/
constructor(SystemConfig memory _config) Ownable() {
config = _config;
_transferOwnership(config.globalConfig.controller);
}
}
......@@ -123,18 +123,18 @@ contract MigrationSystemDictator is BaseSystemDictator {
abi.encodeCall(OptimismPortal.initialize, ())
);
// Upgrade and initialize the L1CrossDomainMessenger.
config.globalConfig.proxyAdmin.upgradeAndCall(
// Upgrade the L1CrossDomainMessenger. No initializer because this is
// already initialized.
config.globalConfig.proxyAdmin.upgrade(
payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),
address(config.implementationAddressConfig.l1CrossDomainMessengerImpl),
abi.encodeCall(L1CrossDomainMessenger.initialize, ())
address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)
);
// Transfer ETH from the L1StandardBridge to the OptimismPortal.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.l1StandardBridgeProxy),
address(config.implementationAddressConfig.portalSenderImpl),
abi.encodeCall(PortalSender.send, ())
abi.encodeCall(PortalSender.donate, ())
);
// Upgrade the L1StandardBridge (no initializer).
......
......@@ -24,7 +24,7 @@ contract PortalSender {
/**
* @notice Sends balance of this contract to the OptimismPortal.
*/
function send() public {
function donate() public {
portal.donateETH{ value: address(this).balance }();
}
}
......@@ -9,6 +9,21 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol";
* @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.
*/
abstract contract ERC721Bridge {
/**
* @notice Messenger contract on this domain.
*/
CrossDomainMessenger public immutable messenger;
/**
* @notice Address of the bridge on the other network.
*/
address public immutable otherBridge;
/**
* @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.
*/
uint256[49] private __gap;
/**
* @notice Emitted when an ERC721 bridge to the other network is initiated.
*
......@@ -47,21 +62,6 @@ abstract contract ERC721Bridge {
bytes extraData
);
/**
* @notice Messenger contract on this domain.
*/
CrossDomainMessenger public immutable messenger;
/**
* @notice Address of the bridge on the other network.
*/
address public immutable otherBridge;
/**
* @notice Reserve extra slots (to a total of 50) in the storage layout for future upgrades.
*/
uint256[49] private __gap;
/**
* @notice Ensures that the caller is a cross-chain message from the other bridge.
*/
......
......@@ -27,21 +27,6 @@ interface IOptimismMintableERC721 is IERC721Enumerable {
*/
event Burn(address indexed account, uint256 tokenId);
/**
* @notice Chain ID of the chain where the remote token is deployed.
*/
function remoteChainId() external view returns (uint256);
/**
* @notice Address of the token on the remote domain.
*/
function remoteToken() external view returns (address);
/**
* @notice Address of the ERC721 bridge on this network.
*/
function bridge() external view returns (address);
/**
* @notice Mints some token ID for a user, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
......@@ -58,4 +43,19 @@ interface IOptimismMintableERC721 is IERC721Enumerable {
* @param _tokenId Token ID to burn.
*/
function burn(address _from, uint256 _tokenId) external;
/**
* @notice Chain ID of the chain where the remote token is deployed.
*/
function remoteChainId() external view returns (uint256);
/**
* @notice Address of the token on the remote domain.
*/
function remoteToken() external view returns (address);
/**
* @notice Address of the ERC721 bridge on this network.
*/
function bridge() external view returns (address);
}
......@@ -36,6 +36,14 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {
*/
string public baseTokenURI;
/**
* @notice Modifier that prevents callers other than the bridge from calling the function.
*/
modifier onlyBridge() {
require(msg.sender == bridge, "OptimismMintableERC721: only bridge can call this function");
_;
}
/**
* @param _bridge Address of the bridge on this network.
* @param _remoteChainId Chain ID where the remote token is deployed.
......@@ -74,14 +82,6 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {
);
}
/**
* @notice Modifier that prevents callers other than the bridge from calling the function.
*/
modifier onlyBridge() {
require(msg.sender == bridge, "OptimismMintableERC721: only bridge can call this function");
_;
}
/**
* @inheritdoc IOptimismMintableERC721
*/
......
......@@ -9,19 +9,6 @@ import { Semver } from "./Semver.sol";
* @notice Factory contract for creating OptimismMintableERC721 contracts.
*/
contract OptimismMintableERC721Factory is Semver {
/**
* @notice Emitted whenever a new OptimismMintableERC721 contract is created.
*
* @param localToken Address of the token on the this domain.
* @param remoteToken Address of the token on the remote domain.
* @param deployer Address of the initiator of the deployment
*/
event OptimismMintableERC721Created(
address indexed localToken,
address indexed remoteToken,
address deployer
);
/**
* @notice Address of the ERC721 bridge on this network.
*/
......@@ -37,6 +24,19 @@ contract OptimismMintableERC721Factory is Semver {
*/
mapping(address => bool) public isOptimismMintableERC721;
/**
* @notice Emitted whenever a new OptimismMintableERC721 contract is created.
*
* @param localToken Address of the token on the this domain.
* @param remoteToken Address of the token on the remote domain.
* @param deployer Address of the initiator of the deployment
*/
event OptimismMintableERC721Created(
address indexed localToken,
address indexed remoteToken,
address deployer
);
/**
* @custom:semver 1.0.0
*
......
......@@ -11,19 +11,16 @@ contract Semver {
/**
* @notice Contract version number (major).
*/
// solhint-disable-next-line var-name-mixedcase
uint256 private immutable MAJOR_VERSION;
/**
* @notice Contract version number (minor).
*/
// solhint-disable-next-line var-name-mixedcase
uint256 private immutable MINOR_VERSION;
/**
* @notice Contract version number (patch).
*/
// solhint-disable-next-line var-name-mixedcase
uint256 private immutable PATCH_VERSION;
/**
......
......@@ -7,7 +7,6 @@
"sequencerWindowSize": 4,
"channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
......
......@@ -8,7 +8,6 @@
"sequencerWindowSize": 120,
"channelTimeout": 120,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0x26862c200bd48c19f39d9e1cd88a3b439611d911",
"batchInboxAddress": "0xff00000000000000000000000000000000000002",
"batchSenderAddress": "0xa11d2b908470e17923fff184d48269bebbd9b2a5",
......
......@@ -10,7 +10,6 @@
"sequencerWindowSize": 4,
"channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
......
{
"l1StartingBlockTag": "0xe7bdc76873bb3fb062fb0125371a096d58aea92752db0e779576e7278a2e3328",
"l1ChainID": 1,
"l2ChainID": 10,
"l2BlockTime": 2,
"maxSequencerDrift": 100,
"sequencerWindowSize": 4,
"channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"l2OutputOracleSubmissionInterval": 20,
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleOwner": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
"l2GenesisBlockCoinbase": "0x42000000000000000000000000000000000000f0",
"l1BlockTime": 15,
"cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467",
"optimismBaseFeeRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"optimismL1FeeRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"finalizationPeriodSeconds": 2,
"deploymentWaitConfirmations": 1,
"fundDevAccounts": false,
"addressManager": "0xdE1FCfB0851916CA5101820A69b13a4E276bd81F"
}
......@@ -13,8 +13,7 @@ const deployFn: DeployFunction = async (hre) => {
)
await deployAndVerifyAndThen({
hre,
name: 'L1CrossDomainMessengerImpl',
contract: 'L1CrossDomainMessenger',
name: 'L1CrossDomainMessenger',
args: [OptimismPortalProxy.address],
postDeployAction: async (contract) => {
await assertContractVariable(
......
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import { predeploys } from '../src'
......@@ -8,14 +9,22 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const L1CrossDomainMessengerProxy = await getContractFromArtifact(
let L1CrossDomainMessengerProxy: ethers.Contract
try {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
} catch {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy'
)
}
await deployAndVerifyAndThen({
hre,
name: 'L1StandardBridgeImpl',
contract: 'L1StandardBridge',
name: 'L1StandardBridge',
args: [L1CrossDomainMessengerProxy.address],
postDeployAction: async (contract) => {
await assertContractVariable(
......
......@@ -2,6 +2,8 @@ import assert from 'assert'
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import '@nomiclabs/hardhat-ethers'
import {
assertContractVariable,
......@@ -26,8 +28,7 @@ const deployFn: DeployFunction = async (hre) => {
await deployAndVerifyAndThen({
hre,
name: 'L2OutputOracleImpl',
contract: 'L2OutputOracle',
name: 'L2OutputOracle',
args: [
hre.deployConfig.l2OutputOracleSubmissionInterval,
hre.deployConfig.l2OutputOracleGenesisL2Output,
......
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import {
assertContractVariable,
......@@ -13,8 +14,7 @@ const deployFn: DeployFunction = async (hre) => {
)
await deployAndVerifyAndThen({
hre,
name: 'OptimismPortalImpl',
contract: 'OptimismPortal',
name: 'OptimismPortal',
args: [
L2OutputOracleProxy.address,
hre.deployConfig.finalizationPeriodSeconds,
......
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
......@@ -7,14 +8,22 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const L1StandardBridgeProxy = await getContractFromArtifact(
let L1StandardBridgeProxy: ethers.Contract
try {
L1StandardBridgeProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1StandardBridge'
)
} catch (e) {
L1StandardBridgeProxy = await getContractFromArtifact(
hre,
'L1StandardBridgeProxy'
)
}
await deployAndVerifyAndThen({
hre,
name: 'OptimismMintableERC20FactoryImpl',
contract: 'OptimismMintableERC20Factory',
name: 'OptimismMintableERC20Factory',
args: [L1StandardBridgeProxy.address],
postDeployAction: async (contract) => {
await assertContractVariable(
......
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import { predeploys } from '../src'
......@@ -8,14 +9,22 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const L1CrossDomainMessengerProxy = await getContractFromArtifact(
let L1CrossDomainMessengerProxy: ethers.Contract
try {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
} catch {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy'
)
}
await deployAndVerifyAndThen({
hre,
name: 'L1ERC721BridgeImpl',
contract: 'L1ERC721Bridge',
name: 'L1ERC721Bridge',
args: [L1CrossDomainMessengerProxy.address, predeploys.L2ERC721Bridge],
postDeployAction: async (contract) => {
await assertContractVariable(
......
......@@ -13,8 +13,7 @@ const deployFn: DeployFunction = async (hre) => {
)
await deployAndVerifyAndThen({
hre,
name: 'PortalSenderImpl',
contract: 'PortalSender',
name: 'PortalSender',
args: [OptimismPortalProxy.address],
postDeployAction: async (contract) => {
await assertContractVariable(
......
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import {
getDeploymentAddress,
......@@ -46,31 +48,22 @@ const deployFn: DeployFunction = async (hre) => {
),
},
implementationAddressConfig: {
l2OutputOracleImpl: await getDeploymentAddress(
hre,
'L2OutputOracleImpl'
),
optimismPortalImpl: await getDeploymentAddress(
hre,
'OptimismPortalImpl'
),
l2OutputOracleImpl: await getDeploymentAddress(hre, 'L2OutputOracle'),
optimismPortalImpl: await getDeploymentAddress(hre, 'OptimismPortal'),
l1CrossDomainMessengerImpl: await getDeploymentAddress(
hre,
'L1CrossDomainMessengerImpl'
'L1CrossDomainMessenger'
),
l1StandardBridgeImpl: await getDeploymentAddress(
hre,
'L1StandardBridgeImpl'
'L1StandardBridge'
),
optimismMintableERC20FactoryImpl: await getDeploymentAddress(
hre,
'OptimismMintableERC20FactoryImpl'
),
l1ERC721BridgeImpl: await getDeploymentAddress(
hre,
'L1ERC721BridgeImpl'
'OptimismMintableERC20Factory'
),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSenderImpl'),
l1ERC721BridgeImpl: await getDeploymentAddress(hre, 'L1ERC721Bridge'),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSender'),
},
l2OutputOracleConfig: {
l2OutputOracleGenesisL2Output:
......
import { awaitCondition } from '@eth-optimism/core-utils'
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import {
getDeploymentAddress,
......@@ -31,6 +33,22 @@ const deployFn: DeployFunction = async (hre) => {
}
}
let finalOwner = hre.deployConfig.proxyAdminOwner
if (finalOwner === ethers.constants.AddressZero) {
if (hre.network.config.live === false) {
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!! A proxy admin owner address was not provided.`)
console.log(
`WARNING!!! Make sure you are ONLY doing this on a test network.`
)
finalOwner = deployer
} else {
throw new Error(`must specify the proxyAdminOwner on live networks`)
}
}
await deployAndVerifyAndThen({
hre,
name: 'MigrationSystemDictator',
......@@ -38,8 +56,8 @@ const deployFn: DeployFunction = async (hre) => {
{
globalConfig: {
proxyAdmin: await getDeploymentAddress(hre, 'ProxyAdmin'),
controller: deployer, // TODO
finalOwner: hre.deployConfig.proxyAdminOwner,
controller,
finalOwner,
addressManager: hre.deployConfig.addressManager,
},
proxyAddressConfig: {
......@@ -69,31 +87,22 @@ const deployFn: DeployFunction = async (hre) => {
),
},
implementationAddressConfig: {
l2OutputOracleImpl: await getDeploymentAddress(
hre,
'L2OutputOracleImpl'
),
optimismPortalImpl: await getDeploymentAddress(
hre,
'OptimismPortalImpl'
),
l2OutputOracleImpl: await getDeploymentAddress(hre, 'L2OutputOracle'),
optimismPortalImpl: await getDeploymentAddress(hre, 'OptimismPortal'),
l1CrossDomainMessengerImpl: await getDeploymentAddress(
hre,
'L1CrossDomainMessengerImpl'
'L1CrossDomainMessenger'
),
l1StandardBridgeImpl: await getDeploymentAddress(
hre,
'L1StandardBridgeImpl'
'L1StandardBridge'
),
optimismMintableERC20FactoryImpl: await getDeploymentAddress(
hre,
'OptimismMintableERC20FactoryImpl'
'OptimismMintableERC20Factory'
),
l1ERC721BridgeImpl: await getDeploymentAddress(
hre,
'L1ERC721BridgeImpl'
),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSenderImpl'),
l1ERC721BridgeImpl: await getDeploymentAddress(hre, 'L1ERC721Bridge'),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSender'),
},
l2OutputOracleConfig: {
l2OutputOracleGenesisL2Output:
......@@ -125,9 +134,13 @@ const deployFn: DeployFunction = async (hre) => {
await ProxyAdmin.setOwner(MigrationSystemDictator.address)
// Transfer ownership of the AddressManager to MigrationSystemDictator.
const AddressManager = await getContractFromArtifact(hre, 'AddressManager', {
const AddressManager = await getContractFromArtifact(
hre,
'Lib_AddressManager',
{
signerOrProvider: deployer,
})
}
)
if (isLiveDeployer) {
console.log(
`Transferring ownership of AddressManager to the MigrationSystemDictator...`
......@@ -187,8 +200,14 @@ const deployFn: DeployFunction = async (hre) => {
`Please transfer ownership of the L1StandardBridge (proxy) to the MigrationSystemDictator located at: ${MigrationSystemDictator.address}`
)
}
const noSigner = await getContractFromArtifact(
hre,
'Proxy__OVM_L1StandardBridge'
)
await awaitCondition(async () => {
const owner = await L1StandardBridge.owner()
const owner = await noSigner.callStatic.getOwner({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address
})
......@@ -198,12 +217,13 @@ const deployFn: DeployFunction = async (hre) => {
await MigrationSystemDictator[`step${i}`]()
} else {
console.log(`Please execute step ${i}...`)
}
await awaitCondition(async () => {
const step = await MigrationSystemDictator.step()
return step.toNumber() === i
const step = await MigrationSystemDictator.currentStep()
return step.toNumber() === i + 1
})
}
}
}
deployFn.tags = ['MigrationSystemDictator', 'migration']
......
import { ethers } from 'ethers'
import { HardhatUserConfig, task, subtask } from 'hardhat/config'
import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names'
import { HardhatUserConfig } from 'hardhat/config'
// Hardhat plugins
import '@eth-optimism/hardhat-deploy-config'
......@@ -11,22 +10,6 @@ import 'hardhat-deploy'
// Hardhat tasks
import './tasks'
subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(
async (_, __, runSuper) => {
const paths = await runSuper()
return paths.filter((p: string) => !p.endsWith('.t.sol'))
}
)
task('accounts', 'Prints the list of accounts', async (_, hre) => {
const accounts = await hre.ethers.getSigners()
for (const account of accounts) {
console.log(account.address)
}
})
const config: HardhatUserConfig = {
networks: {
devnetL1: {
......@@ -56,6 +39,12 @@ const config: HardhatUserConfig = {
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
},
'mainnet-forked': {
chainId: 1,
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
live: false,
},
},
foundry: {
buildInfo: true,
......@@ -150,11 +139,6 @@ const config: HardhatUserConfig = {
p2pSequencerAddress: {
type: 'address',
},
// L2 address used to send all priority fees to, also known as the coinbase address in the block.
// "fee_recipient_address" in rollup config.
optimismL2FeeRecipient: {
type: 'address',
},
// L1 address that batches are sent to.
// "batch_inbox_address" in rollup config.
batchInboxAddress: {
......@@ -367,6 +351,7 @@ const config: HardhatUserConfig = {
],
deployments: {
goerli: ['../contracts/deployments/goerli'],
'mainnet-forked': ['../contracts/deployments/mainnet'],
},
},
solidity: {
......
import { task } from 'hardhat/config'
import '@nomiclabs/hardhat-ethers'
task('accounts', 'Prints the list of accounts', async (_, hre) => {
const accounts = await hre.ethers.getSigners()
for (const account of accounts) {
console.log(account.address)
}
})
......@@ -6,3 +6,5 @@ import './check-l2-config'
import './watch'
import './forge-verify'
import './validate-spacers'
import './solidity'
import './accounts'
......@@ -11,7 +11,6 @@ task('rekey', 'Generates a new set of keys for a test network').setAction(
'proxyAdminOwner',
'optimismBaseFeeRecipient',
'optimismL1FeeRecipient',
'optimismL2FeeRecipient',
'p2pSequencerAddress',
'l2OutputOracleOwner',
'batchSenderAddress',
......
......@@ -65,7 +65,6 @@ task('rollup-config', 'create a genesis config')
l2_chain_id: deployConfig.l2ChainID,
p2p_sequencer_address: deployConfig.p2pSequencerAddress,
fee_recipient_address: deployConfig.optimismL2FeeRecipient,
batch_inbox_address: deployConfig.batchInboxAddress,
batch_sender_address: deployConfig.batchSenderAddress,
deposit_contract_address: portal.address,
......
import { subtask } from 'hardhat/config'
import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names'
subtask(TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS).setAction(
async (_, __, runSuper) => {
const paths = await runSuper()
return paths.filter((p: string) => !p.endsWith('.t.sol'))
}
)
......@@ -96,6 +96,8 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
/**
* Allows the Burn Admin to update the parameters which determine the amount of gas to burn.
* The value of enqueueL2GasPrepaid is immediately updated as well.
* @param _l2GasDiscountDivisor The ratio of the cost of L1 gas to the cost of L2 gas
* @param _enqueueGasCost The approximate cost of calling the enqueue function
*/
function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost)
external
......@@ -416,6 +418,8 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
* Parses the batch context from the extra data.
* @return Total number of elements submitted.
* @return Index of the next queue element.
* @return Timestamp for the last transaction
* @return Block number for the last transaction.
*/
function _getBatchExtraData()
internal
......
......@@ -62,6 +62,7 @@ interface IStateCommitmentChain {
* @param _element Hash of the element to verify a proof for.
* @param _batchHeader Header of the batch in which the element was included.
* @param _proof Merkle inclusion proof for the element.
* @return _verified Whether or not the batch inclusion proof is verified.
*/
function verifyStateCommitment(
bytes32 _element,
......
......@@ -34,6 +34,9 @@ contract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver {
/**
* @param _libAddressManager Address of the Address Manager.
* @param _fraudProofWindow Number of seconds until fraud proof is in the finalized state.
* @param _sequencerPublishWindow Number of seconds that the sequencer is exclusively allowed
* to post state roots.
*/
constructor(
address _libAddressManager,
......
......@@ -20,10 +20,7 @@ contract BondManager is IBondManager, Lib_AddressResolver {
constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) {}
/**
* Checks whether a given address is properly collateralized and can perform actions within
* the system.
* @param _who Address to check.
* @return true if the address is properly collateralized, false otherwise.
* @inheritdoc IBondManager
*/
// slither-disable-next-line external-function
function isCollateralized(address _who) public view returns (bool) {
......
......@@ -9,5 +9,11 @@ interface IBondManager {
* Public Functions *
********************/
/**
* Checks whether a given address is properly collateralized and can perform actions within
* the system.
* @param _who Address to check.
* @return true if the address is properly collateralized, false otherwise.
*/
function isCollateralized(address _who) external view returns (bool);
}
......@@ -50,7 +50,7 @@ interface IL2ERC20Bridge {
* @dev initiate a withdraw of some tokens to the caller's account on L1
* @param _l2Token Address of L2 token where withdrawal was initiated.
* @param _amount Amount of the token to withdraw.
* param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
......@@ -67,7 +67,7 @@ interface IL2ERC20Bridge {
* @param _l2Token Address of L2 token where withdrawal is initiated.
* @param _to L1 adress to credit the withdrawal to.
* @param _amount Amount of the token to withdraw.
* param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _l1Gas Unused, but included for potential forward compatibility considerations.
* @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content.
......
......@@ -33,6 +33,9 @@ contract L2CrossDomainMessenger is IL2CrossDomainMessenger {
* Constructor *
***************/
/**
* @param _l1CrossDomainMessenger Address of the L1 CrossDomainMessenger
*/
constructor(address _l1CrossDomainMessenger) {
l1CrossDomainMessenger = _l1CrossDomainMessenger;
}
......
......@@ -23,8 +23,7 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
********************/
/**
* Passes a message to L1.
* @param _message Message to pass to L1.
* @inheritdoc iOVM_L2ToL1MessagePasser
*/
// slither-disable-next-line external-function
function passMessageToL1(bytes memory _message) public {
......
......@@ -9,5 +9,8 @@ interface iOVM_L1BlockNumber {
* Public Functions *
********************/
/**
* @return Block number of L1
*/
function getL1BlockNumber() external view returns (uint256);
}
......@@ -15,5 +15,9 @@ interface iOVM_L2ToL1MessagePasser {
* Public Functions *
********************/
/**
* Passes a message to L1.
* @param _message Message to pass to L1.
*/
function passMessageToL1(bytes calldata _message) external;
}
......@@ -352,8 +352,8 @@ Allows the Burn Admin to update the parameters which determine the amount of gas
| Name | Type | Description |
|---|---|---|
| _l2GasDiscountDivisor | uint256 | undefined
| _enqueueGasCost | uint256 | undefined
| _l2GasDiscountDivisor | uint256 | The ratio of the cost of L1 gas to the cost of L2 gas
| _enqueueGasCost | uint256 | The approximate cost of calling the enqueue function
......
......@@ -16,7 +16,7 @@
function isCollateralized(address _who) external view returns (bool)
```
Checks whether a given address is properly collateralized and can perform actions within the system.
......@@ -24,13 +24,13 @@ function isCollateralized(address _who) external view returns (bool)
| Name | Type | Description |
|---|---|---|
| _who | address | undefined
| _who | address | Address to check.
#### Returns
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined
| _0 | bool | true if the address is properly collateralized, false otherwise.
......
......@@ -63,8 +63,8 @@ function withdraw(address _l2Token, uint256 _amount, uint32 _l1Gas, bytes _data)
| Name | Type | Description |
|---|---|---|
| _l2Token | address | Address of L2 token where withdrawal was initiated.
| _amount | uint256 | Amount of the token to withdraw. param _l1Gas Unused, but included for potential forward compatibility considerations.
| _l1Gas | uint32 | undefined
| _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | Unused, but included for potential forward compatibility considerations.
| _data | bytes | Optional data to forward to L1. This data is provided solely as a convenience for external contracts. Aside from enforcing a maximum length, these contracts provide no guarantees about its content.
### withdrawTo
......@@ -83,8 +83,8 @@ function withdrawTo(address _l2Token, address _to, uint256 _amount, uint32 _l1Ga
|---|---|---|
| _l2Token | address | Address of L2 token where withdrawal is initiated.
| _to | address | L1 adress to credit the withdrawal to.
| _amount | uint256 | Amount of the token to withdraw. param _l1Gas Unused, but included for potential forward compatibility considerations.
| _l1Gas | uint32 | undefined
| _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | Unused, but included for potential forward compatibility considerations.
| _data | bytes | Optional data to forward to L1. This data is provided solely as a convenience for external contracts. Aside from enforcing a maximum length, these contracts provide no guarantees about its content.
......
......@@ -138,7 +138,7 @@ Verifies a batch inclusion proof.
| Name | Type | Description |
|---|---|---|
| _verified | bool | undefined
| _verified | bool | Whether or not the batch inclusion proof is verified.
......
......@@ -80,8 +80,8 @@ function withdraw(address _l2Token, uint256 _amount, uint32 _l1Gas, bytes _data)
| Name | Type | Description |
|---|---|---|
| _l2Token | address | Address of L2 token where withdrawal was initiated.
| _amount | uint256 | Amount of the token to withdraw. param _l1Gas Unused, but included for potential forward compatibility considerations.
| _l1Gas | uint32 | undefined
| _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | Unused, but included for potential forward compatibility considerations.
| _data | bytes | Optional data to forward to L1. This data is provided solely as a convenience for external contracts. Aside from enforcing a maximum length, these contracts provide no guarantees about its content.
### withdrawTo
......@@ -100,8 +100,8 @@ function withdrawTo(address _l2Token, address _to, uint256 _amount, uint32 _l1Ga
|---|---|---|
| _l2Token | address | Address of L2 token where withdrawal is initiated.
| _to | address | L1 adress to credit the withdrawal to.
| _amount | uint256 | Amount of the token to withdraw. param _l1Gas Unused, but included for potential forward compatibility considerations.
| _l1Gas | uint32 | undefined
| _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | Unused, but included for potential forward compatibility considerations.
| _data | bytes | Optional data to forward to L1. This data is provided solely as a convenience for external contracts. Aside from enforcing a maximum length, these contracts provide no guarantees about its content.
......
......@@ -228,7 +228,7 @@ Verifies a batch inclusion proof.
| Name | Type | Description |
|---|---|---|
| _0 | bool | undefined
| _0 | bool | Whether or not the batch inclusion proof is verified.
......
......@@ -25,7 +25,7 @@ function getL1BlockNumber() external view returns (uint256)
| Name | Type | Description |
|---|---|---|
| _0 | uint256 | undefined
| _0 | uint256 | Block number of L1
......
......@@ -16,7 +16,7 @@
function passMessageToL1(bytes _message) external nonpayable
```
Passes a message to L1.
......@@ -24,7 +24,7 @@ function passMessageToL1(bytes _message) external nonpayable
| Name | Type | Description |
|---|---|---|
| _message | bytes | undefined
| _message | bytes | Message to pass to L1.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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