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: ignore:
- "l2geth" - "l2geth"
- "**/*.t.sol" - "**/*.t.sol"
...@@ -10,6 +10,11 @@ flag_management: ...@@ -10,6 +10,11 @@ flag_management:
individual_flags: individual_flags:
- name: bedrock-go-tests - name: bedrock-go-tests
- name: contracts-bedrock-tests - name: contracts-bedrock-tests
paths:
- packages/contracts-bedrock/contracts
statuses:
- type: patch
target: 100%
- name: common-ts-tests - name: common-ts-tests
- name: contracts-tests - name: contracts-tests
- name: core-utils-tests - name: core-utils-tests
...@@ -22,3 +27,20 @@ flag_management: ...@@ -22,3 +27,20 @@ flag_management:
- name: message-relayer-tests - name: message-relayer-tests
- name: replica-healthcheck-tests - name: replica-healthcheck-tests
- name: sdk-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
}
This diff is collapsed.
...@@ -2,65 +2,144 @@ package op_batcher ...@@ -2,65 +2,144 @@ package op_batcher
import ( import (
"context" "context"
"crypto/ecdsa"
"fmt"
"math/big"
"time"
"github.com/ethereum-optimism/optimism/op-proposer/txmgr" "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"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto" "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. const networkTimeout = 2 * time.Second // How long a single network request can take. TODO: put in a config somewhere
func (l *BatchSubmitter) CraftTx(ctx context.Context, data []byte, nonce uint64) (*types.Transaction, error) {
gasTipCap, err := l.cfg.L1Client.SuggestGasTipCap(ctx) // 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 { 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 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 { if err != nil {
return nil, err 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{ rawTx := &types.DynamicFeeTx{
ChainID: l.cfg.ChainID, ChainID: t.chainID,
Nonce: nonce, Nonce: nonce,
To: &l.cfg.BatchInboxAddress, To: &t.batchInboxAddress,
GasTipCap: gasTipCap, GasTipCap: gasTipCap,
GasFeeCap: gasFeeCap, GasFeeCap: gasFeeCap,
Data: data, 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) gas, err := core.IntrinsicGas(rawTx.Data, nil, false, true, true)
if err != nil { if err != nil {
return nil, err return nil, fmt.Errorf("failed to calculate intrinsic gas: %w", err)
} }
rawTx.Gas = gas 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 // UpdateGasPrice signs an otherwise identical txn to the one provided but with
// updated gas prices sampled from the existing network conditions. // updated gas prices sampled from the existing network conditions.
// //
// NOTE: Thie method SHOULD NOT publish the resulting transaction. // NOTE: This method SHOULD NOT publish the resulting transaction.
func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) { func (t *TransactionManager) UpdateGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) {
gasTipCap, err := l.cfg.L1Client.SuggestGasTipCap(ctx) gasTipCap, gasFeeCap, err := t.calcGasTipAndFeeCap(ctx)
if err != nil {
return nil, err
}
head, err := l.cfg.L1Client.HeaderByNumber(ctx, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
gasFeeCap := txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap)
rawTx := &types.DynamicFeeTx{ rawTx := &types.DynamicFeeTx{
ChainID: l.cfg.ChainID, ChainID: t.chainID,
Nonce: tx.Nonce(), Nonce: tx.Nonce(),
To: tx.To(), To: tx.To(),
GasTipCap: gasTipCap, GasTipCap: gasTipCap,
...@@ -68,12 +147,8 @@ func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transacti ...@@ -68,12 +147,8 @@ func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transacti
Gas: tx.Gas(), Gas: tx.Gas(),
Data: tx.Data(), 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) return t.signerFn(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)
} }
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var DeployerWhitelistStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var GasPriceOracleStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var GovernanceTokenStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var L1CrossDomainMessengerStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var L2CrossDomainMessengerStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var L2ERC721BridgeStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var L2StandardBridgeStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var LegacyERC20ETHStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var LegacyMessagePasserStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var OptimismMintableERC721FactoryStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var OptimismPortalStorageLayout = new(solc.StorageLayout)
......
...@@ -9,7 +9,7 @@ import ( ...@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc" "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) var ProxyAdminStorageLayout = new(solc.StorageLayout)
......
...@@ -8,12 +8,12 @@ import ( ...@@ -8,12 +8,12 @@ import (
"strings" "strings"
"github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/hardhat" "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"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis/migration"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
...@@ -84,28 +84,28 @@ func main() { ...@@ -84,28 +84,28 @@ func main() {
return err return err
} }
ovmAddresses, err := genesis.NewAddresses(ctx.String("ovm-addresses")) ovmAddresses, err := migration.NewAddresses(ctx.String("ovm-addresses"))
if err != nil { if err != nil {
return err return err
} }
evmAddresess, err := genesis.NewAddresses(ctx.String("evm-addresses")) evmAddresess, err := migration.NewAddresses(ctx.String("evm-addresses"))
if err != nil { if err != nil {
return err return err
} }
ovmAllowances, err := genesis.NewAllowances(ctx.String("ovm-allowances")) ovmAllowances, err := migration.NewAllowances(ctx.String("ovm-allowances"))
if err != nil { if err != nil {
return err return err
} }
ovmMessages, err := genesis.NewSentMessage(ctx.String("ovm-messages")) ovmMessages, err := migration.NewSentMessage(ctx.String("ovm-messages"))
if err != nil { if err != nil {
return err return err
} }
evmMessages, err := genesis.NewSentMessage(ctx.String("evm-messages")) evmMessages, err := migration.NewSentMessage(ctx.String("evm-messages"))
if err != nil { if err != nil {
return err return err
} }
migrationData := genesis.MigrationData{ migrationData := migration.MigrationData{
OvmAddresses: ovmAddresses, OvmAddresses: ovmAddresses,
EvmAddresses: evmAddresess, EvmAddresses: evmAddresess,
OvmAllowances: ovmAllowances, OvmAllowances: ovmAllowances,
...@@ -143,18 +143,6 @@ func main() { ...@@ -143,18 +143,6 @@ func main() {
return err 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 // Get the addresses from the hardhat deploy artifacts
l1StandardBridgeProxyDeployment, err := hh.GetDeployment("Proxy__OVM_L1StandardBridge") l1StandardBridgeProxyDeployment, err := hh.GetDeployment("Proxy__OVM_L1StandardBridge")
if err != nil { if err != nil {
...@@ -176,20 +164,10 @@ func main() { ...@@ -176,20 +164,10 @@ func main() {
L1ERC721BridgeProxy: l1ERC721BridgeProxyDeployment.Address, L1ERC721BridgeProxy: l1ERC721BridgeProxyDeployment.Address,
} }
if err := genesis.MigrateDB(sdb, config, block, &l2Addrs, &migrationData); err != nil { dryRun := ctx.Bool("dry-run")
return err if err := genesis.MigrateDB(ldb, config, block, &l2Addrs, &migrationData, !dryRun); err != nil {
}
if ctx.Bool("dry-run") {
log.Info("Dry run complete")
return nil
}
root, err := sdb.Commit(true)
if err != nil {
return err return err
} }
log.Info("Migration complete", "root", root)
return nil return nil
}, },
......
...@@ -8,8 +8,8 @@ import ( ...@@ -8,8 +8,8 @@ import (
"io" "io"
"strings" "strings"
l2grawdb "github.com/ethereum-optimism/optimism/l2geth/core/rawdb"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
) )
...@@ -31,8 +31,8 @@ type AllowanceCB func(owner, spender common.Address) error ...@@ -31,8 +31,8 @@ type AllowanceCB func(owner, spender common.Address) error
// IterateDBAddresses iterates over each address in Geth's address // IterateDBAddresses iterates over each address in Geth's address
// preimage database, calling the callback with the address. // preimage database, calling the callback with the address.
func IterateDBAddresses(inDB ethdb.Database, cb AddressCB) error { func IterateDBAddresses(db ethdb.Database, cb AddressCB) error {
iter := inDB.NewIterator(AddressPreimagePrefix, nil) iter := db.NewIterator(AddressPreimagePrefix, nil)
for iter.Next() { for iter.Next() {
if iter.Error() != nil { if iter.Error() != nil {
return iter.Error() return iter.Error()
...@@ -98,10 +98,10 @@ func IterateAllowanceList(r io.Reader, cb AllowanceCB) error { ...@@ -98,10 +98,10 @@ func IterateAllowanceList(r io.Reader, cb AllowanceCB) error {
// IterateMintEvents iterates over each mint event in the database starting // IterateMintEvents iterates over each mint event in the database starting
// from head and stopping at genesis. // 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 { for headNum > 0 {
hash := l2grawdb.ReadCanonicalHash(inDB, headNum) hash := rawdb.ReadCanonicalHash(db, headNum)
receipts := l2grawdb.ReadRawReceipts(inDB, hash, headNum) receipts := rawdb.ReadRawReceipts(db, hash, headNum)
for _, receipt := range receipts { for _, receipt := range receipts {
for _, l := range receipt.Logs { for _, l := range receipt.Logs {
if common.BytesToHash(l.Topics[0].Bytes()) != MintTopic { 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 { ...@@ -30,7 +30,6 @@ type DeployConfig struct {
SequencerWindowSize uint64 `json:"sequencerWindowSize"` SequencerWindowSize uint64 `json:"sequencerWindowSize"`
ChannelTimeout uint64 `json:"channelTimeout"` ChannelTimeout uint64 `json:"channelTimeout"`
P2PSequencerAddress common.Address `json:"p2pSequencerAddress"` P2PSequencerAddress common.Address `json:"p2pSequencerAddress"`
OptimismL2FeeRecipient common.Address `json:"optimismL2FeeRecipient"`
BatchInboxAddress common.Address `json:"batchInboxAddress"` BatchInboxAddress common.Address `json:"batchInboxAddress"`
BatchSenderAddress common.Address `json:"batchSenderAddress"` BatchSenderAddress common.Address `json:"batchSenderAddress"`
......
package genesis package genesis
import ( 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/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/types"
"github.com/ethereum/go-ethereum/core/vm" "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 // 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 { if err := SetL2Proxies(db); err != nil {
return err return err
} }
...@@ -26,28 +59,97 @@ func MigrateDB(db vm.StateDB, config *DeployConfig, l1Block *types.Block, l2Addr ...@@ -26,28 +59,97 @@ func MigrateDB(db vm.StateDB, config *DeployConfig, l1Block *types.Block, l2Addr
return err return err
} }
// Convert all of the messages into legacy withdrawals err = crossdomain.MigrateWithdrawals(withdrawals, db, &l2Addrs.L1CrossDomainMessengerProxy, &l2Addrs.L1StandardBridgeProxy)
messages := make([]*crossdomain.LegacyWithdrawal, 0) if err != nil {
for _, msg := range migrationData.OvmMessages { return err
wd, err := msg.ToLegacyWithdrawal()
if err != nil {
return err
}
messages = append(messages, wd)
} }
for _, msg := range migrationData.EvmMessages {
wd, err := msg.ToLegacyWithdrawal() addrs := migrationData.Addresses()
if err := ether.MigrateLegacyETH(ldb, addrs, migrationData.OvmAllowances, int(config.L1ChainID)); err != nil {
return err
}
if !commit {
return nil
}
root, err := db.Commit(true)
if err != nil {
return err
}
// 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),
}
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 { if err != nil {
return err return err
} }
messages = append(messages, wd) knownSlots[slot] = true
} }
// Build a map of all the slots in the LegacyMessagePasser
if err := crossdomain.MigrateWithdrawals(messages, db, &l2Addrs.L1CrossDomainMessengerProxy, &l2Addrs.L1StandardBridgeProxy); err != nil { 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 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 return nil
} }
...@@ -52,8 +52,8 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro ...@@ -52,8 +52,8 @@ func NewL2Genesis(config *DeployConfig, block *types.Block) (*core.Genesis, erro
TerminalTotalDifficulty: big.NewInt(0), TerminalTotalDifficulty: big.NewInt(0),
TerminalTotalDifficultyPassed: true, TerminalTotalDifficultyPassed: true,
Optimism: &params.OptimismConfig{ Optimism: &params.OptimismConfig{
L1FeeRecipient: config.OptimismL1FeeRecipient,
BaseFeeRecipient: config.OptimismBaseFeeRecipient, BaseFeeRecipient: config.OptimismBaseFeeRecipient,
L1FeeRecipient: config.OptimismL2FeeRecipient,
EIP1559Denominator: eip1559Denom, EIP1559Denominator: eip1559Denom,
EIP1559Elasticity: eip1559Elasticity, EIP1559Elasticity: eip1559Elasticity,
}, },
......
package genesis package migration
import ( import (
"encoding/json" "encoding/json"
...@@ -116,3 +116,36 @@ type MigrationData struct { ...@@ -116,3 +116,36 @@ type MigrationData struct {
// L2CrossDomainMessenger from after the evm equivalence upgrade // L2CrossDomainMessenger from after the evm equivalence upgrade
EvmMessages []*SentMessage 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 @@ ...@@ -8,7 +8,6 @@
"sequencerWindowSize": 4, "sequencerWindowSize": 4,
"channelTimeout": 40, "channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000", "batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
"sequencerWindowSize": 100, "sequencerWindowSize": 100,
"channelTimeout": 30, "channelTimeout": 30,
"p2pSequencerAddress": "0x0000000000000000000000000000000000000000", "p2pSequencerAddress": "0x0000000000000000000000000000000000000000",
"optimismL2FeeRecipient": "0x42000000000000000000000000000000000000f0",
"batchInboxAddress": "0x42000000000000000000000000000000000000ff", "batchInboxAddress": "0x42000000000000000000000000000000000000ff",
"batchSenderAddress": "0x0000000000000000000000000000000000000000", "batchSenderAddress": "0x0000000000000000000000000000000000000000",
"l2OutputOracleSubmissionInterval": 6, "l2OutputOracleSubmissionInterval": 6,
......
...@@ -3,7 +3,6 @@ module github.com/ethereum-optimism/optimism/op-chain-ops ...@@ -3,7 +3,6 @@ module github.com/ethereum-optimism/optimism/op-chain-ops
go 1.18 go 1.18
require ( 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-optimism/optimism/op-bindings v0.8.10
github.com/ethereum/go-ethereum v1.10.23 github.com/ethereum/go-ethereum v1.10.23
github.com/holiman/uint256 v1.2.0 github.com/holiman/uint256 v1.2.0
...@@ -16,45 +15,35 @@ require ( ...@@ -16,45 +15,35 @@ require (
require ( require (
github.com/VictoriaMetrics/fastcache v1.9.0 // indirect 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/btcsuite/btcd/btcec/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
github.com/edsrzf/mmap-go v1.1.0 // indirect github.com/edsrzf/mmap-go v1.0.0 // indirect
github.com/elastic/gosigar v0.12.0 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect github.com/go-stack/stack v1.8.1 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.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/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d // indirect
github.com/holiman/bloomfilter/v2 v2.0.3 // 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/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/olekukonko/tablewriter v0.0.5 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/tsdb v0.10.0 // indirect github.com/prometheus/tsdb v0.10.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect
github.com/rjeczalik/notify v0.9.2 // 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/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.11+incompatible // 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/syndtr/goleveldb v1.0.1-0.20220614013038-64ee5596c38a // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect github.com/tklauser/numcpus v0.4.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // 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-20220520151302-bc2c85ada10a // indirect
golang.org/x/sys v0.0.0-20220701225701-179beb0bd1a1 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v3 v3.0.1 // 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 { ...@@ -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). // ActL1FinalizeNext finalizes the next block, which must be marked as safe before doing so (see ActL1SafeNext).
func (s *L1Replica) ActL1FinalizeNext(t Testing) { func (s *L1Replica) ActL1FinalizeNext(t Testing) {
safe := s.l1Chain.CurrentSafeBlock() safe := s.l1Chain.CurrentSafeBlock()
finalizedNum := s.l1Chain.CurrentFinalizedBlock().NumberU64() safeNum := uint64(0)
if safe.NumberU64() <= finalizedNum { 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") t.InvalidAction("need to move forward safe block before moving finalized block")
return return
} }
...@@ -192,7 +200,11 @@ func (s *L1Replica) ActL1FinalizeNext(t Testing) { ...@@ -192,7 +200,11 @@ func (s *L1Replica) ActL1FinalizeNext(t Testing) {
// ActL1SafeNext marks the next unsafe block as safe. // ActL1SafeNext marks the next unsafe block as safe.
func (s *L1Replica) ActL1SafeNext(t Testing) { func (s *L1Replica) ActL1SafeNext(t Testing) {
safe := s.l1Chain.CurrentSafeBlock() 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 { if next == nil {
t.InvalidAction("if head of chain is marked as safe then there's no next block") t.InvalidAction("if head of chain is marked as safe then there's no next block")
return return
......
...@@ -7,15 +7,16 @@ import ( ...@@ -7,15 +7,16 @@ import (
"io" "io"
"math/big" "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/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require" "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 { type SyncStatusAPI interface {
...@@ -149,8 +150,8 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing) { ...@@ -149,8 +150,8 @@ func (s *L2Batcher) ActL2BatchSubmit(t Testing) {
data.WriteByte(derive.DerivationVersion0) data.WriteByte(derive.DerivationVersion0)
// subtract one, to account for the version byte // subtract one, to account for the version byte
if err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF { if err := s.l2ChannelOut.OutputFrame(data, s.l2BatcherCfg.MaxL1TxSize-1); err == io.EOF {
s.l2ChannelOut = nil
s.l2Submitting = false s.l2Submitting = false
// there may still be some data to submit
} else if err != nil { } else if err != nil {
s.l2Submitting = false s.l2Submitting = false
t.Fatalf("failed to output channel data to frame: %v", err) t.Fatalf("failed to output channel data to frame: %v", err)
......
...@@ -4,12 +4,14 @@ import ( ...@@ -4,12 +4,14 @@ import (
"math/big" "math/big"
"testing" "testing"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" "github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
) )
...@@ -87,3 +89,108 @@ func TestBatcher(gt *testing.T) { ...@@ -87,3 +89,108 @@ func TestBatcher(gt *testing.T) {
require.False(t, isPending) require.False(t, isPending)
require.NotNil(t, vTx) 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 { ...@@ -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()) e.l2GasPool, e.l2BuildingState, e.l2BuildingHeader, tx, &e.l2BuildingHeader.GasUsed, *e.l2Chain.GetVMConfig())
if err != nil { if err != nil {
e.l2TxFailed = append(e.l2TxFailed, tx) 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.l2Receipts = append(e.l2Receipts, receipt)
e.l2Transactions = append(e.l2Transactions, tx) e.l2Transactions = append(e.l2Transactions, tx)
......
...@@ -118,13 +118,14 @@ func (s *L2Verifier) L2Unsafe() eth.L2BlockRef { ...@@ -118,13 +118,14 @@ func (s *L2Verifier) L2Unsafe() eth.L2BlockRef {
func (s *L2Verifier) SyncStatus() *eth.SyncStatus { func (s *L2Verifier) SyncStatus() *eth.SyncStatus {
return &eth.SyncStatus{ return &eth.SyncStatus{
CurrentL1: s.derivation.Origin(), CurrentL1: s.derivation.Origin(),
HeadL1: s.l1State.L1Head(), CurrentL1Finalized: s.derivation.FinalizedL1(),
SafeL1: s.l1State.L1Safe(), HeadL1: s.l1State.L1Head(),
FinalizedL1: s.l1State.L1Finalized(), SafeL1: s.l1State.L1Safe(),
UnsafeL2: s.L2Unsafe(), FinalizedL1: s.l1State.L1Finalized(),
SafeL2: s.L2Safe(), UnsafeL2: s.L2Unsafe(),
FinalizedL2: s.L2Finalized(), SafeL2: s.L2Safe(),
FinalizedL2: s.L2Finalized(),
} }
} }
...@@ -160,15 +161,16 @@ func (s *L2Verifier) ActL1HeadSignal(t Testing) { ...@@ -160,15 +161,16 @@ func (s *L2Verifier) ActL1HeadSignal(t Testing) {
} }
func (s *L2Verifier) ActL1SafeSignal(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) require.NoError(t, err)
s.l1State.HandleNewL1SafeBlock(head) s.l1State.HandleNewL1SafeBlock(safe)
} }
func (s *L2Verifier) ActL1FinalizedSignal(t Testing) { 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) 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 // ActL2PipelineStep runs one iteration of the L2 derivation pipeline
......
...@@ -7,6 +7,7 @@ import ( ...@@ -7,6 +7,7 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
"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/crossdomain"
) )
...@@ -41,7 +42,7 @@ func CollectAddresses(sd *SetupData, dp *DeployParams) (out []common.Address) { ...@@ -41,7 +42,7 @@ func CollectAddresses(sd *SetupData, dp *DeployParams) (out []common.Address) {
sd.L1Cfg.Coinbase, sd.L1Cfg.Coinbase,
sd.L2Cfg.Coinbase, sd.L2Cfg.Coinbase,
sd.RollupCfg.P2PSequencerAddress, sd.RollupCfg.P2PSequencerAddress,
sd.RollupCfg.FeeRecipientAddress, predeploys.SequencerFeeVaultAddr,
sd.RollupCfg.BatchInboxAddress, sd.RollupCfg.BatchInboxAddress,
sd.RollupCfg.BatchSenderAddress, sd.RollupCfg.BatchSenderAddress,
sd.RollupCfg.DepositContractAddress, sd.RollupCfg.DepositContractAddress,
......
...@@ -58,13 +58,12 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { ...@@ -58,13 +58,12 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
L2ChainID: 902, L2ChainID: 902,
L2BlockTime: 2, L2BlockTime: 2,
MaxSequencerDrift: tp.MaxSequencerDrift, MaxSequencerDrift: tp.MaxSequencerDrift,
SequencerWindowSize: tp.SequencerWindowSize, SequencerWindowSize: tp.SequencerWindowSize,
ChannelTimeout: tp.ChannelTimeout, ChannelTimeout: tp.ChannelTimeout,
P2PSequencerAddress: addresses.SequencerP2P, P2PSequencerAddress: addresses.SequencerP2P,
OptimismL2FeeRecipient: common.Address{0: 0x42, 19: 0xf0}, // tbd BatchInboxAddress: common.Address{0: 0x42, 19: 0xff}, // tbd
BatchInboxAddress: common.Address{0: 0x42, 19: 0xff}, // tbd BatchSenderAddress: addresses.Batcher,
BatchSenderAddress: addresses.Batcher,
L2OutputOracleSubmissionInterval: 6, L2OutputOracleSubmissionInterval: 6,
L2OutputOracleStartingTimestamp: -1, L2OutputOracleStartingTimestamp: -1,
...@@ -89,7 +88,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams { ...@@ -89,7 +88,7 @@ func MakeDeployParams(t require.TestingT, tp *TestParams) *DeployParams {
L2GenesisBlockGasLimit: 15_000_000, L2GenesisBlockGasLimit: 15_000_000,
L2GenesisBlockDifficulty: uint64ToBig(0), L2GenesisBlockDifficulty: uint64ToBig(0),
L2GenesisBlockMixHash: common.Hash{}, L2GenesisBlockMixHash: common.Hash{},
L2GenesisBlockCoinbase: common.Address{0: 0x42, 19: 0xf0}, // matching OptimismL2FeeRecipient L2GenesisBlockCoinbase: predeploys.SequencerFeeVaultAddr,
L2GenesisBlockNumber: 0, L2GenesisBlockNumber: 0,
L2GenesisBlockGasUsed: 0, L2GenesisBlockGasUsed: 0,
L2GenesisBlockParentHash: common.Hash{}, L2GenesisBlockParentHash: common.Hash{},
...@@ -201,7 +200,6 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * ...@@ -201,7 +200,6 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) *
L1ChainID: new(big.Int).SetUint64(deployConf.L1ChainID), L1ChainID: new(big.Int).SetUint64(deployConf.L1ChainID),
L2ChainID: new(big.Int).SetUint64(deployConf.L2ChainID), L2ChainID: new(big.Int).SetUint64(deployConf.L2ChainID),
P2PSequencerAddress: deployConf.P2PSequencerAddress, P2PSequencerAddress: deployConf.P2PSequencerAddress,
FeeRecipientAddress: deployConf.OptimismL2FeeRecipient,
BatchInboxAddress: deployConf.BatchInboxAddress, BatchInboxAddress: deployConf.BatchInboxAddress,
BatchSenderAddress: deployConf.BatchSenderAddress, BatchSenderAddress: deployConf.BatchSenderAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr, DepositContractAddress: predeploys.DevOptimismPortalAddr,
......
...@@ -94,7 +94,6 @@ func DefaultSystemConfig(t *testing.T) SystemConfig { ...@@ -94,7 +94,6 @@ func DefaultSystemConfig(t *testing.T) SystemConfig {
OptimismBaseFeeRecipient: common.Address{0: 0x52, 19: 0xf0}, // tbd OptimismBaseFeeRecipient: common.Address{0: 0x52, 19: 0xf0}, // tbd
OptimismL1FeeRecipient: common.Address{0: 0x52, 19: 0xf1}, OptimismL1FeeRecipient: common.Address{0: 0x52, 19: 0xf1},
OptimismL2FeeRecipient: common.Address{0: 0x52, 19: 0xf2}, // tbd
L2CrossDomainMessengerOwner: common.Address{0: 0x52, 19: 0xf3}, // tbd L2CrossDomainMessengerOwner: common.Address{0: 0x52, 19: 0xf3}, // tbd
GasPriceOracleOwner: addresses.Alice, // tbd GasPriceOracleOwner: addresses.Alice, // tbd
GasPriceOracleOverhead: 0, GasPriceOracleOverhead: 0,
...@@ -283,7 +282,6 @@ func (cfg SystemConfig) Start() (*System, error) { ...@@ -283,7 +282,6 @@ func (cfg SystemConfig) Start() (*System, error) {
L1ChainID: cfg.L1ChainIDBig(), L1ChainID: cfg.L1ChainIDBig(),
L2ChainID: cfg.L2ChainIDBig(), L2ChainID: cfg.L2ChainIDBig(),
P2PSequencerAddress: cfg.DeployConfig.P2PSequencerAddress, P2PSequencerAddress: cfg.DeployConfig.P2PSequencerAddress,
FeeRecipientAddress: l2Genesis.Coinbase,
BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress, BatchInboxAddress: cfg.DeployConfig.BatchInboxAddress,
BatchSenderAddress: cfg.DeployConfig.BatchSenderAddress, BatchSenderAddress: cfg.DeployConfig.BatchSenderAddress,
DepositContractAddress: predeploys.DevOptimismPortalAddr, DepositContractAddress: predeploys.DevOptimismPortalAddr,
......
...@@ -915,7 +915,7 @@ func TestFees(t *testing.T) { ...@@ -915,7 +915,7 @@ func TestFees(t *testing.T) {
// L1Fee Recipient // L1Fee Recipient
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel() defer cancel()
l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL2FeeRecipient, nil) l1FeeRecipientStartBalance, err := l2Seq.BalanceAt(ctx, cfg.DeployConfig.OptimismL1FeeRecipient, nil)
require.Nil(t, err) require.Nil(t, err)
// Simple transfer from signer to random account // Simple transfer from signer to random account
...@@ -976,7 +976,7 @@ func TestFees(t *testing.T) { ...@@ -976,7 +976,7 @@ func TestFees(t *testing.T) {
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second) ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
defer cancel() 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) require.Nil(t, err)
// Diff fee recipient + coinbase balances // Diff fee recipient + coinbase balances
......
...@@ -193,7 +193,6 @@ func makeRollupConfig( ...@@ -193,7 +193,6 @@ func makeRollupConfig(
L1ChainID: new(big.Int).SetUint64(config.L1ChainID), L1ChainID: new(big.Int).SetUint64(config.L1ChainID),
L2ChainID: new(big.Int).SetUint64(config.L2ChainID), L2ChainID: new(big.Int).SetUint64(config.L2ChainID),
P2PSequencerAddress: config.P2PSequencerAddress, P2PSequencerAddress: config.P2PSequencerAddress,
FeeRecipientAddress: config.OptimismL2FeeRecipient,
BatchInboxAddress: config.BatchInboxAddress, BatchInboxAddress: config.BatchInboxAddress,
BatchSenderAddress: config.BatchSenderAddress, BatchSenderAddress: config.BatchSenderAddress,
DepositContractAddress: portalAddr, DepositContractAddress: portalAddr,
......
...@@ -3,10 +3,18 @@ package eth ...@@ -3,10 +3,18 @@ package eth
// SyncStatus is a snapshot of the driver. // SyncStatus is a snapshot of the driver.
// Values may be zeroed if not yet initialized. // Values may be zeroed if not yet initialized.
type SyncStatus struct { type SyncStatus struct {
// CurrentL1 is the block that the derivation process is currently at, // 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. // 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. // If the node is synced, this matches the HeadL1, minus the verifier confirmation distance.
CurrentL1 L1BlockRef `json:"current_l1"` 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. // 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, // 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. // as the node may be in progress of resetting to adapt to a L1 reorg.
......
...@@ -4,6 +4,7 @@ import ( ...@@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -74,7 +75,7 @@ func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1Rece ...@@ -74,7 +75,7 @@ func PreparePayloadAttributes(ctx context.Context, cfg *rollup.Config, dl L1Rece
return &eth.PayloadAttributes{ return &eth.PayloadAttributes{
Timestamp: hexutil.Uint64(timestamp), Timestamp: hexutil.Uint64(timestamp),
PrevRandao: eth.Bytes32(l1Info.MixDigest()), PrevRandao: eth.Bytes32(l1Info.MixDigest()),
SuggestedFeeRecipient: cfg.FeeRecipientAddress, SuggestedFeeRecipient: predeploys.SequencerFeeVaultAddr,
Transactions: txs, Transactions: txs,
NoTxPool: true, NoTxPool: true,
}, nil }, nil
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/require" "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/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testlog" "github.com/ethereum-optimism/optimism/op-node/testlog"
...@@ -25,7 +26,6 @@ func TestAttributesQueue(t *testing.T) { ...@@ -25,7 +26,6 @@ func TestAttributesQueue(t *testing.T) {
BlockTime: 2, BlockTime: 2,
L1ChainID: big.NewInt(101), L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102), L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb}, DepositContractAddress: common.Address{0xbb},
} }
rng := rand.New(rand.NewSource(1234)) rng := rand.New(rand.NewSource(1234))
...@@ -52,7 +52,7 @@ func TestAttributesQueue(t *testing.T) { ...@@ -52,7 +52,7 @@ func TestAttributesQueue(t *testing.T) {
attrs := eth.PayloadAttributes{ attrs := eth.PayloadAttributes{
Timestamp: eth.Uint64Quantity(safeHead.Time + cfg.BlockTime), Timestamp: eth.Uint64Quantity(safeHead.Time + cfg.BlockTime),
PrevRandao: eth.Bytes32(l1Info.InfoMixDigest), PrevRandao: eth.Bytes32(l1Info.InfoMixDigest),
SuggestedFeeRecipient: cfg.FeeRecipientAddress, SuggestedFeeRecipient: predeploys.SequencerFeeVaultAddr,
Transactions: []eth.Data{l1InfoTx, eth.Data("foobar"), eth.Data("example")}, Transactions: []eth.Data{l1InfoTx, eth.Data("foobar"), eth.Data("example")},
NoTxPool: true, NoTxPool: true,
} }
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"github.com/stretchr/testify/require" "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/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testutils" "github.com/ethereum-optimism/optimism/op-node/testutils"
...@@ -23,7 +24,6 @@ func TestPreparePayloadAttributes(t *testing.T) { ...@@ -23,7 +24,6 @@ func TestPreparePayloadAttributes(t *testing.T) {
BlockTime: 2, BlockTime: 2,
L1ChainID: big.NewInt(101), L1ChainID: big.NewInt(101),
L2ChainID: big.NewInt(102), L2ChainID: big.NewInt(102),
FeeRecipientAddress: common.Address{0xaa},
DepositContractAddress: common.Address{0xbb}, DepositContractAddress: common.Address{0xbb},
} }
...@@ -99,7 +99,7 @@ func TestPreparePayloadAttributes(t *testing.T) { ...@@ -99,7 +99,7 @@ func TestPreparePayloadAttributes(t *testing.T) {
require.NotNil(t, attrs) require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) 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, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0])) require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool) require.True(t, attrs.NoTxPool)
...@@ -136,7 +136,7 @@ func TestPreparePayloadAttributes(t *testing.T) { ...@@ -136,7 +136,7 @@ func TestPreparePayloadAttributes(t *testing.T) {
require.NotNil(t, attrs) require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) 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, len(l2Txs), len(attrs.Transactions), "Expected txs to equal l1 info tx + user deposit txs")
require.Equal(t, l2Txs, attrs.Transactions) require.Equal(t, l2Txs, attrs.Transactions)
require.True(t, attrs.NoTxPool) require.True(t, attrs.NoTxPool)
...@@ -161,7 +161,7 @@ func TestPreparePayloadAttributes(t *testing.T) { ...@@ -161,7 +161,7 @@ func TestPreparePayloadAttributes(t *testing.T) {
require.NotNil(t, attrs) require.NotNil(t, attrs)
require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp)) require.Equal(t, l2Parent.Time+cfg.BlockTime, uint64(attrs.Timestamp))
require.Equal(t, eth.Bytes32(l1Info.InfoMixDigest), attrs.PrevRandao) 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, 1, len(attrs.Transactions))
require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0])) require.Equal(t, l1InfoTx, []byte(attrs.Transactions[0]))
require.True(t, attrs.NoTxPool) require.True(t, attrs.NoTxPool)
......
...@@ -72,7 +72,7 @@ type EngineQueue struct { ...@@ -72,7 +72,7 @@ type EngineQueue struct {
// This update may repeat if the engine returns a temporary error. // This update may repeat if the engine returns a temporary error.
needForkchoiceUpdate bool needForkchoiceUpdate bool
finalizedL1 eth.BlockID finalizedL1 eth.L1BlockRef
safeAttributes []*eth.PayloadAttributes safeAttributes []*eth.PayloadAttributes
unsafePayloads PayloadsQueue // queue of unsafe payloads, ordered by ascending block number, may have gaps unsafePayloads PayloadsQueue // queue of unsafe payloads, ordered by ascending block number, may have gaps
...@@ -83,7 +83,7 @@ type EngineQueue struct { ...@@ -83,7 +83,7 @@ type EngineQueue struct {
engine Engine engine Engine
prev NextAttributesProvider 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 metrics Metrics
l1Fetcher L1Fetcher l1Fetcher L1Fetcher
...@@ -106,6 +106,7 @@ func NewEngineQueue(log log.Logger, cfg *rollup.Config, engine Engine, metrics M ...@@ -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 { func (eq *EngineQueue) Origin() eth.L1BlockRef {
return eq.origin return eq.origin
} }
...@@ -134,9 +135,28 @@ func (eq *EngineQueue) AddSafeAttributes(attributes *eth.PayloadAttributes) { ...@@ -134,9 +135,28 @@ func (eq *EngineQueue) AddSafeAttributes(attributes *eth.PayloadAttributes) {
eq.safeAttributes = append(eq.safeAttributes, attributes) eq.safeAttributes = append(eq.safeAttributes, attributes)
} }
func (eq *EngineQueue) Finalize(l1Origin eth.BlockID) { func (eq *EngineQueue) Finalize(l1Origin eth.L1BlockRef) {
eq.finalizedL1 = l1Origin if l1Origin.Number < eq.finalizedL1.Number {
eq.tryFinalizeL2() 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 { func (eq *EngineQueue) Finalized() eth.L2BlockRef {
...@@ -167,6 +187,7 @@ func (eq *EngineQueue) Step(ctx context.Context) error { ...@@ -167,6 +187,7 @@ func (eq *EngineQueue) Step(ctx context.Context) error {
} }
outOfData := false outOfData := false
if len(eq.safeAttributes) == 0 { if len(eq.safeAttributes) == 0 {
eq.origin = eq.prev.Origin()
if next, err := eq.prev.NextAttributes(ctx, eq.safeHead); err == io.EOF { if next, err := eq.prev.NextAttributes(ctx, eq.safeHead); err == io.EOF {
outOfData = true outOfData = true
} else if err != nil { } else if err != nil {
...@@ -191,7 +212,7 @@ func (eq *EngineQueue) Step(ctx context.Context) error { ...@@ -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, // and then marks the latest fully derived L2 block from this as finalized,
// or defaults to the current finalized L2 block. // or defaults to the current finalized L2 block.
func (eq *EngineQueue) tryFinalizeL2() { 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 return // if no L1 information is finalized yet, then skip this
} }
// default to keep the same finalized block // default to keep the same finalized block
...@@ -200,6 +221,7 @@ func (eq *EngineQueue) tryFinalizeL2() { ...@@ -200,6 +221,7 @@ func (eq *EngineQueue) tryFinalizeL2() {
for _, fd := range eq.finalityData { for _, fd := range eq.finalityData {
if fd.L2Block.Number > finalizedL2.Number && fd.L1Block.Number <= eq.finalizedL1.Number { if fd.L2Block.Number > finalizedL2.Number && fd.L1Block.Number <= eq.finalizedL1.Number {
finalizedL2 = fd.L2Block finalizedL2 = fd.L2Block
eq.needForkchoiceUpdate = true
} }
} }
eq.finalized = finalizedL2 eq.finalized = finalizedL2
...@@ -214,11 +236,11 @@ func (eq *EngineQueue) postProcessSafeL2() { ...@@ -214,11 +236,11 @@ func (eq *EngineQueue) postProcessSafeL2() {
eq.finalityData = append(eq.finalityData[:0], eq.finalityData[1:finalityLookback]...) eq.finalityData = append(eq.finalityData[:0], eq.finalityData[1:finalityLookback]...)
} }
// remember the last L2 block that we fully derived from the given finality data // 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 // append entry for new L1 block
eq.finalityData = append(eq.finalityData, FinalityData{ eq.finalityData = append(eq.finalityData, FinalityData{
L2Block: eq.safeHead, L2Block: eq.safeHead,
L1Block: eq.prev.Origin().ID(), L1Block: eq.origin.ID(),
}) })
} else { } else {
// if it's a now L2 block that was derived from the same latest L1 block, then just update the entry // 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) { ...@@ -233,7 +255,7 @@ func (eq *EngineQueue) logSyncProgress(reason string) {
"l2_safe", eq.safeHead, "l2_safe", eq.safeHead,
"l2_unsafe", eq.unsafeHead, "l2_unsafe", eq.unsafeHead,
"l2_time", eq.unsafeHead.Time, "l2_time", eq.unsafeHead.Time,
"l1_derived", eq.prev.Origin(), "l1_derived", eq.origin,
) )
} }
......
...@@ -250,7 +250,7 @@ func TestEngineQueue_Finalize(t *testing.T) { ...@@ -250,7 +250,7 @@ func TestEngineQueue_Finalize(t *testing.T) {
eq.postProcessSafeL2() eq.postProcessSafeL2()
// let's finalize D (current L1), from which we fully derived C1 (it was safe head), but not D0 (included in E) // 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") require.Equal(t, refC1, eq.Finalized(), "C1 was included in finalized D, and should now be finalized")
......
...@@ -5,9 +5,10 @@ import ( ...@@ -5,9 +5,10 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/rollup" "github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum/go-ethereum/log"
) )
type Metrics interface { type Metrics interface {
...@@ -30,13 +31,14 @@ type ResetableStage interface { ...@@ -30,13 +31,14 @@ type ResetableStage interface {
} }
type EngineQueueStage interface { type EngineQueueStage interface {
FinalizedL1() eth.L1BlockRef
Finalized() eth.L2BlockRef Finalized() eth.L2BlockRef
UnsafeL2Head() eth.L2BlockRef UnsafeL2Head() eth.L2BlockRef
SafeL2Head() eth.L2BlockRef SafeL2Head() eth.L2BlockRef
Origin() eth.L1BlockRef Origin() eth.L1BlockRef
SetUnsafeHead(head eth.L2BlockRef) SetUnsafeHead(head eth.L2BlockRef)
Finalize(l1Origin eth.BlockID) Finalize(l1Origin eth.L1BlockRef)
AddSafeAttributes(attributes *eth.PayloadAttributes) AddSafeAttributes(attributes *eth.PayloadAttributes)
AddUnsafePayload(payload *eth.ExecutionPayload) AddUnsafePayload(payload *eth.ExecutionPayload)
Step(context.Context) error Step(context.Context) error
...@@ -97,14 +99,22 @@ func (dp *DerivationPipeline) Reset() { ...@@ -97,14 +99,22 @@ func (dp *DerivationPipeline) Reset() {
dp.resetting = 0 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 { func (dp *DerivationPipeline) Origin() eth.L1BlockRef {
return dp.eng.Origin() return dp.eng.Origin()
} }
func (dp *DerivationPipeline) Finalize(l1Origin eth.BlockID) { func (dp *DerivationPipeline) Finalize(l1Origin eth.L1BlockRef) {
dp.eng.Finalize(l1Origin) 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 { func (dp *DerivationPipeline) Finalized() eth.L2BlockRef {
return dp.eng.Finalized() return dp.eng.Finalized()
} }
......
...@@ -39,6 +39,7 @@ type L2Chain interface { ...@@ -39,6 +39,7 @@ type L2Chain interface {
derive.Engine derive.Engine
L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel) (eth.L2BlockRef, error)
L2BlockRefByHash(ctx context.Context, l2Hash common.Hash) (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 { type DerivationPipeline interface {
...@@ -46,7 +47,8 @@ type DerivationPipeline interface { ...@@ -46,7 +47,8 @@ type DerivationPipeline interface {
Step(ctx context.Context) error Step(ctx context.Context) error
SetUnsafeHead(head eth.L2BlockRef) SetUnsafeHead(head eth.L2BlockRef)
AddUnsafePayload(payload *eth.ExecutionPayload) AddUnsafePayload(payload *eth.ExecutionPayload)
Finalize(ref eth.BlockID) Finalize(ref eth.L1BlockRef)
FinalizedL1() eth.L1BlockRef
Finalized() eth.L2BlockRef Finalized() eth.L2BlockRef
SafeL2Head() eth.L2BlockRef SafeL2Head() eth.L2BlockRef
UnsafeL2Head() eth.L2BlockRef UnsafeL2Head() eth.L2BlockRef
...@@ -92,7 +94,7 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, ne ...@@ -92,7 +94,7 @@ func NewDriver(driverCfg *Config, cfg *rollup.Config, l2 L2Chain, l1 L1Chain, ne
l1State: l1State, l1State: l1State,
derivation: derivationPipeline, derivation: derivationPipeline,
idleDerivation: false, idleDerivation: false,
syncStatusReq: make(chan chan eth.SyncStatus, 10), stateReq: make(chan chan struct{}),
forceReset: make(chan chan struct{}, 10), forceReset: make(chan chan struct{}, 10),
config: cfg, config: cfg,
driverConfig: driverCfg, driverConfig: driverCfg,
......
...@@ -30,8 +30,8 @@ type Driver struct { ...@@ -30,8 +30,8 @@ type Driver struct {
// When the derivation pipeline is waiting for new data to do anything // When the derivation pipeline is waiting for new data to do anything
idleDerivation bool idleDerivation bool
// Requests for sync status. Synchronized with event loop to avoid reading an inconsistent sync status. // Requests to block the event loop for synchronous execution to avoid reading an inconsistent state
syncStatusReq chan chan eth.SyncStatus stateReq chan chan struct{}
// Upon receiving a channel in this channel, the derivation pipeline is forced to be reset. // 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. // It tells the caller that the reset occurred by closing the passed in channel.
...@@ -300,7 +300,7 @@ func (s *Driver) eventLoop() { ...@@ -300,7 +300,7 @@ func (s *Driver) eventLoop() {
// no step, justified L1 information does not do anything for L2 derivation or status // no step, justified L1 information does not do anything for L2 derivation or status
case newL1Finalized := <-s.l1FinalizedSig: case newL1Finalized := <-s.l1FinalizedSig:
s.l1State.HandleNewL1FinalizedBlock(newL1Finalized) 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 reqStep() // we may be able to mark more L2 data as finalized now
case <-delayedStepReq: case <-delayedStepReq:
delayedStepReq = nil delayedStepReq = nil
...@@ -342,16 +342,8 @@ func (s *Driver) eventLoop() { ...@@ -342,16 +342,8 @@ func (s *Driver) eventLoop() {
stepAttempts = 0 stepAttempts = 0
reqStep() // continue with the next step if we can reqStep() // continue with the next step if we can
} }
case respCh := <-s.syncStatusReq: case respCh := <-s.stateReq:
respCh <- eth.SyncStatus{ respCh <- struct{}{}
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.forceReset: case respCh := <-s.forceReset:
s.log.Warn("Derivation pipeline is manually reset") s.log.Warn("Derivation pipeline is manually reset")
s.derivation.Reset() s.derivation.Reset()
...@@ -381,18 +373,48 @@ func (s *Driver) ResetDerivationPipeline(ctx context.Context) error { ...@@ -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) { func (s *Driver) SyncStatus(ctx context.Context) (*eth.SyncStatus, error) {
respCh := make(chan eth.SyncStatus, 1) wait := make(chan struct{})
select { select {
case s.stateReq <- wait:
resp := s.syncStatus()
<-wait
return resp, nil
case <-ctx.Done(): case <-ctx.Done():
return nil, ctx.Err() return nil, ctx.Err()
case s.syncStatusReq <- respCh: }
select { }
case <-ctx.Done():
return nil, ctx.Err() // BlockRefWithStatus blocks the driver event loop and captures the syncing status,
case resp := <-respCh: // along with an L2 block reference by number consistent with that same status.
return &resp, nil // 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 eth.L2BlockRef{}, nil, ctx.Err()
} }
} }
......
...@@ -45,8 +45,6 @@ type Config struct { ...@@ -45,8 +45,6 @@ type Config struct {
// Note: below addresses are part of the block-derivation process, // Note: below addresses are part of the block-derivation process,
// and required to be the same network-wide to stay in consensus. // 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. // L1 address that batches are sent to.
BatchInboxAddress common.Address `json:"batch_inbox_address"` BatchInboxAddress common.Address `json:"batch_inbox_address"`
// Acceptable batch-sender address // Acceptable batch-sender address
...@@ -81,9 +79,6 @@ func (cfg *Config) Check() error { ...@@ -81,9 +79,6 @@ func (cfg *Config) Check() error {
if cfg.P2PSequencerAddress == (common.Address{}) { if cfg.P2PSequencerAddress == (common.Address{}) {
return errors.New("missing p2p sequencer 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{}) { if cfg.BatchInboxAddress == (common.Address{}) {
return errors.New("missing batch inbox address") return errors.New("missing batch inbox address")
} }
......
...@@ -28,13 +28,12 @@ func randConfig() *Config { ...@@ -28,13 +28,12 @@ func randConfig() *Config {
L2: eth.BlockID{Hash: randHash(), Number: 1337}, L2: eth.BlockID{Hash: randHash(), Number: 1337},
L2Time: uint64(time.Now().Unix()), L2Time: uint64(time.Now().Unix()),
}, },
BlockTime: 2, BlockTime: 2,
MaxSequencerDrift: 100, MaxSequencerDrift: 100,
SeqWindowSize: 2, SeqWindowSize: 2,
L1ChainID: big.NewInt(900), L1ChainID: big.NewInt(900),
FeeRecipientAddress: randAddr(), BatchInboxAddress: randAddr(),
BatchInboxAddress: randAddr(), BatchSenderAddress: randAddr(),
BatchSenderAddress: randAddr(),
} }
} }
......
...@@ -11,6 +11,7 @@ const config = { ...@@ -11,6 +11,7 @@ const config = {
hardhat: { hardhat: {
gasPrice, gasPrice,
initialBaseFeePerGas: 0, initialBaseFeePerGas: 0,
chainId: process.env.FORK_CHAIN_ID ? Number(process.env.FORK_CHAIN_ID) : 31337
}, },
}, },
analytics: { enabled: false }, analytics: { enabled: false },
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
"event-name-camelcase": "off", "event-name-camelcase": "off",
"reason-string": "off", "reason-string": "off",
"avoid-tx-origin": "off", "avoid-tx-origin": "off",
"var-name-mixedcase": "off",
"func-visibility": ["warn", { "ignoreConstructors": true }] "func-visibility": ["warn", { "ignoreConstructors": true }]
} }
} }
...@@ -19,31 +19,26 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -19,31 +19,26 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
/** /**
* @notice The interval in L2 blocks at which checkpoints must be submitted. * @notice The interval in L2 blocks at which checkpoints must be submitted.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable SUBMISSION_INTERVAL; uint256 public immutable SUBMISSION_INTERVAL;
/** /**
* @notice The number of blocks in the chain before the first block in this contract. * @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; uint256 public immutable HISTORICAL_TOTAL_BLOCKS;
/** /**
* @notice The number of the first L2 block recorded in this contract. * @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; uint256 public immutable STARTING_BLOCK_NUMBER;
/** /**
* @notice The timestamp of the first L2 block recorded in this contract. * @notice The timestamp of the first L2 block recorded in this contract.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable STARTING_TIMESTAMP; uint256 public immutable STARTING_TIMESTAMP;
/** /**
* @notice The time between L2 blocks in seconds. * @notice The time between L2 blocks in seconds.
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 public immutable L2_BLOCK_TIME; uint256 public immutable L2_BLOCK_TIME;
/** /**
...@@ -170,6 +165,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver { ...@@ -170,6 +165,7 @@ contract L2OutputOracle is OwnableUpgradeable, Semver {
* *
* @param _proposal Represents the output proposal to delete * @param _proposal Represents the output proposal to delete
*/ */
// solhint-disable-next-line ordering
function deleteL2Output(Types.OutputProposal memory _proposal) external onlyOwner { function deleteL2Output(Types.OutputProposal memory _proposal) external onlyOwner {
Types.OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber]; Types.OutputProposal memory outputToDelete = l2Outputs[latestBlockNumber];
......
...@@ -32,13 +32,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -32,13 +32,11 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
/** /**
* @notice Minimum time (in seconds) that must elapse before a withdrawal can be finalized. * @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; uint256 public immutable FINALIZATION_PERIOD_SECONDS;
/** /**
* @notice Address of the L2OutputOracle. * @notice Address of the L2OutputOracle.
*/ */
// solhint-disable-next-line var-name-mixedcase
L2OutputOracle public immutable L2_ORACLE; L2OutputOracle public immutable L2_ORACLE;
/** /**
...@@ -113,6 +111,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver { ...@@ -113,6 +111,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
* function for EOAs. Contracts should call the depositTransaction() function directly * function for EOAs. Contracts should call the depositTransaction() function directly
* otherwise any deposited funds will be lost due to address aliasing. * otherwise any deposited funds will be lost due to address aliasing.
*/ */
// solhint-disable-next-line ordering
receive() external payable { receive() external payable {
depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes("")); depositTransaction(msg.sender, msg.value, RECEIVE_DEFAULT_GAS_LIMIT, false, bytes(""));
} }
......
...@@ -19,14 +19,6 @@ contract BaseSystemDictator is Ownable { ...@@ -19,14 +19,6 @@ contract BaseSystemDictator is Ownable {
*/ */
uint256 public currentStep = 1; 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. * @notice Checks that the current step is the expected step, then bumps the current step.
* *
...@@ -37,4 +29,12 @@ contract BaseSystemDictator is Ownable { ...@@ -37,4 +29,12 @@ contract BaseSystemDictator is Ownable {
_; _;
currentStep++; currentStep++;
} }
/**
* @param _config System configuration.
*/
constructor(SystemConfig memory _config) Ownable() {
config = _config;
_transferOwnership(config.globalConfig.controller);
}
} }
...@@ -123,18 +123,18 @@ contract MigrationSystemDictator is BaseSystemDictator { ...@@ -123,18 +123,18 @@ contract MigrationSystemDictator is BaseSystemDictator {
abi.encodeCall(OptimismPortal.initialize, ()) abi.encodeCall(OptimismPortal.initialize, ())
); );
// Upgrade and initialize the L1CrossDomainMessenger. // Upgrade the L1CrossDomainMessenger. No initializer because this is
config.globalConfig.proxyAdmin.upgradeAndCall( // already initialized.
config.globalConfig.proxyAdmin.upgrade(
payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy), payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),
address(config.implementationAddressConfig.l1CrossDomainMessengerImpl), address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)
abi.encodeCall(L1CrossDomainMessenger.initialize, ())
); );
// Transfer ETH from the L1StandardBridge to the OptimismPortal. // Transfer ETH from the L1StandardBridge to the OptimismPortal.
config.globalConfig.proxyAdmin.upgradeAndCall( config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.l1StandardBridgeProxy), payable(config.proxyAddressConfig.l1StandardBridgeProxy),
address(config.implementationAddressConfig.portalSenderImpl), address(config.implementationAddressConfig.portalSenderImpl),
abi.encodeCall(PortalSender.send, ()) abi.encodeCall(PortalSender.donate, ())
); );
// Upgrade the L1StandardBridge (no initializer). // Upgrade the L1StandardBridge (no initializer).
......
...@@ -24,7 +24,7 @@ contract PortalSender { ...@@ -24,7 +24,7 @@ contract PortalSender {
/** /**
* @notice Sends balance of this contract to the OptimismPortal. * @notice Sends balance of this contract to the OptimismPortal.
*/ */
function send() public { function donate() public {
portal.donateETH{ value: address(this).balance }(); portal.donateETH{ value: address(this).balance }();
} }
} }
...@@ -9,6 +9,21 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol"; ...@@ -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. * @notice ERC721Bridge is a base contract for the L1 and L2 ERC721 bridges.
*/ */
abstract contract ERC721Bridge { 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. * @notice Emitted when an ERC721 bridge to the other network is initiated.
* *
...@@ -47,21 +62,6 @@ abstract contract ERC721Bridge { ...@@ -47,21 +62,6 @@ abstract contract ERC721Bridge {
bytes extraData 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. * @notice Ensures that the caller is a cross-chain message from the other bridge.
*/ */
......
...@@ -27,21 +27,6 @@ interface IOptimismMintableERC721 is IERC721Enumerable { ...@@ -27,21 +27,6 @@ interface IOptimismMintableERC721 is IERC721Enumerable {
*/ */
event Burn(address indexed account, uint256 tokenId); 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 * @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. * are aware of the ERC721 protocol to prevent tokens from being forever locked.
...@@ -58,4 +43,19 @@ interface IOptimismMintableERC721 is IERC721Enumerable { ...@@ -58,4 +43,19 @@ interface IOptimismMintableERC721 is IERC721Enumerable {
* @param _tokenId Token ID to burn. * @param _tokenId Token ID to burn.
*/ */
function burn(address _from, uint256 _tokenId) external; 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 { ...@@ -36,6 +36,14 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 {
*/ */
string public baseTokenURI; 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 _bridge Address of the bridge on this network.
* @param _remoteChainId Chain ID where the remote token is deployed. * @param _remoteChainId Chain ID where the remote token is deployed.
...@@ -74,14 +82,6 @@ contract OptimismMintableERC721 is ERC721Enumerable, IOptimismMintableERC721 { ...@@ -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 * @inheritdoc IOptimismMintableERC721
*/ */
......
...@@ -9,19 +9,6 @@ import { Semver } from "./Semver.sol"; ...@@ -9,19 +9,6 @@ import { Semver } from "./Semver.sol";
* @notice Factory contract for creating OptimismMintableERC721 contracts. * @notice Factory contract for creating OptimismMintableERC721 contracts.
*/ */
contract OptimismMintableERC721Factory is Semver { 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. * @notice Address of the ERC721 bridge on this network.
*/ */
...@@ -37,6 +24,19 @@ contract OptimismMintableERC721Factory is Semver { ...@@ -37,6 +24,19 @@ contract OptimismMintableERC721Factory is Semver {
*/ */
mapping(address => bool) public isOptimismMintableERC721; 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 * @custom:semver 1.0.0
* *
......
...@@ -11,19 +11,16 @@ contract Semver { ...@@ -11,19 +11,16 @@ contract Semver {
/** /**
* @notice Contract version number (major). * @notice Contract version number (major).
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 private immutable MAJOR_VERSION; uint256 private immutable MAJOR_VERSION;
/** /**
* @notice Contract version number (minor). * @notice Contract version number (minor).
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 private immutable MINOR_VERSION; uint256 private immutable MINOR_VERSION;
/** /**
* @notice Contract version number (patch). * @notice Contract version number (patch).
*/ */
// solhint-disable-next-line var-name-mixedcase
uint256 private immutable PATCH_VERSION; uint256 private immutable PATCH_VERSION;
/** /**
......
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
"sequencerWindowSize": 4, "sequencerWindowSize": 4,
"channelTimeout": 40, "channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000", "batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
"sequencerWindowSize": 120, "sequencerWindowSize": 120,
"channelTimeout": 120, "channelTimeout": 120,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0x26862c200bd48c19f39d9e1cd88a3b439611d911",
"batchInboxAddress": "0xff00000000000000000000000000000000000002", "batchInboxAddress": "0xff00000000000000000000000000000000000002",
"batchSenderAddress": "0xa11d2b908470e17923fff184d48269bebbd9b2a5", "batchSenderAddress": "0xa11d2b908470e17923fff184d48269bebbd9b2a5",
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
"sequencerWindowSize": 4, "sequencerWindowSize": 4,
"channelTimeout": 40, "channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc", "p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"optimismL2FeeRecipient": "0xd9c09e21b57c98e58a80552c170989b426766aa7",
"batchInboxAddress": "0xff00000000000000000000000000000000000000", "batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", "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) => { ...@@ -13,8 +13,7 @@ const deployFn: DeployFunction = async (hre) => {
) )
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'L1CrossDomainMessengerImpl', name: 'L1CrossDomainMessenger',
contract: 'L1CrossDomainMessenger',
args: [OptimismPortalProxy.address], args: [OptimismPortalProxy.address],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
......
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import { predeploys } from '../src' import { predeploys } from '../src'
...@@ -8,14 +9,22 @@ import { ...@@ -8,14 +9,22 @@ import {
} from '../src/deploy-utils' } from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const L1CrossDomainMessengerProxy = await getContractFromArtifact( let L1CrossDomainMessengerProxy: ethers.Contract
hre, try {
'L1CrossDomainMessengerProxy' L1CrossDomainMessengerProxy = await getContractFromArtifact(
) hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
} catch {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy'
)
}
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'L1StandardBridgeImpl', name: 'L1StandardBridge',
contract: 'L1StandardBridge',
args: [L1CrossDomainMessengerProxy.address], args: [L1CrossDomainMessengerProxy.address],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
......
...@@ -2,6 +2,8 @@ import assert from 'assert' ...@@ -2,6 +2,8 @@ import assert from 'assert'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import '@nomiclabs/hardhat-ethers'
import { import {
assertContractVariable, assertContractVariable,
...@@ -26,8 +28,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -26,8 +28,7 @@ const deployFn: DeployFunction = async (hre) => {
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'L2OutputOracleImpl', name: 'L2OutputOracle',
contract: 'L2OutputOracle',
args: [ args: [
hre.deployConfig.l2OutputOracleSubmissionInterval, hre.deployConfig.l2OutputOracleSubmissionInterval,
hre.deployConfig.l2OutputOracleGenesisL2Output, hre.deployConfig.l2OutputOracleGenesisL2Output,
......
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import { import {
assertContractVariable, assertContractVariable,
...@@ -13,8 +14,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -13,8 +14,7 @@ const deployFn: DeployFunction = async (hre) => {
) )
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'OptimismPortalImpl', name: 'OptimismPortal',
contract: 'OptimismPortal',
args: [ args: [
L2OutputOracleProxy.address, L2OutputOracleProxy.address,
hre.deployConfig.finalizationPeriodSeconds, hre.deployConfig.finalizationPeriodSeconds,
......
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import { import {
...@@ -7,14 +8,22 @@ import { ...@@ -7,14 +8,22 @@ import {
} from '../src/deploy-utils' } from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const L1StandardBridgeProxy = await getContractFromArtifact( let L1StandardBridgeProxy: ethers.Contract
hre, try {
'L1StandardBridgeProxy' L1StandardBridgeProxy = await getContractFromArtifact(
) hre,
'Proxy__OVM_L1StandardBridge'
)
} catch (e) {
L1StandardBridgeProxy = await getContractFromArtifact(
hre,
'L1StandardBridgeProxy'
)
}
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'OptimismMintableERC20FactoryImpl', name: 'OptimismMintableERC20Factory',
contract: 'OptimismMintableERC20Factory',
args: [L1StandardBridgeProxy.address], args: [L1StandardBridgeProxy.address],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
......
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import { predeploys } from '../src' import { predeploys } from '../src'
...@@ -8,14 +9,22 @@ import { ...@@ -8,14 +9,22 @@ import {
} from '../src/deploy-utils' } from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const L1CrossDomainMessengerProxy = await getContractFromArtifact( let L1CrossDomainMessengerProxy: ethers.Contract
hre, try {
'L1CrossDomainMessengerProxy' L1CrossDomainMessengerProxy = await getContractFromArtifact(
) hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
} catch {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy'
)
}
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'L1ERC721BridgeImpl', name: 'L1ERC721Bridge',
contract: 'L1ERC721Bridge',
args: [L1CrossDomainMessengerProxy.address, predeploys.L2ERC721Bridge], args: [L1CrossDomainMessengerProxy.address, predeploys.L2ERC721Bridge],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
......
...@@ -13,8 +13,7 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -13,8 +13,7 @@ const deployFn: DeployFunction = async (hre) => {
) )
await deployAndVerifyAndThen({ await deployAndVerifyAndThen({
hre, hre,
name: 'PortalSenderImpl', name: 'PortalSender',
contract: 'PortalSender',
args: [OptimismPortalProxy.address], args: [OptimismPortalProxy.address],
postDeployAction: async (contract) => { postDeployAction: async (contract) => {
await assertContractVariable( await assertContractVariable(
......
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import { import {
getDeploymentAddress, getDeploymentAddress,
...@@ -46,31 +48,22 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -46,31 +48,22 @@ const deployFn: DeployFunction = async (hre) => {
), ),
}, },
implementationAddressConfig: { implementationAddressConfig: {
l2OutputOracleImpl: await getDeploymentAddress( l2OutputOracleImpl: await getDeploymentAddress(hre, 'L2OutputOracle'),
hre, optimismPortalImpl: await getDeploymentAddress(hre, 'OptimismPortal'),
'L2OutputOracleImpl'
),
optimismPortalImpl: await getDeploymentAddress(
hre,
'OptimismPortalImpl'
),
l1CrossDomainMessengerImpl: await getDeploymentAddress( l1CrossDomainMessengerImpl: await getDeploymentAddress(
hre, hre,
'L1CrossDomainMessengerImpl' 'L1CrossDomainMessenger'
), ),
l1StandardBridgeImpl: await getDeploymentAddress( l1StandardBridgeImpl: await getDeploymentAddress(
hre, hre,
'L1StandardBridgeImpl' 'L1StandardBridge'
), ),
optimismMintableERC20FactoryImpl: await getDeploymentAddress( optimismMintableERC20FactoryImpl: await getDeploymentAddress(
hre, hre,
'OptimismMintableERC20FactoryImpl' 'OptimismMintableERC20Factory'
),
l1ERC721BridgeImpl: await getDeploymentAddress(
hre,
'L1ERC721BridgeImpl'
), ),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSenderImpl'), l1ERC721BridgeImpl: await getDeploymentAddress(hre, 'L1ERC721Bridge'),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSender'),
}, },
l2OutputOracleConfig: { l2OutputOracleConfig: {
l2OutputOracleGenesisL2Output: l2OutputOracleGenesisL2Output:
......
import { awaitCondition } from '@eth-optimism/core-utils' import { awaitCondition } from '@eth-optimism/core-utils'
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types' import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import { import {
getDeploymentAddress, getDeploymentAddress,
...@@ -31,6 +33,22 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -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({ await deployAndVerifyAndThen({
hre, hre,
name: 'MigrationSystemDictator', name: 'MigrationSystemDictator',
...@@ -38,8 +56,8 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -38,8 +56,8 @@ const deployFn: DeployFunction = async (hre) => {
{ {
globalConfig: { globalConfig: {
proxyAdmin: await getDeploymentAddress(hre, 'ProxyAdmin'), proxyAdmin: await getDeploymentAddress(hre, 'ProxyAdmin'),
controller: deployer, // TODO controller,
finalOwner: hre.deployConfig.proxyAdminOwner, finalOwner,
addressManager: hre.deployConfig.addressManager, addressManager: hre.deployConfig.addressManager,
}, },
proxyAddressConfig: { proxyAddressConfig: {
...@@ -69,31 +87,22 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -69,31 +87,22 @@ const deployFn: DeployFunction = async (hre) => {
), ),
}, },
implementationAddressConfig: { implementationAddressConfig: {
l2OutputOracleImpl: await getDeploymentAddress( l2OutputOracleImpl: await getDeploymentAddress(hre, 'L2OutputOracle'),
hre, optimismPortalImpl: await getDeploymentAddress(hre, 'OptimismPortal'),
'L2OutputOracleImpl'
),
optimismPortalImpl: await getDeploymentAddress(
hre,
'OptimismPortalImpl'
),
l1CrossDomainMessengerImpl: await getDeploymentAddress( l1CrossDomainMessengerImpl: await getDeploymentAddress(
hre, hre,
'L1CrossDomainMessengerImpl' 'L1CrossDomainMessenger'
), ),
l1StandardBridgeImpl: await getDeploymentAddress( l1StandardBridgeImpl: await getDeploymentAddress(
hre, hre,
'L1StandardBridgeImpl' 'L1StandardBridge'
), ),
optimismMintableERC20FactoryImpl: await getDeploymentAddress( optimismMintableERC20FactoryImpl: await getDeploymentAddress(
hre, hre,
'OptimismMintableERC20FactoryImpl' 'OptimismMintableERC20Factory'
),
l1ERC721BridgeImpl: await getDeploymentAddress(
hre,
'L1ERC721BridgeImpl'
), ),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSenderImpl'), l1ERC721BridgeImpl: await getDeploymentAddress(hre, 'L1ERC721Bridge'),
portalSenderImpl: await getDeploymentAddress(hre, 'PortalSender'),
}, },
l2OutputOracleConfig: { l2OutputOracleConfig: {
l2OutputOracleGenesisL2Output: l2OutputOracleGenesisL2Output:
...@@ -125,9 +134,13 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -125,9 +134,13 @@ const deployFn: DeployFunction = async (hre) => {
await ProxyAdmin.setOwner(MigrationSystemDictator.address) await ProxyAdmin.setOwner(MigrationSystemDictator.address)
// Transfer ownership of the AddressManager to MigrationSystemDictator. // Transfer ownership of the AddressManager to MigrationSystemDictator.
const AddressManager = await getContractFromArtifact(hre, 'AddressManager', { const AddressManager = await getContractFromArtifact(
signerOrProvider: deployer, hre,
}) 'Lib_AddressManager',
{
signerOrProvider: deployer,
}
)
if (isLiveDeployer) { if (isLiveDeployer) {
console.log( console.log(
`Transferring ownership of AddressManager to the MigrationSystemDictator...` `Transferring ownership of AddressManager to the MigrationSystemDictator...`
...@@ -187,8 +200,14 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -187,8 +200,14 @@ const deployFn: DeployFunction = async (hre) => {
`Please transfer ownership of the L1StandardBridge (proxy) to the MigrationSystemDictator located at: ${MigrationSystemDictator.address}` `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 () => { await awaitCondition(async () => {
const owner = await L1StandardBridge.owner() const owner = await noSigner.callStatic.getOwner({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address return owner === MigrationSystemDictator.address
}) })
...@@ -198,11 +217,12 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -198,11 +217,12 @@ const deployFn: DeployFunction = async (hre) => {
await MigrationSystemDictator[`step${i}`]() await MigrationSystemDictator[`step${i}`]()
} else { } else {
console.log(`Please execute step ${i}...`) console.log(`Please execute step ${i}...`)
await awaitCondition(async () => {
const step = await MigrationSystemDictator.step()
return step.toNumber() === i
})
} }
await awaitCondition(async () => {
const step = await MigrationSystemDictator.currentStep()
return step.toNumber() === i + 1
})
} }
} }
......
import { ethers } from 'ethers' import { ethers } from 'ethers'
import { HardhatUserConfig, task, subtask } from 'hardhat/config' import { HardhatUserConfig } from 'hardhat/config'
import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names'
// Hardhat plugins // Hardhat plugins
import '@eth-optimism/hardhat-deploy-config' import '@eth-optimism/hardhat-deploy-config'
...@@ -11,22 +10,6 @@ import 'hardhat-deploy' ...@@ -11,22 +10,6 @@ import 'hardhat-deploy'
// Hardhat tasks // Hardhat tasks
import './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 = { const config: HardhatUserConfig = {
networks: { networks: {
devnetL1: { devnetL1: {
...@@ -56,6 +39,12 @@ const config: HardhatUserConfig = { ...@@ -56,6 +39,12 @@ const config: HardhatUserConfig = {
url: process.env.L1_RPC || '', url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero], 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: { foundry: {
buildInfo: true, buildInfo: true,
...@@ -150,11 +139,6 @@ const config: HardhatUserConfig = { ...@@ -150,11 +139,6 @@ const config: HardhatUserConfig = {
p2pSequencerAddress: { p2pSequencerAddress: {
type: 'address', 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. // L1 address that batches are sent to.
// "batch_inbox_address" in rollup config. // "batch_inbox_address" in rollup config.
batchInboxAddress: { batchInboxAddress: {
...@@ -367,6 +351,7 @@ const config: HardhatUserConfig = { ...@@ -367,6 +351,7 @@ const config: HardhatUserConfig = {
], ],
deployments: { deployments: {
goerli: ['../contracts/deployments/goerli'], goerli: ['../contracts/deployments/goerli'],
'mainnet-forked': ['../contracts/deployments/mainnet'],
}, },
}, },
solidity: { 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' ...@@ -6,3 +6,5 @@ import './check-l2-config'
import './watch' import './watch'
import './forge-verify' import './forge-verify'
import './validate-spacers' import './validate-spacers'
import './solidity'
import './accounts'
...@@ -11,7 +11,6 @@ task('rekey', 'Generates a new set of keys for a test network').setAction( ...@@ -11,7 +11,6 @@ task('rekey', 'Generates a new set of keys for a test network').setAction(
'proxyAdminOwner', 'proxyAdminOwner',
'optimismBaseFeeRecipient', 'optimismBaseFeeRecipient',
'optimismL1FeeRecipient', 'optimismL1FeeRecipient',
'optimismL2FeeRecipient',
'p2pSequencerAddress', 'p2pSequencerAddress',
'l2OutputOracleOwner', 'l2OutputOracleOwner',
'batchSenderAddress', 'batchSenderAddress',
......
...@@ -65,7 +65,6 @@ task('rollup-config', 'create a genesis config') ...@@ -65,7 +65,6 @@ task('rollup-config', 'create a genesis config')
l2_chain_id: deployConfig.l2ChainID, l2_chain_id: deployConfig.l2ChainID,
p2p_sequencer_address: deployConfig.p2pSequencerAddress, p2p_sequencer_address: deployConfig.p2pSequencerAddress,
fee_recipient_address: deployConfig.optimismL2FeeRecipient,
batch_inbox_address: deployConfig.batchInboxAddress, batch_inbox_address: deployConfig.batchInboxAddress,
batch_sender_address: deployConfig.batchSenderAddress, batch_sender_address: deployConfig.batchSenderAddress,
deposit_contract_address: portal.address, 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 ...@@ -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. * 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. * 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) function setGasParams(uint256 _l2GasDiscountDivisor, uint256 _enqueueGasCost)
external external
...@@ -416,6 +418,8 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes ...@@ -416,6 +418,8 @@ contract CanonicalTransactionChain is ICanonicalTransactionChain, Lib_AddressRes
* Parses the batch context from the extra data. * Parses the batch context from the extra data.
* @return Total number of elements submitted. * @return Total number of elements submitted.
* @return Index of the next queue element. * @return Index of the next queue element.
* @return Timestamp for the last transaction
* @return Block number for the last transaction.
*/ */
function _getBatchExtraData() function _getBatchExtraData()
internal internal
......
...@@ -62,6 +62,7 @@ interface IStateCommitmentChain { ...@@ -62,6 +62,7 @@ interface IStateCommitmentChain {
* @param _element Hash of the element to verify a proof for. * @param _element Hash of the element to verify a proof for.
* @param _batchHeader Header of the batch in which the element was included. * @param _batchHeader Header of the batch in which the element was included.
* @param _proof Merkle inclusion proof for the element. * @param _proof Merkle inclusion proof for the element.
* @return _verified Whether or not the batch inclusion proof is verified.
*/ */
function verifyStateCommitment( function verifyStateCommitment(
bytes32 _element, bytes32 _element,
......
...@@ -34,6 +34,9 @@ contract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver { ...@@ -34,6 +34,9 @@ contract StateCommitmentChain is IStateCommitmentChain, Lib_AddressResolver {
/** /**
* @param _libAddressManager Address of the Address Manager. * @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( constructor(
address _libAddressManager, address _libAddressManager,
......
...@@ -20,10 +20,7 @@ contract BondManager is IBondManager, Lib_AddressResolver { ...@@ -20,10 +20,7 @@ contract BondManager is IBondManager, Lib_AddressResolver {
constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) {} constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) {}
/** /**
* Checks whether a given address is properly collateralized and can perform actions within * @inheritdoc IBondManager
* the system.
* @param _who Address to check.
* @return true if the address is properly collateralized, false otherwise.
*/ */
// slither-disable-next-line external-function // slither-disable-next-line external-function
function isCollateralized(address _who) public view returns (bool) { function isCollateralized(address _who) public view returns (bool) {
......
...@@ -9,5 +9,11 @@ interface IBondManager { ...@@ -9,5 +9,11 @@ interface IBondManager {
* Public Functions * * 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); function isCollateralized(address _who) external view returns (bool);
} }
...@@ -50,7 +50,7 @@ interface IL2ERC20Bridge { ...@@ -50,7 +50,7 @@ interface IL2ERC20Bridge {
* @dev initiate a withdraw of some tokens to the caller's account on L1 * @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 _l2Token Address of L2 token where withdrawal was initiated.
* @param _amount Amount of the token to withdraw. * @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 * @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum * solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content. * length, these contracts provide no guarantees about its content.
...@@ -67,7 +67,7 @@ interface IL2ERC20Bridge { ...@@ -67,7 +67,7 @@ interface IL2ERC20Bridge {
* @param _l2Token Address of L2 token where withdrawal is initiated. * @param _l2Token Address of L2 token where withdrawal is initiated.
* @param _to L1 adress to credit the withdrawal to. * @param _to L1 adress to credit the withdrawal to.
* @param _amount Amount of the token to withdraw. * @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 * @param _data Optional data to forward to L1. This data is provided
* solely as a convenience for external contracts. Aside from enforcing a maximum * solely as a convenience for external contracts. Aside from enforcing a maximum
* length, these contracts provide no guarantees about its content. * length, these contracts provide no guarantees about its content.
......
...@@ -33,6 +33,9 @@ contract L2CrossDomainMessenger is IL2CrossDomainMessenger { ...@@ -33,6 +33,9 @@ contract L2CrossDomainMessenger is IL2CrossDomainMessenger {
* Constructor * * Constructor *
***************/ ***************/
/**
* @param _l1CrossDomainMessenger Address of the L1 CrossDomainMessenger
*/
constructor(address _l1CrossDomainMessenger) { constructor(address _l1CrossDomainMessenger) {
l1CrossDomainMessenger = _l1CrossDomainMessenger; l1CrossDomainMessenger = _l1CrossDomainMessenger;
} }
......
...@@ -23,8 +23,7 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser { ...@@ -23,8 +23,7 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
********************/ ********************/
/** /**
* Passes a message to L1. * @inheritdoc iOVM_L2ToL1MessagePasser
* @param _message Message to pass to L1.
*/ */
// slither-disable-next-line external-function // slither-disable-next-line external-function
function passMessageToL1(bytes memory _message) public { function passMessageToL1(bytes memory _message) public {
......
...@@ -9,5 +9,8 @@ interface iOVM_L1BlockNumber { ...@@ -9,5 +9,8 @@ interface iOVM_L1BlockNumber {
* Public Functions * * Public Functions *
********************/ ********************/
/**
* @return Block number of L1
*/
function getL1BlockNumber() external view returns (uint256); function getL1BlockNumber() external view returns (uint256);
} }
...@@ -15,5 +15,9 @@ interface iOVM_L2ToL1MessagePasser { ...@@ -15,5 +15,9 @@ interface iOVM_L2ToL1MessagePasser {
* Public Functions * * Public Functions *
********************/ ********************/
/**
* Passes a message to L1.
* @param _message Message to pass to L1.
*/
function passMessageToL1(bytes calldata _message) external; function passMessageToL1(bytes calldata _message) external;
} }
...@@ -352,8 +352,8 @@ Allows the Burn Admin to update the parameters which determine the amount of gas ...@@ -352,8 +352,8 @@ Allows the Burn Admin to update the parameters which determine the amount of gas
| Name | Type | Description | | Name | Type | Description |
|---|---|---| |---|---|---|
| _l2GasDiscountDivisor | uint256 | undefined | _l2GasDiscountDivisor | uint256 | The ratio of the cost of L1 gas to the cost of L2 gas
| _enqueueGasCost | uint256 | undefined | _enqueueGasCost | uint256 | The approximate cost of calling the enqueue function
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
function isCollateralized(address _who) external view returns (bool) 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) ...@@ -24,13 +24,13 @@ function isCollateralized(address _who) external view returns (bool)
| Name | Type | Description | | Name | Type | Description |
|---|---|---| |---|---|---|
| _who | address | undefined | _who | address | Address to check.
#### Returns #### Returns
| Name | Type | Description | | 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) ...@@ -63,8 +63,8 @@ function withdraw(address _l2Token, uint256 _amount, uint32 _l1Gas, bytes _data)
| Name | Type | Description | | Name | Type | Description |
|---|---|---| |---|---|---|
| _l2Token | address | Address of L2 token where withdrawal was initiated. | _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. | _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | undefined | _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. | _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 ### withdrawTo
...@@ -83,8 +83,8 @@ function withdrawTo(address _l2Token, address _to, uint256 _amount, uint32 _l1Ga ...@@ -83,8 +83,8 @@ function withdrawTo(address _l2Token, address _to, uint256 _amount, uint32 _l1Ga
|---|---|---| |---|---|---|
| _l2Token | address | Address of L2 token where withdrawal is initiated. | _l2Token | address | Address of L2 token where withdrawal is initiated.
| _to | address | L1 adress to credit the withdrawal to. | _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. | _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | undefined | _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. | _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. ...@@ -138,7 +138,7 @@ Verifies a batch inclusion proof.
| Name | Type | Description | | 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) ...@@ -80,8 +80,8 @@ function withdraw(address _l2Token, uint256 _amount, uint32 _l1Gas, bytes _data)
| Name | Type | Description | | Name | Type | Description |
|---|---|---| |---|---|---|
| _l2Token | address | Address of L2 token where withdrawal was initiated. | _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. | _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | undefined | _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. | _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 ### withdrawTo
...@@ -100,8 +100,8 @@ function withdrawTo(address _l2Token, address _to, uint256 _amount, uint32 _l1Ga ...@@ -100,8 +100,8 @@ function withdrawTo(address _l2Token, address _to, uint256 _amount, uint32 _l1Ga
|---|---|---| |---|---|---|
| _l2Token | address | Address of L2 token where withdrawal is initiated. | _l2Token | address | Address of L2 token where withdrawal is initiated.
| _to | address | L1 adress to credit the withdrawal to. | _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. | _amount | uint256 | Amount of the token to withdraw.
| _l1Gas | uint32 | undefined | _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. | _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. ...@@ -228,7 +228,7 @@ Verifies a batch inclusion proof.
| Name | Type | Description | | 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) ...@@ -25,7 +25,7 @@ function getL1BlockNumber() external view returns (uint256)
| Name | Type | Description | | Name | Type | Description |
|---|---|---| |---|---|---|
| _0 | uint256 | undefined | _0 | uint256 | Block number of L1
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
function passMessageToL1(bytes _message) external nonpayable function passMessageToL1(bytes _message) external nonpayable
``` ```
Passes a message to L1.
...@@ -24,7 +24,7 @@ function passMessageToL1(bytes _message) external nonpayable ...@@ -24,7 +24,7 @@ function passMessageToL1(bytes _message) external nonpayable
| Name | Type | Description | | 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