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

Merge branch 'develop' into aj/reject-old-gossip-hash

parents 8fd1bb42 900d5f7b
...@@ -75,6 +75,7 @@ jobs: ...@@ -75,6 +75,7 @@ jobs:
uses: changesets/action@v1 uses: changesets/action@v1
id: changesets id: changesets
with: with:
createGithubReleases: false
publish: yarn changeset publish --tag canary publish: yarn changeset publish --tag canary
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
......
...@@ -67,6 +67,7 @@ jobs: ...@@ -67,6 +67,7 @@ jobs:
uses: changesets/action@v1 uses: changesets/action@v1
id: changesets id: changesets
with: with:
createGithubReleases: false
publish: yarn release publish: yarn release
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
......
This diff is collapsed.
package main
import (
"context"
"errors"
"fmt"
"math/big"
"os"
"sync"
"time"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
legacy_bindings "github.com/ethereum-optimism/optimism/op-bindings/legacy-bindings"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum-optimism/optimism/op-chain-ops/util"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2"
)
func main() {
app := cli.NewApp()
app.Name = "rollover"
app.Usage = "Commands for assisting in the rollover of the system"
var flags []cli.Flag
flags = append(flags, util.ClientsFlags...)
flags = append(flags, util.AddressesFlags...)
app.Commands = []*cli.Command{
{
Name: "deposits",
Usage: "Ensures that all deposits have been ingested into L2",
Flags: flags,
Action: func(cliCtx *cli.Context) error {
clients, err := util.NewClients(cliCtx)
if err != nil {
return err
}
addresses, err := util.NewAddresses(cliCtx)
if err != nil {
return err
}
log.Info("Connecting to AddressManager", "address", addresses.AddressManager)
addressManager, err := bindings.NewAddressManager(addresses.AddressManager, clients.L1Client)
if err != nil {
return err
}
for {
shutoffBlock, err := addressManager.GetAddress(&bind.CallOpts{}, "DTL_SHUTOFF_BLOCK")
if err != nil {
return err
}
if num := shutoffBlock.Big(); num.Cmp(common.Big0) != 0 {
log.Info("DTL_SHUTOFF_BLOCK is set", "number", num.Uint64())
break
}
log.Info("DTL_SHUTOFF_BLOCK not set yet")
time.Sleep(3 * time.Second)
}
log.Info("Connecting to CanonicalTransactionChain", "address", addresses.CanonicalTransactionChain)
ctc, err := legacy_bindings.NewCanonicalTransactionChain(addresses.CanonicalTransactionChain, clients.L1Client)
if err != nil {
return err
}
queueLength, err := ctc.GetQueueLength(&bind.CallOpts{})
if err != nil {
return err
}
totalElements, err := ctc.GetTotalElements(&bind.CallOpts{})
if err != nil {
return err
}
totalBatches, err := ctc.GetTotalBatches(&bind.CallOpts{})
if err != nil {
return err
}
pending, err := ctc.GetNumPendingQueueElements(&bind.CallOpts{})
if err != nil {
return err
}
log.Info(
"CanonicalTransactionChain",
"address", addresses.CanonicalTransactionChain,
"queue-length", queueLength,
"total-elements", totalElements,
"total-batches", totalBatches,
"pending", pending,
)
blockNumber, err := clients.L2Client.BlockNumber(context.Background())
if err != nil {
return err
}
log.Info("Searching backwards for final deposit", "start", blockNumber)
for {
bn := new(big.Int).SetUint64(blockNumber)
log.Info("Checking L2 block", "number", bn)
block, err := clients.L2Client.BlockByNumber(context.Background(), bn)
if err != nil {
return err
}
if length := len(block.Transactions()); length != 1 {
return fmt.Errorf("unexpected number of transactions in block: %d", length)
}
tx := block.Transactions()[0]
hash := tx.Hash()
json, err := legacyTransactionByHash(clients.L2RpcClient, hash)
if err != nil {
return err
}
if json.QueueOrigin == "l1" {
if json.QueueIndex == nil {
// This should never happen
return errors.New("queue index is nil")
}
queueIndex := uint64(*json.QueueIndex)
if queueIndex == queueLength.Uint64()-1 {
log.Info("Found final deposit in l2geth", "queue-index", queueIndex)
break
}
if queueIndex < queueLength.Uint64() {
return errors.New("missed final deposit")
}
}
blockNumber--
}
finalPending, err := ctc.GetNumPendingQueueElements(&bind.CallOpts{})
if err != nil {
return err
}
log.Info("Remaining deposits that must be submitted", "count", finalPending)
return nil
},
},
{
Name: "batches",
Usage: "Ensures that all batches have been submitted to L1",
Flags: flags,
Action: func(cliCtx *cli.Context) error {
clients, err := util.NewClients(cliCtx)
if err != nil {
return err
}
addresses, err := util.NewAddresses(cliCtx)
if err != nil {
return err
}
log.Info("Connecting to CanonicalTransactionChain", "address", addresses.CanonicalTransactionChain)
ctc, err := legacy_bindings.NewCanonicalTransactionChain(addresses.CanonicalTransactionChain, clients.L1Client)
if err != nil {
return err
}
log.Info("Connecting to StateCommitmentChain", "address", addresses.StateCommitmentChain)
scc, err := legacy_bindings.NewStateCommitmentChain(addresses.StateCommitmentChain, clients.L1Client)
if err != nil {
return err
}
var wg sync.WaitGroup
log.Info("Waiting for CanonicalTransactionChain")
wg.Add(1)
go waitForTotalElements(&wg, ctc, clients.L2Client)
log.Info("Waiting for StateCommitmentChain")
wg.Add(1)
go waitForTotalElements(&wg, scc, clients.L2Client)
wg.Wait()
log.Info("All batches have been submitted")
return nil
},
},
}
if err := app.Run(os.Args); err != nil {
log.Crit("Application failed", "message", err)
}
}
// RollupContract represents a legacy rollup contract interface that
// exposes the GetTotalElements function. Both the StateCommitmentChain
// and the CanonicalTransactionChain implement this interface.
type RollupContract interface {
GetTotalElements(opts *bind.CallOpts) (*big.Int, error)
}
// waitForTotalElements will poll to see
func waitForTotalElements(wg *sync.WaitGroup, contract RollupContract, client *ethclient.Client) {
defer wg.Done()
for {
bn, err := client.BlockNumber(context.Background())
if err != nil {
log.Error("cannot fetch blocknumber", "error", err)
time.Sleep(3 * time.Second)
continue
}
totalElements, err := contract.GetTotalElements(&bind.CallOpts{})
if err != nil {
log.Error("cannot fetch total elements", "error", err)
time.Sleep(3 * time.Second)
continue
}
if totalElements.Uint64() == bn {
return
}
log.Info("Waiting for elements to be submitted", "count", totalElements.Uint64()-bn, "height", bn, "total-elements", totalElements.Uint64())
time.Sleep(3 * time.Second)
}
}
// legacyTransactionByHash will fetch a transaction by hash and be sure to decode
// the additional fields added to legacy transactions.
func legacyTransactionByHash(client *rpc.Client, hash common.Hash) (*RPCTransaction, error) {
var json *RPCTransaction
err := client.CallContext(context.Background(), &json, "eth_getTransactionByHash", hash)
if err != nil {
return nil, err
}
return json, nil
}
// RPCTransaction represents a transaction that will serialize to the RPC representation of a
// transaction. This handles the extra legacy fields added to transactions.
type RPCTransaction struct {
BlockHash *common.Hash `json:"blockHash"`
BlockNumber *hexutil.Big `json:"blockNumber"`
From common.Address `json:"from"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
Nonce hexutil.Uint64 `json:"nonce"`
To *common.Address `json:"to"`
TransactionIndex *hexutil.Uint64 `json:"transactionIndex"`
Value *hexutil.Big `json:"value"`
V *hexutil.Big `json:"v"`
R *hexutil.Big `json:"r"`
S *hexutil.Big `json:"s"`
QueueOrigin string `json:"queueOrigin"`
L1TxOrigin *common.Address `json:"l1TxOrigin"`
L1BlockNumber *hexutil.Big `json:"l1BlockNumber"`
L1Timestamp hexutil.Uint64 `json:"l1Timestamp"`
Index *hexutil.Uint64 `json:"index"`
QueueIndex *hexutil.Uint64 `json:"queueIndex"`
RawTransaction hexutil.Bytes `json:"rawTransaction"`
}
...@@ -18,6 +18,7 @@ import ( ...@@ -18,6 +18,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/predeploys" "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/genesis" "github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/util"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
...@@ -25,9 +26,7 @@ import ( ...@@ -25,9 +26,7 @@ import (
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth/tracers" "github.com/ethereum/go-ethereum/eth/tracers"
"github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
) )
// abiTrue represents the storage representation of the boolean // abiTrue represents the storage representation of the boolean
...@@ -115,7 +114,7 @@ func main() { ...@@ -115,7 +114,7 @@ func main() {
}, },
}, },
Action: func(ctx *cli.Context) error { Action: func(ctx *cli.Context) error {
clients, err := newClients(ctx) clients, err := util.NewClients(ctx)
if err != nil { if err != nil {
return err return err
} }
...@@ -433,7 +432,7 @@ func main() { ...@@ -433,7 +432,7 @@ func main() {
} }
// callTrace will call `debug_traceTransaction` on a remote node // callTrace will call `debug_traceTransaction` on a remote node
func callTrace(c *clients, receipt *types.Receipt) (callFrame, error) { func callTrace(c *util.Clients, receipt *types.Receipt) (callFrame, error) {
var finalizationTrace callFrame var finalizationTrace callFrame
tracer := "callTracer" tracer := "callTracer"
traceConfig := tracers.TraceConfig{ traceConfig := tracers.TraceConfig{
...@@ -558,7 +557,7 @@ func handleFinalizeERC20Withdrawal(args []any, receipt *types.Receipt, l1Standar ...@@ -558,7 +557,7 @@ func handleFinalizeERC20Withdrawal(args []any, receipt *types.Receipt, l1Standar
// proveWithdrawalTransaction will build the data required for proving a // proveWithdrawalTransaction will build the data required for proving a
// withdrawal and then send the transaction and make sure that it is included // withdrawal and then send the transaction and make sure that it is included
// and successful and then wait for the finalization period to elapse. // and successful and then wait for the finalization period to elapse.
func proveWithdrawalTransaction(c *contracts, cl *clients, opts *bind.TransactOpts, withdrawal *crossdomain.Withdrawal, bn, finalizationPeriod *big.Int) error { func proveWithdrawalTransaction(c *contracts, cl *util.Clients, opts *bind.TransactOpts, withdrawal *crossdomain.Withdrawal, bn, finalizationPeriod *big.Int) error {
l2OutputIndex, outputRootProof, trieNodes, err := createOutput(withdrawal, c.L2OutputOracle, bn, cl) l2OutputIndex, outputRootProof, trieNodes, err := createOutput(withdrawal, c.L2OutputOracle, bn, cl)
if err != nil { if err != nil {
return err return err
...@@ -614,7 +613,7 @@ func proveWithdrawalTransaction(c *contracts, cl *clients, opts *bind.TransactOp ...@@ -614,7 +613,7 @@ func proveWithdrawalTransaction(c *contracts, cl *clients, opts *bind.TransactOp
func finalizeWithdrawalTransaction( func finalizeWithdrawalTransaction(
c *contracts, c *contracts,
cl *clients, cl *util.Clients,
opts *bind.TransactOpts, opts *bind.TransactOpts,
wd *crossdomain.LegacyWithdrawal, wd *crossdomain.LegacyWithdrawal,
withdrawal *crossdomain.Withdrawal, withdrawal *crossdomain.Withdrawal,
...@@ -699,67 +698,6 @@ func newContracts(ctx *cli.Context, l1Backend, l2Backend bind.ContractBackend) ( ...@@ -699,67 +698,6 @@ func newContracts(ctx *cli.Context, l1Backend, l2Backend bind.ContractBackend) (
}, nil }, nil
} }
// clients represents a set of initialized RPC clients
type clients struct {
L1Client *ethclient.Client
L2Client *ethclient.Client
L1RpcClient *rpc.Client
L2RpcClient *rpc.Client
L1GethClient *gethclient.Client
L2GethClient *gethclient.Client
}
// newClients will create new RPC clients
func newClients(ctx *cli.Context) (*clients, error) {
l1RpcURL := ctx.String("l1-rpc-url")
l1Client, err := ethclient.Dial(l1RpcURL)
if err != nil {
return nil, err
}
l1ChainID, err := l1Client.ChainID(context.Background())
if err != nil {
return nil, err
}
l2RpcURL := ctx.String("l2-rpc-url")
l2Client, err := ethclient.Dial(l2RpcURL)
if err != nil {
return nil, err
}
l2ChainID, err := l2Client.ChainID(context.Background())
if err != nil {
return nil, err
}
l1RpcClient, err := rpc.DialContext(context.Background(), l1RpcURL)
if err != nil {
return nil, err
}
l2RpcClient, err := rpc.DialContext(context.Background(), l2RpcURL)
if err != nil {
return nil, err
}
l1GethClient := gethclient.New(l1RpcClient)
l2GethClient := gethclient.New(l2RpcClient)
log.Info(
"Set up RPC clients",
"l1-chain-id", l1ChainID,
"l2-chain-id", l2ChainID,
)
return &clients{
L1Client: l1Client,
L2Client: l2Client,
L1RpcClient: l1RpcClient,
L2RpcClient: l2RpcClient,
L1GethClient: l1GethClient,
L2GethClient: l2GethClient,
}, nil
}
// newWithdrawals will create a set of legacy withdrawals // newWithdrawals will create a set of legacy withdrawals
func newWithdrawals(ctx *cli.Context, l1ChainID *big.Int) ([]*crossdomain.LegacyWithdrawal, error) { func newWithdrawals(ctx *cli.Context, l1ChainID *big.Int) ([]*crossdomain.LegacyWithdrawal, error) {
ovmMsgs := ctx.String("ovm-messages") ovmMsgs := ctx.String("ovm-messages")
...@@ -849,7 +787,7 @@ func createOutput( ...@@ -849,7 +787,7 @@ func createOutput(
withdrawal *crossdomain.Withdrawal, withdrawal *crossdomain.Withdrawal,
oracle *bindings.L2OutputOracle, oracle *bindings.L2OutputOracle,
blockNumber *big.Int, blockNumber *big.Int,
clients *clients, clients *util.Clients,
) (*big.Int, bindings.TypesOutputRootProof, [][]byte, error) { ) (*big.Int, bindings.TypesOutputRootProof, [][]byte, error) {
// compute the storage slot that the withdrawal is stored in // compute the storage slot that the withdrawal is stored in
slot, err := withdrawal.StorageSlot() slot, err := withdrawal.StorageSlot()
......
package util package util
import ( import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
"github.com/urfave/cli/v2"
) )
func ProgressLogger(n int, msg string) func(...any) { func ProgressLogger(n int, msg string) func(...any) {
...@@ -15,3 +23,171 @@ func ProgressLogger(n int, msg string) func(...any) { ...@@ -15,3 +23,171 @@ func ProgressLogger(n int, msg string) func(...any) {
log.Info(msg, append([]any{"count", i}, args...)...) log.Info(msg, append([]any{"count", i}, args...)...)
} }
} }
// clients represents a set of initialized RPC clients
type Clients struct {
L1Client *ethclient.Client
L2Client *ethclient.Client
L1RpcClient *rpc.Client
L2RpcClient *rpc.Client
L1GethClient *gethclient.Client
L2GethClient *gethclient.Client
}
// NewClients will create new RPC clients from a CLI context
func NewClients(ctx *cli.Context) (*Clients, error) {
l1RpcURL := ctx.String("l1-rpc-url")
l1Client, err := ethclient.Dial(l1RpcURL)
if err != nil {
return nil, err
}
l1ChainID, err := l1Client.ChainID(context.Background())
if err != nil {
return nil, err
}
l2RpcURL := ctx.String("l2-rpc-url")
l2Client, err := ethclient.Dial(l2RpcURL)
if err != nil {
return nil, err
}
l2ChainID, err := l2Client.ChainID(context.Background())
if err != nil {
return nil, err
}
l1RpcClient, err := rpc.DialContext(context.Background(), l1RpcURL)
if err != nil {
return nil, err
}
l2RpcClient, err := rpc.DialContext(context.Background(), l2RpcURL)
if err != nil {
return nil, err
}
l1GethClient := gethclient.New(l1RpcClient)
l2GethClient := gethclient.New(l2RpcClient)
log.Info(
"Set up RPC clients",
"l1-chain-id", l1ChainID,
"l2-chain-id", l2ChainID,
)
return &Clients{
L1Client: l1Client,
L2Client: l2Client,
L1RpcClient: l1RpcClient,
L2RpcClient: l2RpcClient,
L1GethClient: l1GethClient,
L2GethClient: l2GethClient,
}, nil
}
// ClientsFlags represent the flags associated with creating RPC clients.
var ClientsFlags = []cli.Flag{
&cli.StringFlag{
Name: "l1-rpc-url",
Required: true,
Usage: "L1 RPC URL",
EnvVars: []string{"L1_RPC_URL"},
},
&cli.StringFlag{
Name: "l2-rpc-url",
Required: true,
Usage: "L2 RPC URL",
EnvVars: []string{"L2_RPC_URL"},
},
}
// Addresses represents the address values of various contracts. The values can
// be easily populated via a [cli.Context].
type Addresses struct {
AddressManager common.Address
OptimismPortal common.Address
L1StandardBridge common.Address
L1CrossDomainMessenger common.Address
CanonicalTransactionChain common.Address
StateCommitmentChain common.Address
}
// AddressesFlags represent the flags associated with address parsing.
var AddressesFlags = []cli.Flag{
&cli.StringFlag{
Name: "address-manager-address",
Usage: "AddressManager address",
EnvVars: []string{"ADDRESS_MANAGER_ADDRESS"},
},
&cli.StringFlag{
Name: "optimism-portal-address",
Usage: "OptimismPortal address",
EnvVars: []string{"OPTIMISM_PORTAL_ADDRESS"},
},
&cli.StringFlag{
Name: "l1-standard-bridge-address",
Usage: "L1StandardBridge address",
EnvVars: []string{"L1_STANDARD_BRIDGE_ADDRESS"},
},
&cli.StringFlag{
Name: "l1-crossdomain-messenger-address",
Usage: "L1CrossDomainMessenger address",
EnvVars: []string{"L1_CROSSDOMAIN_MESSENGER_ADDRESS"},
},
&cli.StringFlag{
Name: "canonical-transaction-chain-address",
Usage: "CanonicalTransactionChain address",
EnvVars: []string{"CANONICAL_TRANSACTION_CHAIN_ADDRESS"},
},
&cli.StringFlag{
Name: "state-commitment-chain-address",
Usage: "StateCommitmentChain address",
EnvVars: []string{"STATE_COMMITMENT_CHAIN_ADDRESS"},
},
}
// NewAddresses populates an Addresses struct given a [cli.Context].
// This is useful for writing scripts that interact with smart contracts.
func NewAddresses(ctx *cli.Context) (*Addresses, error) {
var addresses Addresses
var err error
addresses.AddressManager, err = parseAddress(ctx, "address-manager-address")
if err != nil {
return nil, err
}
addresses.OptimismPortal, err = parseAddress(ctx, "optimism-portal-address")
if err != nil {
return nil, err
}
addresses.L1StandardBridge, err = parseAddress(ctx, "l1-standard-bridge-address")
if err != nil {
return nil, err
}
addresses.L1CrossDomainMessenger, err = parseAddress(ctx, "l1-crossdomain-messenger-address")
if err != nil {
return nil, err
}
addresses.CanonicalTransactionChain, err = parseAddress(ctx, "canonical-transaction-chain-address")
if err != nil {
return nil, err
}
addresses.StateCommitmentChain, err = parseAddress(ctx, "state-commitment-chain-address")
if err != nil {
return nil, err
}
return &addresses, nil
}
// parseAddress will parse a [common.Address] from a [cli.Context] and return
// an error if the configured address is not correct.
func parseAddress(ctx *cli.Context, name string) (common.Address, error) {
value := ctx.String(name)
if value == "" {
return common.Address{}, nil
}
if !common.IsHexAddress(value) {
return common.Address{}, fmt.Errorf("invalid address: %s", value)
}
return common.HexToAddress(value), nil
}
...@@ -12,7 +12,7 @@ import { FeeVault } from "../universal/FeeVault.sol"; ...@@ -12,7 +12,7 @@ import { FeeVault } from "../universal/FeeVault.sol";
*/ */
contract L1FeeVault is FeeVault, Semver { contract L1FeeVault is FeeVault, Semver {
/** /**
* @custom:semver 1.0.0 * @custom:semver 1.1.0
* *
* @param _recipient Address that will receive the accumulated fees. * @param _recipient Address that will receive the accumulated fees.
*/ */
......
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.7.0 <0.9.0;
/**
* @title Enum - Collection of enums used in Safe contracts.
* @author Richard Meissner - @rmeissner
*/
abstract contract Enum {
enum Operation {
Call,
DelegateCall
}
}
pragma solidity ^0.8.10;
import { Enum } from "./Enum.sol";
interface IGnosisSafe {
event AddedOwner(address owner);
event ApproveHash(bytes32 indexed approvedHash, address indexed owner);
event ChangedFallbackHandler(address handler);
event ChangedGuard(address guard);
event ChangedThreshold(uint256 threshold);
event DisabledModule(address module);
event EnabledModule(address module);
event ExecutionFailure(bytes32 txHash, uint256 payment);
event ExecutionFromModuleFailure(address indexed module);
event ExecutionFromModuleSuccess(address indexed module);
event ExecutionSuccess(bytes32 txHash, uint256 payment);
event RemovedOwner(address owner);
event SafeReceived(address indexed sender, uint256 value);
event SafeSetup(
address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler
);
event SignMsg(bytes32 indexed msgHash);
function VERSION() external view returns (string memory);
function addOwnerWithThreshold(address owner, uint256 _threshold) external;
function approveHash(bytes32 hashToApprove) external;
function approvedHashes(address, bytes32) external view returns (uint256);
function changeThreshold(uint256 _threshold) external;
function checkNSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures, uint256 requiredSignatures)
external
view;
function checkSignatures(bytes32 dataHash, bytes memory data, bytes memory signatures) external view;
function disableModule(address prevModule, address module) external;
function domainSeparator() external view returns (bytes32);
function enableModule(address module) external;
function encodeTransactionData(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
uint256 _nonce
) external view returns (bytes memory);
function execTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
bytes memory signatures
) external payable returns (bool success);
function execTransactionFromModule(address to, uint256 value, bytes memory data, Enum.Operation operation)
external
returns (bool success);
function execTransactionFromModuleReturnData(address to, uint256 value, bytes memory data, Enum.Operation operation)
external
returns (bool success, bytes memory returnData);
function getChainId() external view returns (uint256);
function getModulesPaginated(address start, uint256 pageSize)
external
view
returns (address[] memory array, address next);
function getOwners() external view returns (address[] memory);
function getStorageAt(uint256 offset, uint256 length) external view returns (bytes memory);
function getThreshold() external view returns (uint256);
function getTransactionHash(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
uint256 safeTxGas,
uint256 baseGas,
uint256 gasPrice,
address gasToken,
address refundReceiver,
uint256 _nonce
) external view returns (bytes32);
function isModuleEnabled(address module) external view returns (bool);
function isOwner(address owner) external view returns (bool);
function nonce() external view returns (uint256);
function removeOwner(address prevOwner, address owner, uint256 _threshold) external;
function requiredTxGas(address to, uint256 value, bytes memory data, Enum.Operation operation) external returns (uint256);
function setFallbackHandler(address handler) external;
function setGuard(address guard) external;
function setup(
address[] memory _owners,
uint256 _threshold,
address to,
bytes memory data,
address fallbackHandler,
address paymentToken,
uint256 payment,
address paymentReceiver
) external;
function signedMessages(bytes32) external view returns (uint256);
function simulateAndRevert(address targetContract, bytes memory calldataPayload) external;
function swapOwner(address prevOwner, address oldOwner, address newOwner) external;
}
This diff is collapsed.
This diff is collapsed.
...@@ -8,6 +8,4 @@ import './solidity' ...@@ -8,6 +8,4 @@ import './solidity'
import './accounts' import './accounts'
import './check-l2' import './check-l2'
import './update-dynamic-oracle-config' import './update-dynamic-oracle-config'
import './wait-for-final-batch'
import './wait-for-final-deposit'
import './generate-deploy-config' import './generate-deploy-config'
import { task, types } from 'hardhat/config'
import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import { Contract } from 'ethers'
import { sleep } from '@eth-optimism/core-utils'
task('wait-for-final-batch', 'Waits for the final batch to be submitted')
.addParam(
'l1RpcUrl',
'L1 RPC URL remote node',
'http://127.0.0.1:8545',
types.string
)
.addParam(
'l2RpcUrl',
'L2 RPC URL remote node',
'http://127.0.0.1:9545',
types.string
)
.setAction(async (args, hre: HardhatRuntimeEnvironment) => {
const l1Provider = new hre.ethers.providers.StaticJsonRpcProvider(
args.l1RpcUrl
)
const l2Provider = new hre.ethers.providers.StaticJsonRpcProvider(
args.l2RpcUrl
)
const Deployment__CanonicalTransactionChain = await hre.deployments.get(
'CanonicalTransactionChain'
)
const CanonicalTransactionChain = new hre.ethers.Contract(
Deployment__CanonicalTransactionChain.address,
Deployment__CanonicalTransactionChain.abi,
l1Provider
)
const Deployment__StateCommitmentChain = await hre.deployments.get(
'StateCommitmentChain'
)
const StateCommitmentChain = new hre.ethers.Contract(
Deployment__StateCommitmentChain.address,
Deployment__StateCommitmentChain.abi,
l1Provider
)
const wait = async (contract: Contract) => {
let height = await l2Provider.getBlockNumber()
let totalElements = await contract.getTotalElements()
console.log(` - height: ${height}`)
console.log(` - totalElements: ${totalElements}`)
while (totalElements.toNumber() !== height) {
console.log('Total elements does not match')
console.log(` - height: ${height}`)
console.log(` - totalElements: ${totalElements}`)
console.log(
`Waiting for ${height - totalElements} elements to be submitted`
)
totalElements = await contract.getTotalElements()
height = await l2Provider.getBlockNumber()
await sleep(5 * 1000)
}
}
console.log('Waiting for the CanonicalTransactionChain...')
await wait(CanonicalTransactionChain)
console.log('All transaction batches have been submitted')
console.log()
console.log('Waiting for the StateCommitmentChain...')
await wait(StateCommitmentChain)
console.log('All state root batches have been submitted')
console.log()
console.log('All batches have been submitted')
})
import { task, types } from 'hardhat/config'
import '@nomiclabs/hardhat-ethers'
import 'hardhat-deploy'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import { BigNumber } from 'ethers'
import { sleep, toRpcHexString } from '@eth-optimism/core-utils'
task('wait-for-final-deposit', 'Waits for the final deposit to be ingested')
.addParam(
'l1RpcUrl',
'L1 RPC URL remote node',
'http://127.0.0.1:8545',
types.string
)
.addParam(
'l2RpcUrl',
'L2 RPC URL remote node',
'http://127.0.0.1:9545',
types.string
)
.setAction(async (args, hre: HardhatRuntimeEnvironment) => {
const l1Provider = new hre.ethers.providers.StaticJsonRpcProvider(
args.l1RpcUrl
)
const l2Provider = new hre.ethers.providers.StaticJsonRpcProvider(
args.l2RpcUrl
)
// Handle legacy deployments
let Deployment__AddressManager = await hre.deployments.getOrNull(
'Lib_AddressManager'
)
if (!Deployment__AddressManager) {
Deployment__AddressManager = await hre.deployments.get('AddressManager')
}
const AddressManager = new hre.ethers.Contract(
Deployment__AddressManager.address,
Deployment__AddressManager.abi,
l1Provider
)
const Deployment__CanonicalTransactionChain = await hre.deployments.get(
'CanonicalTransactionChain'
)
const CanonicalTransactionChain = new hre.ethers.Contract(
Deployment__CanonicalTransactionChain.address,
Deployment__CanonicalTransactionChain.abi,
l1Provider
)
// Wait for DTL_SHUTOFF_BLOCK block to be set in the AddressManager
let dtlShutoffBlock = BigNumber.from(0)
while (true) {
console.log('Waiting for DTL shutoff block to be set...')
const val = await AddressManager.getAddress('DTL_SHUTOFF_BLOCK')
dtlShutoffBlock = BigNumber.from(val)
if (!dtlShutoffBlock.eq(0)) {
break
}
await sleep(3000)
}
console.log(`DTL shutoff block ${dtlShutoffBlock.toString()}`)
let pending = await CanonicalTransactionChain.getNumPendingQueueElements()
console.log(`${pending} deposits must be batch submitted`)
// Now query the number of queue elements in the CTC
const queueLength = await CanonicalTransactionChain.getQueueLength()
console.log(`Total number of deposits: ${queueLength}`)
console.log('Searching backwards for final deposit')
let height = await l2Provider.getBlockNumber()
while (true) {
console.log(`Trying block ${height}`)
const hex = toRpcHexString(height)
const b = await l2Provider.send('eth_getBlockByNumber', [hex, true])
const tx = b.transactions[0]
if (tx === undefined) {
throw new Error(`unable to fetch transaction`)
}
if (tx.queueOrigin === 'l1') {
const queueIndex = BigNumber.from(tx.queueIndex).toNumber()
if (queueIndex === queueLength - 1) {
break
}
if (queueIndex < queueLength) {
throw new Error(
`Missed the final deposit. queueIndex ${queueIndex}, queueLength ${queueLength}`
)
}
}
height--
}
console.log('Final deposit has been ingested by l2geth')
pending = await CanonicalTransactionChain.getNumPendingQueueElements()
console.log(`${pending} deposits must be batch submitted`)
})
...@@ -7,7 +7,7 @@ if [ ! -d "$OUTDIR" ]; then ...@@ -7,7 +7,7 @@ if [ ! -d "$OUTDIR" ]; then
exit 1 exit 1
fi fi
CONTRACTS=("CanonicalTransactionChain") CONTRACTS=("CanonicalTransactionChain" "StateCommitmentChain")
PKG=legacy_bindings PKG=legacy_bindings
for contract in ${CONTRACTS[@]}; do for contract in ${CONTRACTS[@]}; do
......
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