Commit b2202f6f authored by clabby's avatar clabby

Merge branch 'develop' into cl/ctb/deployment-checks

parents 8ada905b 0361bd89
......@@ -14,6 +14,7 @@ COPY ./indexer /app/indexer
COPY ./op-bindings /app/op-bindings
COPY ./op-service /app/op-service
COPY ./op-node /app/op-node
COPY ./op-chain-ops /app/op-chain-ops
WORKDIR /app/indexer
......
......@@ -39,6 +39,11 @@ type L2BridgeMessage struct {
TransactionWithdrawalHash common.Hash `gorm:"serializer:bytes"`
}
type L2BridgeMessageVersionedMessageHash struct {
MessageHash common.Hash `gorm:"primaryKey;serializer:bytes"`
V1MessageHash common.Hash `gorm:"serializer:bytes"`
}
type BridgeMessagesView interface {
L1BridgeMessage(common.Hash) (*L1BridgeMessage, error)
L1BridgeMessageWithFilter(BridgeMessage) (*L1BridgeMessage, error)
......@@ -55,6 +60,8 @@ type BridgeMessagesDB interface {
StoreL2BridgeMessages([]L2BridgeMessage) error
MarkRelayedL2BridgeMessage(common.Hash, uuid.UUID) error
StoreL2BridgeMessageV1MessageHash(common.Hash, common.Hash) error
}
/**
......@@ -134,8 +141,37 @@ func (db bridgeMessagesDB) StoreL2BridgeMessages(messages []L2BridgeMessage) err
return result.Error
}
func (db bridgeMessagesDB) StoreL2BridgeMessageV1MessageHash(msgHash, v1MsgHash common.Hash) error {
if msgHash == v1MsgHash {
return fmt.Errorf("message hash is equal to the v1 message: %s", msgHash)
}
deduped := db.gorm.Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "message_hash"}}, DoNothing: true})
result := deduped.Create(&L2BridgeMessageVersionedMessageHash{MessageHash: msgHash, V1MessageHash: v1MsgHash})
if result.Error == nil && int(result.RowsAffected) < 1 {
db.log.Warn("ignored L2 bridge v1 message hash duplicates")
}
return result.Error
}
func (db bridgeMessagesDB) L2BridgeMessage(msgHash common.Hash) (*L2BridgeMessage, error) {
return db.L2BridgeMessageWithFilter(BridgeMessage{MessageHash: msgHash})
message, err := db.L2BridgeMessageWithFilter(BridgeMessage{MessageHash: msgHash})
if message != nil || err != nil {
return message, err
}
// check if this is a v1 hash of an older message
versioned := L2BridgeMessageVersionedMessageHash{V1MessageHash: msgHash}
result := db.gorm.Where(&versioned).Take(&versioned)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return db.L2BridgeMessageWithFilter(BridgeMessage{MessageHash: versioned.MessageHash})
}
func (db bridgeMessagesDB) L2BridgeMessageWithFilter(filter BridgeMessage) (*L2BridgeMessage, error) {
......
......@@ -4,12 +4,11 @@ import (
"errors"
"math/big"
"github.com/ethereum-optimism/optimism/indexer/processors/contracts"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
type CrossDomainMessengerSentMessage struct {
......@@ -40,7 +39,17 @@ func ParseCrossDomainMessage(sentMessageReceipt *types.Receipt) (CrossDomainMess
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
msgHash, err := CrossDomainMessengerSentMessageHash(sentMessage, sentMessageExtension.Value)
msg := crossdomain.NewCrossDomainMessage(
sentMessage.MessageNonce,
sentMessage.Sender,
sentMessage.Target,
sentMessageExtension.Value,
sentMessage.GasLimit,
sentMessage.Message,
)
msgHash, err := msg.Hash()
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
......@@ -51,17 +60,3 @@ func ParseCrossDomainMessage(sentMessageReceipt *types.Receipt) (CrossDomainMess
return CrossDomainMessengerSentMessage{}, errors.New("missing SentMessage receipts")
}
func CrossDomainMessengerSentMessageHash(sentMessage *bindings.CrossDomainMessengerSentMessage, value *big.Int) (common.Hash, error) {
abi, err := bindings.CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return common.Hash{}, err
}
calldata, err := contracts.CrossDomainMessageCalldata(abi, sentMessage, value)
if err != nil {
return common.Hash{}, err
}
return crypto.Keccak256Hash(calldata), nil
}
......@@ -176,6 +176,22 @@ CREATE INDEX IF NOT EXISTS l2_bridge_messages_timestamp ON l2_bridge_messages(ti
CREATE INDEX IF NOT EXISTS l2_bridge_messages_transaction_withdrawal_hash ON l2_bridge_messages(transaction_withdrawal_hash);
CREATE INDEX IF NOT EXISTS l2_bridge_messages_from_address ON l2_bridge_messages(from_address);
/**
* Since the CDM uses the latest versioned message hash when emitting the `RelayedMessage` event, we need
* to keep track of all of the future versions of message hashes such that legacy messages can be queried
* queried for when relayed on L1
*
* As new the CDM is updated with new versions, we need to ensure that there's a better way to correlate message between
* chains (adding the message nonce to the RelayedMessage event) or continue to add columns to this table and migrate
* unrelayed messages such that finalization logic can handle switching between the varying versioned message hashes
*/
CREATE TABLE IF NOT EXISTS l2_bridge_message_versioned_message_hashes(
message_hash VARCHAR PRIMARY KEY NOT NULL UNIQUE REFERENCES l2_bridge_messages(message_hash),
-- only filled in if `message_hash` is for a v0 message
v1_message_hash VARCHAR UNIQUE
);
-- StandardBridge
CREATE TABLE IF NOT EXISTS l1_bridge_deposits (
transaction_source_hash VARCHAR PRIMARY KEY REFERENCES l1_transaction_deposits(source_hash) ON DELETE CASCADE,
......
......@@ -256,7 +256,7 @@ func (b *BridgeProcessor) processInitiatedL2Events() error {
legacyBridgeLog := l2BridgeLog.New("mode", "legacy", "from_block_number", legacyFromL2Height, "to_block_number", legacyToL2Height)
legacyBridgeLog.Info("scanning for initiated bridge events")
if err := bridge.LegacyL2ProcessInitiatedBridgeEvents(legacyBridgeLog, tx, b.metrics, b.chainConfig.L2Contracts, legacyFromL2Height, legacyToL2Height); err != nil {
if err := bridge.LegacyL2ProcessInitiatedBridgeEvents(legacyBridgeLog, tx, b.metrics, b.chainConfig.Preset, b.chainConfig.L2Contracts, legacyFromL2Height, legacyToL2Height); err != nil {
return err
} else if legacyToL2Height.Cmp(toL2Height) == 0 {
return nil // a-ok! Entire range was legacy blocks
......
......@@ -12,6 +12,8 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/node"
"github.com/ethereum-optimism/optimism/indexer/processors/contracts"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
)
// Legacy Bridge Initiation
......@@ -145,7 +147,7 @@ func LegacyL1ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metri
// 1. L2CrossDomainMessenger - The LegacyMessagePasser contract cannot be used as entrypoint to bridge transactions from L2. The protocol
// only allows the L2CrossDomainMessenger as the sole sender when relaying a bridged message.
// 2. L2StandardBridge
func LegacyL2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2Metricer, l2Contracts config.L2Contracts, fromHeight, toHeight *big.Int) error {
func LegacyL2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metrics L2Metricer, preset int, l2Contracts config.L2Contracts, fromHeight, toHeight *big.Int) error {
// (1) L2CrossDomainMessenger
crossDomainSentMessages, err := contracts.CrossDomainMessengerSentMessageEvents("l2", l2Contracts.L2CrossDomainMessenger, db, fromHeight, toHeight)
if err != nil {
......@@ -168,22 +170,38 @@ func LegacyL2ProcessInitiatedBridgeEvents(log log.Logger, db *database.DB, metri
sentMessage := crossDomainSentMessages[i]
withdrawnWEI = new(big.Int).Add(withdrawnWEI, sentMessage.BridgeMessage.Tx.Amount)
// We re-use the L2CrossDomainMessenger message hash as the withdrawal hash to remain consistent in the schema.
// Since these message can be relayed in bedrock, we utilize the migrated withdrawal hash
// and also store the v1 version of the message hash such that the bedrock l1 finalization
// processor works as expected
v1MessageHash, err := legacyBridgeMessageV1MessageHash(&sentMessage.BridgeMessage)
if err != nil {
return fmt.Errorf("failed to compute versioned message hash: %w", err)
}
if err := db.BridgeMessages.StoreL2BridgeMessageV1MessageHash(sentMessage.BridgeMessage.MessageHash, v1MessageHash); err != nil {
return err
}
withdrawalHash, err := legacyBridgeMessageWithdrawalHash(preset, &sentMessage.BridgeMessage)
if err != nil {
return fmt.Errorf("failed to construct migrated withdrawal hash: %w", err)
}
transactionWithdrawals[i] = database.L2TransactionWithdrawal{
WithdrawalHash: sentMessage.BridgeMessage.MessageHash,
WithdrawalHash: withdrawalHash,
InitiatedL2EventGUID: sentMessage.Event.GUID,
Nonce: sentMessage.BridgeMessage.Nonce,
GasLimit: sentMessage.BridgeMessage.GasLimit,
Tx: database.Transaction{
FromAddress: sentMessage.BridgeMessage.Tx.FromAddress,
ToAddress: sentMessage.BridgeMessage.Tx.ToAddress,
Amount: big.NewInt(0),
Amount: bigint.Zero,
Data: sentMessage.BridgeMessage.Tx.Data,
Timestamp: sentMessage.Event.Timestamp,
},
}
sentMessages[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex}] = sentMessageEvent{&sentMessage, sentMessage.BridgeMessage.MessageHash}
sentMessages[logKey{sentMessage.Event.BlockHash, sentMessage.Event.LogIndex}] = sentMessageEvent{&sentMessage, withdrawalHash}
bridgeMessages[i] = database.L2BridgeMessage{
TransactionWithdrawalHash: sentMessage.BridgeMessage.MessageHash,
BridgeMessage: sentMessage.BridgeMessage,
......@@ -297,16 +315,17 @@ func LegacyL1ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metri
}
}
// Mark the associated tx withdrawal as proven/finalized with the same event. The message hash is also the transaction withdrawal hash
if err := db.BridgeTransactions.MarkL2TransactionWithdrawalProvenEvent(relayedMessage.MessageHash, relayedMessage.Event.GUID); err != nil {
if err := db.BridgeMessages.MarkRelayedL2BridgeMessage(relayedMessage.MessageHash, relayedMessage.Event.GUID); err != nil {
return fmt.Errorf("failed to relay cross domain message. tx_hash = %s: %w", relayedMessage.Event.TransactionHash, err)
}
// Mark the associated tx withdrawal as proven/finalized with the same event.
if err := db.BridgeTransactions.MarkL2TransactionWithdrawalProvenEvent(message.TransactionWithdrawalHash, relayedMessage.Event.GUID); err != nil {
return fmt.Errorf("failed to mark withdrawal as proven. tx_hash = %s: %w", relayedMessage.Event.TransactionHash, err)
}
if err := db.BridgeTransactions.MarkL2TransactionWithdrawalFinalizedEvent(relayedMessage.MessageHash, relayedMessage.Event.GUID, true); err != nil {
if err := db.BridgeTransactions.MarkL2TransactionWithdrawalFinalizedEvent(message.TransactionWithdrawalHash, relayedMessage.Event.GUID, true); err != nil {
return fmt.Errorf("failed to mark withdrawal as finalized. tx_hash = %s: %w", relayedMessage.Event.TransactionHash, err)
}
if err := db.BridgeMessages.MarkRelayedL2BridgeMessage(relayedMessage.MessageHash, relayedMessage.Event.GUID); err != nil {
return fmt.Errorf("failed to relay cross domain message. tx_hash = %s: %w", relayedMessage.Event.TransactionHash, err)
}
}
if len(crossDomainRelayedMessages) > 0 {
metrics.RecordL1ProvenWithdrawals(len(crossDomainRelayedMessages))
......@@ -370,3 +389,27 @@ func LegacyL2ProcessFinalizedBridgeEvents(log log.Logger, db *database.DB, metri
// a-ok!
return nil
}
// Utils
func legacyBridgeMessageWithdrawalHash(preset int, msg *database.BridgeMessage) (common.Hash, error) {
l1Cdm := config.Presets[preset].ChainConfig.L1Contracts.L1CrossDomainMessengerProxy
legacyWithdrawal := crossdomain.NewLegacyWithdrawal(predeploys.L2CrossDomainMessengerAddr, msg.Tx.ToAddress, msg.Tx.FromAddress, msg.Tx.Data, msg.Nonce)
migratedWithdrawal, err := crossdomain.MigrateWithdrawal(legacyWithdrawal, &l1Cdm, big.NewInt(int64(preset)))
if err != nil {
return common.Hash{}, err
}
return migratedWithdrawal.Hash()
}
func legacyBridgeMessageV1MessageHash(msg *database.BridgeMessage) (common.Hash, error) {
legacyWithdrawal := crossdomain.NewLegacyWithdrawal(predeploys.L2CrossDomainMessengerAddr, msg.Tx.ToAddress, msg.Tx.FromAddress, msg.Tx.Data, msg.Nonce)
value, err := legacyWithdrawal.Value()
if err != nil {
return common.Hash{}, fmt.Errorf("failed to extract ETH value from legacy bridge message: %w", err)
}
// Note: GasLimit is always zero. Only the GasLimit for the withdrawal transaction was migrated
return crossdomain.HashCrossDomainMessageV1(msg.Nonce, msg.Tx.FromAddress, msg.Tx.ToAddress, value, new(big.Int), msg.Tx.Data)
}
package bridge
import (
"testing"
"github.com/ethereum-optimism/optimism/indexer/bigint"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/indexer/processors/contracts"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/stretchr/testify/require"
)
func TestLegacyWithdrawalAndMessageHash(t *testing.T) {
// Pre-Bedrock OP-Goerli withdrawal that was proven post-bedrock
// - L1 proven withdrawal tx: 0xa8853a3532f40052385602c66512e438bc1e3736d3cb7abde359f5b9377441c7
value := bigint.Zero
expectedWithdrawalHash := common.HexToHash("0xae99d25df3e38730f6ee6588733417e20a131923b84870be6aedb4f863b6302d")
// Ensure the L2 Tx which correlates with the above proven withdrawal results in the same computed withdrawal hash
// - L2 withdrawal tx: 0x254d9c28add020404142f840ed794cea51f86c0f0a737e3e7bdd7e1e4550962e
abi, err := bindings.CrossDomainMessengerMetaData.GetAbi()
require.NoError(t, err)
var sentMessage bindings.CrossDomainMessengerSentMessage
sentMessageEvent := abi.Events["SentMessage"]
logData := common.FromHex("0x0000000000000000000000004200000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000186a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e4a9f9e67500000000000000000000000007865c6e87b9f70255377e024ace6630c1eaa37f0000000000000000000000003b8e53b3ab8e01fb57d0c9e893bc4d655aa67d84000000000000000000000000b91882244f7f82540f2941a759724523c7b9a166000000000000000000000000b91882244f7f82540f2941a759724523c7b9a166000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
require.NoError(t, contracts.UnpackLog(&sentMessage, &types.Log{Data: logData, Topics: []common.Hash{sentMessageEvent.ID, common.HexToHash("0x000000000000000000000000636af16bf2f682dd3109e60102b8e1a089fedaa8")}}, sentMessageEvent.Name, abi))
// timestamp and message hash are filled in fields. not core to the event
msg := database.BridgeMessage{
Nonce: sentMessage.MessageNonce,
GasLimit: sentMessage.GasLimit,
Tx: database.Transaction{FromAddress: sentMessage.Sender, ToAddress: sentMessage.Target, Amount: value, Data: sentMessage.Message},
}
hash, err := legacyBridgeMessageWithdrawalHash(420, &msg)
require.NoError(t, err)
require.Equal(t, expectedWithdrawalHash, hash)
// Ensure the relayed message hash (v1) matches
expectedMessageHash := common.HexToHash("0xcb16ecc1967f5d7aed909349a4351d28fbb396429ef7faf1c9d2a670e3ca906f")
v1MessageHash, err := legacyBridgeMessageV1MessageHash(&msg)
require.NoError(t, err)
require.Equal(t, expectedMessageHash, v1MessageHash)
}
......@@ -6,17 +6,18 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/indexer/bigint"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
)
var (
// Standard ABI types copied from golang ABI tests
uint256Type, _ = abi.NewType("uint256", "", nil)
bytesType, _ = abi.NewType("bytes", "", nil)
addressType, _ = abi.NewType("address", "", nil)
bytesType, _ = abi.NewType("bytes", "", nil)
uint256Type, _ = abi.NewType("uint256", "", nil)
CrossDomainMessengerLegacyRelayMessageEncoding = abi.NewMethod(
"relayMessage",
......@@ -39,8 +40,8 @@ var (
type CrossDomainMessengerSentMessageEvent struct {
Event *database.ContractEvent
MessageCalldata []byte
BridgeMessage database.BridgeMessage
Version uint16
}
type CrossDomainMessengerRelayedMessageEvent struct {
......@@ -85,32 +86,46 @@ func CrossDomainMessengerSentMessageEvents(chainSelector string, contractAddress
return nil, err
}
version, _ := DecodeVersionedNonce(sentMessage.MessageNonce)
_, versionBig := crossdomain.DecodeVersionedNonce(sentMessage.MessageNonce)
version := uint16(versionBig.Uint64())
if i < numVersionZeroMessages && version != 0 {
return nil, fmt.Errorf("expected version zero nonce. nonce %d tx_hash %s", sentMessage.MessageNonce, sentMessage.Raw.TxHash)
return nil, fmt.Errorf("expected version zero nonce: nonce %d, tx_hash %s", sentMessage.MessageNonce, sentMessage.Raw.TxHash)
}
// In version zero, to value is bridged through the cross domain messenger.
value := big.NewInt(0)
if version > 0 {
value := bigint.Zero
var messageHash common.Hash
switch version {
case 0:
messageHash, err = crossdomain.HashCrossDomainMessageV0(sentMessage.Target, sentMessage.Sender, sentMessage.Message, sentMessage.MessageNonce)
if err != nil {
return nil, err
}
case 1:
sentMessageExtension := bindings.CrossDomainMessengerSentMessageExtension1{Raw: *sentMessageExtensionEvents[i].RLPLog}
err = UnpackLog(&sentMessageExtension, sentMessageExtensionEvents[i].RLPLog, sentMessageExtensionEventAbi.Name, crossDomainMessengerAbi)
if err != nil {
return nil, err
}
value = sentMessageExtension.Value
}
messageCalldata, err := CrossDomainMessageCalldata(crossDomainMessengerAbi, &sentMessage, value)
value = sentMessageExtension.Value
messageHash, err = crossdomain.HashCrossDomainMessageV1(sentMessage.MessageNonce, sentMessage.Sender, sentMessage.Target, value, sentMessage.GasLimit, sentMessage.Message)
if err != nil {
return nil, err
}
default:
// NOTE: We explicitly fail here since the presence of a new version means finalization
// logic needs to be updated to ensure L1 finalization can run from genesis and handle
// the changing version formats. This is meant to be a serving indicator of this.
return nil, fmt.Errorf("expected cross domain version 0 or version 1: %d", version)
}
crossDomainSentMessages[i] = CrossDomainMessengerSentMessageEvent{
Event: &sentMessageEvents[i],
MessageCalldata: messageCalldata,
Version: version,
BridgeMessage: database.BridgeMessage{
MessageHash: crypto.Keccak256Hash(messageCalldata),
MessageHash: messageHash,
Nonce: sentMessage.MessageNonce,
SentMessageEventGUID: sentMessageEvents[i].GUID,
GasLimit: sentMessage.GasLimit,
......@@ -157,26 +172,3 @@ func CrossDomainMessengerRelayedMessageEvents(chainSelector string, contractAddr
return crossDomainRelayedMessages, nil
}
// Replica of `Encoding.sol#encodeCrossDomainMessage` solidity implementation
func CrossDomainMessageCalldata(abi *abi.ABI, sentMsg *bindings.CrossDomainMessengerSentMessage, value *big.Int) ([]byte, error) {
version, _ := DecodeVersionedNonce(sentMsg.MessageNonce)
switch version {
case 0:
// Legacy Message
inputBytes, err := CrossDomainMessengerLegacyRelayMessageEncoding.Inputs.Pack(sentMsg.Target, sentMsg.Sender, sentMsg.Message, sentMsg.MessageNonce)
if err != nil {
return nil, err
}
return append(CrossDomainMessengerLegacyRelayMessageEncoding.ID, inputBytes...), nil
case 1:
// Current Message
msgBytes, err := abi.Pack("relayMessage", sentMsg.MessageNonce, sentMsg.Sender, sentMsg.Target, value, sentMsg.GasLimit, sentMsg.Message)
if err != nil {
return nil, err
}
return msgBytes, nil
}
return nil, fmt.Errorf("unsupported cross domain messenger version: %d", version)
}
package contracts
import (
"encoding/binary"
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/core/types"
)
// DecodeVersionNonce is an re-implementation of Encoding.sol#decodeVersionedNonce.
// If the nonce is greater than 32 bytes (solidity uint256), bytes [32:] are ignored
func DecodeVersionedNonce(nonce *big.Int) (uint16, *big.Int) {
nonceBytes := nonce.Bytes()
nonceByteLen := len(nonceBytes)
if nonceByteLen < 30 {
// version is 0x0000
return 0, nonce
} else if nonceByteLen == 31 {
// version is 0x00[01..ff]
return uint16(nonceBytes[0]), new(big.Int).SetBytes(nonceBytes[1:])
} else {
// fully specified
version := binary.BigEndian.Uint16(nonceBytes[:2])
return version, new(big.Int).SetBytes(nonceBytes[2:])
}
}
func UnpackLog(out interface{}, log *types.Log, name string, contractAbi *abi.ABI) error {
eventAbi, ok := contractAbi.Events[name]
if !ok {
......
......@@ -312,6 +312,10 @@ func (bs *BatcherService) Stop(ctx context.Context) error {
result = errors.Join(result, fmt.Errorf("failed to close balance metricer: %w", err))
}
}
if bs.TxManager != nil {
bs.TxManager.Close()
}
if bs.metricsSrv != nil {
if err := bs.metricsSrv.Stop(ctx); err != nil {
result = errors.Join(result, fmt.Errorf("failed to stop metrics server: %w", err))
......
......@@ -2,22 +2,19 @@ package op_challenger
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
)
// Main is the programmatic entry-point for running op-challenger
func Main(ctx context.Context, logger log.Logger, cfg *config.Config) error {
// Main is the programmatic entry-point for running op-challenger with a given configuration.
func Main(ctx context.Context, logger log.Logger, cfg *config.Config) (cliapp.Lifecycle, error) {
if err := cfg.Check(); err != nil {
return err
return nil, err
}
service, err := game.NewService(ctx, logger, cfg)
if err != nil {
return fmt.Errorf("failed to create the fault service: %w", err)
}
return service.MonitorGame(ctx)
srv, err := game.NewService(ctx, logger, cfg)
return srv, err
}
......@@ -12,6 +12,7 @@ import (
func TestMainShouldReturnErrorWhenConfigInvalid(t *testing.T) {
cfg := &config.Config{}
err := Main(context.Background(), testlog.Logger(t, log.LvlInfo), cfg)
app, err := Main(context.Background(), testlog.Logger(t, log.LvlInfo), cfg)
require.ErrorIs(t, err, cfg.Check())
require.Nil(t, app)
}
......@@ -4,16 +4,18 @@ import (
"context"
"os"
op_challenger "github.com/ethereum-optimism/optimism/op-challenger"
opservice "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum/go-ethereum/log"
"github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum/log"
challenger "github.com/ethereum-optimism/optimism/op-challenger"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/flags"
"github.com/ethereum-optimism/optimism/op-challenger/version"
opservice "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/opio"
)
var (
......@@ -26,14 +28,15 @@ var VersionWithMeta = opservice.FormatVersion(version.Version, GitCommit, GitDat
func main() {
args := os.Args
if err := run(args, op_challenger.Main); err != nil {
ctx := opio.WithInterruptBlocker(context.Background())
if err := run(ctx, args, challenger.Main); err != nil {
log.Crit("Application failed", "err", err)
}
}
type ConfigAction func(ctx context.Context, log log.Logger, config *config.Config) error
type ConfiguredLifecycle func(ctx context.Context, log log.Logger, config *config.Config) (cliapp.Lifecycle, error)
func run(args []string, action ConfigAction) error {
func run(ctx context.Context, args []string, action ConfiguredLifecycle) error {
oplog.SetupDefaults()
app := cli.NewApp()
......@@ -42,20 +45,20 @@ func run(args []string, action ConfigAction) error {
app.Name = "op-challenger"
app.Usage = "Challenge outputs"
app.Description = "Ensures that on chain outputs are correct."
app.Action = func(ctx *cli.Context) error {
app.Action = cliapp.LifecycleCmd(func(ctx *cli.Context, close context.CancelCauseFunc) (cliapp.Lifecycle, error) {
logger, err := setupLogging(ctx)
if err != nil {
return err
return nil, err
}
logger.Info("Starting op-challenger", "version", VersionWithMeta)
cfg, err := flags.NewConfigFromCLI(ctx)
if err != nil {
return err
return nil, err
}
return action(ctx.Context, logger, cfg)
}
return app.Run(args)
})
return app.RunContext(ctx, args)
}
func setupLogging(ctx *cli.Context) (log.Logger, error) {
......
......@@ -2,15 +2,19 @@ package main
import (
"context"
"errors"
"fmt"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
)
var (
......@@ -36,7 +40,7 @@ func TestLogLevel(t *testing.T) {
for _, lvl := range []string{"trace", "debug", "info", "error", "crit"} {
lvl := lvl
t.Run("AcceptValid_"+lvl, func(t *testing.T) {
logger, _, err := runWithArgs(addRequiredArgs(config.TraceTypeAlphabet, "--log.level", lvl))
logger, _, err := dryRunWithArgs(addRequiredArgs(config.TraceTypeAlphabet, "--log.level", lvl))
require.NoError(t, err)
require.NotNil(t, logger)
})
......@@ -431,25 +435,29 @@ func TestCannonL2Genesis(t *testing.T) {
}
func verifyArgsInvalid(t *testing.T, messageContains string, cliArgs []string) {
_, _, err := runWithArgs(cliArgs)
_, _, err := dryRunWithArgs(cliArgs)
require.ErrorContains(t, err, messageContains)
}
func configForArgs(t *testing.T, cliArgs []string) config.Config {
_, cfg, err := runWithArgs(cliArgs)
_, cfg, err := dryRunWithArgs(cliArgs)
require.NoError(t, err)
return cfg
}
func runWithArgs(cliArgs []string) (log.Logger, config.Config, error) {
func dryRunWithArgs(cliArgs []string) (log.Logger, config.Config, error) {
cfg := new(config.Config)
var logger log.Logger
fullArgs := append([]string{"op-challenger"}, cliArgs...)
err := run(fullArgs, func(ctx context.Context, log log.Logger, config *config.Config) error {
testErr := errors.New("dry-run")
err := run(context.Background(), fullArgs, func(ctx context.Context, log log.Logger, config *config.Config) (cliapp.Lifecycle, error) {
logger = log
cfg = config
return nil
return nil, testErr
})
if errors.Is(err, testErr) { // expected error
err = nil
}
return logger, *cfg, err
}
......
......@@ -65,7 +65,7 @@ func registerOutputCannon(
if err != nil {
return nil, nil, err
}
accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, cfg.RollupRpc, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64())
accessor, err := outputs.NewOutputCannonTraceAccessor(ctx, logger, m, cfg, contract, dir, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64())
if err != nil {
return nil, nil, err
}
......
......@@ -232,6 +232,9 @@ func (m *mockTxManager) From() common.Address {
return m.from
}
func (m *mockTxManager) Close() {
}
type mockContract struct {
calls int
callFails bool
......
......@@ -23,21 +23,29 @@ type L2DataSource interface {
HeaderByNumber(context.Context, *big.Int) (*ethtypes.Header, error)
}
type GameInputsSource interface {
type L1HeadSource interface {
GetL1Head(ctx context.Context) (common.Hash, error)
}
type GameInputsSource interface {
L1HeadSource
GetProposals(ctx context.Context) (agreed contracts.Proposal, disputed contracts.Proposal, err error)
}
func fetchLocalInputs(ctx context.Context, caller GameInputsSource, l2Client L2DataSource) (LocalGameInputs, error) {
l1Head, err := caller.GetL1Head(ctx)
agreedOutput, claimedOutput, err := caller.GetProposals(ctx)
if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err)
return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err)
}
return fetchLocalInputsFromProposals(ctx, caller, l2Client, agreedOutput, claimedOutput)
}
agreedOutput, claimedOutput, err := caller.GetProposals(ctx)
func fetchLocalInputsFromProposals(ctx context.Context, caller L1HeadSource, l2Client L2DataSource, agreedOutput contracts.Proposal, claimedOutput contracts.Proposal) (LocalGameInputs, error) {
l1Head, err := caller.GetL1Head(ctx)
if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch proposals: %w", err)
return LocalGameInputs{}, fmt.Errorf("fetch L1 head: %w", err)
}
agreedHeader, err := l2Client.HeaderByNumber(ctx, agreedOutput.L2BlockNumber)
if err != nil {
return LocalGameInputs{}, fmt.Errorf("fetch L2 block header %v: %w", agreedOutput.L2BlockNumber, err)
......
......@@ -42,6 +42,36 @@ func TestFetchLocalInputs(t *testing.T) {
require.Equal(t, contract.disputed.L2BlockNumber, inputs.L2BlockNumber)
}
func TestFetchLocalInputsFromProposals(t *testing.T) {
ctx := context.Background()
agreed := contracts.Proposal{
L2BlockNumber: big.NewInt(2222),
OutputRoot: common.Hash{0xdd},
}
claimed := contracts.Proposal{
L2BlockNumber: big.NewInt(3333),
OutputRoot: common.Hash{0xee},
}
contract := &mockGameInputsSource{
l1Head: common.Hash{0xcc},
}
l2Client := &mockL2DataSource{
chainID: big.NewInt(88422),
header: ethtypes.Header{
Number: agreed.L2BlockNumber,
},
}
inputs, err := fetchLocalInputsFromProposals(ctx, contract, l2Client, agreed, claimed)
require.NoError(t, err)
require.Equal(t, contract.l1Head, inputs.L1Head)
require.Equal(t, l2Client.header.Hash(), inputs.L2Head)
require.EqualValues(t, agreed.OutputRoot, inputs.L2OutputRoot)
require.EqualValues(t, claimed.OutputRoot, inputs.L2Claim)
require.Equal(t, claimed.L2BlockNumber, inputs.L2BlockNumber)
}
type mockGameInputsSource struct {
l1Head common.Hash
starting contracts.Proposal
......
......@@ -69,6 +69,30 @@ func NewTraceProvider(ctx context.Context, logger log.Logger, m CannonMetricer,
return NewTraceProviderFromInputs(logger, m, cfg, localContext, localInputs, dir, gameDepth), nil
}
func NewTraceProviderFromProposals(
ctx context.Context,
logger log.Logger,
m CannonMetricer,
cfg *config.Config,
gameContract *contracts.FaultDisputeGameContract,
localContext common.Hash,
agreed contracts.Proposal,
claimed contracts.Proposal,
dir string,
gameDepth uint64,
) (*CannonTraceProvider, error) {
l2Client, err := ethclient.DialContext(ctx, cfg.CannonL2)
if err != nil {
return nil, fmt.Errorf("dial l2 client %v: %w", cfg.CannonL2, err)
}
defer l2Client.Close() // Not needed after fetching the inputs
localInputs, err := fetchLocalInputsFromProposals(ctx, gameContract, l2Client, agreed, claimed)
if err != nil {
return nil, fmt.Errorf("fetch local game inputs: %w", err)
}
return NewTraceProviderFromInputs(logger, m, cfg, localContext, localInputs, dir, gameDepth), nil
}
func NewTraceProviderFromInputs(logger log.Logger, m CannonMetricer, cfg *config.Config, localContext common.Hash, localInputs LocalGameInputs, dir string, gameDepth uint64) *CannonTraceProvider {
return &CannonTraceProvider{
logger: logger,
......
......@@ -2,28 +2,50 @@ package outputs
import (
"context"
"errors"
"fmt"
"path/filepath"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/cannon"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/split"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
func NewOutputCannonTraceAccessor(ctx context.Context, logger log.Logger, rollupRpc string, gameDepth uint64, prestateBlock uint64, poststateBlock uint64) (*trace.Accessor, error) {
topDepth := gameDepth / 2 // TODO(client-pod#43): Load this from the contract
outputProvider, err := NewTraceProvider(ctx, logger, rollupRpc, topDepth, prestateBlock, poststateBlock)
func NewOutputCannonTraceAccessor(
ctx context.Context,
logger log.Logger,
m metrics.Metricer,
cfg *config.Config,
contract *contracts.FaultDisputeGameContract,
dir string,
gameDepth uint64,
prestateBlock uint64,
poststateBlock uint64,
) (*trace.Accessor, error) {
// TODO(client-pod#43): Load depths from the contract
topDepth := gameDepth / 2
bottomDepth := gameDepth - topDepth
outputProvider, err := NewTraceProvider(ctx, logger, cfg.RollupRpc, topDepth, prestateBlock, poststateBlock)
if err != nil {
return nil, err
}
cannonCreator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
// TODO(client-pod#43): Actually create the cannon trace provider for the trace between the given claims.
return nil, errors.New("not implemented")
logger := logger.New("pre", agreed.OutputRoot, "post", claimed.OutputRoot, "localContext", localContext)
subdir := filepath.Join(dir, localContext.Hex())
provider, err := cannon.NewTraceProviderFromProposals(ctx, logger, m, cfg, contract, localContext, agreed, claimed, subdir, bottomDepth)
if err != nil {
return nil, fmt.Errorf("failed to create cannon trace provider: %w", err)
}
return provider, nil
}
selector := split.NewSplitProviderSelector(outputProvider, int(topDepth), OutputRootSplitAdapter(outputProvider, cannonCreator))
cache := NewProviderCache(m, "output_cannon_provider", cannonCreator)
selector := split.NewSplitProviderSelector(outputProvider, int(topDepth), OutputRootSplitAdapter(outputProvider, cache.GetOrCreate))
return trace.NewAccessor(selector), nil
}
package outputs
import (
"context"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/sources/caching"
"github.com/ethereum/go-ethereum/common"
)
type ProviderCache struct {
cache *caching.LRUCache[common.Hash, types.TraceProvider]
creator ProposalTraceProviderCreator
}
func (c *ProviderCache) GetOrCreate(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
provider, ok := c.cache.Get(localContext)
if ok {
return provider, nil
}
provider, err := c.creator(ctx, localContext, agreed, claimed)
if err != nil {
return nil, err
}
c.cache.Add(localContext, provider)
return provider, nil
}
func NewProviderCache(m caching.Metrics, metricsLabel string, creator ProposalTraceProviderCreator) *ProviderCache {
cache := caching.NewLRUCache[common.Hash, types.TraceProvider](m, metricsLabel, 100)
return &ProviderCache{
cache: cache,
creator: creator,
}
}
package outputs
import (
"context"
"errors"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/trace/alphabet"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestProviderCache(t *testing.T) {
agreed := contracts.Proposal{
L2BlockNumber: big.NewInt(34),
OutputRoot: common.Hash{0xaa},
}
claimed := contracts.Proposal{
L2BlockNumber: big.NewInt(35),
OutputRoot: common.Hash{0xcc},
}
var createdProvider types.TraceProvider
creator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
createdProvider = alphabet.NewTraceProvider("abcdef", 6)
return createdProvider, nil
}
localContext1 := common.Hash{0xdd}
localContext2 := common.Hash{0xee}
cache := NewProviderCache(metrics.NoopMetrics, "test", creator)
// Create on first call
provider1, err := cache.GetOrCreate(context.Background(), localContext1, agreed, claimed)
require.NoError(t, err)
require.Same(t, createdProvider, provider1, "should return created trace provider")
// Return the cached provider on subsequent calls.
createdProvider = nil
cached, err := cache.GetOrCreate(context.Background(), localContext1, agreed, claimed)
require.NoError(t, err)
require.Same(t, provider1, cached, "should return exactly the same instance from cache")
require.Nil(t, createdProvider)
// Create a new provider when the local context is different
createdProvider = nil
otherProvider, err := cache.GetOrCreate(context.Background(), localContext2, agreed, claimed)
require.NoError(t, err)
require.Same(t, otherProvider, createdProvider, "should return newly created trace provider")
require.NotSame(t, otherProvider, provider1, "should not use cached provider for different local context")
}
func TestProviderCache_DoNotCacheErrors(t *testing.T) {
callCount := 0
providerErr := errors.New("boom")
creator := func(ctx context.Context, localContext common.Hash, agreed contracts.Proposal, claimed contracts.Proposal) (types.TraceProvider, error) {
callCount++
return nil, providerErr
}
localContext1 := common.Hash{0xdd}
cache := NewProviderCache(metrics.NoopMetrics, "test", creator)
provider, err := cache.GetOrCreate(context.Background(), localContext1, contracts.Proposal{}, contracts.Proposal{})
require.Nil(t, provider)
require.ErrorIs(t, err, providerErr)
require.Equal(t, 1, callCount)
// Should call the creator again on the second attempt
provider, err = cache.GetOrCreate(context.Background(), localContext1, contracts.Proposal{}, contracts.Proposal{})
require.Nil(t, provider)
require.ErrorIs(t, err, providerErr)
require.Equal(t, 2, callCount)
}
......@@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"sync"
"time"
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
......@@ -39,6 +40,7 @@ type gameMonitor struct {
allowedGames []common.Address
l1HeadsSub ethereum.Subscription
l1Source *headSource
runState sync.Mutex
}
type MinimalSubscriber interface {
......@@ -126,8 +128,10 @@ func (m *gameMonitor) onNewL1Head(ctx context.Context, sig eth.L1BlockRef) {
}
}
func (m *gameMonitor) resubscribeFunction(ctx context.Context) event.ResubscribeErrFunc {
return func(innerCtx context.Context, err error) (event.Subscription, error) {
func (m *gameMonitor) resubscribeFunction() event.ResubscribeErrFunc {
// The ctx is cancelled as soon as the subscription is returned,
// but is only used to create the subscription, and does not affect the returned subscription.
return func(ctx context.Context, err error) (event.Subscription, error) {
if err != nil {
m.logger.Warn("resubscribing after failed L1 subscription", "err", err)
}
......@@ -135,18 +139,21 @@ func (m *gameMonitor) resubscribeFunction(ctx context.Context) event.Resubscribe
}
}
func (m *gameMonitor) MonitorGames(ctx context.Context) error {
m.l1HeadsSub = event.ResubscribeErr(time.Second*10, m.resubscribeFunction(ctx))
for {
select {
case <-ctx.Done():
m.l1HeadsSub.Unsubscribe()
return nil
case err, ok := <-m.l1HeadsSub.Err():
if !ok {
return err
}
m.logger.Error("L1 subscription error", "err", err)
func (m *gameMonitor) StartMonitoring() {
m.runState.Lock()
defer m.runState.Unlock()
if m.l1HeadsSub != nil {
return // already started
}
m.l1HeadsSub = event.ResubscribeErr(time.Second*10, m.resubscribeFunction())
}
func (m *gameMonitor) StopMonitoring() {
m.runState.Lock()
defer m.runState.Unlock()
if m.l1HeadsSub == nil {
return // already stopped
}
m.l1HeadsSub.Unsubscribe()
m.l1HeadsSub = nil
}
......@@ -84,8 +84,9 @@ func TestMonitorGames(t *testing.T) {
cancel()
}()
err := monitor.MonitorGames(ctx)
require.NoError(t, err)
monitor.StartMonitoring()
<-ctx.Done()
monitor.StopMonitoring()
require.Len(t, sched.scheduled, 1)
require.Equal(t, []common.Address{addr1, addr2}, sched.scheduled[0])
})
......@@ -129,8 +130,9 @@ func TestMonitorGames(t *testing.T) {
cancel()
}()
err := monitor.MonitorGames(ctx)
require.NoError(t, err)
monitor.StartMonitoring()
<-ctx.Done()
monitor.StopMonitoring()
require.NotEmpty(t, sched.scheduled) // We might get more than one update scheduled.
require.Equal(t, []common.Address{addr1, addr2}, sched.scheduled[0])
})
......
......@@ -4,6 +4,11 @@ import (
"context"
"errors"
"fmt"
"io"
"sync/atomic"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault"
......@@ -13,14 +18,14 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/game/scheduler"
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-challenger/version"
opClient "github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/client"
"github.com/ethereum-optimism/optimism/op-service/clock"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/httputil"
opmetrics "github.com/ethereum-optimism/optimism/op-service/metrics"
oppprof "github.com/ethereum-optimism/optimism/op-service/pprof"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/log"
)
type Service struct {
......@@ -29,101 +34,196 @@ type Service struct {
monitor *gameMonitor
sched *scheduler.Scheduler
txMgr *txmgr.SimpleTxManager
loader *loader.GameLoader
l1Client *ethclient.Client
pollClient client.RPC
pprofSrv *httputil.HTTPServer
metricsSrv *httputil.HTTPServer
balanceMetricer io.Closer
stopped atomic.Bool
}
func (s *Service) Stop(ctx context.Context) error {
var result error
if s.sched != nil {
result = errors.Join(result, s.sched.Close())
// NewService creates a new Service.
func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Service, error) {
s := &Service{
logger: logger,
metrics: metrics.NewMetrics(),
}
if s.pprofSrv != nil {
result = errors.Join(result, s.pprofSrv.Stop(ctx))
if err := s.initFromConfig(ctx, cfg); err != nil {
// upon initialization error we can try to close any of the service components that may have started already.
return nil, errors.Join(fmt.Errorf("failed to init challenger game service: %w", err), s.Stop(ctx))
}
if s.metricsSrv != nil {
result = errors.Join(result, s.metricsSrv.Stop(ctx))
return s, nil
}
func (s *Service) initFromConfig(ctx context.Context, cfg *config.Config) error {
if err := s.initTxManager(cfg); err != nil {
return err
}
return result
if err := s.initL1Client(ctx, cfg); err != nil {
return err
}
if err := s.initPollClient(ctx, cfg); err != nil {
return err
}
if err := s.initPProfServer(&cfg.PprofConfig); err != nil {
return err
}
if err := s.initMetricsServer(&cfg.MetricsConfig); err != nil {
return err
}
if err := s.initGameLoader(cfg); err != nil {
return err
}
s.initScheduler(ctx, cfg)
s.initMonitor(cfg)
s.metrics.RecordInfo(version.SimpleWithMeta)
s.metrics.RecordUp()
return nil
}
// NewService creates a new Service.
func NewService(ctx context.Context, logger log.Logger, cfg *config.Config) (*Service, error) {
cl := clock.SystemClock
m := metrics.NewMetrics()
txMgr, err := txmgr.NewSimpleTxManager("challenger", logger, &m.TxMetrics, cfg.TxMgrConfig)
func (s *Service) initTxManager(cfg *config.Config) error {
txMgr, err := txmgr.NewSimpleTxManager("challenger", s.logger, s.metrics, cfg.TxMgrConfig)
if err != nil {
return nil, fmt.Errorf("failed to create the transaction manager: %w", err)
return fmt.Errorf("failed to create the transaction manager: %w", err)
}
s.txMgr = txMgr
return nil
}
l1Client, err := dial.DialEthClientWithTimeout(ctx, dial.DefaultDialTimeout, logger, cfg.L1EthRpc)
func (s *Service) initL1Client(ctx context.Context, cfg *config.Config) error {
l1Client, err := dial.DialEthClientWithTimeout(ctx, dial.DefaultDialTimeout, s.logger, cfg.L1EthRpc)
if err != nil {
return nil, fmt.Errorf("failed to dial L1: %w", err)
return fmt.Errorf("failed to dial L1: %w", err)
}
s.l1Client = l1Client
return nil
}
s := &Service{
logger: logger,
metrics: m,
func (s *Service) initPollClient(ctx context.Context, cfg *config.Config) error {
pollClient, err := client.NewRPCWithClient(ctx, s.logger, cfg.L1EthRpc, client.NewBaseRPCClient(s.l1Client.Client()), cfg.PollInterval)
if err != nil {
return fmt.Errorf("failed to create RPC client: %w", err)
}
s.pollClient = pollClient
return nil
}
pprofConfig := cfg.PprofConfig
if pprofConfig.Enabled {
logger.Debug("starting pprof", "addr", pprofConfig.ListenAddr, "port", pprofConfig.ListenPort)
pprofSrv, err := oppprof.StartServer(pprofConfig.ListenAddr, pprofConfig.ListenPort)
func (s *Service) initPProfServer(cfg *oppprof.CLIConfig) error {
if !cfg.Enabled {
return nil
}
s.logger.Debug("starting pprof", "addr", cfg.ListenAddr, "port", cfg.ListenPort)
pprofSrv, err := oppprof.StartServer(cfg.ListenAddr, cfg.ListenPort)
if err != nil {
return nil, errors.Join(fmt.Errorf("failed to start pprof server: %w", err), s.Stop(ctx))
return fmt.Errorf("failed to start pprof server: %w", err)
}
s.pprofSrv = pprofSrv
logger.Info("started pprof server", "addr", pprofSrv.Addr())
}
s.logger.Info("started pprof server", "addr", pprofSrv.Addr())
return nil
}
metricsCfg := cfg.MetricsConfig
if metricsCfg.Enabled {
logger.Debug("starting metrics server", "addr", metricsCfg.ListenAddr, "port", metricsCfg.ListenPort)
metricsSrv, err := m.Start(metricsCfg.ListenAddr, metricsCfg.ListenPort)
func (s *Service) initMetricsServer(cfg *opmetrics.CLIConfig) error {
if !cfg.Enabled {
return nil
}
s.logger.Debug("starting metrics server", "addr", cfg.ListenAddr, "port", cfg.ListenPort)
m, ok := s.metrics.(opmetrics.RegistryMetricer)
if !ok {
return fmt.Errorf("metrics were enabled, but metricer %T does not expose registry for metrics-server", s.metrics)
}
metricsSrv, err := opmetrics.StartServer(m.Registry(), cfg.ListenAddr, cfg.ListenPort)
if err != nil {
return nil, errors.Join(fmt.Errorf("failed to start metrics server: %w", err), s.Stop(ctx))
return fmt.Errorf("failed to start metrics server: %w", err)
}
logger.Info("started metrics server", "addr", metricsSrv.Addr())
s.logger.Info("started metrics server", "addr", metricsSrv.Addr())
s.metricsSrv = metricsSrv
m.StartBalanceMetrics(ctx, logger, l1Client, txMgr.From())
}
s.balanceMetricer = s.metrics.StartBalanceMetrics(s.logger, s.l1Client, s.txMgr.From())
return nil
}
factoryContract, err := contracts.NewDisputeGameFactoryContract(cfg.GameFactoryAddress, batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize))
func (s *Service) initGameLoader(cfg *config.Config) error {
factoryContract, err := contracts.NewDisputeGameFactoryContract(cfg.GameFactoryAddress,
batching.NewMultiCaller(s.l1Client.Client(), batching.DefaultBatchSize))
if err != nil {
return nil, errors.Join(fmt.Errorf("failed to bind the fault dispute game factory contract: %w", err), s.Stop(ctx))
return fmt.Errorf("failed to bind the fault dispute game factory contract: %w", err)
}
loader := loader.NewGameLoader(factoryContract)
s.loader = loader.NewGameLoader(factoryContract)
return nil
}
func (s *Service) initScheduler(ctx context.Context, cfg *config.Config) {
gameTypeRegistry := registry.NewGameTypeRegistry()
fault.RegisterGameTypes(gameTypeRegistry, ctx, logger, m, cfg, txMgr, l1Client)
fault.RegisterGameTypes(gameTypeRegistry, ctx, s.logger, s.metrics, cfg, s.txMgr, s.l1Client)
disk := newDiskManager(cfg.Datadir)
s.sched = scheduler.NewScheduler(
logger,
m,
disk,
cfg.MaxConcurrency,
gameTypeRegistry.CreatePlayer)
pollClient, err := opClient.NewRPCWithClient(ctx, logger, cfg.L1EthRpc, opClient.NewBaseRPCClient(l1Client.Client()), cfg.PollInterval)
if err != nil {
return nil, errors.Join(fmt.Errorf("failed to create RPC client: %w", err), s.Stop(ctx))
}
s.monitor = newGameMonitor(logger, cl, loader, s.sched, cfg.GameWindow, l1Client.BlockNumber, cfg.GameAllowlist, pollClient)
m.RecordInfo(version.SimpleWithMeta)
m.RecordUp()
s.sched = scheduler.NewScheduler(s.logger, s.metrics, disk, cfg.MaxConcurrency, gameTypeRegistry.CreatePlayer)
}
return s, nil
func (s *Service) initMonitor(cfg *config.Config) {
cl := clock.SystemClock
s.monitor = newGameMonitor(s.logger, cl, s.loader, s.sched, cfg.GameWindow, s.l1Client.BlockNumber, cfg.GameAllowlist, s.pollClient)
}
// MonitorGame monitors the fault dispute game and attempts to progress it.
func (s *Service) MonitorGame(ctx context.Context) error {
func (s *Service) Start(ctx context.Context) error {
s.logger.Info("starting scheduler")
s.sched.Start(ctx)
err := s.monitor.MonitorGames(ctx)
// The other ctx is the close-trigger.
// We need to refactor Service more to allow for graceful/force-shutdown granularity.
err = errors.Join(err, s.Stop(context.Background()))
return err
s.logger.Info("starting monitoring")
s.monitor.StartMonitoring()
s.logger.Info("challenger game service start completed")
return nil
}
func (s *Service) Stopped() bool {
return s.stopped.Load()
}
func (s *Service) Stop(ctx context.Context) error {
s.logger.Info("stopping challenger game service")
var result error
if s.sched != nil {
if err := s.sched.Close(); err != nil {
result = errors.Join(result, fmt.Errorf("failed to close scheduler: %w", err))
}
}
if s.monitor != nil {
s.monitor.StopMonitoring()
}
if s.pprofSrv != nil {
if err := s.pprofSrv.Stop(ctx); err != nil {
result = errors.Join(result, fmt.Errorf("failed to close pprof server: %w", err))
}
}
if s.balanceMetricer != nil {
if err := s.balanceMetricer.Close(); err != nil {
result = errors.Join(result, fmt.Errorf("failed to close balance metricer: %w", err))
}
}
if s.txMgr != nil {
s.txMgr.Close()
}
if s.l1Client != nil {
s.l1Client.Close()
}
if s.metricsSrv != nil {
if err := s.metricsSrv.Stop(ctx); err != nil {
result = errors.Join(result, fmt.Errorf("failed to close metrics server: %w", err))
}
}
s.stopped.Store(true)
s.logger.Info("stopped challenger game service", "err", result)
return result
}
package metrics
import (
"context"
"io"
"github.com/ethereum-optimism/optimism/op-service/sources/caching"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
......@@ -19,9 +20,14 @@ type Metricer interface {
RecordInfo(version string)
RecordUp()
StartBalanceMetrics(l log.Logger, client *ethclient.Client, account common.Address) io.Closer
// Record Tx metrics
txmetrics.TxMetricer
// Record cache metrics
caching.Metrics
RecordGameStep()
RecordGameMove()
RecordCannonExecutionTime(t float64)
......@@ -44,6 +50,8 @@ type Metrics struct {
txmetrics.TxMetrics
*opmetrics.CacheMetrics
info prometheus.GaugeVec
up prometheus.Gauge
......@@ -71,6 +79,8 @@ func NewMetrics() *Metrics {
TxMetrics: txmetrics.MakeTxMetrics(Namespace, factory),
CacheMetrics: opmetrics.NewCacheMetrics(factory, Namespace, "provider_cache", "Provider cache"),
info: *factory.NewGaugeVec(prometheus.GaugeOpts{
Namespace: Namespace,
Name: "info",
......@@ -128,17 +138,11 @@ func (m *Metrics) Start(host string, port int) (*httputil.HTTPServer, error) {
}
func (m *Metrics) StartBalanceMetrics(
ctx context.Context,
l log.Logger,
client *ethclient.Client,
account common.Address,
) {
// TODO(7684): util was refactored to close, but ctx is still being used by caller for shutdown
balanceMetric := opmetrics.LaunchBalanceMetrics(l, m.registry, m.ns, client, account)
go func() {
<-ctx.Done()
_ = balanceMetric.Close()
}()
) io.Closer {
return opmetrics.LaunchBalanceMetrics(l, m.registry, m.ns, client, account)
}
// RecordInfo sets a pseudo-metric that contains versioning and
......
package metrics
import (
"io"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
txmetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
)
......@@ -8,6 +14,10 @@ type NoopMetricsImpl struct {
txmetrics.NoopTxMetrics
}
func (i *NoopMetricsImpl) StartBalanceMetrics(l log.Logger, client *ethclient.Client, account common.Address) io.Closer {
return nil
}
var NoopMetrics Metricer = new(NoopMetricsImpl)
func (*NoopMetricsImpl) RecordInfo(version string) {}
......@@ -27,3 +37,6 @@ func (*NoopMetricsImpl) IncActiveExecutors() {}
func (*NoopMetricsImpl) DecActiveExecutors() {}
func (*NoopMetricsImpl) IncIdleExecutors() {}
func (*NoopMetricsImpl) DecIdleExecutors() {}
func (*NoopMetricsImpl) CacheAdd(_ string, _ int, _ bool) {}
func (*NoopMetricsImpl) CacheGet(_ string, _ bool) {}
......@@ -54,6 +54,8 @@ func (f fakeTxMgr) BlockNumber(_ context.Context) (uint64, error) {
func (f fakeTxMgr) Send(_ context.Context, _ txmgr.TxCandidate) (*types.Receipt, error) {
panic("unimplemented")
}
func (f fakeTxMgr) Close() {
}
func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Client, rollupCl *sources.RollupClient) *L2Proposer {
proposerConfig := proposer.ProposerConfig{
......
......@@ -11,16 +11,19 @@ import (
"testing"
"time"
op_challenger "github.com/ethereum-optimism/optimism/op-challenger"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
challenger "github.com/ethereum-optimism/optimism/op-challenger"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-service/cliapp"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
type Helper struct {
......@@ -28,8 +31,7 @@ type Helper struct {
t *testing.T
require *require.Assertions
dir string
cancel func()
errors chan error
chl cliapp.Lifecycle
}
type Option func(config2 *config.Config)
......@@ -127,20 +129,16 @@ func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name st
log := testlog.Logger(t, log.LvlDebug).New("role", name)
log.Info("Creating challenger", "l1", l1Endpoint)
cfg := NewChallengerConfig(t, l1Endpoint, options...)
chl, err := challenger.Main(ctx, log, cfg)
require.NoError(t, err, "must init challenger")
require.NoError(t, chl.Start(ctx), "must start challenger")
errCh := make(chan error, 1)
ctx, cancel := context.WithCancel(ctx)
go func() {
defer close(errCh)
errCh <- op_challenger.Main(ctx, log, cfg)
}()
return &Helper{
log: log,
t: t,
require: require.New(t),
dir: cfg.Datadir,
cancel: cancel,
errors: errCh,
chl: chl,
}
}
......@@ -179,16 +177,9 @@ func NewChallengerConfig(t *testing.T, l1Endpoint string, options ...Option) *co
}
func (h *Helper) Close() error {
h.cancel()
select {
case <-time.After(1 * time.Minute):
return errors.New("timed out while stopping challenger")
case err := <-h.errors:
if !errors.Is(err, context.Canceled) {
return err
}
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
return h.chl.Stop(ctx)
}
type GameAddr interface {
......
......@@ -12,6 +12,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
)
var (
......@@ -80,7 +81,6 @@ func WaitForTransaction(hash common.Hash, client *ethclient.Client, timeout time
}
func WaitForBlock(number *big.Int, client *ethclient.Client, timeout time.Duration) (*types.Block, error) {
timeoutCh := time.After(timeout)
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
......@@ -99,8 +99,43 @@ func WaitForBlock(number *big.Int, client *ethclient.Client, timeout time.Durati
}
case err := <-headSub.Err():
return nil, fmt.Errorf("error in head subscription: %w", err)
case <-timeoutCh:
return nil, errTimeout
case <-ctx.Done():
return nil, ctx.Err()
}
}
}
func WaitForBlockToBeFinalized(number *big.Int, client *ethclient.Client, timeout time.Duration) (*types.Block, error) {
return waitForBlockTag(number, client, timeout, rpc.FinalizedBlockNumber)
}
func WaitForBlockToBeSafe(number *big.Int, client *ethclient.Client, timeout time.Duration) (*types.Block, error) {
return waitForBlockTag(number, client, timeout, rpc.SafeBlockNumber)
}
// waitForBlockTag polls for a block number to reach the specified tag & then returns that block at the number.
func waitForBlockTag(number *big.Int, client *ethclient.Client, timeout time.Duration, tag rpc.BlockNumber) (*types.Block, error) {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// Wait for it to be finalized. Poll every half second.
ticker := time.NewTicker(500 * time.Millisecond)
defer ticker.Stop()
tagBigInt := big.NewInt(tag.Int64())
for {
select {
case <-ticker.C:
block, err := client.BlockByNumber(ctx, tagBigInt)
if err != nil {
return nil, err
}
if block != nil && block.NumberU64() >= number.Uint64() {
return client.BlockByNumber(ctx, number)
}
case <-ctx.Done():
return nil, ctx.Err()
}
}
}
......@@ -368,17 +368,8 @@ func TestFinalize(t *testing.T) {
l2Seq := sys.Clients["sequencer"]
// as configured in the extra geth lifecycle in testing setup
const finalizedDistance = 8
// Wait enough time for L1 to finalize and L2 to confirm its data in finalized L1 blocks
time.Sleep(time.Duration((finalizedDistance+6)*cfg.DeployConfig.L1BlockTime) * time.Second)
// fetch the finalizes head of geth
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
l2Finalized, err := l2Seq.BlockByNumber(ctx, big.NewInt(int64(rpc.FinalizedBlockNumber)))
require.NoError(t, err)
l2Finalized, err := geth.WaitForBlockToBeFinalized(big.NewInt(12), l2Seq, 1*time.Minute)
require.NoError(t, err, "must be able to fetch a finalized L2 block")
require.NotZerof(t, l2Finalized.NumberU64(), "must have finalized L2 block")
}
......
......@@ -174,7 +174,7 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
if err != nil {
n.log.Warn("resubscribing after failed L1 subscription", "err", err)
}
return eth.WatchHeadChanges(n.resourcesCtx, n.l1Source, n.OnNewL1Head)
return eth.WatchHeadChanges(ctx, n.l1Source, n.OnNewL1Head)
})
go func() {
err, ok := <-n.l1HeadsSub.Err()
......@@ -186,9 +186,9 @@ func (n *OpNode) initL1(ctx context.Context, cfg *Config) error {
// Poll for the safe L1 block and finalized block,
// which only change once per epoch at most and may be delayed.
n.l1SafeSub = eth.PollBlockChanges(n.resourcesCtx, n.log, n.l1Source, n.OnNewL1Safe, eth.Safe,
n.l1SafeSub = eth.PollBlockChanges(n.log, n.l1Source, n.OnNewL1Safe, eth.Safe,
cfg.L1EpochPollInterval, time.Second*10)
n.l1FinalizedSub = eth.PollBlockChanges(n.resourcesCtx, n.log, n.l1Source, n.OnNewL1Finalized, eth.Finalized,
n.l1FinalizedSub = eth.PollBlockChanges(n.log, n.l1Source, n.OnNewL1Finalized, eth.Finalized,
cfg.L1EpochPollInterval, time.Second*10)
return nil
}
......@@ -582,6 +582,14 @@ func (n *OpNode) Stop(ctx context.Context) error {
if n.l1HeadsSub != nil {
n.l1HeadsSub.Unsubscribe()
}
// stop polling for L1 safe-head changes
if n.l1SafeSub != nil {
n.l1SafeSub.Unsubscribe()
}
// stop polling for L1 finalized-head changes
if n.l1FinalizedSub != nil {
n.l1FinalizedSub.Unsubscribe()
}
// close L2 driver
if n.l2Driver != nil {
......
......@@ -94,7 +94,7 @@ func (d *recordsBook[K, V]) dsKey(key K) ds.Key {
func (d *recordsBook[K, V]) deleteRecord(key K) error {
d.cache.Remove(key)
err := d.store.Delete(d.ctx, d.dsKey(key))
if errors.Is(err, ds.ErrNotFound) {
if err == nil || errors.Is(err, ds.ErrNotFound) {
return nil
}
return fmt.Errorf("failed to delete entry with key %v: %w", key, err)
......
......@@ -279,6 +279,11 @@ func (ps *ProposerService) Stop(ctx context.Context) error {
result = errors.Join(result, fmt.Errorf("failed to close balance metricer: %w", err))
}
}
if ps.TxManager != nil {
ps.TxManager.Close()
}
if ps.metricsSrv != nil {
if err := ps.metricsSrv.Stop(ctx); err != nil {
result = errors.Join(result, fmt.Errorf("failed to stop metrics server: %w", err))
......
......@@ -17,7 +17,8 @@ type NewHeadSource interface {
SubscribeNewHead(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error)
}
// WatchHeadChanges wraps a new-head subscription from NewHeadSource to feed the given Tracker
// WatchHeadChanges wraps a new-head subscription from NewHeadSource to feed the given Tracker.
// The ctx is only used to create the subscription, and does not affect the returned subscription.
func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) (ethereum.Subscription, error) {
headChanges := make(chan *types.Header, 10)
sub, err := src.SubscribeNewHead(ctx, headChanges)
......@@ -25,22 +26,33 @@ func WatchHeadChanges(ctx context.Context, src NewHeadSource, fn HeadSignalFn) (
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
eventsCtx, eventsCancel := context.WithCancel(context.Background())
defer sub.Unsubscribe()
defer eventsCancel()
// We can handle a quit signal while fn is running, by closing the ctx.
go func() {
select {
case <-quit:
eventsCancel()
case <-eventsCtx.Done(): // don't wait for quit signal if we closed for other reasons.
return
}
}()
for {
select {
case header := <-headChanges:
fn(ctx, L1BlockRef{
fn(eventsCtx, L1BlockRef{
Hash: header.Hash(),
Number: header.Number.Uint64(),
ParentHash: header.ParentHash,
Time: header.Time,
})
case err := <-sub.Err():
return err
case <-ctx.Done():
return ctx.Err()
case <-quit:
case <-eventsCtx.Done():
return nil
case err := <-sub.Err(): // if the underlying subscription fails, stop
return err
}
}
}), nil
......@@ -53,7 +65,7 @@ type L1BlockRefsSource interface {
// PollBlockChanges opens a polling loop to fetch the L1 block reference with the given label,
// on provided interval and with request timeout. Results are returned with provided callback fn,
// which may block to pause/back-pressure polling.
func PollBlockChanges(ctx context.Context, log log.Logger, src L1BlockRefsSource, fn HeadSignalFn,
func PollBlockChanges(log log.Logger, src L1BlockRefsSource, fn HeadSignalFn,
label BlockLabel, interval time.Duration, timeout time.Duration) ethereum.Subscription {
return event.NewSubscription(func(quit <-chan struct{}) error {
if interval <= 0 {
......@@ -61,22 +73,32 @@ func PollBlockChanges(ctx context.Context, log log.Logger, src L1BlockRefsSource
<-quit
return nil
}
eventsCtx, eventsCancel := context.WithCancel(context.Background())
defer eventsCancel()
// We can handle a quit signal while fn is running, by closing the ctx.
go func() {
select {
case <-quit:
eventsCancel()
case <-eventsCtx.Done(): // don't wait for quit signal if we closed for other reasons.
return
}
}()
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
reqCtx, reqCancel := context.WithTimeout(ctx, timeout)
reqCtx, reqCancel := context.WithTimeout(eventsCtx, timeout)
ref, err := src.L1BlockRefByLabel(reqCtx, label)
reqCancel()
if err != nil {
log.Warn("failed to poll L1 block", "label", label, "err", err)
} else {
fn(ctx, ref)
fn(eventsCtx, ref)
}
case <-ctx.Done():
return ctx.Err()
case <-quit:
case <-eventsCtx.Done():
return nil
}
}
......
......@@ -43,6 +43,11 @@ func (_m *TxManager) BlockNumber(ctx context.Context) (uint64, error) {
return r0, r1
}
// Close provides a mock function with given fields:
func (_m *TxManager) Close() {
_m.Called()
}
// From provides a mock function with given fields:
func (_m *TxManager) From() common.Address {
ret := _m.Called()
......
......@@ -49,6 +49,9 @@ type TxManager interface {
// BlockNumber returns the most recent block number from the underlying network.
BlockNumber(ctx context.Context) (uint64, error)
// Close the underlying connection
Close()
}
// ETHBackend is the set of methods that the transaction manager uses to resubmit gas & determine
......@@ -80,6 +83,8 @@ type ETHBackend interface {
// EstimateGas returns an estimate of the amount of gas needed to execute the given
// transaction against the current pending block.
EstimateGas(ctx context.Context, msg ethereum.CallMsg) (uint64, error)
// Close the underlying eth connection
Close()
}
// SimpleTxManager is a implementation of TxManager that performs linear fee
......@@ -131,6 +136,10 @@ func (m *SimpleTxManager) BlockNumber(ctx context.Context) (uint64, error) {
return m.backend.BlockNumber(ctx)
}
func (m *SimpleTxManager) Close() {
m.backend.Close()
}
// TxCandidate is a transaction candidate that can be submitted to ask the
// [TxManager] to construct a transaction with gas price bounds.
type TxCandidate struct {
......
......@@ -261,6 +261,9 @@ func (b *mockBackend) TransactionReceipt(ctx context.Context, txHash common.Hash
}, nil
}
func (b *mockBackend) Close() {
}
// TestTxMgrConfirmAtMinGasPrice asserts that Send returns the min gas price tx
// if the tx is mined instantly.
func TestTxMgrConfirmAtMinGasPrice(t *testing.T) {
......@@ -755,6 +758,9 @@ func (b *failingBackend) ChainID(ctx context.Context) (*big.Int, error) {
return nil, errors.New("unimplemented")
}
func (b *failingBackend) Close() {
}
// TestWaitMinedReturnsReceiptAfterFailure asserts that WaitMined is able to
// recover from failed calls to the backend. It uses the failedBackend to
// simulate an rpc call failure, followed by the successful return of a receipt.
......
# @eth-optimism/drippie-mon
## 0.5.4
### Patch Changes
- Updated dependencies [[`dd0e46986`](https://github.com/ethereum-optimism/optimism/commit/dd0e46986f19dcceb304fc48f2bd410685ecd179)]:
- @eth-optimism/sdk@3.1.6
## 0.5.3
### Patch Changes
......
{
"private": true,
"name": "@eth-optimism/chain-mon",
"version": "0.5.3",
"version": "0.5.4",
"description": "[Optimism] Chain monitoring services",
"main": "dist/index",
"types": "dist/index",
......@@ -63,6 +63,6 @@
"@nomiclabs/hardhat-waffle": "^2.0.6",
"hardhat": "^2.19.0",
"ts-node": "^10.9.1",
"tsx": "^4.1.1"
"tsx": "^4.2.0"
}
}
......@@ -26,24 +26,24 @@ Bytes_toNibbles_Test:test_toNibbles_expectedResult128Bytes_works() (gas: 78882)
Bytes_toNibbles_Test:test_toNibbles_expectedResult5Bytes_works() (gas: 3992)
Bytes_toNibbles_Test:test_toNibbles_zeroLengthInput_works() (gas: 845)
Constants_Test:test_eip1967Constants_succeeds() (gas: 453)
CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20458)
CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8539)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57518)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16655)
CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73619)
CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10627)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28363)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 74002)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32118)
CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91600)
CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13260)
CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35271)
CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52158)
CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48662)
CrossDomainMessenger_BaseGas_Test:test_baseGas_succeeds() (gas: 20480)
CrossDomainOwnable2_Test:test_onlyOwner_notMessenger_reverts() (gas: 8517)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner2_reverts() (gas: 57583)
CrossDomainOwnable2_Test:test_onlyOwner_notOwner_reverts() (gas: 16699)
CrossDomainOwnable2_Test:test_onlyOwner_succeeds() (gas: 73662)
CrossDomainOwnable3_Test:test_constructor_succeeds() (gas: 10628)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notMessenger_reverts() (gas: 28341)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner2_reverts() (gas: 74021)
CrossDomainOwnable3_Test:test_crossDomainOnlyOwner_notOwner_reverts() (gas: 32096)
CrossDomainOwnable3_Test:test_crossDomainTransferOwnership_succeeds() (gas: 91578)
CrossDomainOwnable3_Test:test_localOnlyOwner_notOwner_reverts() (gas: 13238)
CrossDomainOwnable3_Test:test_localOnlyOwner_succeeds() (gas: 35294)
CrossDomainOwnable3_Test:test_localTransferOwnership_succeeds() (gas: 52202)
CrossDomainOwnable3_Test:test_transferOwnershipNoLocal_succeeds() (gas: 48706)
CrossDomainOwnable3_Test:test_transferOwnership_noLocalZeroAddress_reverts() (gas: 12090)
CrossDomainOwnable3_Test:test_transferOwnership_notOwner_reverts() (gas: 13460)
CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12177)
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81570)
CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 12155)
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81526)
CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34905)
DelayedVetoable_Getters_Test:test_getters() (gas: 24400)
......@@ -51,11 +51,11 @@ DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 360
DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 15172)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33417)
DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12611)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16078)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44323)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15974)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18738)
DisputeGameFactory_Owner_Test:test_owner_succeeds() (gas: 12677)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_notOwner_reverts() (gas: 16121)
DisputeGameFactory_SetImplementation_Test:test_setImplementation_succeeds() (gas: 44368)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_notOwner_reverts() (gas: 15996)
DisputeGameFactory_TransferOwnership_Test:test_transferOwnership_succeeds() (gas: 18716)
Drippie_Test:test_create_calledTwice_reverts() (gas: 168887)
Drippie_Test:test_create_succeeds() (gas: 183459)
Drippie_Test:test_drip_amount_succeeds() (gas: 285433)
......@@ -134,173 +134,173 @@ GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_0() (gas: 352336)
GasBenchMark_L1CrossDomainMessenger:test_sendMessage_benchmark_1() (gas: 2950586)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_0() (gas: 540752)
GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 4052922)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 442107)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3487834)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 43032)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 86675)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 442085)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 3487812)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 43010)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 86653)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 68485)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68966)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143233)
GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8348)
GasPriceOracle_Test:test_decimals_succeeds() (gas: 6234)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 68988)
GasBenchMark_OptimismPortal:test_proveWithdrawalTransaction_benchmark() (gas: 143255)
GasPriceOracle_Test:test_baseFee_succeeds() (gas: 8392)
GasPriceOracle_Test:test_decimals_succeeds() (gas: 6212)
GasPriceOracle_Test:test_gasPrice_succeeds() (gas: 8340)
GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10680)
GasPriceOracle_Test:test_overhead_succeeds() (gas: 10637)
GasPriceOracle_Test:test_scalar_succeeds() (gas: 10700)
GasPriceOracle_Test:test_setGasPrice_doesNotExist_reverts() (gas: 5956)
GasPriceOracle_Test:test_setL1BaseFee_doesNotExist_reverts() (gas: 5976)
GasPriceOracle_Test:test_l1BaseFee_succeeds() (gas: 10702)
GasPriceOracle_Test:test_overhead_succeeds() (gas: 10681)
GasPriceOracle_Test:test_scalar_succeeds() (gas: 10678)
GasPriceOracle_Test:test_setGasPrice_doesNotExist_reverts() (gas: 5999)
GasPriceOracle_Test:test_setL1BaseFee_doesNotExist_reverts() (gas: 5977)
GovernanceToken_Test:test_approve_succeeds() (gas: 138023)
GovernanceToken_Test:test_burnFrom_succeeds() (gas: 127582)
GovernanceToken_Test:test_burn_succeeds() (gas: 119092)
GovernanceToken_Test:test_constructor_succeeds() (gas: 23693)
GovernanceToken_Test:test_decreaseAllowance_succeeds() (gas: 141912)
GovernanceToken_Test:test_increaseAllowance_succeeds() (gas: 142022)
GovernanceToken_Test:test_mint_fromNotOwner_reverts() (gas: 21378)
GovernanceToken_Test:test_mint_fromOwner_succeeds() (gas: 110940)
GovernanceToken_Test:test_transferFrom_succeeds() (gas: 151340)
GovernanceToken_Test:test_transfer_succeeds() (gas: 142867)
Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 700)
GovernanceToken_Test:test_burnFrom_succeeds() (gas: 127560)
GovernanceToken_Test:test_burn_succeeds() (gas: 119070)
GovernanceToken_Test:test_constructor_succeeds() (gas: 23735)
GovernanceToken_Test:test_decreaseAllowance_succeeds() (gas: 141889)
GovernanceToken_Test:test_increaseAllowance_succeeds() (gas: 142066)
GovernanceToken_Test:test_mint_fromNotOwner_reverts() (gas: 21421)
GovernanceToken_Test:test_mint_fromOwner_succeeds() (gas: 110960)
GovernanceToken_Test:test_transferFrom_succeeds() (gas: 151296)
GovernanceToken_Test:test_transfer_succeeds() (gas: 142823)
Hashing_hashDepositSource_Test:test_hashDepositSource_succeeds() (gas: 656)
L1BlockNumberTest:test_fallback_succeeds() (gas: 18677)
L1BlockNumberTest:test_getL1BlockNumber_succeeds() (gas: 10647)
L1BlockNumberTest:test_receive_succeeds() (gas: 25384)
L1BlockTest:test_basefee_succeeds() (gas: 7576)
L1BlockTest:test_hash_succeeds() (gas: 7694)
L1BlockTest:test_number_succeeds() (gas: 7674)
L1BlockTest:test_basefee_succeeds() (gas: 7599)
L1BlockTest:test_hash_succeeds() (gas: 7716)
L1BlockTest:test_number_succeeds() (gas: 7696)
L1BlockTest:test_sequenceNumber_succeeds() (gas: 7676)
L1BlockTest:test_timestamp_succeeds() (gas: 7663)
L1BlockTest:test_updateValues_succeeds() (gas: 63327)
L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24803)
L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49385)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 237022)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 230978)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 123950)
L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 77309)
L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 224938)
L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 74345)
L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 56475)
L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12410)
L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 31031)
L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 390952)
L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1666956)
L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 85630)
L1BlockTest:test_timestamp_succeeds() (gas: 7685)
L1BlockTest:test_updateValues_succeeds() (gas: 63305)
L1CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 24759)
L1CrossDomainMessenger_Test:test_relayMessage_legacyOldReplay_reverts() (gas: 49408)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailureThenSuccess_reverts() (gas: 237000)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterFailure_succeeds() (gas: 230956)
L1CrossDomainMessenger_Test:test_relayMessage_legacyRetryAfterSuccess_reverts() (gas: 123973)
L1CrossDomainMessenger_Test:test_relayMessage_legacy_succeeds() (gas: 77331)
L1CrossDomainMessenger_Test:test_relayMessage_retryAfterFailure_succeeds() (gas: 224981)
L1CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 74322)
L1CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 56453)
L1CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 12366)
L1CrossDomainMessenger_Test:test_replayMessage_withValue_reverts() (gas: 31075)
L1CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 390974)
L1CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 1666975)
L1CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 85607)
L1CrossDomainMessenger_Test:test_xDomainSender_notSet_reverts() (gas: 24282)
L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 62788)
L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 37362)
L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 451075)
L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 71051)
L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 35736)
L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 60595)
L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 35172)
L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 450770)
L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 70854)
L1ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 62789)
L1ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 37383)
L1ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 451097)
L1ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 71007)
L1ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 35757)
L1ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 60596)
L1ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 35191)
L1ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 450771)
L1ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 70810)
L1ERC721Bridge_Test:test_constructor_succeeds() (gas: 16611)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 27154)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notEscrowed_reverts() (gas: 27198)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 24920)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 21150)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 22694)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 420728)
L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 513135)
L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 500344)
L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 719145)
L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 716764)
L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 24977)
L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 513188)
L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 500483)
L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 43404)
L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 55399)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 37976)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 38011)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 38003)
L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 476244)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 34965)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 35344)
L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 67111)
L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 30489)
L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 25183)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 21128)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 22672)
L1ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 420684)
L1StandardBridge_BridgeETHTo_Test:test_bridgeETHTo_succeeds() (gas: 513177)
L1StandardBridge_BridgeETH_Test:test_bridgeETH_succeeds() (gas: 500366)
L1StandardBridge_DepositERC20To_Test:test_depositERC20To_succeeds() (gas: 719101)
L1StandardBridge_DepositERC20_Test:test_depositERC20_succeeds() (gas: 716742)
L1StandardBridge_DepositERC20_TestFail:test_depositERC20_notEoa_reverts() (gas: 24933)
L1StandardBridge_DepositETHTo_Test:test_depositETHTo_succeeds() (gas: 513144)
L1StandardBridge_DepositETH_Test:test_depositETH_succeeds() (gas: 500461)
L1StandardBridge_DepositETH_TestFail:test_depositETH_notEoa_reverts() (gas: 43360)
L1StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 55355)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 37932)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 37967)
L1StandardBridge_FinalizeBridgeETH_TestFail:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 37959)
L1StandardBridge_FinalizeERC20Withdrawal_Test:test_finalizeERC20Withdrawal_succeeds() (gas: 476279)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notMessenger_reverts() (gas: 34921)
L1StandardBridge_FinalizeERC20Withdrawal_TestFail:test_finalizeERC20Withdrawal_notOtherBridge_reverts() (gas: 35322)
L1StandardBridge_FinalizeETHWithdrawal_Test:test_finalizeETHWithdrawal_succeeds() (gas: 67089)
L1StandardBridge_Getter_Test:test_getters_succeeds() (gas: 30467)
L1StandardBridge_Initialize_Test:test_initialize_succeeds() (gas: 25227)
L1StandardBridge_Receive_Test:test_receive_succeeds() (gas: 613466)
L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8521)
L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 191101)
L2CrossDomainMessenger_Test:test_messageVersion_succeeds() (gas: 8477)
L2CrossDomainMessenger_Test:test_relayMessage_retry_succeeds() (gas: 191079)
L2CrossDomainMessenger_Test:test_relayMessage_succeeds() (gas: 48936)
L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 29056)
L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11756)
L2CrossDomainMessenger_Test:test_relayMessage_toSystemContract_reverts() (gas: 29034)
L2CrossDomainMessenger_Test:test_relayMessage_v2_reverts() (gas: 11734)
L2CrossDomainMessenger_Test:test_sendMessage_succeeds() (gas: 124025)
L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135857)
L2CrossDomainMessenger_Test:test_sendMessage_twice_succeeds() (gas: 135899)
L2CrossDomainMessenger_Test:test_xDomainMessageSender_reset_succeeds() (gas: 49311)
L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10686)
L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 26498)
L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 21814)
L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 150000)
L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 29494)
L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 22193)
L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 24354)
L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 19651)
L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 147663)
L2ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 29326)
L2CrossDomainMessenger_Test:test_xDomainSender_senderNotSet_reverts() (gas: 10664)
L2ERC721Bridge_Test:test_bridgeERC721To_localTokenZeroAddress_reverts() (gas: 26499)
L2ERC721Bridge_Test:test_bridgeERC721To_remoteTokenZeroAddress_reverts() (gas: 21815)
L2ERC721Bridge_Test:test_bridgeERC721To_succeeds() (gas: 150022)
L2ERC721Bridge_Test:test_bridgeERC721To_wrongOwner_reverts() (gas: 29515)
L2ERC721Bridge_Test:test_bridgeERC721_fromContract_reverts() (gas: 22194)
L2ERC721Bridge_Test:test_bridgeERC721_localTokenZeroAddress_reverts() (gas: 24310)
L2ERC721Bridge_Test:test_bridgeERC721_remoteTokenZeroAddress_reverts() (gas: 19629)
L2ERC721Bridge_Test:test_bridgeERC721_succeeds() (gas: 147619)
L2ERC721Bridge_Test:test_bridgeERC721_wrongOwner_reverts() (gas: 29345)
L2ERC721Bridge_Test:test_constructor_succeeds() (gas: 12411)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 31353)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 238955)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 19918)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 16171)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 19816)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 172094)
L2OutputOracleUpgradeable_Test:test_initValuesOnImpl_succeeds() (gas: 43714)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 53427)
L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 24715)
L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 26328)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_alreadyExists_reverts() (gas: 31375)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_interfaceNotCompliant_reverts() (gas: 238978)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notFromRemoteMessenger_reverts() (gas: 19919)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_notViaLocalMessenger_reverts() (gas: 16149)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_selfToken_reverts() (gas: 19794)
L2ERC721Bridge_Test:test_finalizeBridgeERC721_succeeds() (gas: 172050)
L2OutputOracleUpgradeable_Test:test_initValuesOnImpl_succeeds() (gas: 43691)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy_succeeds() (gas: 53471)
L2OutputOracleUpgradeable_Test:test_initializeImpl_alreadyInitialized_reverts() (gas: 24693)
L2OutputOracleUpgradeable_Test:test_initializeProxy_alreadyInitialized_reverts() (gas: 26350)
L2OutputOracleUpgradeable_Test:test_upgrading_succeeds() (gas: 191094)
L2OutputOracle_constructor_Test:test_constructor_l2BlockTimeZero_reverts() (gas: 53454)
L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 53486)
L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 56916)
L2OutputOracle_constructor_Test:test_initialize_badTimestamp_reverts() (gas: 15270)
L2OutputOracle_constructor_Test:test_constructor_submissionInterval_reverts() (gas: 53530)
L2OutputOracle_constructor_Test:test_constructor_succeeds() (gas: 56872)
L2OutputOracle_constructor_Test:test_initialize_badTimestamp_reverts() (gas: 15292)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_afterLatest_reverts() (gas: 225293)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 115915)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 18974)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 114320)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 315178)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 190566)
L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 44465)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 274992)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17915)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 101420)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 101328)
L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 107900)
L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 102405)
L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17560)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 32089)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 32118)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 23999)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 107202)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_finalized_reverts() (gas: 115959)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_ifNotChallenger_reverts() (gas: 18951)
L2OutputOracle_deleteOutputs_Test:test_deleteL2Outputs_nonExistent_reverts() (gas: 114298)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_multipleOutputs_succeeds() (gas: 315221)
L2OutputOracle_deleteOutputs_Test:test_deleteOutputs_singleOutput_succeeds() (gas: 190544)
L2OutputOracle_getter_Test:test_computeL2Timestamp_succeeds() (gas: 44443)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_multipleOutputsExist_succeeds() (gas: 274993)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_noOutputsExis_reverts() (gas: 17893)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_previousBlock_succeeds() (gas: 101376)
L2OutputOracle_getter_Test:test_getL2OutputIndexAfter_sameBlock_succeeds() (gas: 101370)
L2OutputOracle_getter_Test:test_getL2Output_succeeds() (gas: 107901)
L2OutputOracle_getter_Test:test_latestBlockNumber_succeeds() (gas: 102383)
L2OutputOracle_getter_Test:test_nextBlockNumber_succeeds() (gas: 17604)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_emptyOutput_reverts() (gas: 32044)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_futureTimetamp_reverts() (gas: 32096)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_notProposer_reverts() (gas: 23977)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_proposeAnotherOutput_succeeds() (gas: 107244)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unexpectedBlockNumber_reverts() (gas: 31846)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 32869)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_unmatchedBlockhash_reverts() (gas: 32912)
L2OutputOracle_proposeL2Output_Test:test_proposeL2Output_wrongFork_reverts() (gas: 32367)
L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 98746)
L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 390647)
L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 390895)
L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 386260)
L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 394528)
L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 394890)
L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251904)
L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 386556)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23867)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 23983)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 23894)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 93814)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 92711)
L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 43171)
L2StandardBridge_Test:test_initialize_succeeds() (gas: 26804)
L2OutputOracle_proposeL2Output_Test:test_proposeWithBlockhashAndHeight_succeeds() (gas: 98724)
L2StandardBridge_BridgeERC20To_Test:test_bridgeERC20To_succeeds() (gas: 390612)
L2StandardBridge_BridgeERC20To_Test:test_withdrawTo_withdrawingERC20_succeeds() (gas: 390877)
L2StandardBridge_BridgeERC20_Test:test_bridgeERC20_succeeds() (gas: 386242)
L2StandardBridge_BridgeERC20_Test:test_bridgeLegacyERC20_succeeds() (gas: 394510)
L2StandardBridge_BridgeERC20_Test:test_withdrawLegacyERC20_succeeds() (gas: 394855)
L2StandardBridge_BridgeERC20_Test:test_withdraw_notEOA_reverts() (gas: 251886)
L2StandardBridge_BridgeERC20_Test:test_withdraw_withdrawingERC20_succeeds() (gas: 386539)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_incorrectValue_reverts() (gas: 23845)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToMessenger_reverts() (gas: 23984)
L2StandardBridge_Bridge_Test:test_finalizeBridgeETH_sendToSelf_reverts() (gas: 23872)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingERC20_succeeds() (gas: 93879)
L2StandardBridge_Bridge_Test:test_finalizeDeposit_depositingETH_succeeds() (gas: 92667)
L2StandardBridge_FinalizeBridgeETH_Test:test_finalizeBridgeETH_succeeds() (gas: 43127)
L2StandardBridge_Test:test_initialize_succeeds() (gas: 26826)
L2StandardBridge_Test:test_receive_succeeds() (gas: 175032)
L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 141296)
L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16586)
LegacyERC20ETH_Test:test_approve_doesNotExist_reverts() (gas: 10745)
LegacyERC20ETH_Test:test_burn_doesNotExist_reverts() (gas: 10705)
LegacyERC20ETH_Test:test_crossDomain_succeeds() (gas: 6400)
LegacyERC20ETH_Test:test_decreaseAllowance_doesNotExist_reverts() (gas: 10747)
L2StandardBridge_Test:test_withdraw_ether_succeeds() (gas: 141340)
L2StandardBridge_Test:test_withdraw_insufficientValue_reverts() (gas: 16609)
LegacyERC20ETH_Test:test_approve_doesNotExist_reverts() (gas: 10746)
LegacyERC20ETH_Test:test_burn_doesNotExist_reverts() (gas: 10661)
LegacyERC20ETH_Test:test_crossDomain_succeeds() (gas: 6442)
LegacyERC20ETH_Test:test_decreaseAllowance_doesNotExist_reverts() (gas: 10724)
LegacyERC20ETH_Test:test_increaseAllowance_doesNotExist_reverts() (gas: 10757)
LegacyERC20ETH_Test:test_metadata_succeeds() (gas: 15795)
LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10672)
LegacyERC20ETH_Test:test_metadata_succeeds() (gas: 15773)
LegacyERC20ETH_Test:test_mint_doesNotExist_reverts() (gas: 10694)
LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 13002)
LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10801)
LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34629)
LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10779)
LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34607)
LibPosition_Test:test_pos_correctness_succeeds() (gas: 38711)
LivenessGuard_CheckAfterExecution_TestFails:test_checkAfterExecution_callerIsNotSafe_revert() (gas: 8576)
LivenessGuard_CheckTx_Test:test_checkTransaction_succeeds() (gas: 233535)
......@@ -329,81 +329,81 @@ LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasShownLivenessRece
LivenessModule_RemoveOwners_TestFail:test_removeOwners_ownerHasSignedRecently_reverts() (gas: 615047)
LivenessModule_RemoveOwners_TestFail:test_removeOwners_swapToFallbackOwner_reverts() (gas: 1278252)
LivenessModule_RemoveOwners_TestFail:test_removeOwners_wrongPreviousOwner_reverts() (gas: 73954)
MIPS_Test:test_add_succeeds() (gas: 123021)
MIPS_Test:test_add_succeeds() (gas: 122999)
MIPS_Test:test_addiSign_succeeds() (gas: 122946)
MIPS_Test:test_addi_succeeds() (gas: 123166)
MIPS_Test:test_addu_succeeds() (gas: 122975)
MIPS_Test:test_addui_succeeds() (gas: 123162)
MIPS_Test:test_and_succeeds() (gas: 123017)
MIPS_Test:test_andi_succeeds() (gas: 122994)
MIPS_Test:test_beq_succeeds() (gas: 203427)
MIPS_Test:test_bgez_succeeds() (gas: 122265)
MIPS_Test:test_bgtz_succeeds() (gas: 122205)
MIPS_Test:test_blez_succeeds() (gas: 122142)
MIPS_Test:test_bltz_succeeds() (gas: 122262)
MIPS_Test:test_bne_succeeds() (gas: 122351)
MIPS_Test:test_branch_inDelaySlot_fails() (gas: 86536)
MIPS_Test:test_brk_succeeds() (gas: 122655)
MIPS_Test:test_clo_succeeds() (gas: 122707)
MIPS_Test:test_clone_succeeds() (gas: 122563)
MIPS_Test:test_clz_succeeds() (gas: 123177)
MIPS_Test:test_div_succeeds() (gas: 123134)
MIPS_Test:test_divu_succeeds() (gas: 123142)
MIPS_Test:test_exit_succeeds() (gas: 122657)
MIPS_Test:test_fcntl_succeeds() (gas: 204864)
MIPS_Test:test_illegal_instruction_fails() (gas: 92045)
MIPS_Test:test_invalid_root_fails() (gas: 436238)
MIPS_Test:test_jal_nonzeroRegion_succeeds() (gas: 121250)
MIPS_Test:test_jal_succeeds() (gas: 121217)
MIPS_Test:test_addi_succeeds() (gas: 123144)
MIPS_Test:test_addu_succeeds() (gas: 123041)
MIPS_Test:test_addui_succeeds() (gas: 123228)
MIPS_Test:test_and_succeeds() (gas: 122995)
MIPS_Test:test_andi_succeeds() (gas: 123016)
MIPS_Test:test_beq_succeeds() (gas: 203405)
MIPS_Test:test_bgez_succeeds() (gas: 122243)
MIPS_Test:test_bgtz_succeeds() (gas: 122206)
MIPS_Test:test_blez_succeeds() (gas: 122120)
MIPS_Test:test_bltz_succeeds() (gas: 122284)
MIPS_Test:test_bne_succeeds() (gas: 122329)
MIPS_Test:test_branch_inDelaySlot_fails() (gas: 86558)
MIPS_Test:test_brk_succeeds() (gas: 122611)
MIPS_Test:test_clo_succeeds() (gas: 122685)
MIPS_Test:test_clone_succeeds() (gas: 122541)
MIPS_Test:test_clz_succeeds() (gas: 123133)
MIPS_Test:test_div_succeeds() (gas: 123112)
MIPS_Test:test_divu_succeeds() (gas: 123185)
MIPS_Test:test_exit_succeeds() (gas: 122679)
MIPS_Test:test_fcntl_succeeds() (gas: 204906)
MIPS_Test:test_illegal_instruction_fails() (gas: 92023)
MIPS_Test:test_invalid_root_fails() (gas: 436194)
MIPS_Test:test_jal_nonzeroRegion_succeeds() (gas: 121228)
MIPS_Test:test_jal_succeeds() (gas: 121283)
MIPS_Test:test_jalr_succeeds() (gas: 122425)
MIPS_Test:test_jr_succeeds() (gas: 122096)
MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85884)
MIPS_Test:test_jump_nonzeroRegion_succeeds() (gas: 120994)
MIPS_Test:test_jump_succeeds() (gas: 120969)
MIPS_Test:test_lb_succeeds() (gas: 128187)
MIPS_Test:test_lbu_succeeds() (gas: 128085)
MIPS_Test:test_lh_succeeds() (gas: 128229)
MIPS_Test:test_lhu_succeeds() (gas: 128103)
MIPS_Test:test_ll_succeeds() (gas: 128303)
MIPS_Test:test_lui_succeeds() (gas: 122293)
MIPS_Test:test_jr_succeeds() (gas: 122074)
MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85906)
MIPS_Test:test_jump_nonzeroRegion_succeeds() (gas: 120972)
MIPS_Test:test_jump_succeeds() (gas: 120925)
MIPS_Test:test_lb_succeeds() (gas: 128210)
MIPS_Test:test_lbu_succeeds() (gas: 128063)
MIPS_Test:test_lh_succeeds() (gas: 128230)
MIPS_Test:test_lhu_succeeds() (gas: 128168)
MIPS_Test:test_ll_succeeds() (gas: 128369)
MIPS_Test:test_lui_succeeds() (gas: 122271)
MIPS_Test:test_lw_succeeds() (gas: 127976)
MIPS_Test:test_lwl_succeeds() (gas: 243161)
MIPS_Test:test_lwr_succeeds() (gas: 243428)
MIPS_Test:test_lwl_succeeds() (gas: 243183)
MIPS_Test:test_lwr_succeeds() (gas: 243450)
MIPS_Test:test_mfhi_succeeds() (gas: 122634)
MIPS_Test:test_mflo_succeeds() (gas: 122718)
MIPS_Test:test_mmap_succeeds() (gas: 119637)
MIPS_Test:test_movn_succeeds() (gas: 204054)
MIPS_Test:test_movz_succeeds() (gas: 203945)
MIPS_Test:test_mthi_succeeds() (gas: 122678)
MIPS_Test:test_mtlo_succeeds() (gas: 122741)
MIPS_Test:test_mul_succeeds() (gas: 122278)
MIPS_Test:test_mult_succeeds() (gas: 122959)
MIPS_Test:test_multu_succeeds() (gas: 123018)
MIPS_Test:test_nor_succeeds() (gas: 123109)
MIPS_Test:test_or_succeeds() (gas: 123024)
MIPS_Test:test_mmap_succeeds() (gas: 119681)
MIPS_Test:test_movn_succeeds() (gas: 204032)
MIPS_Test:test_movz_succeeds() (gas: 203967)
MIPS_Test:test_mthi_succeeds() (gas: 122656)
MIPS_Test:test_mtlo_succeeds() (gas: 122784)
MIPS_Test:test_mul_succeeds() (gas: 122234)
MIPS_Test:test_mult_succeeds() (gas: 122937)
MIPS_Test:test_multu_succeeds() (gas: 123040)
MIPS_Test:test_nor_succeeds() (gas: 123065)
MIPS_Test:test_or_succeeds() (gas: 123068)
MIPS_Test:test_ori_succeeds() (gas: 123026)
MIPS_Test:test_preimage_read_succeeds() (gas: 235502)
MIPS_Test:test_preimage_read_succeeds() (gas: 235480)
MIPS_Test:test_preimage_write_succeeds() (gas: 127574)
MIPS_Test:test_prestate_exited_succeeds() (gas: 113835)
MIPS_Test:test_prestate_exited_succeeds() (gas: 113813)
MIPS_Test:test_sb_succeeds() (gas: 161547)
MIPS_Test:test_sc_succeeds() (gas: 161752)
MIPS_Test:test_sh_succeeds() (gas: 161606)
MIPS_Test:test_sll_succeeds() (gas: 122260)
MIPS_Test:test_sllv_succeeds() (gas: 122402)
MIPS_Test:test_slt_succeeds() (gas: 205250)
MIPS_Test:test_sltu_succeeds() (gas: 123285)
MIPS_Test:test_sra_succeeds() (gas: 122490)
MIPS_Test:test_srav_succeeds() (gas: 122758)
MIPS_Test:test_srl_succeeds() (gas: 122276)
MIPS_Test:test_srlv_succeeds() (gas: 122506)
MIPS_Test:test_step_abi_succeeds() (gas: 58532)
MIPS_Test:test_sub_succeeds() (gas: 123007)
MIPS_Test:test_subu_succeeds() (gas: 123092)
MIPS_Test:test_sw_succeeds() (gas: 161604)
MIPS_Test:test_swl_succeeds() (gas: 161621)
MIPS_Test:test_swr_succeeds() (gas: 161696)
MIPS_Test:test_xor_succeeds() (gas: 123029)
MIPS_Test:test_xori_succeeds() (gas: 123147)
MIPS_Test:test_sh_succeeds() (gas: 161651)
MIPS_Test:test_sll_succeeds() (gas: 122238)
MIPS_Test:test_sllv_succeeds() (gas: 122446)
MIPS_Test:test_slt_succeeds() (gas: 205206)
MIPS_Test:test_sltu_succeeds() (gas: 123263)
MIPS_Test:test_sra_succeeds() (gas: 122468)
MIPS_Test:test_srav_succeeds() (gas: 122714)
MIPS_Test:test_srl_succeeds() (gas: 122254)
MIPS_Test:test_srlv_succeeds() (gas: 122462)
MIPS_Test:test_step_abi_succeeds() (gas: 58510)
MIPS_Test:test_sub_succeeds() (gas: 123050)
MIPS_Test:test_subu_succeeds() (gas: 123048)
MIPS_Test:test_sw_succeeds() (gas: 161582)
MIPS_Test:test_swl_succeeds() (gas: 161662)
MIPS_Test:test_swr_succeeds() (gas: 161652)
MIPS_Test:test_xor_succeeds() (gas: 123095)
MIPS_Test:test_xori_succeeds() (gas: 123103)
MerkleTrie_get_Test:test_get_corruptedProof_reverts() (gas: 5710)
MerkleTrie_get_Test:test_get_extraProofElements_reverts() (gas: 58889)
MerkleTrie_get_Test:test_get_invalidDataRemainder_reverts() (gas: 35867)
......@@ -425,47 +425,47 @@ MerkleTrie_get_Test:test_get_validProof9_succeeds() (gas: 48802)
MerkleTrie_get_Test:test_get_wrongKeyProof_reverts() (gas: 50752)
MerkleTrie_get_Test:test_get_zeroBranchValueLength_reverts() (gas: 41706)
MerkleTrie_get_Test:test_get_zeroLengthKey_reverts() (gas: 3632)
MintManager_constructor_Test:test_constructor_succeeds() (gas: 10623)
MintManager_constructor_Test:test_constructor_succeeds() (gas: 10579)
MintManager_mint_Test:test_mint_afterPeriodElapsed_succeeds() (gas: 148184)
MintManager_mint_Test:test_mint_beforePeriodElapsed_reverts() (gas: 140479)
MintManager_mint_Test:test_mint_beforePeriodElapsed_reverts() (gas: 140523)
MintManager_mint_Test:test_mint_fromNotOwner_reverts() (gas: 11054)
MintManager_mint_Test:test_mint_fromOwner_succeeds() (gas: 137330)
MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142590)
MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 11041)
MintManager_mint_Test:test_mint_fromOwner_succeeds() (gas: 137308)
MintManager_mint_Test:test_mint_moreThanCap_reverts() (gas: 142568)
MintManager_upgrade_Test:test_upgrade_fromNotOwner_reverts() (gas: 10975)
MintManager_upgrade_Test:test_upgrade_fromOwner_succeeds() (gas: 23509)
MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11070)
OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7732)
OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11168)
OptimismMintableERC20_Test:test_burn_succeeds() (gas: 51057)
OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7863)
OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7732)
OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7687)
OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14630)
OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11212)
OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63595)
OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7755)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8424)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_sameTwice_reverts() (gas: 8937393460516800078)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2316545)
MintManager_upgrade_Test:test_upgrade_toZeroAddress_reverts() (gas: 11092)
OptimismMintableERC20_Test:test_bridge_succeeds() (gas: 7710)
OptimismMintableERC20_Test:test_burn_notBridge_reverts() (gas: 11190)
OptimismMintableERC20_Test:test_burn_succeeds() (gas: 51040)
OptimismMintableERC20_Test:test_erc165_supportsInterface_succeeds() (gas: 7819)
OptimismMintableERC20_Test:test_l1Token_succeeds() (gas: 7710)
OptimismMintableERC20_Test:test_l2Bridge_succeeds() (gas: 7710)
OptimismMintableERC20_Test:test_legacy_succeeds() (gas: 14631)
OptimismMintableERC20_Test:test_mint_notBridge_reverts() (gas: 11190)
OptimismMintableERC20_Test:test_mint_succeeds() (gas: 63639)
OptimismMintableERC20_Test:test_remoteToken_succeeds() (gas: 7733)
OptimismMintableERC721Factory_Test:test_constructor_succeeds() (gas: 8380)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_sameTwice_reverts() (gas: 8937393460516800076)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_succeeds() (gas: 2316523)
OptimismMintableERC721Factory_Test:test_createOptimismMintableERC721_zeroRemoteToken_reverts() (gas: 9542)
OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136967)
OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118874)
OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24516)
OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11209)
OptimismMintableERC721_Test:test_burn_notBridge_reverts() (gas: 136989)
OptimismMintableERC721_Test:test_burn_succeeds() (gas: 118892)
OptimismMintableERC721_Test:test_constructor_succeeds() (gas: 24517)
OptimismMintableERC721_Test:test_safeMint_notBridge_reverts() (gas: 11165)
OptimismMintableERC721_Test:test_safeMint_succeeds() (gas: 140599)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9050)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163605)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 7720)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenWithDecimals_succeeds() (gas: 1140441)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9620)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516764345)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1140433)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 14453)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16051)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26689)
OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 185977)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 178074)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 181439)
OptimismMintableERC721_Test:test_supportsInterfaces_succeeds() (gas: 9093)
OptimismMintableERC721_Test:test_tokenURI_succeeds() (gas: 163583)
OptimismMintableTokenFactory_Test:test_bridge_succeeds() (gas: 7698)
OptimismMintableTokenFactory_Test:test_createStandardL2TokenWithDecimals_succeeds() (gas: 1140419)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_remoteIsZero_reverts() (gas: 9643)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_sameTwice_reverts() (gas: 8937393460516764344)
OptimismMintableTokenFactory_Test:test_createStandardL2Token_succeeds() (gas: 1140410)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 14409)
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 16007)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_succeeds() (gas: 26711)
OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_succeeds() (gas: 185999)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 178052)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 181461)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41777)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 173449)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 180336)
......@@ -476,25 +476,25 @@ OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 208960)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 8797746687696162666)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 170961)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85758)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85714)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidWithdrawalProof_reverts() (gas: 111248)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 52989)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 73807)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 294672)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 227343)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 166490)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154361)
OptimismPortal_Test:test_constructor_succeeds() (gas: 31035)
OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14322)
OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512252)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 52944)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_paused_reverts() (gas: 73785)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRootAndOutputIndex_succeeds() (gas: 294694)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_succeeds() (gas: 227365)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 166513)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_succeeds() (gas: 154405)
OptimismPortal_Test:test_constructor_succeeds() (gas: 31014)
OptimismPortal_Test:test_depositTransaction_contractCreation_reverts() (gas: 14300)
OptimismPortal_Test:test_depositTransaction_largeData_reverts() (gas: 512272)
OptimismPortal_Test:test_depositTransaction_smallGasLimit_reverts() (gas: 14578)
OptimismPortal_Test:test_isOutputFinalized_succeeds() (gas: 122745)
OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17643)
OptimismPortal_Test:test_minimumGasLimit_succeeds() (gas: 17663)
OptimismPortal_Test:test_pause_onlyGuardian_reverts() (gas: 22284)
OptimismPortal_Test:test_pause_succeeds() (gas: 42226)
OptimismPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 38180)
OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 46274)
OptimismPortal_Test:test_unpause_succeeds() (gas: 31744)
OptimismPortal_Test:test_pause_succeeds() (gas: 42182)
OptimismPortal_Test:test_simple_isOutputFinalized_succeeds() (gas: 38181)
OptimismPortal_Test:test_unpause_onlyGuardian_reverts() (gas: 46252)
OptimismPortal_Test:test_unpause_succeeds() (gas: 31727)
OptimistAllowlistTest:test_constructor_succeeds() (gas: 16362)
OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestorWithFalsyValue_fails() (gas: 49652)
OptimistAllowlistTest:test_isAllowedToMint_fromAllowlistAttestor_succeeds() (gas: 49276)
......@@ -549,9 +549,9 @@ PreimageOracle_Test:test_loadLocalData_multipleContexts_succeeds() (gas: 147718)
PreimageOracle_Test:test_loadLocalData_onePart_succeeds() (gas: 75905)
PreimageOracle_Test:test_loadLocalData_outOfBoundsOffset_reverts() (gas: 8882)
ProtocolVersions_Initialize_Test:test_initialize_events_succeeds() (gas: 59548)
ProtocolVersions_Initialize_Test:test_initialize_values_succeeds() (gas: 45046)
ProtocolVersions_Setters_TestFail:test_setRecommended_notOwner_reverts() (gas: 15553)
ProtocolVersions_Setters_TestFail:test_setRequired_notOwner_reverts() (gas: 15587)
ProtocolVersions_Initialize_Test:test_initialize_values_succeeds() (gas: 45091)
ProtocolVersions_Setters_TestFail:test_setRecommended_notOwner_reverts() (gas: 15597)
ProtocolVersions_Setters_TestFail:test_setRequired_notOwner_reverts() (gas: 15543)
ProxyAdmin_Test:test_chugsplashChangeProxyAdmin_succeeds() (gas: 36440)
ProxyAdmin_Test:test_chugsplashGetProxyAdmin_succeeds() (gas: 15610)
ProxyAdmin_Test:test_chugsplashGetProxyImplementation_succeeds() (gas: 51040)
......@@ -660,34 +660,33 @@ ResourceMetering_Test:test_meter_useMax_succeeds() (gas: 20020816)
ResourceMetering_Test:test_meter_useMoreThanMax_reverts() (gas: 19549)
SafeCall_Test:test_callWithMinGas_noLeakageHigh_succeeds() (gas: 1020805932)
SafeCall_Test:test_callWithMinGas_noLeakageLow_succeeds() (gas: 1094905711)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 80502)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2recipientReverts_fails() (gas: 48948)
SequencerFeeVault_Test:test_constructor_succeeds() (gas: 7705)
SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 12794)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2_succeeds() (gas: 80524)
SequencerFeeVault_L2Withdrawal_Test:test_withdraw_toL2recipientReverts_fails() (gas: 48904)
SequencerFeeVault_Test:test_constructor_succeeds() (gas: 7706)
SequencerFeeVault_Test:test_minWithdrawalAmount_succeeds() (gas: 12860)
SequencerFeeVault_Test:test_receive_succeeds() (gas: 17395)
SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9399)
SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 616090)
SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11595)
StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 50149)
StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33142)
SequencerFeeVault_Test:test_withdraw_notEnough_reverts() (gas: 9421)
SequencerFeeVault_Test:test_withdraw_toL1_succeeds() (gas: 616068)
SetPrevBaseFee_Test:test_setPrevBaseFee_succeeds() (gas: 11617)
StandardBridge_Stateless_Test:test_isCorrectTokenPair_succeeds() (gas: 50171)
StandardBridge_Stateless_Test:test_isOptimismMintableERC20_succeeds() (gas: 33098)
Storage_Roundtrip_Test:test_setGetAddress_succeeds(bytes32,address) (runs: 64, μ: 31221, ~: 31843)
Storage_Roundtrip_Test:test_setGetBytes32_succeeds(bytes32,bytes32) (runs: 64, μ: 31654, ~: 31654)
Storage_Roundtrip_Test:test_setGetUint_succeeds(bytes32,uint256) (runs: 64, μ: 30731, ~: 31664)
SystemConfig_Initialize_Test:test_initialize_values_succeeds() (gas: 45459)
SystemConfig_Initialize_Test:test_initialize_values_succeeds() (gas: 45504)
SystemConfig_Initialize_TestFail:test_initialize_lowGasLimit_reverts() (gas: 61167)
SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 15609)
SystemConfig_Setters_TestFail:test_setBatcherHash_notOwner_reverts() (gas: 15631)
SystemConfig_Setters_TestFail:test_setGasConfig_notOwner_reverts() (gas: 15687)
SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 15677)
SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 18558)
SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 21182)
SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 22185)
SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 16877)
SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 18595)
SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 15658)
SystemConfig_Setters_TestFail:test_setGasLimit_notOwner_reverts() (gas: 15655)
SystemConfig_Setters_TestFail:test_setResourceConfig_badMinMax_reverts() (gas: 18559)
SystemConfig_Setters_TestFail:test_setResourceConfig_badPrecision_reverts() (gas: 21160)
SystemConfig_Setters_TestFail:test_setResourceConfig_lowGasLimit_reverts() (gas: 22163)
SystemConfig_Setters_TestFail:test_setResourceConfig_notOwner_reverts() (gas: 16854)
SystemConfig_Setters_TestFail:test_setResourceConfig_zeroDenominator_reverts() (gas: 18573)
SystemConfig_Setters_TestFail:test_setUnsafeBlockSigner_notOwner_reverts() (gas: 15679)
TransactorTest:test_call_succeeds() (gas: 26754)
TransactorTest:test_call_unauthorized_reverts() (gas: 18139)
TransactorTest:test_constructor_succeeds() (gas: 9673)
TransactorTest:test_delegateCall_succeeds() (gas: 20931)
TransactorTest:test_delegateCall_unauthorized_reverts() (gas: 18124)
TransferOnionTest:test_constructor_succeeds() (gas: 564789)
TransferOnionTest:test_unwrap_succeeds() (gas: 724955)
\ No newline at end of file
......@@ -86,26 +86,11 @@ To deploy the smart contracts on a local devnet, run `make devnet-up` in the mon
### Tools
#### Layout Locking
We use a system called "layout locking" as a safety mechanism to prevent certain contract variables from being moved to different storage slots accidentally.
To lock a contract variable, add it to the `layout-lock.json` file which has the following format:
```json
{
"MyContractName": {
"myVariableName": {
"slot": 1,
"offset": 0,
"length": 32
}
}
}
```
With the above config, the `validate-spacers` script will check that we have a contract called `MyContractName`, that the contract has a variable named `myVariableName`, and that the variable is in the correct position as defined in the lock file.
You should add things to the `layout-lock.json` file when you want those variables to **never** change.
Layout locking should be used in combination with diffing the `.storage-layout` file in CI.
#### Validate Spacing
In order to make sure that we don't accidentally overwrite storage slots, contract storage layouts are checked to make sure spacing is correct.
This uses the `.storage-layout` file to check contract spacing. Run `pnpm validate-spacers` to check the spacing of all contracts.
#### Gas Snapshots
......
{
"L1CrossDomainMessenger": {
"spacer_0_0_20": {
"slot": 0,
"offset": 0,
"length": 20
},
"spacer_1_0_1600": {
"slot": 1,
"offset": 0,
"length": 1600
},
"spacer_51_0_20": {
"slot": 51,
"offset": 0,
"length": 20
},
"spacer_52_0_1568": {
"slot": 52,
"offset": 0,
"length": 1568
},
"spacer_101_0_1": {
"slot": 101,
"offset": 0,
"length": 1
},
"spacer_102_0_1568": {
"slot": 102,
"offset": 0,
"length": 1568
},
"spacer_151_0_32": {
"slot": 151,
"offset": 0,
"length": 32
},
"spacer_201_0_32": {
"slot": 201,
"offset": 0,
"length": 32
},
"spacer_202_0_32": {
"slot": 202,
"offset": 0,
"length": 32
}
},
"L2CrossDomainMessenger": {
"spacer_0_0_20": {
"slot": 0,
"offset": 0,
"length": 20
},
"spacer_1_0_1600": {
"slot": 1,
"offset": 0,
"length": 1600
},
"spacer_51_0_20": {
"slot": 51,
"offset": 0,
"length": 20
},
"spacer_52_0_1568": {
"slot": 52,
"offset": 0,
"length": 1568
},
"spacer_101_0_1": {
"slot": 101,
"offset": 0,
"length": 1
},
"spacer_102_0_1568": {
"slot": 102,
"offset": 0,
"length": 1568
},
"spacer_151_0_32": {
"slot": 151,
"offset": 0,
"length": 32
},
"spacer_201_0_32": {
"slot": 201,
"offset": 0,
"length": 32
},
"spacer_202_0_32": {
"slot": 202,
"offset": 0,
"length": 32
}
},
"L1StandardBridge": {
"spacer_0_2_20": {
"slot": 0,
"offset": 2,
"length": 20
},
"spacer_1_0_20": {
"slot": 1,
"offset": 0,
"length": 20
}
}
}
......@@ -45,9 +45,9 @@
"lint": "pnpm lint:fix && pnpm lint:check"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/eslint-plugin": "^6.12.0",
"@typescript-eslint/parser": "^6.11.0",
"tsx": "^4.1.1",
"tsx": "^4.2.0",
"typescript": "^5.2.2"
}
}
......@@ -55,11 +55,149 @@ import { Types } from "scripts/Types.sol";
contract Deploy is Deployer {
DeployConfig cfg;
////////////////////////////////////////////////////////////////
// Modifiers //
////////////////////////////////////////////////////////////////
/// @notice Modifier that wraps a function in broadcasting.
modifier broadcast() {
vm.startBroadcast();
_;
vm.stopBroadcast();
}
/// @notice Modifier that will only allow a function to be called on devnet.
modifier onlyDevnet() {
uint256 chainid = block.chainid;
if (chainid == Chains.LocalDevnet || chainid == Chains.GethDevnet) {
_;
}
}
/// @notice Modifier that will only allow a function to be called on a public
/// testnet or devnet.
modifier onlyTestnetOrDevnet() {
uint256 chainid = block.chainid;
if (
chainid == Chains.Goerli || chainid == Chains.Sepolia || chainid == Chains.LocalDevnet
|| chainid == Chains.GethDevnet
) {
_;
}
}
////////////////////////////////////////////////////////////////
// Accessors //
////////////////////////////////////////////////////////////////
/// @inheritdoc Deployer
function name() public pure override returns (string memory name_) {
name_ = "Deploy";
}
/// @notice The create2 salt used for deployment of the contract implementations.
/// Using this helps to reduce config across networks as the implementation
/// addresses will be the same across networks when deployed with create2.
function _implSalt() internal returns (bytes32) {
return keccak256(bytes(vm.envOr("IMPL_SALT", string("ethers phoenix"))));
}
/// @notice Returns the proxy addresses
function _proxies() private view returns (Types.ContractSet memory proxies_) {
proxies_ = Types.ContractSet({
L1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"),
L1StandardBridge: mustGetAddress("L1StandardBridgeProxy"),
L2OutputOracle: mustGetAddress("L2OutputOracleProxy"),
OptimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: mustGetAddress("OptimismPortalProxy"),
SystemConfig: mustGetAddress("SystemConfigProxy"),
L1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"),
ProtocolVersions: mustGetAddress("ProtocolVersionsProxy")
});
}
/// @notice Returns the proxy addresses, not reverting if any are unset.
function _proxiesUnstrict() private view returns (Types.ContractSet memory proxies_) {
proxies_ = Types.ContractSet({
L1CrossDomainMessenger: getAddress("L1CrossDomainMessengerProxy"),
L1StandardBridge: getAddress("L1StandardBridgeProxy"),
L2OutputOracle: getAddress("L2OutputOracleProxy"),
OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: getAddress("OptimismPortalProxy"),
SystemConfig: getAddress("SystemConfigProxy"),
L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"),
ProtocolVersions: getAddress("ProtocolVersionsProxy")
});
}
////////////////////////////////////////////////////////////////
// State Changing Helper Functions //
////////////////////////////////////////////////////////////////
/// @notice Gets the address of the SafeProxyFactory and Safe singleton for use in deploying a new GnosisSafe.
function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) {
// These are they standard create2 deployed contracts. First we'll check if they are deployed,
// if not we'll deploy new ones, though not at these addresses.
address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2;
address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552;
safeProxyFactory.code.length == 0
? safeProxyFactory_ = new SafeProxyFactory()
: safeProxyFactory_ = SafeProxyFactory(safeProxyFactory);
safeSingleton.code.length == 0 ? safeSingleton_ = new Safe() : safeSingleton_ = Safe(payable(safeSingleton));
save("SafeProxyFactory", address(safeProxyFactory_));
save("SafeSingleton", address(safeSingleton_));
}
/// @notice Make a call from the Safe contract to an arbitrary address with arbitrary data
function _callViaSafe(address _target, bytes memory _data) internal {
Safe safe = Safe(mustGetAddress("SystemOwnerSafe"));
// This is the signature format used the caller is also the signer.
bytes memory signature = abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1));
safe.execTransaction({
to: _target,
value: 0,
data: _data,
operation: SafeOps.Operation.Call,
safeTxGas: 0,
baseGas: 0,
gasPrice: 0,
gasToken: address(0),
refundReceiver: payable(address(0)),
signatures: signature
});
}
/// @notice Call from the Safe contract to the Proxy Admin's upgrade and call method
function _upgradeAndCallViaSafe(address _proxy, address _implementation, bytes memory _innerCallData) internal {
address proxyAdmin = mustGetAddress("ProxyAdmin");
bytes memory data =
abi.encodeCall(ProxyAdmin.upgradeAndCall, (payable(_proxy), _implementation, _innerCallData));
_callViaSafe({ _target: proxyAdmin, _data: data });
}
/// @notice Transfer ownership of the ProxyAdmin contract to the final system owner
function transferProxyAdminOwnership() public broadcast {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
address owner = proxyAdmin.owner();
address safe = mustGetAddress("SystemOwnerSafe");
if (owner != safe) {
proxyAdmin.transferOwnership(safe);
console.log("ProxyAdmin ownership transferred to Safe at: %s", safe);
}
}
////////////////////////////////////////////////////////////////
// SetUp and Run //
////////////////////////////////////////////////////////////////
function setUp() public virtual override {
super.setUp();
......@@ -96,54 +234,24 @@ contract Deploy is Deployer {
transferDisputeGameFactoryOwnership();
}
/// @notice The create2 salt used for deployment of the contract implementations.
/// Using this helps to reduce config across networks as the implementation
/// addresses will be the same across networks when deployed with create2.
function implSalt() internal returns (bytes32) {
return keccak256(bytes(vm.envOr("IMPL_SALT", string("ethers phoenix"))));
}
/// @notice Modifier that wraps a function in broadcasting.
modifier broadcast() {
vm.startBroadcast();
_;
vm.stopBroadcast();
}
/// @notice Modifier that will only allow a function to be called on devnet.
modifier onlyDevnet() {
uint256 chainid = block.chainid;
if (chainid == Chains.LocalDevnet || chainid == Chains.GethDevnet) {
_;
}
}
/// @notice Modifier that will only allow a function to be called on a public
/// testnet or devnet.
modifier onlyTestnetOrDevnet() {
uint256 chainid = block.chainid;
if (
chainid == Chains.Goerli || chainid == Chains.Sepolia || chainid == Chains.LocalDevnet
|| chainid == Chains.GethDevnet
) {
_;
}
}
////////////////////////////////////////////////////////////////
// High Level Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy all of the proxies
function deployProxies() public {
deployAddressManager();
deployProxyAdmin();
deployOptimismPortalProxy();
deployL2OutputOracleProxy();
deploySystemConfigProxy();
deployERC1967Proxy("OptimismPortalProxy");
deployERC1967Proxy("L2OutputOracleProxy");
deployERC1967Proxy("SystemConfigProxy");
deployL1StandardBridgeProxy();
deployL1CrossDomainMessengerProxy();
deployOptimismMintableERC20FactoryProxy();
deployL1ERC721BridgeProxy();
deployDisputeGameFactoryProxy();
deployProtocolVersionsProxy();
deployERC1967Proxy("OptimismMintableERC20FactoryProxy");
deployERC1967Proxy("L1ERC721BridgeProxy");
deployERC1967Proxy("DisputeGameFactoryProxy");
deployERC1967Proxy("ProtocolVersionsProxy");
transferAddressManagerOwnership(); // to the ProxyAdmin
}
......@@ -164,22 +272,9 @@ contract Deploy is Deployer {
deployProtocolVersions();
}
// @notice Gets the address of the SafeProxyFactory and Safe singleton for use in deploying a new GnosisSafe.
function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) {
// These are they standard create2 deployed contracts. First we'll check if they are deployed,
// if not we'll deploy new ones, though not at these addresses.
address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2;
address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552;
safeProxyFactory.code.length == 0
? safeProxyFactory_ = new SafeProxyFactory()
: safeProxyFactory_ = SafeProxyFactory(safeProxyFactory);
safeSingleton.code.length == 0 ? safeSingleton_ = new Safe() : safeSingleton_ = Safe(payable(safeSingleton));
save("SafeProxyFactory", address(safeProxyFactory_));
save("SafeSingleton", address(safeSingleton_));
}
////////////////////////////////////////////////////////////////
// Non-Proxied Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy the Safe
function deploySafe() public broadcast returns (address addr_) {
......@@ -227,7 +322,20 @@ contract Deploy is Deployer {
addr_ = address(admin);
}
/// @notice Deploy the L1StandardBridgeProxy
/// @notice Deploy the StorageSetter contract, used for upgrades.
function deployStorageSetter() public broadcast returns (address addr_) {
StorageSetter setter = new StorageSetter{ salt: _implSalt() }();
console.log("StorageSetter deployed at: %s", address(setter));
string memory version = setter.version();
console.log("StorageSetter version: %s", version);
addr_ = address(setter);
}
////////////////////////////////////////////////////////////////
// Proxy Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy the L1StandardBridgeProxy using a ChugSplashProxy
function deployL1StandardBridgeProxy() public broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
L1ChugSplashProxy proxy = new L1ChugSplashProxy(proxyAdmin);
......@@ -240,22 +348,7 @@ contract Deploy is Deployer {
addr_ = address(proxy);
}
/// @notice Deploy the L2OutputOracleProxy
function deployL2OutputOracleProxy() public broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("L2OutputOracleProxy", address(proxy));
console.log("L2OutputOracleProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
/// @notice Deploy the L1CrossDomainMessengerProxy
/// @notice Deploy the L1CrossDomainMessengerProxy using a ResolvedDelegateProxy
function deployL1CrossDomainMessengerProxy() public broadcast returns (address addr_) {
AddressManager addressManager = AddressManager(mustGetAddress("AddressManager"));
string memory contractName = "OVM_L1CrossDomainMessenger";
......@@ -274,40 +367,8 @@ contract Deploy is Deployer {
addr_ = address(proxy);
}
/// @notice Deploy the OptimismPortalProxy
function deployOptimismPortalProxy() public broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("OptimismPortalProxy", address(proxy));
console.log("OptimismPortalProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
/// @notice Deploy the OptimismMintableERC20FactoryProxy
function deployOptimismMintableERC20FactoryProxy() public broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("OptimismMintableERC20FactoryProxy", address(proxy));
console.log("OptimismMintableERC20FactoryProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
/// @notice Deploy the L1ERC721BridgeProxy
function deployL1ERC721BridgeProxy() public broadcast returns (address addr_) {
function deployERC1967Proxy(string memory _name) public broadcast returns (address addr_) {
console.log(string.concat("Deploying ", _name));
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
......@@ -316,64 +377,19 @@ contract Deploy is Deployer {
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("L1ERC721BridgeProxy", address(proxy));
console.log("L1ERC721BridgeProxy deployed at %s", address(proxy));
save(_name, address(proxy));
console.log(" at %s", address(proxy));
addr_ = address(proxy);
}
/// @notice Deploy the SystemConfigProxy
function deploySystemConfigProxy() public broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("SystemConfigProxy", address(proxy));
console.log("SystemConfigProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
/// @notice Deploy the DisputeGameFactoryProxy
function deployDisputeGameFactoryProxy() public onlyDevnet broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("DisputeGameFactoryProxy", address(proxy));
console.log("DisputeGameFactoryProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
/// @notice Deploy the ProtocolVersionsProxy
function deployProtocolVersionsProxy() public broadcast returns (address addr_) {
address proxyAdmin = mustGetAddress("ProxyAdmin");
Proxy proxy = new Proxy({
_admin: proxyAdmin
});
address admin = address(uint160(uint256(vm.load(address(proxy), OWNER_KEY))));
require(admin == proxyAdmin);
save("ProtocolVersionsProxy", address(proxy));
console.log("ProtocolVersionsProxy deployed at %s", address(proxy));
addr_ = address(proxy);
}
////////////////////////////////////////////////////////////////
// Implementation Deployment Functions //
////////////////////////////////////////////////////////////////
/// @notice Deploy the L1CrossDomainMessenger
function deployL1CrossDomainMessenger() public broadcast returns (address addr_) {
address portal = mustGetAddress("OptimismPortalProxy");
L1CrossDomainMessenger messenger = new L1CrossDomainMessenger{ salt: implSalt() }({
L1CrossDomainMessenger messenger = new L1CrossDomainMessenger{ salt: _implSalt() }({
_portal: OptimismPortal(payable(portal))
});
......@@ -399,7 +415,7 @@ contract Deploy is Deployer {
L2OutputOracle l2OutputOracle = L2OutputOracle(mustGetAddress("L2OutputOracleProxy"));
SystemConfig systemConfig = SystemConfig(mustGetAddress("SystemConfigProxy"));
OptimismPortal portal = new OptimismPortal{ salt: implSalt() }({
OptimismPortal portal = new OptimismPortal{ salt: _implSalt() }({
_l2Oracle: l2OutputOracle,
_guardian: guardian,
_paused: true,
......@@ -420,7 +436,7 @@ contract Deploy is Deployer {
/// @notice Deploy the L2OutputOracle
function deployL2OutputOracle() public broadcast returns (address addr_) {
L2OutputOracle oracle = new L2OutputOracle{ salt: implSalt() }({
L2OutputOracle oracle = new L2OutputOracle{ salt: _implSalt() }({
_submissionInterval: cfg.l2OutputOracleSubmissionInterval(),
_l2BlockTime: cfg.l2BlockTime(),
_startingBlockNumber: 0,
......@@ -446,7 +462,7 @@ contract Deploy is Deployer {
function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) {
address l1standardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");
OptimismMintableERC20Factory factory =
new OptimismMintableERC20Factory{ salt: implSalt() }({_bridge: l1standardBridgeProxy});
new OptimismMintableERC20Factory{ salt: _implSalt() }({_bridge: l1standardBridgeProxy});
save("OptimismMintableERC20Factory", address(factory));
console.log("OptimismMintableERC20Factory deployed at %s", address(factory));
......@@ -460,7 +476,7 @@ contract Deploy is Deployer {
/// @notice Deploy the DisputeGameFactory
function deployDisputeGameFactory() public onlyDevnet broadcast returns (address addr_) {
DisputeGameFactory factory = new DisputeGameFactory{ salt: implSalt() }();
DisputeGameFactory factory = new DisputeGameFactory{ salt: _implSalt() }();
save("DisputeGameFactory", address(factory));
console.log("DisputeGameFactory deployed at %s", address(factory));
......@@ -469,7 +485,7 @@ contract Deploy is Deployer {
/// @notice Deploy the BlockOracle
function deployBlockOracle() public onlyDevnet broadcast returns (address addr_) {
BlockOracle oracle = new BlockOracle{ salt: implSalt() }();
BlockOracle oracle = new BlockOracle{ salt: _implSalt() }();
save("BlockOracle", address(oracle));
console.log("BlockOracle deployed at %s", address(oracle));
......@@ -478,7 +494,7 @@ contract Deploy is Deployer {
/// @notice Deploy the ProtocolVersions
function deployProtocolVersions() public broadcast returns (address addr_) {
ProtocolVersions versions = new ProtocolVersions{ salt: implSalt() }();
ProtocolVersions versions = new ProtocolVersions{ salt: _implSalt() }();
save("ProtocolVersions", address(versions));
console.log("ProtocolVersions deployed at %s", address(versions));
......@@ -493,7 +509,7 @@ contract Deploy is Deployer {
/// @notice Deploy the PreimageOracle
function deployPreimageOracle() public onlyDevnet broadcast returns (address addr_) {
PreimageOracle preimageOracle = new PreimageOracle{ salt: implSalt() }();
PreimageOracle preimageOracle = new PreimageOracle{ salt: _implSalt() }();
save("PreimageOracle", address(preimageOracle));
console.log("PreimageOracle deployed at %s", address(preimageOracle));
......@@ -502,7 +518,7 @@ contract Deploy is Deployer {
/// @notice Deploy Mips
function deployMips() public onlyDevnet broadcast returns (address addr_) {
MIPS mips = new MIPS{ salt: implSalt() }(IPreimageOracle(mustGetAddress("PreimageOracle")));
MIPS mips = new MIPS{ salt: _implSalt() }(IPreimageOracle(mustGetAddress("PreimageOracle")));
save("Mips", address(mips));
console.log("MIPS deployed at %s", address(mips));
......@@ -539,7 +555,7 @@ contract Deploy is Deployer {
function deployL1StandardBridge() public broadcast returns (address addr_) {
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
L1StandardBridge bridge = new L1StandardBridge{ salt: implSalt() }({
L1StandardBridge bridge = new L1StandardBridge{ salt: _implSalt() }({
_messenger: payable(l1CrossDomainMessengerProxy)
});
......@@ -556,7 +572,7 @@ contract Deploy is Deployer {
/// @notice Deploy the L1ERC721Bridge
function deployL1ERC721Bridge() public broadcast returns (address addr_) {
address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
L1ERC721Bridge bridge = new L1ERC721Bridge{ salt: implSalt() }({
L1ERC721Bridge bridge = new L1ERC721Bridge{ salt: _implSalt() }({
_messenger: l1CrossDomainMessengerProxy,
_otherBridge: Predeploys.L2_ERC721_BRIDGE
});
......@@ -584,36 +600,9 @@ contract Deploy is Deployer {
require(addressManager.owner() == proxyAdmin);
}
/// @notice Make a call from the Safe contract to an arbitrary address with arbitrary data
function _callViaSafe(address _target, bytes memory _data) internal {
Safe safe = Safe(mustGetAddress("SystemOwnerSafe"));
// This is the signature format used the caller is also the signer.
bytes memory signature = abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1));
safe.execTransaction({
to: _target,
value: 0,
data: _data,
operation: SafeOps.Operation.Call,
safeTxGas: 0,
baseGas: 0,
gasPrice: 0,
gasToken: address(0),
refundReceiver: payable(address(0)),
signatures: signature
});
}
/// @notice Call from the Safe contract to the Proxy Admin's upgrade and call method
function _upgradeAndCallViaSafe(address _proxy, address _implementation, bytes memory _innerCallData) internal {
address proxyAdmin = mustGetAddress("ProxyAdmin");
bytes memory data =
abi.encodeCall(ProxyAdmin.upgradeAndCall, (payable(_proxy), _implementation, _innerCallData));
_callViaSafe({ _target: proxyAdmin, _data: data });
}
////////////////////////////////////////////////////////////////
// Initialize Functions //
////////////////////////////////////////////////////////////////
/// @notice Initialize the DisputeGameFactory
function initializeDisputeGameFactory() public onlyDevnet broadcast {
......@@ -846,17 +835,6 @@ contract Deploy is Deployer {
require(loadInitializedSlot("ProtocolVersions", true) == 1, "ProtocolVersionsProxy is not initialized");
}
/// @notice Transfer ownership of the ProxyAdmin contract to the final system owner
function transferProxyAdminOwnership() public broadcast {
ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
address owner = proxyAdmin.owner();
address safe = mustGetAddress("SystemOwnerSafe");
if (owner != safe) {
proxyAdmin.transferOwnership(safe);
console.log("ProxyAdmin ownership transferred to Safe at: %s", safe);
}
}
/// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner
function transferDisputeGameFactoryOwnership() public onlyDevnet broadcast {
DisputeGameFactory disputeGameFactory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
......@@ -955,41 +933,4 @@ contract Deploy is Deployer {
);
}
}
/// @notice Deploy the StorageSetter contract, used for upgrades.
function deployStorageSetter() public broadcast returns (address addr_) {
StorageSetter setter = new StorageSetter{ salt: implSalt() }();
console.log("StorageSetter deployed at: %s", address(setter));
string memory version = setter.version();
console.log("StorageSetter version: %s", version);
addr_ = address(setter);
}
/// @notice Returns the proxy addresses
function _proxies() private view returns (Types.ContractSet memory proxies_) {
proxies_ = Types.ContractSet({
L1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"),
L1StandardBridge: mustGetAddress("L1StandardBridgeProxy"),
L2OutputOracle: mustGetAddress("L2OutputOracleProxy"),
OptimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: mustGetAddress("OptimismPortalProxy"),
SystemConfig: mustGetAddress("SystemConfigProxy"),
L1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"),
ProtocolVersions: mustGetAddress("ProtocolVersionsProxy")
});
}
/// @notice Returns the proxy addresses, not reverting if any are unset.
function _proxiesUnstrict() private view returns (Types.ContractSet memory proxies_) {
proxies_ = Types.ContractSet({
L1CrossDomainMessenger: getAddress("L1CrossDomainMessengerProxy"),
L1StandardBridge: getAddress("L1StandardBridgeProxy"),
L2OutputOracle: getAddress("L2OutputOracleProxy"),
OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"),
OptimismPortal: getAddress("OptimismPortalProxy"),
SystemConfig: getAddress("SystemConfigProxy"),
L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"),
ProtocolVersions: getAddress("ProtocolVersionsProxy")
});
}
}
import fs from 'fs'
import path from 'path'
import layoutLock from '../layout-lock.json'
/**
* Directory path to the artifacts.
* Can be configured as the first argument to the script or
......@@ -22,15 +20,6 @@ const skipped = (contractName: string): boolean => {
return contractName.includes('CrossDomainMessengerLegacySpacer')
}
/**
* Parses the fully qualified name of a contract into the name of the contract.
* For example `contracts/Foo.sol:Foo` becomes `Foo`.
*/
const parseFqn = (name: string): string => {
const parts = name.split(':')
return parts[parts.length - 1]
}
/**
* Parses out variable info from the variable structure in standard compiler json output.
*
......@@ -89,7 +78,6 @@ const parseVariableInfo = (
/**
* Main logic of the script
* - Ensures that all of the spacer variables are named correctly
* - Ensures that storage slots in the layout lock file do not change
*/
const main = async () => {
const paths = []
......@@ -128,24 +116,6 @@ const main = async () => {
continue
}
const contractName = parseFqn(fqn)
// Check that the layout lock has not changed
const lock = layoutLock[contractName] || {}
if (lock[variable.label]) {
const variableInfo = parseVariableInfo(variable)
const expectedInfo = lock[variable.label]
if (variableInfo.slot !== expectedInfo.slot) {
throw new Error(`${fqn}.${variable.label} slot has changed`)
}
if (variableInfo.offset !== expectedInfo.offset) {
throw new Error(`${fqn}.${variable.label} offset has changed`)
}
if (variableInfo.length !== expectedInfo.length) {
throw new Error(`${fqn}.${variable.label} length has changed`)
}
}
// Check that the spacers are all named correctly
if (variable.label.startsWith('spacer_')) {
const [, slot, offset, length] = variable.label.split('_')
......
......@@ -49,7 +49,7 @@
"node-fetch": "^2.6.7"
},
"devDependencies": {
"@types/node": "^20.9.0",
"@types/node": "^20.9.3",
"mocha": "^10.2.0"
}
}
# @eth-optimism/sdk
## 3.1.6
### Patch Changes
- [#8212](https://github.com/ethereum-optimism/optimism/pull/8212) [`dd0e46986`](https://github.com/ethereum-optimism/optimism/commit/dd0e46986f19dcceb304fc48f2bd410685ecd179) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Simplifies getMessageStatus to use an O(1) lookup instead of an event query
## 3.1.5
### Patch Changes
......
{
"name": "@eth-optimism/sdk",
"version": "3.1.5",
"version": "3.1.6",
"description": "[Optimism] Tools for working with Optimism",
"main": "dist/index",
"types": "dist/index",
......@@ -43,8 +43,8 @@
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@types/chai": "^4.3.10",
"@types/chai-as-promised": "^7.1.8",
"@types/mocha": "^10.0.4",
"@types/node": "^20.9.0",
"@types/mocha": "^10.0.6",
"@types/node": "^20.9.3",
"chai-as-promised": "^7.1.1",
"ethereum-waffle": "^4.0.10",
"ethers": "^5.7.2",
......
......@@ -667,25 +667,54 @@ export class CrossChainMessenger {
toBlockOrBlockHash?: BlockTag
): Promise<MessageStatus> {
const resolved = await this.toCrossChainMessage(message, messageIndex)
const receipt = await this.getMessageReceipt(
resolved,
messageIndex,
fromBlockOrBlockHash,
toBlockOrBlockHash
// legacy withdrawals relayed prebedrock are v1
const messageHashV0 = hashCrossDomainMessagev0(
resolved.target,
resolved.sender,
resolved.message,
resolved.messageNonce
)
// bedrock withdrawals are v1
// legacy withdrawals relayed postbedrock are v1
// there is no good way to differentiate between the two types of legacy
// so what we will check for both
const messageHashV1 = hashCrossDomainMessagev1(
resolved.messageNonce,
resolved.sender,
resolved.target,
resolved.value,
resolved.minGasLimit,
resolved.message
)
// Here we want the messenger that will receive the message, not the one that sent it.
const messenger =
resolved.direction === MessageDirection.L1_TO_L2
? this.contracts.l2.L2CrossDomainMessenger
: this.contracts.l1.L1CrossDomainMessenger
const success =
(await messenger.successfulMessages(messageHashV0)) ||
(await messenger.successfulMessages(messageHashV1))
const failure =
(await messenger.failedMessages(messageHashV0)) ||
(await messenger.failedMessages(messageHashV1))
if (resolved.direction === MessageDirection.L1_TO_L2) {
if (receipt === null) {
return MessageStatus.UNCONFIRMED_L1_TO_L2_MESSAGE
} else {
if (receipt.receiptStatus === MessageReceiptStatus.RELAYED_SUCCEEDED) {
if (success) {
return MessageStatus.RELAYED
} else {
} else if (failure) {
return MessageStatus.FAILED_L1_TO_L2_MESSAGE
} else {
return MessageStatus.UNCONFIRMED_L1_TO_L2_MESSAGE
}
}
} else {
if (receipt === null) {
if (success) {
return MessageStatus.RELAYED
} else if (failure) {
return MessageStatus.READY_FOR_RELAY
} else {
let timestamp: number
if (this.bedrock) {
const output = await this.getMessageBedrockOutput(
......@@ -737,12 +766,6 @@ export class CrossChainMessenger {
} else {
return MessageStatus.READY_FOR_RELAY
}
} else {
if (receipt.receiptStatus === MessageReceiptStatus.RELAYED_SUCCEEDED) {
return MessageStatus.RELAYED
} else {
return MessageStatus.READY_FOR_RELAY
}
}
}
}
......
......@@ -8,6 +8,8 @@ contract MockMessenger is ICrossDomainMessenger {
}
uint256 public nonce;
mapping (bytes32 => bool) public successfulMessages;
mapping (bytes32 => bool) public failedMessages;
// Empty function to satisfy the interface.
function sendMessage(
......@@ -81,6 +83,7 @@ contract MockMessenger is ICrossDomainMessenger {
) public {
for (uint256 i = 0; i < _params.length; i++) {
emit RelayedMessage(_params[i]);
successfulMessages[_params[i]] = true;
}
}
......@@ -89,6 +92,7 @@ contract MockMessenger is ICrossDomainMessenger {
) public {
for (uint256 i = 0; i < _params.length; i++) {
emit FailedRelayedMessage(_params[i]);
failedMessages[_params[i]] = true;
}
}
}
......@@ -33,7 +33,7 @@
},
"devDependencies": {
"@eth-optimism/contracts-ts": "workspace:^",
"@swc/core": "^1.3.95",
"@swc/core": "^1.3.99",
"@vitest/coverage-istanbul": "^0.34.6",
"tsup": "^7.2.0",
"typescript": "^5.2.2",
......
......@@ -28,14 +28,14 @@ importers:
specifier: ^7.1.8
version: 7.1.8
'@types/mocha':
specifier: ^10.0.4
version: 10.0.4
specifier: ^10.0.6
version: 10.0.6
'@types/node':
specifier: ^20.9.0
version: 20.9.0
specifier: ^20.9.3
version: 20.9.3
'@typescript-eslint/eslint-plugin':
specifier: ^6.11.0
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2)
specifier: ^6.12.0
version: 6.12.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/parser':
specifier: ^6.11.0
version: 6.11.0(eslint@8.54.0)(typescript@5.2.2)
......@@ -127,7 +127,7 @@ importers:
devDependencies:
tsup:
specifier: ^7.2.0
version: 7.2.0(@swc/core@1.3.95)(typescript@5.2.2)
version: 7.2.0(@swc/core@1.3.99)(typescript@5.2.2)
vitest:
specifier: ^0.34.4
version: 0.34.4
......@@ -181,10 +181,10 @@ importers:
version: 2.19.0(ts-node@10.9.1)(typescript@5.2.2)
ts-node:
specifier: ^10.9.1
version: 10.9.1(@types/node@20.9.0)(typescript@5.2.2)
version: 10.9.1(@types/node@20.9.3)(typescript@5.2.2)
tsx:
specifier: ^4.1.1
version: 4.1.1
specifier: ^4.2.0
version: 4.2.0
packages/common-ts:
dependencies:
......@@ -265,14 +265,14 @@ importers:
packages/contracts-bedrock:
devDependencies:
'@typescript-eslint/eslint-plugin':
specifier: ^6.11.0
version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2)
specifier: ^6.12.0
version: 6.12.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/parser':
specifier: ^6.11.0
version: 6.11.0(eslint@8.53.0)(typescript@5.2.2)
version: 6.11.0(eslint@8.54.0)(typescript@5.2.2)
tsx:
specifier: ^4.1.1
version: 4.1.1
specifier: ^4.2.0
version: 4.2.0
typescript:
specifier: ^5.2.2
version: 5.2.2
......@@ -339,13 +339,13 @@ importers:
version: 22.1.0
tsup:
specifier: ^7.2.0
version: 7.2.0(@swc/core@1.3.95)(typescript@5.2.2)
version: 7.2.0(@swc/core@1.3.99)(typescript@5.2.2)
typescript:
specifier: ^5.2.2
version: 5.2.2
vite:
specifier: ^4.5.0
version: 4.5.0(@types/node@20.9.0)
version: 4.5.0(@types/node@20.9.3)
vitest:
specifier: ^0.34.2
version: 0.34.2(jsdom@22.1.0)
......@@ -396,8 +396,8 @@ importers:
version: 2.6.7
devDependencies:
'@types/node':
specifier: ^20.9.0
version: 20.9.0
specifier: ^20.9.3
version: 20.9.3
mocha:
specifier: ^10.2.0
version: 10.2.0
......@@ -430,7 +430,7 @@ importers:
version: 22.1.0
tsup:
specifier: ^7.2.0
version: 7.2.0(@swc/core@1.3.95)(typescript@5.2.2)
version: 7.2.0(@swc/core@1.3.99)(typescript@5.2.2)
typescript:
specifier: ^5.2.2
version: 5.2.2
......@@ -439,7 +439,7 @@ importers:
version: 1.19.4(typescript@5.2.2)(zod@3.22.4)
vite:
specifier: ^4.5.0
version: 4.5.0(@types/node@20.9.0)
version: 4.5.0(@types/node@20.9.3)
vitest:
specifier: ^0.34.2
version: 0.34.2(jsdom@22.1.0)
......@@ -487,11 +487,11 @@ importers:
specifier: ^7.1.8
version: 7.1.8
'@types/mocha':
specifier: ^10.0.4
version: 10.0.4
specifier: ^10.0.6
version: 10.0.6
'@types/node':
specifier: ^20.9.0
version: 20.9.0
specifier: ^20.9.3
version: 20.9.3
chai-as-promised:
specifier: ^7.1.1
version: 7.1.1(chai@4.3.10)
......@@ -518,7 +518,7 @@ importers:
version: 15.1.0
ts-node:
specifier: ^10.9.1
version: 10.9.1(@types/node@20.9.0)(typescript@5.2.2)
version: 10.9.1(@types/node@20.9.3)(typescript@5.2.2)
typedoc:
specifier: ^0.25.3
version: 0.25.3(typescript@5.2.2)
......@@ -554,14 +554,14 @@ importers:
specifier: workspace:^
version: link:../contracts-ts
'@swc/core':
specifier: ^1.3.95
version: 1.3.95
specifier: ^1.3.99
version: 1.3.99
'@vitest/coverage-istanbul':
specifier: ^0.34.6
version: 0.34.6(vitest@0.34.1)
tsup:
specifier: ^7.2.0
version: 7.2.0(@swc/core@1.3.95)(typescript@5.2.2)
version: 7.2.0(@swc/core@1.3.99)(typescript@5.2.2)
typescript:
specifier: ^5.2.2
version: 5.2.2
......@@ -570,7 +570,7 @@ importers:
version: 1.19.4(typescript@5.2.2)(zod@3.22.4)
vite:
specifier: ^4.5.0
version: 4.5.0(@types/node@20.9.0)
version: 4.5.0(@types/node@20.9.3)
vitest:
specifier: ^0.34.1
version: 0.34.1
......@@ -1798,16 +1798,6 @@ packages:
dev: true
optional: true
/@eslint-community/eslint-utils@4.4.0(eslint@8.53.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
dependencies:
eslint: 8.53.0
eslint-visitor-keys: 3.4.3
dev: true
/@eslint-community/eslint-utils@4.4.0(eslint@8.54.0):
resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
......@@ -1840,11 +1830,6 @@ packages:
- supports-color
dev: true
/@eslint/js@8.53.0:
resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@eslint/js@8.54.0:
resolution: {integrity: sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
......@@ -3519,8 +3504,8 @@ packages:
'@stablelib/random': 1.0.2
'@stablelib/wipe': 1.0.1
/@swc/core-darwin-arm64@1.3.95:
resolution: {integrity: sha512-VAuBAP3MNetO/yBIBzvorUXq7lUBwhfpJxYViSxyluMwtoQDhE/XWN598TWMwMl1ZuImb56d7eUsuFdjgY7pJw==}
/@swc/core-darwin-arm64@1.3.99:
resolution: {integrity: sha512-Qj7Jct68q3ZKeuJrjPx7k8SxzWN6PqLh+VFxzA+KwLDpQDPzOlKRZwkIMzuFjLhITO4RHgSnXoDk/Syz0ZeN+Q==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
......@@ -3528,8 +3513,8 @@ packages:
dev: true
optional: true
/@swc/core-darwin-x64@1.3.95:
resolution: {integrity: sha512-20vF2rvUsN98zGLZc+dsEdHvLoCuiYq/1B+TDeE4oolgTFDmI1jKO+m44PzWjYtKGU9QR95sZ6r/uec0QC5O4Q==}
/@swc/core-darwin-x64@1.3.99:
resolution: {integrity: sha512-wR7m9QVJjgiBu1PSOHy7s66uJPa45Kf9bZExXUL+JAa9OQxt5y+XVzr+n+F045VXQOwdGWplgPnWjgbUUHEVyw==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
......@@ -3537,17 +3522,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-arm-gnueabihf@1.3.95:
resolution: {integrity: sha512-oEudEM8PST1MRNGs+zu0cx5i9uP8TsLE4/L9HHrS07Ck0RJ3DCj3O2fU832nmLe2QxnAGPwBpSO9FntLfOiWEQ==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
requiresBuild: true
dev: true
optional: true
/@swc/core-linux-arm64-gnu@1.3.95:
resolution: {integrity: sha512-pIhFI+cuC1aYg+0NAPxwT/VRb32f2ia8oGxUjQR6aJg65gLkUYQzdwuUmpMtFR2WVf7WVFYxUnjo4UyMuyh3ng==}
/@swc/core-linux-arm64-gnu@1.3.99:
resolution: {integrity: sha512-gcGv1l5t0DScEONmw5OhdVmEI/o49HCe9Ik38zzH0NtDkc+PDYaCcXU5rvfZP2qJFaAAr8cua8iJcOunOSLmnA==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
......@@ -3555,8 +3531,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-arm64-musl@1.3.95:
resolution: {integrity: sha512-ZpbTr+QZDT4OPJfjPAmScqdKKaT+wGurvMU5AhxLaf85DuL8HwUwwlL0n1oLieLc47DwIJEMuKQkYhXMqmJHlg==}
/@swc/core-linux-arm64-musl@1.3.99:
resolution: {integrity: sha512-XL1/eUsTO8BiKsWq9i3iWh7H99iPO61+9HYiWVKhSavknfj4Plbn+XyajDpxsauln5o8t+BRGitymtnAWJM4UQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
......@@ -3564,8 +3540,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-x64-gnu@1.3.95:
resolution: {integrity: sha512-n9SuHEFtdfSJ+sHdNXNRuIOVprB8nbsz+08apKfdo4lEKq6IIPBBAk5kVhPhkjmg2dFVHVo4Tr/OHXM1tzWCCw==}
/@swc/core-linux-x64-gnu@1.3.99:
resolution: {integrity: sha512-fGrXYE6DbTfGNIGQmBefYxSk3rp/1lgbD0nVg4rl4mfFRQPi7CgGhrrqSuqZ/ezXInUIgoCyvYGWFSwjLXt/Qg==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
......@@ -3573,8 +3549,8 @@ packages:
dev: true
optional: true
/@swc/core-linux-x64-musl@1.3.95:
resolution: {integrity: sha512-L1JrVlsXU3LC0WwmVnMK9HrOT2uhHahAoPNMJnZQpc18a0paO9fqifPG8M/HjNRffMUXR199G/phJsf326UvVg==}
/@swc/core-linux-x64-musl@1.3.99:
resolution: {integrity: sha512-kvgZp/mqf3IJ806gUOL6gN6VU15+DfzM1Zv4Udn8GqgXiUAvbQehrtruid4Snn5pZTLj4PEpSCBbxgxK1jbssA==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
......@@ -3582,8 +3558,8 @@ packages:
dev: true
optional: true
/@swc/core-win32-arm64-msvc@1.3.95:
resolution: {integrity: sha512-YaP4x/aZbUyNdqCBpC2zL8b8n58MEpOUpmOIZK6G1SxGi+2ENht7gs7+iXpWPc0sy7X3YPKmSWMAuui0h8lgAA==}
/@swc/core-win32-arm64-msvc@1.3.99:
resolution: {integrity: sha512-yt8RtZ4W/QgFF+JUemOUQAkVW58cCST7mbfKFZ1v16w3pl3NcWd9OrtppFIXpbjU1rrUX2zp2R7HZZzZ2Zk/aQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
......@@ -3591,8 +3567,8 @@ packages:
dev: true
optional: true
/@swc/core-win32-ia32-msvc@1.3.95:
resolution: {integrity: sha512-w0u3HI916zT4BC/57gOd+AwAEjXeUlQbGJ9H4p/gzs1zkSHtoDQghVUNy3n/ZKp9KFod/95cA8mbVF9t1+6epQ==}
/@swc/core-win32-ia32-msvc@1.3.99:
resolution: {integrity: sha512-62p5fWnOJR/rlbmbUIpQEVRconICy5KDScWVuJg1v3GPLBrmacjphyHiJC1mp6dYvvoEWCk/77c/jcQwlXrDXw==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
......@@ -3600,8 +3576,8 @@ packages:
dev: true
optional: true
/@swc/core-win32-x64-msvc@1.3.95:
resolution: {integrity: sha512-5RGnMt0S6gg4Gc6QtPUJ3Qs9Un4sKqccEzgH/tj7V/DVTJwKdnBKxFZfgQ34OR2Zpz7zGOn889xwsFVXspVWNA==}
/@swc/core-win32-x64-msvc@1.3.99:
resolution: {integrity: sha512-PdppWhkoS45VGdMBxvClVgF1hVjqamtvYd82Gab1i4IV45OSym2KinoDCKE1b6j3LwBLOn2J9fvChGSgGfDCHQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
......@@ -3609,8 +3585,8 @@ packages:
dev: true
optional: true
/@swc/core@1.3.95:
resolution: {integrity: sha512-PMrNeuqIusq9DPDooV3FfNEbZuTu5jKAc04N3Hm6Uk2Fl49cqElLFQ4xvl4qDmVDz97n3n/C1RE0/f6WyGPEiA==}
/@swc/core@1.3.99:
resolution: {integrity: sha512-8O996RfuPC4ieb4zbYMfbyCU9k4gSOpyCNnr7qBQ+o7IEmh8JCV6B8wwu+fT/Om/6Lp34KJe1IpJ/24axKS6TQ==}
engines: {node: '>=10'}
requiresBuild: true
peerDependencies:
......@@ -3622,16 +3598,15 @@ packages:
'@swc/counter': 0.1.1
'@swc/types': 0.1.5
optionalDependencies:
'@swc/core-darwin-arm64': 1.3.95
'@swc/core-darwin-x64': 1.3.95
'@swc/core-linux-arm-gnueabihf': 1.3.95
'@swc/core-linux-arm64-gnu': 1.3.95
'@swc/core-linux-arm64-musl': 1.3.95
'@swc/core-linux-x64-gnu': 1.3.95
'@swc/core-linux-x64-musl': 1.3.95
'@swc/core-win32-arm64-msvc': 1.3.95
'@swc/core-win32-ia32-msvc': 1.3.95
'@swc/core-win32-x64-msvc': 1.3.95
'@swc/core-darwin-arm64': 1.3.99
'@swc/core-darwin-x64': 1.3.99
'@swc/core-linux-arm64-gnu': 1.3.99
'@swc/core-linux-arm64-musl': 1.3.99
'@swc/core-linux-x64-gnu': 1.3.99
'@swc/core-linux-x64-musl': 1.3.99
'@swc/core-win32-arm64-msvc': 1.3.99
'@swc/core-win32-ia32-msvc': 1.3.99
'@swc/core-win32-x64-msvc': 1.3.99
dev: true
/@swc/counter@0.1.1:
......@@ -3866,20 +3841,20 @@ packages:
/@types/bn.js@4.11.6:
resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/bn.js@5.1.0:
resolution: {integrity: sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/body-parser@1.19.1:
resolution: {integrity: sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg==}
dependencies:
'@types/connect': 3.4.35
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/chai-as-promised@7.1.8:
......@@ -3912,7 +3887,7 @@ packages:
/@types/connect@3.4.35:
resolution: {integrity: sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
/@types/dateformat@5.0.0:
resolution: {integrity: sha512-SZg4JdHIWHQGEokbYGZSDvo5wA4TLYPXaqhigs/wH+REDOejcJzgH+qyY+HtEUtWOZxEUkbhbdYPqQDiEgrXeA==}
......@@ -3926,7 +3901,7 @@ packages:
/@types/express-serve-static-core@4.17.35:
resolution: {integrity: sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
'@types/qs': 6.9.7
'@types/range-parser': 1.2.4
'@types/send': 0.17.1
......@@ -3945,7 +3920,7 @@ packages:
resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==}
dependencies:
'@types/minimatch': 5.1.2
'@types/node': 20.8.9
'@types/node': 20.9.0
dev: true
/@types/is-ci@3.0.0:
......@@ -3972,7 +3947,7 @@ packages:
dependencies:
'@types/abstract-leveldown': 5.0.2
'@types/level-errors': 3.0.0
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/lru-cache@5.1.1:
......@@ -4004,11 +3979,11 @@ packages:
/@types/mkdirp@0.5.2:
resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/mocha@10.0.4:
resolution: {integrity: sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==}
/@types/mocha@10.0.6:
resolution: {integrity: sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==}
dev: true
/@types/morgan@1.9.9:
......@@ -4023,7 +3998,7 @@ packages:
/@types/node-fetch@2.6.4:
resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
form-data: 3.0.1
dev: true
......@@ -4034,14 +4009,14 @@ packages:
/@types/node@12.20.55:
resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==}
/@types/node@20.8.9:
resolution: {integrity: sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==}
/@types/node@20.9.0:
resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==}
dependencies:
undici-types: 5.26.5
dev: true
/@types/node@20.9.0:
resolution: {integrity: sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==}
/@types/node@20.9.3:
resolution: {integrity: sha512-nk5wXLAXGBKfrhLB0cyHGbSqopS+nz0BUgZkUQqSHSSgdee0kssp1IAqlQOu333bW+gMNs2QREx7iynm19Abxw==}
dependencies:
undici-types: 5.26.5
......@@ -4055,7 +4030,7 @@ packages:
/@types/pbkdf2@3.1.0:
resolution: {integrity: sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/pino-multi-stream@5.1.5:
......@@ -4073,13 +4048,13 @@ packages:
/@types/pino-std-serializers@2.4.1:
resolution: {integrity: sha512-17XcksO47M24IVTVKPeAByWUd3Oez7EbIjXpSbzMPhXVzgjGtrOa49gKBwxH9hb8dKv58OelsWQ+A1G1l9S3wQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/pino@6.3.11:
resolution: {integrity: sha512-S7+fLONqSpHeW9d7TApUqO6VN47KYgOXhCNKwGBVLHObq8HhaAYlVqUNdfnvoXjCMiwE5xcPm/5R2ZUh8bgaXQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
'@types/pino-pretty': 4.7.1
'@types/pino-std-serializers': 2.4.1
sonic-boom: 2.8.0
......@@ -4125,7 +4100,7 @@ packages:
/@types/readable-stream@2.3.15:
resolution: {integrity: sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
safe-buffer: 5.1.2
dev: true
......@@ -4136,7 +4111,7 @@ packages:
/@types/secp256k1@4.0.3:
resolution: {integrity: sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/seedrandom@3.0.1:
......@@ -4155,14 +4130,14 @@ packages:
resolution: {integrity: sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==}
dependencies:
'@types/mime': 1.3.2
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/serve-static@1.13.10:
resolution: {integrity: sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==}
dependencies:
'@types/mime': 1.3.2
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: true
/@types/sinon-chai@3.2.5:
......@@ -4199,45 +4174,16 @@ packages:
/@types/ws@7.4.7:
resolution: {integrity: sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
/@types/ws@8.5.3:
resolution: {integrity: sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==}
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
dev: false
/@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.53.0
graphemer: 1.4.0
ignore: 5.2.4
natural-compare: 1.4.0
semver: 7.5.4
ts-api-utils: 1.0.1(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==}
/@typescript-eslint/eslint-plugin@6.12.0(@typescript-eslint/parser@6.11.0)(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-XOpZ3IyJUIV1b15M7HVOpgQxPPF7lGXgsfcEIu3yDxFPaf/xZKt7s9QO/pbk7vpWQyVulpJbu4E5LwpZiQo4kA==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
......@@ -4249,10 +4195,10 @@ packages:
dependencies:
'@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 6.11.0(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/type-utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.11.0
'@typescript-eslint/scope-manager': 6.12.0
'@typescript-eslint/type-utils': 6.12.0(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.12.0(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.12.0
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.54.0
graphemer: 1.4.0
......@@ -4265,27 +4211,6 @@ packages:
- supports-color
dev: true
/@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.53.0
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/parser@6.11.0(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==}
engines: {node: ^16.0.0 || >=18.0.0}
......@@ -4315,28 +4240,16 @@ packages:
'@typescript-eslint/visitor-keys': 6.11.0
dev: true
/@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==}
/@typescript-eslint/scope-manager@6.12.0:
resolution: {integrity: sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.53.0
ts-api-utils: 1.0.1(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
'@typescript-eslint/types': 6.12.0
'@typescript-eslint/visitor-keys': 6.12.0
dev: true
/@typescript-eslint/type-utils@6.11.0(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==}
/@typescript-eslint/type-utils@6.12.0(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-WWmRXxhm1X8Wlquj+MhsAG4dU/Blvf1xDgGaYCzfvStP2NwPQh6KBvCDbiOEvaE0filhranjIlK/2fSTVwtBng==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
......@@ -4345,8 +4258,8 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.11.0(eslint@8.54.0)(typescript@5.2.2)
'@typescript-eslint/typescript-estree': 6.12.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.12.0(eslint@8.54.0)(typescript@5.2.2)
debug: 4.3.4(supports-color@8.1.1)
eslint: 8.54.0
ts-api-utils: 1.0.1(typescript@5.2.2)
......@@ -4360,6 +4273,11 @@ packages:
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/types@6.12.0:
resolution: {integrity: sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2):
resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==}
engines: {node: ^16.0.0 || >=18.0.0}
......@@ -4381,27 +4299,29 @@ packages:
- supports-color
dev: true
/@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==}
/@typescript-eslint/typescript-estree@6.12.0(typescript@5.2.2):
resolution: {integrity: sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
eslint: 8.53.0
'@typescript-eslint/types': 6.12.0
'@typescript-eslint/visitor-keys': 6.12.0
debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.4
ts-api-utils: 1.0.1(typescript@5.2.2)
typescript: 5.2.2
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@typescript-eslint/utils@6.11.0(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==}
/@typescript-eslint/utils@6.12.0(eslint@8.54.0)(typescript@5.2.2):
resolution: {integrity: sha512-LywPm8h3tGEbgfyjYnu3dauZ0U7R60m+miXgKcZS8c7QALO9uWJdvNoP+duKTk2XMWc7/Q3d/QiCuLN9X6SWyQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
eslint: ^7.0.0 || ^8.0.0
......@@ -4409,9 +4329,9 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.54.0)
'@types/json-schema': 7.0.12
'@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.12.0
'@typescript-eslint/types': 6.12.0
'@typescript-eslint/typescript-estree': 6.12.0(typescript@5.2.2)
eslint: 8.54.0
semver: 7.5.4
transitivePeerDependencies:
......@@ -4427,6 +4347,14 @@ packages:
eslint-visitor-keys: 3.4.3
dev: true
/@typescript-eslint/visitor-keys@6.12.0:
resolution: {integrity: sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.12.0
eslint-visitor-keys: 3.4.3
dev: true
/@ungap/structured-clone@1.2.0:
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
dev: true
......@@ -7811,53 +7739,6 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/eslint@8.53.0:
resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@eslint-community/regexpp': 4.6.2
'@eslint/eslintrc': 2.1.3
'@eslint/js': 8.53.0
'@humanwhocodes/config-array': 0.11.13
'@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8
'@ungap/structured-clone': 1.2.0
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4(supports-color@8.1.1)
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.2
eslint-visitor-keys: 3.4.3
espree: 9.6.1
esquery: 1.5.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
file-entry-cache: 6.0.1
find-up: 5.0.0
glob-parent: 6.0.2
globals: 13.21.0
graphemer: 1.4.0
ignore: 5.2.4
imurmurhash: 0.1.4
is-glob: 4.0.3
is-path-inside: 3.0.3
js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.3
strip-ansi: 6.0.1
text-table: 0.2.0
transitivePeerDependencies:
- supports-color
dev: true
/eslint@8.54.0:
resolution: {integrity: sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
......@@ -9097,7 +8978,7 @@ packages:
solc: 0.7.3(debug@4.3.4)
source-map-support: 0.5.21
stacktrace-parser: 0.1.10
ts-node: 10.9.1(@types/node@20.9.0)(typescript@5.2.2)
ts-node: 10.9.1(@types/node@20.9.3)(typescript@5.2.2)
tsort: 0.0.1
typescript: 5.2.2
undici: 5.24.0
......@@ -13832,7 +13713,7 @@ packages:
tsconfig-paths: 3.14.2
dev: true
/ts-node@10.9.1(@types/node@20.9.0)(typescript@5.2.2):
/ts-node@10.9.1(@types/node@20.9.3)(typescript@5.2.2):
resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==}
hasBin: true
peerDependencies:
......@@ -13851,7 +13732,7 @@ packages:
'@tsconfig/node12': 1.0.11
'@tsconfig/node14': 1.0.3
'@tsconfig/node16': 1.0.4
'@types/node': 20.9.0
'@types/node': 20.9.3
acorn: 8.10.0
acorn-walk: 8.2.0
arg: 4.1.3
......@@ -13922,7 +13803,7 @@ packages:
resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==}
dev: true
/tsup@7.2.0(@swc/core@1.3.95)(typescript@5.2.2):
/tsup@7.2.0(@swc/core@1.3.99)(typescript@5.2.2):
resolution: {integrity: sha512-vDHlczXbgUvY3rWvqFEbSqmC1L7woozbzngMqTtL2PGBODTtWlRwGDDawhvWzr5c1QjKe4OAKqJGfE1xeXUvtQ==}
engines: {node: '>=16.14'}
hasBin: true
......@@ -13938,7 +13819,7 @@ packages:
typescript:
optional: true
dependencies:
'@swc/core': 1.3.95
'@swc/core': 1.3.99
bundle-require: 4.0.1(esbuild@0.18.15)
cac: 6.7.14
chokidar: 3.5.3
......@@ -13959,8 +13840,8 @@ packages:
- ts-node
dev: true
/tsx@4.1.1:
resolution: {integrity: sha512-zyPn5BFMB0TB5kMLbYPNx4x/oL/oSlaecdKCv6WeJ0TeSEfx8RTJWjuB5TZ2dSewktgfBsBO/HNA9mrMWqLXMA==}
/tsx@4.2.0:
resolution: {integrity: sha512-hvAXAz4KUYNyjXOjJJgyjT7YOGFUNLC8jnODI6Omc/wGKaZ7z0FvW5d2haqg1GLfX49H3nZOpLYRlHMYGI8Wbw==}
engines: {node: '>=18.0.0'}
hasBin: true
dependencies:
......@@ -14453,7 +14334,7 @@ packages:
- utf-8-validate
- zod
/vite-node@0.34.1(@types/node@20.9.0):
/vite-node@0.34.1(@types/node@20.9.3):
resolution: {integrity: sha512-odAZAL9xFMuAg8aWd7nSPT+hU8u2r9gU3LRm9QKjxBEF2rRdWpMuqkrkjvyVQEdNFiBctqr2Gg4uJYizm5Le6w==}
engines: {node: '>=v14.18.0'}
hasBin: true
......@@ -14463,7 +14344,7 @@ packages:
mlly: 1.4.0
pathe: 1.1.1
picocolors: 1.0.0
vite: 4.5.0(@types/node@20.9.0)
vite: 4.5.0(@types/node@20.9.3)
transitivePeerDependencies:
- '@types/node'
- less
......@@ -14475,7 +14356,7 @@ packages:
- terser
dev: true
/vite-node@0.34.2(@types/node@20.8.9):
/vite-node@0.34.2(@types/node@20.9.0):
resolution: {integrity: sha512-JtW249Zm3FB+F7pQfH56uWSdlltCo1IOkZW5oHBzeQo0iX4jtC7o1t9aILMGd9kVekXBP2lfJBEQt9rBh07ebA==}
engines: {node: '>=v14.18.0'}
hasBin: true
......@@ -14485,7 +14366,7 @@ packages:
mlly: 1.4.0
pathe: 1.1.1
picocolors: 1.0.0
vite: 4.5.0(@types/node@20.8.9)
vite: 4.5.0(@types/node@20.9.0)
transitivePeerDependencies:
- '@types/node'
- less
......@@ -14497,7 +14378,7 @@ packages:
- terser
dev: true
/vite-node@0.34.2(@types/node@20.9.0):
/vite-node@0.34.2(@types/node@20.9.3):
resolution: {integrity: sha512-JtW249Zm3FB+F7pQfH56uWSdlltCo1IOkZW5oHBzeQo0iX4jtC7o1t9aILMGd9kVekXBP2lfJBEQt9rBh07ebA==}
engines: {node: '>=v14.18.0'}
hasBin: true
......@@ -14507,7 +14388,7 @@ packages:
mlly: 1.4.0
pathe: 1.1.1
picocolors: 1.0.0
vite: 4.5.0(@types/node@20.9.0)
vite: 4.5.0(@types/node@20.9.3)
transitivePeerDependencies:
- '@types/node'
- less
......@@ -14519,7 +14400,7 @@ packages:
- terser
dev: true
/vite-node@0.34.4(@types/node@20.8.9):
/vite-node@0.34.4(@types/node@20.9.0):
resolution: {integrity: sha512-ho8HtiLc+nsmbwZMw8SlghESEE3KxJNp04F/jPUCLVvaURwt0d+r9LxEqCX5hvrrOQ0GSyxbYr5ZfRYhQ0yVKQ==}
engines: {node: '>=v14.18.0'}
hasBin: true
......@@ -14529,7 +14410,7 @@ packages:
mlly: 1.4.0
pathe: 1.1.1
picocolors: 1.0.0
vite: 4.5.0(@types/node@20.8.9)
vite: 4.5.0(@types/node@20.9.0)
transitivePeerDependencies:
- '@types/node'
- less
......@@ -14541,7 +14422,7 @@ packages:
- terser
dev: true
/vite@4.4.10(@types/node@20.8.9):
/vite@4.4.10(@types/node@20.9.0):
resolution: {integrity: sha512-TzIjiqx9BEXF8yzYdF2NTf1kFFbjMjUSV0LFZ3HyHoI3SGSPLnnFUKiIQtL3gl2AjHvMrprOvQ3amzaHgQlAxw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
......@@ -14569,7 +14450,7 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 20.8.9
'@types/node': 20.9.0
esbuild: 0.18.20
postcss: 8.4.27
rollup: 3.28.0
......@@ -14577,7 +14458,7 @@ packages:
fsevents: 2.3.3
dev: true
/vite@4.5.0(@types/node@20.8.9):
/vite@4.5.0(@types/node@20.9.0):
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
......@@ -14605,7 +14486,7 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 20.8.9
'@types/node': 20.9.0
esbuild: 0.18.20
postcss: 8.4.27
rollup: 3.28.0
......@@ -14613,7 +14494,7 @@ packages:
fsevents: 2.3.3
dev: true
/vite@4.5.0(@types/node@20.9.0):
/vite@4.5.0(@types/node@20.9.3):
resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==}
engines: {node: ^14.18.0 || >=16.0.0}
hasBin: true
......@@ -14641,7 +14522,7 @@ packages:
terser:
optional: true
dependencies:
'@types/node': 20.9.0
'@types/node': 20.9.3
esbuild: 0.18.20
postcss: 8.4.27
rollup: 3.28.0
......@@ -14682,7 +14563,7 @@ packages:
dependencies:
'@types/chai': 4.3.10
'@types/chai-subset': 1.3.3
'@types/node': 20.9.0
'@types/node': 20.9.3
'@vitest/expect': 0.34.1
'@vitest/runner': 0.34.1
'@vitest/snapshot': 0.34.1
......@@ -14701,8 +14582,8 @@ packages:
strip-literal: 1.0.1
tinybench: 2.5.0
tinypool: 0.7.0
vite: 4.5.0(@types/node@20.9.0)
vite-node: 0.34.1(@types/node@20.9.0)
vite: 4.5.0(@types/node@20.9.3)
vite-node: 0.34.1(@types/node@20.9.3)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
......@@ -14747,7 +14628,7 @@ packages:
dependencies:
'@types/chai': 4.3.10
'@types/chai-subset': 1.3.3
'@types/node': 20.9.0
'@types/node': 20.9.3
'@vitest/expect': 0.34.2
'@vitest/runner': 0.34.2
'@vitest/snapshot': 0.34.2
......@@ -14766,8 +14647,8 @@ packages:
strip-literal: 1.0.1
tinybench: 2.5.0
tinypool: 0.7.0
vite: 4.5.0(@types/node@20.9.0)
vite-node: 0.34.2(@types/node@20.9.0)
vite: 4.5.0(@types/node@20.9.3)
vite-node: 0.34.2(@types/node@20.9.3)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
......@@ -14812,7 +14693,7 @@ packages:
dependencies:
'@types/chai': 4.3.8
'@types/chai-subset': 1.3.3
'@types/node': 20.8.9
'@types/node': 20.9.0
'@vitest/expect': 0.34.2
'@vitest/runner': 0.34.2
'@vitest/snapshot': 0.34.2
......@@ -14832,8 +14713,8 @@ packages:
strip-literal: 1.0.1
tinybench: 2.5.0
tinypool: 0.7.0
vite: 4.5.0(@types/node@20.8.9)
vite-node: 0.34.2(@types/node@20.8.9)
vite: 4.5.0(@types/node@20.9.0)
vite-node: 0.34.2(@types/node@20.9.0)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
......@@ -14878,7 +14759,7 @@ packages:
dependencies:
'@types/chai': 4.3.8
'@types/chai-subset': 1.3.3
'@types/node': 20.8.9
'@types/node': 20.9.0
'@vitest/expect': 0.34.4
'@vitest/runner': 0.34.4
'@vitest/snapshot': 0.34.4
......@@ -14897,8 +14778,8 @@ packages:
strip-literal: 1.0.1
tinybench: 2.5.0
tinypool: 0.7.0
vite: 4.4.10(@types/node@20.8.9)
vite-node: 0.34.4(@types/node@20.8.9)
vite: 4.4.10(@types/node@20.9.0)
vite-node: 0.34.4(@types/node@20.9.0)
why-is-node-running: 2.2.2
transitivePeerDependencies:
- less
......
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