Commit 6436a1e2 authored by Adrian Sutton's avatar Adrian Sutton

Merge branch 'develop' into aj/register-output-game

parents c39737dc bfb62726
...@@ -1522,7 +1522,7 @@ workflows: ...@@ -1522,7 +1522,7 @@ workflows:
- cannon-build-test-vectors - cannon-build-test-vectors
- check-values-match: - check-values-match:
pattern_file1: "uint8 internal constant INITIALIZER =" pattern_file1: "uint8 internal constant INITIALIZER ="
pattern_file2: "const initializedValue =" pattern_file2: "const InitializedValue ="
file1_path: "packages/contracts-bedrock/src/libraries/Constants.sol" file1_path: "packages/contracts-bedrock/src/libraries/Constants.sol"
file2_path: "op-chain-ops/genesis/config.go" file2_path: "op-chain-ops/genesis/config.go"
release: release:
...@@ -1827,6 +1827,7 @@ workflows: ...@@ -1827,6 +1827,7 @@ workflows:
name: chain-mon-docker-publish name: chain-mon-docker-publish
docker_name: chain-mon docker_name: chain-mon
docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>> docker_tags: <<pipeline.git.revision>>,<<pipeline.git.branch>>
resource_class: xlarge
publish: true publish: true
context: context:
- oplabs-gcr - oplabs-gcr
......
b205b6add562c778206a9edba1c0676c04a709b1 1a2e2e071ef0a1b6f41fdcba773b04c30498752f
module.exports = { module.exports = {
$schema: 'http://json.schemastore.org/prettierrc', $schema: 'http://json.schemastore.org/prettierrc',
plugins: ['prettier-plugin-solidity'], plugins: [],
trailingComma: 'es5', trailingComma: 'es5',
tabWidth: 2, tabWidth: 2,
semi: false, semi: false,
singleQuote: true, singleQuote: true,
arrowParens: 'always', arrowParens: 'always',
overrides: [ overrides: [],
{
files: '*.sol',
options: {
// These options are native to Prettier.
printWidth: 100,
tabWidth: 4,
useTabs: false,
singleQuote: false,
bracketSpacing: true,
// These options are specific to the Solidity Plugin
explicitTypes: 'always',
compiler: '>=0.8.15',
},
},
],
} }
...@@ -7,12 +7,14 @@ import ( ...@@ -7,12 +7,14 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"os" "os"
"strings"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
"github.com/mattn/go-isatty" "github.com/mattn/go-isatty"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum-optimism/optimism/op-bindings/bindings" "github.com/ethereum-optimism/optimism/op-bindings/bindings"
...@@ -24,7 +26,15 @@ import ( ...@@ -24,7 +26,15 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
) )
var defaultCrossDomainMessageSender = common.HexToAddress("0x000000000000000000000000000000000000dead") var (
defaultCrossDomainMessageSender = common.HexToAddress("0x000000000000000000000000000000000000dead")
// errInvalidInitialized represents when the initialized value is not set to the expected value.
// This is an assertion on `_initialized`. We do not care about the value of `_initializing`.
errInvalidInitialized = errors.New("invalid initialized value")
// errAlreadyInitialized represents a revert from when a contract is already initialized.
// This error is used to assert with `eth_call` on contracts that are `Initializable`
errAlreadyInitialized = errors.New("Initializable: contract is already initialized")
)
// Default script for checking that L2 has been configured correctly. This should be extended in the future // Default script for checking that L2 has been configured correctly. This should be extended in the future
// to pull in L1 deploy artifacts and assert that the L2 state is consistent with the L1 state. // to pull in L1 deploy artifacts and assert that the L2 state is consistent with the L1 state.
...@@ -138,7 +148,7 @@ func checkPredeployConfig(client *ethclient.Client, name string) error { ...@@ -138,7 +148,7 @@ func checkPredeployConfig(client *ethclient.Client, name string) error {
return err return err
} }
if impl != standardImpl { if impl != standardImpl {
log.Warn("%s does not have the standard implementation", name) log.Warn(name + " does not have the standard implementation")
} }
implCode, err := client.CodeAt(context.Background(), impl, nil) implCode, err := client.CodeAt(context.Background(), impl, nil)
if err != nil { if err != nil {
...@@ -151,6 +161,8 @@ func checkPredeployConfig(client *ethclient.Client, name string) error { ...@@ -151,6 +161,8 @@ func checkPredeployConfig(client *ethclient.Client, name string) error {
}) })
// Ensure that the code is set to the proxy bytecode as expected // Ensure that the code is set to the proxy bytecode as expected
// This will not work against production networks where the bytecode
// has deviated from the current bytecode. We need a more reliable way to check for this.
g.Go(func() error { g.Go(func() error {
proxyCode, err := client.CodeAt(context.Background(), p, nil) proxyCode, err := client.CodeAt(context.Background(), p, nil)
if err != nil { if err != nil {
...@@ -172,97 +184,97 @@ func checkPredeployConfig(client *ethclient.Client, name string) error { ...@@ -172,97 +184,97 @@ func checkPredeployConfig(client *ethclient.Client, name string) error {
switch p { switch p {
case predeploys.LegacyMessagePasserAddr: case predeploys.LegacyMessagePasserAddr:
if err := checkLegacyMessagePasser(p, client); err != nil { if err := checkLegacyMessagePasser(p, client); err != nil {
return err return fmt.Errorf("LegacyMessagePasser: %w", err)
} }
case predeploys.DeployerWhitelistAddr: case predeploys.DeployerWhitelistAddr:
if err := checkDeployerWhitelist(p, client); err != nil { if err := checkDeployerWhitelist(p, client); err != nil {
return err return fmt.Errorf("DeployerWhiteList: %w", err)
} }
case predeploys.L2CrossDomainMessengerAddr: case predeploys.L2CrossDomainMessengerAddr:
if err := checkL2CrossDomainMessenger(p, client); err != nil { if err := checkL2CrossDomainMessenger(p, client); err != nil {
return err return fmt.Errorf("L2CrossDomainMessenger: %w", err)
} }
case predeploys.GasPriceOracleAddr: case predeploys.GasPriceOracleAddr:
if err := checkGasPriceOracle(p, client); err != nil { if err := checkGasPriceOracle(p, client); err != nil {
return err return fmt.Errorf("GasPriceOracle: %w", err)
} }
case predeploys.L2StandardBridgeAddr: case predeploys.L2StandardBridgeAddr:
if err := checkL2StandardBridge(p, client); err != nil { if err := checkL2StandardBridge(p, client); err != nil {
return err return fmt.Errorf("L2StandardBridge: %w", err)
} }
case predeploys.SequencerFeeVaultAddr: case predeploys.SequencerFeeVaultAddr:
if err := checkSequencerFeeVault(p, client); err != nil { if err := checkSequencerFeeVault(p, client); err != nil {
return err return fmt.Errorf("SequencerFeeVault: %w", err)
} }
case predeploys.OptimismMintableERC20FactoryAddr: case predeploys.OptimismMintableERC20FactoryAddr:
if err := checkOptimismMintableERC20Factory(p, client); err != nil { if err := checkOptimismMintableERC20Factory(p, client); err != nil {
return err return fmt.Errorf("OptimismMintableERC20Factory: %w", err)
} }
case predeploys.L1BlockNumberAddr: case predeploys.L1BlockNumberAddr:
if err := checkL1BlockNumber(p, client); err != nil { if err := checkL1BlockNumber(p, client); err != nil {
return err return fmt.Errorf("L1BlockNumber: %w", err)
} }
case predeploys.L1BlockAddr: case predeploys.L1BlockAddr:
if err := checkL1Block(p, client); err != nil { if err := checkL1Block(p, client); err != nil {
return err return fmt.Errorf("L1Block: %w", err)
} }
case predeploys.WETH9Addr: case predeploys.WETH9Addr:
if err := checkWETH9(p, client); err != nil { if err := checkWETH9(p, client); err != nil {
return err return fmt.Errorf("WETH9: %w", err)
} }
case predeploys.GovernanceTokenAddr: case predeploys.GovernanceTokenAddr:
if err := checkGovernanceToken(p, client); err != nil { if err := checkGovernanceToken(p, client); err != nil {
return err return fmt.Errorf("GovernanceToken: %w", err)
} }
case predeploys.L2ERC721BridgeAddr: case predeploys.L2ERC721BridgeAddr:
if err := checkL2ERC721Bridge(p, client); err != nil { if err := checkL2ERC721Bridge(p, client); err != nil {
return err return fmt.Errorf("L2ERC721Bridge: %w", err)
} }
case predeploys.OptimismMintableERC721FactoryAddr: case predeploys.OptimismMintableERC721FactoryAddr:
if err := checkOptimismMintableERC721Factory(p, client); err != nil { if err := checkOptimismMintableERC721Factory(p, client); err != nil {
return err return fmt.Errorf("OptimismMintableERC721Factory: %w", err)
} }
case predeploys.ProxyAdminAddr: case predeploys.ProxyAdminAddr:
if err := checkProxyAdmin(p, client); err != nil { if err := checkProxyAdmin(p, client); err != nil {
return err return fmt.Errorf("ProxyAdmin: %w", err)
} }
case predeploys.BaseFeeVaultAddr: case predeploys.BaseFeeVaultAddr:
if err := checkBaseFeeVault(p, client); err != nil { if err := checkBaseFeeVault(p, client); err != nil {
return err return fmt.Errorf("BaseFeeVault: %w", err)
} }
case predeploys.L1FeeVaultAddr: case predeploys.L1FeeVaultAddr:
if err := checkL1FeeVault(p, client); err != nil { if err := checkL1FeeVault(p, client); err != nil {
return err return fmt.Errorf("L1FeeVault: %w", err)
} }
case predeploys.L2ToL1MessagePasserAddr: case predeploys.L2ToL1MessagePasserAddr:
if err := checkL2ToL1MessagePasser(p, client); err != nil { if err := checkL2ToL1MessagePasser(p, client); err != nil {
return err return fmt.Errorf("L2ToL1MessagePasser: %w", err)
} }
case predeploys.SchemaRegistryAddr: case predeploys.SchemaRegistryAddr:
if err := checkSchemaRegistry(p, client); err != nil { if err := checkSchemaRegistry(p, client); err != nil {
return err return fmt.Errorf("SchemaRegistry: %w", err)
} }
case predeploys.EASAddr: case predeploys.EASAddr:
if err := checkEAS(p, client); err != nil { if err := checkEAS(p, client); err != nil {
return err return fmt.Errorf("EAS: %w", err)
} }
} }
return nil return nil
...@@ -429,6 +441,21 @@ func checkL2ERC721Bridge(addr common.Address, client *ethclient.Client) error { ...@@ -429,6 +441,21 @@ func checkL2ERC721Bridge(addr common.Address, client *ethclient.Client) error {
return err return err
} }
log.Info("L2ERC721Bridge", "_initialized", initialized) log.Info("L2ERC721Bridge", "_initialized", initialized)
if initialized.Uint64() != genesis.InitializedValue {
return fmt.Errorf("%w: %s", errInvalidInitialized, initialized)
}
abi, err := bindings.L2ERC721BridgeMetaData.GetAbi()
if err != nil {
return err
}
calldata, err := abi.Pack("initialize")
if err != nil {
return err
}
if err := checkAlreadyInitialized(addr, calldata, client); err != nil {
return err
}
initializing, err := getInitializing("L2ERC721Bridge", addr, client) initializing, err := getInitializing("L2ERC721Bridge", addr, client)
if err != nil { if err != nil {
...@@ -566,6 +593,21 @@ func checkOptimismMintableERC20Factory(addr common.Address, client *ethclient.Cl ...@@ -566,6 +593,21 @@ func checkOptimismMintableERC20Factory(addr common.Address, client *ethclient.Cl
return err return err
} }
log.Info("OptimismMintableERC20Factory", "_initialized", initialized) log.Info("OptimismMintableERC20Factory", "_initialized", initialized)
if initialized.Uint64() != genesis.InitializedValue {
return fmt.Errorf("%w: %s", errInvalidInitialized, initialized)
}
abi, err := bindings.OptimismMintableERC20FactoryMetaData.GetAbi()
if err != nil {
return err
}
calldata, err := abi.Pack("initialize", common.Address{})
if err != nil {
return err
}
if err := checkAlreadyInitialized(addr, calldata, client); err != nil {
return err
}
initializing, err := getInitializing("OptimismMintableERC20Factory", addr, client) initializing, err := getInitializing("OptimismMintableERC20Factory", addr, client)
if err != nil { if err != nil {
...@@ -647,6 +689,21 @@ func checkL2StandardBridge(addr common.Address, client *ethclient.Client) error ...@@ -647,6 +689,21 @@ func checkL2StandardBridge(addr common.Address, client *ethclient.Client) error
return err return err
} }
log.Info("L2StandardBridge", "_initialized", initialized) log.Info("L2StandardBridge", "_initialized", initialized)
if initialized.Uint64() != genesis.InitializedValue {
return fmt.Errorf("%w: %s", errInvalidInitialized, initialized)
}
abi, err := bindings.L2StandardBridgeMetaData.GetAbi()
if err != nil {
return err
}
calldata, err := abi.Pack("initialize")
if err != nil {
return err
}
if err := checkAlreadyInitialized(addr, calldata, client); err != nil {
return err
}
initializing, err := getInitializing("L2StandardBridge", addr, client) initializing, err := getInitializing("L2StandardBridge", addr, client)
if err != nil { if err != nil {
...@@ -766,6 +823,21 @@ func checkL2CrossDomainMessenger(addr common.Address, client *ethclient.Client) ...@@ -766,6 +823,21 @@ func checkL2CrossDomainMessenger(addr common.Address, client *ethclient.Client)
return err return err
} }
log.Info("L2CrossDomainMessenger", "_initialized", initialized) log.Info("L2CrossDomainMessenger", "_initialized", initialized)
if initialized.Uint64() != genesis.InitializedValue {
return fmt.Errorf("%w: %s", errInvalidInitialized, initialized)
}
abi, err := bindings.L2CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return err
}
calldata, err := abi.Pack("initialize")
if err != nil {
return err
}
if err := checkAlreadyInitialized(addr, calldata, client); err != nil {
return err
}
initializing, err := getInitializing("L2CrossDomainMessenger", addr, client) initializing, err := getInitializing("L2CrossDomainMessenger", addr, client)
if err != nil { if err != nil {
...@@ -918,3 +990,16 @@ func getStorageValue(name, entryName string, addr common.Address, client *ethcli ...@@ -918,3 +990,16 @@ func getStorageValue(name, entryName string, addr common.Address, client *ethcli
} }
return slice[entry.Offset : entry.Offset+typ.NumberOfBytes], nil return slice[entry.Offset : entry.Offset+typ.NumberOfBytes], nil
} }
// checkAlreadyInitialized will check if a contract has already been initialized
// based on error message string matching.
func checkAlreadyInitialized(addr common.Address, calldata []byte, client *ethclient.Client) error {
msg := ethereum.CallMsg{
To: &addr,
Data: calldata,
}
if _, err := client.CallContract(context.Background(), msg, nil); !strings.Contains(err.Error(), errAlreadyInitialized.Error()) {
return err
}
return nil
}
...@@ -29,7 +29,7 @@ import ( ...@@ -29,7 +29,7 @@ import (
// initialzedValue represents the `Initializable` contract value. It should be kept in // initialzedValue represents the `Initializable` contract value. It should be kept in
// sync with the constant in `Constants.sol`. // sync with the constant in `Constants.sol`.
// https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/libraries/Constants.sol // https://github.com/ethereum-optimism/optimism/blob/develop/packages/contracts-bedrock/src/libraries/Constants.sol
const initializedValue = 3 const InitializedValue = 3
var ( var (
ErrInvalidDeployConfig = errors.New("invalid deploy config") ErrInvalidDeployConfig = errors.New("invalid deploy config")
...@@ -726,13 +726,13 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage ...@@ -726,13 +726,13 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"msgNonce": 0, "msgNonce": 0,
} }
storage["L2CrossDomainMessenger"] = state.StorageValues{ storage["L2CrossDomainMessenger"] = state.StorageValues{
"_initialized": initializedValue, "_initialized": InitializedValue,
"_initializing": false, "_initializing": false,
"xDomainMsgSender": "0x000000000000000000000000000000000000dEaD", "xDomainMsgSender": "0x000000000000000000000000000000000000dEaD",
"msgNonce": 0, "msgNonce": 0,
} }
storage["L2StandardBridge"] = state.StorageValues{ storage["L2StandardBridge"] = state.StorageValues{
"_initialized": initializedValue, "_initialized": InitializedValue,
"_initializing": false, "_initializing": false,
"messenger": predeploys.L2CrossDomainMessengerAddr, "messenger": predeploys.L2CrossDomainMessengerAddr,
} }
...@@ -767,12 +767,12 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage ...@@ -767,12 +767,12 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
} }
storage["L2ERC721Bridge"] = state.StorageValues{ storage["L2ERC721Bridge"] = state.StorageValues{
"messenger": predeploys.L2CrossDomainMessengerAddr, "messenger": predeploys.L2CrossDomainMessengerAddr,
"_initialized": initializedValue, "_initialized": InitializedValue,
"_initializing": false, "_initializing": false,
} }
storage["OptimismMintableERC20Factory"] = state.StorageValues{ storage["OptimismMintableERC20Factory"] = state.StorageValues{
"bridge": predeploys.L2StandardBridgeAddr, "bridge": predeploys.L2StandardBridgeAddr,
"_initialized": initializedValue, "_initialized": InitializedValue,
"_initializing": false, "_initializing": false,
} }
return storage, nil return storage, nil
......
...@@ -33,19 +33,17 @@ type Agent struct { ...@@ -33,19 +33,17 @@ type Agent struct {
solver *solver.GameSolver solver *solver.GameSolver
loader ClaimLoader loader ClaimLoader
responder Responder responder Responder
updater types.OracleUpdater
maxDepth int maxDepth int
agreeWithProposedOutput bool agreeWithProposedOutput bool
log log.Logger log log.Logger
} }
func NewAgent(m metrics.Metricer, loader ClaimLoader, maxDepth int, trace types.TraceAccessor, responder Responder, updater types.OracleUpdater, agreeWithProposedOutput bool, log log.Logger) *Agent { func NewAgent(m metrics.Metricer, loader ClaimLoader, maxDepth int, trace types.TraceAccessor, responder Responder, agreeWithProposedOutput bool, log log.Logger) *Agent {
return &Agent{ return &Agent{
metrics: m, metrics: m,
solver: solver.NewGameSolver(maxDepth, trace), solver: solver.NewGameSolver(maxDepth, trace),
loader: loader, loader: loader,
responder: responder, responder: responder,
updater: updater,
maxDepth: maxDepth, maxDepth: maxDepth,
agreeWithProposedOutput: agreeWithProposedOutput, agreeWithProposedOutput: agreeWithProposedOutput,
log: log, log: log,
...@@ -77,13 +75,6 @@ func (a *Agent) Act(ctx context.Context) error { ...@@ -77,13 +75,6 @@ func (a *Agent) Act(ctx context.Context) error {
log = log.New("value", action.Value) log = log.New("value", action.Value)
} }
if action.OracleData != nil {
a.log.Info("Updating oracle data", "oracleKey", action.OracleData.OracleKey, "oracleData", action.OracleData.OracleData)
if err := a.updater.UpdateOracle(ctx, action.OracleData); err != nil {
return fmt.Errorf("failed to load oracle data: %w", err)
}
}
switch action.Type { switch action.Type {
case types.ActionTypeMove: case types.ActionTypeMove:
a.metrics.RecordGameMove() a.metrics.RecordGameMove()
......
...@@ -115,8 +115,7 @@ func setupTestAgent(t *testing.T, agreeWithProposedOutput bool) (*Agent, *stubCl ...@@ -115,8 +115,7 @@ func setupTestAgent(t *testing.T, agreeWithProposedOutput bool) (*Agent, *stubCl
depth := 4 depth := 4
provider := alphabet.NewTraceProvider("abcd", uint64(depth)) provider := alphabet.NewTraceProvider("abcd", uint64(depth))
responder := &stubResponder{} responder := &stubResponder{}
updater := &stubUpdater{} agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, agreeWithProposedOutput, logger)
agent := NewAgent(metrics.NoopMetrics, claimLoader, depth, trace.NewSimpleTraceAccessor(provider), responder, updater, agreeWithProposedOutput, logger)
return agent, claimLoader, responder return agent, claimLoader, responder
} }
...@@ -166,10 +165,3 @@ func (s *stubResponder) ResolveClaim(ctx context.Context, clainIdx uint64) error ...@@ -166,10 +165,3 @@ func (s *stubResponder) ResolveClaim(ctx context.Context, clainIdx uint64) error
func (s *stubResponder) PerformAction(ctx context.Context, response types.Action) error { func (s *stubResponder) PerformAction(ctx context.Context, response types.Action) error {
return nil return nil
} }
type stubUpdater struct {
}
func (s *stubUpdater) UpdateOracle(ctx context.Context, data *types.PreimageOracleData) error {
panic("Not implemented")
}
...@@ -27,6 +27,8 @@ const ( ...@@ -27,6 +27,8 @@ const (
methodAttack = "attack" methodAttack = "attack"
methodDefend = "defend" methodDefend = "defend"
methodStep = "step" methodStep = "step"
methodAddLocalData = "addLocalData"
methodVM = "VM"
) )
type FaultDisputeGameContract struct { type FaultDisputeGameContract struct {
...@@ -144,6 +146,15 @@ func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context) ([]types.Cl ...@@ -144,6 +146,15 @@ func (f *FaultDisputeGameContract) GetAllClaims(ctx context.Context) ([]types.Cl
return claims, nil return claims, nil
} }
func (f *FaultDisputeGameContract) vm(ctx context.Context) (*VMContract, error) {
result, err := f.multiCaller.SingleCall(ctx, batching.BlockLatest, f.contract.Call(methodVM))
if err != nil {
return nil, fmt.Errorf("failed to fetch VM addr: %w", err)
}
vmAddr := result.GetAddress(0)
return NewVMContract(vmAddr, f.multiCaller)
}
func (f *FaultDisputeGameContract) AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) { func (f *FaultDisputeGameContract) AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) {
call := f.contract.Call(methodAttack, new(big.Int).SetUint64(parentContractIndex), pivot) call := f.contract.Call(methodAttack, new(big.Int).SetUint64(parentContractIndex), pivot)
return call.ToTxCandidate() return call.ToTxCandidate()
...@@ -195,6 +206,35 @@ func (f *FaultDisputeGameContract) resolveCall() *batching.ContractCall { ...@@ -195,6 +206,35 @@ func (f *FaultDisputeGameContract) resolveCall() *batching.ContractCall {
return f.contract.Call(methodResolve) return f.contract.Call(methodResolve)
} }
func (f *FaultDisputeGameContract) UpdateOracleTx(ctx context.Context, data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
if data.IsLocal {
return f.addLocalDataTx(data)
}
return f.addGlobalDataTx(ctx, data)
}
func (f *FaultDisputeGameContract) addLocalDataTx(data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
call := f.contract.Call(
methodAddLocalData,
data.GetIdent(),
new(big.Int).SetUint64(data.LocalContext),
new(big.Int).SetUint64(uint64(data.OracleOffset)),
)
return call.ToTxCandidate()
}
func (f *FaultDisputeGameContract) addGlobalDataTx(ctx context.Context, data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
vm, err := f.vm(ctx)
if err != nil {
return txmgr.TxCandidate{}, err
}
oracle, err := vm.Oracle(ctx)
if err != nil {
return txmgr.TxCandidate{}, err
}
return oracle.AddGlobalDataTx(data)
}
func (f *FaultDisputeGameContract) decodeClaim(result *batching.CallResult, contractIndex int) types.Claim { func (f *FaultDisputeGameContract) decodeClaim(result *batching.CallResult, contractIndex int) types.Claim {
parentIndex := result.GetUint32(0) parentIndex := result.GetUint32(0)
countered := result.GetBool(1) countered := result.GetBool(1)
......
...@@ -15,6 +15,12 @@ import ( ...@@ -15,6 +15,12 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var (
fdgAddr = common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB")
vmAddr = common.HexToAddress("0x33332842371dFC380576ebb09Ae16Cb6B6c3333")
oracleAddr = common.HexToAddress("0x44442842371dFC380576ebb09Ae16Cb6B6ca4444")
)
func TestSimpleGetters(t *testing.T) { func TestSimpleGetters(t *testing.T) {
tests := []struct { tests := []struct {
method string method string
...@@ -79,7 +85,7 @@ func TestSimpleGetters(t *testing.T) { ...@@ -79,7 +85,7 @@ func TestSimpleGetters(t *testing.T) {
test := test test := test
t.Run(test.method, func(t *testing.T) { t.Run(test.method, func(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
stubRpc.SetResponse(test.method, batching.BlockLatest, nil, []interface{}{test.result}) stubRpc.SetResponse(fdgAddr, test.method, batching.BlockLatest, nil, []interface{}{test.result})
status, err := test.call(game) status, err := test.call(game)
require.NoError(t, err) require.NoError(t, err)
expected := test.expected expected := test.expected
...@@ -109,7 +115,7 @@ func TestGetProposals(t *testing.T) { ...@@ -109,7 +115,7 @@ func TestGetProposals(t *testing.T) {
L2BlockNumber: disputedBlockNum, L2BlockNumber: disputedBlockNum,
OutputRoot: disputedRoot, OutputRoot: disputedRoot,
} }
stubRpc.SetResponse(methodProposals, batching.BlockLatest, []interface{}{}, []interface{}{ stubRpc.SetResponse(fdgAddr, methodProposals, batching.BlockLatest, []interface{}{}, []interface{}{
agreed, disputed, agreed, disputed,
}) })
actualAgreed, actualDisputed, err := game.GetProposals(context.Background()) actualAgreed, actualDisputed, err := game.GetProposals(context.Background())
...@@ -126,7 +132,7 @@ func TestGetClaim(t *testing.T) { ...@@ -126,7 +132,7 @@ func TestGetClaim(t *testing.T) {
value := common.Hash{0xab} value := common.Hash{0xab}
position := big.NewInt(2) position := big.NewInt(2)
clock := big.NewInt(1234) clock := big.NewInt(1234)
stubRpc.SetResponse(methodClaim, batching.BlockLatest, []interface{}{idx}, []interface{}{parentIndex, countered, value, position, clock}) stubRpc.SetResponse(fdgAddr, methodClaim, batching.BlockLatest, []interface{}{idx}, []interface{}{parentIndex, countered, value, position, clock})
status, err := game.GetClaim(context.Background(), idx.Uint64()) status, err := game.GetClaim(context.Background(), idx.Uint64())
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, faultTypes.Claim{ require.Equal(t, faultTypes.Claim{
...@@ -174,7 +180,7 @@ func TestGetAllClaims(t *testing.T) { ...@@ -174,7 +180,7 @@ func TestGetAllClaims(t *testing.T) {
ParentContractIndex: 1, ParentContractIndex: 1,
} }
expectedClaims := []faultTypes.Claim{claim0, claim1, claim2} expectedClaims := []faultTypes.Claim{claim0, claim1, claim2}
stubRpc.SetResponse(methodClaimCount, batching.BlockLatest, nil, []interface{}{big.NewInt(int64(len(expectedClaims)))}) stubRpc.SetResponse(fdgAddr, methodClaimCount, batching.BlockLatest, nil, []interface{}{big.NewInt(int64(len(expectedClaims)))})
for _, claim := range expectedClaims { for _, claim := range expectedClaims {
expectGetClaim(stubRpc, claim) expectGetClaim(stubRpc, claim)
} }
...@@ -185,14 +191,14 @@ func TestGetAllClaims(t *testing.T) { ...@@ -185,14 +191,14 @@ func TestGetAllClaims(t *testing.T) {
func TestCallResolveClaim(t *testing.T) { func TestCallResolveClaim(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
stubRpc.SetResponse(methodResolveClaim, batching.BlockLatest, []interface{}{big.NewInt(123)}, nil) stubRpc.SetResponse(fdgAddr, methodResolveClaim, batching.BlockLatest, []interface{}{big.NewInt(123)}, nil)
err := game.CallResolveClaim(context.Background(), 123) err := game.CallResolveClaim(context.Background(), 123)
require.NoError(t, err) require.NoError(t, err)
} }
func TestResolveClaimTx(t *testing.T) { func TestResolveClaimTx(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
stubRpc.SetResponse(methodResolveClaim, batching.BlockLatest, []interface{}{big.NewInt(123)}, nil) stubRpc.SetResponse(fdgAddr, methodResolveClaim, batching.BlockLatest, []interface{}{big.NewInt(123)}, nil)
tx, err := game.ResolveClaimTx(123) tx, err := game.ResolveClaimTx(123)
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
...@@ -200,7 +206,7 @@ func TestResolveClaimTx(t *testing.T) { ...@@ -200,7 +206,7 @@ func TestResolveClaimTx(t *testing.T) {
func TestResolveTx(t *testing.T) { func TestResolveTx(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
stubRpc.SetResponse(methodResolve, batching.BlockLatest, nil, nil) stubRpc.SetResponse(fdgAddr, methodResolve, batching.BlockLatest, nil, nil)
tx, err := game.ResolveTx() tx, err := game.ResolveTx()
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
...@@ -209,7 +215,7 @@ func TestResolveTx(t *testing.T) { ...@@ -209,7 +215,7 @@ func TestResolveTx(t *testing.T) {
func TestAttackTx(t *testing.T) { func TestAttackTx(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
value := common.Hash{0xaa} value := common.Hash{0xaa}
stubRpc.SetResponse(methodAttack, batching.BlockLatest, []interface{}{big.NewInt(111), value}, nil) stubRpc.SetResponse(fdgAddr, methodAttack, batching.BlockLatest, []interface{}{big.NewInt(111), value}, nil)
tx, err := game.AttackTx(111, value) tx, err := game.AttackTx(111, value)
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
...@@ -218,7 +224,7 @@ func TestAttackTx(t *testing.T) { ...@@ -218,7 +224,7 @@ func TestAttackTx(t *testing.T) {
func TestDefendTx(t *testing.T) { func TestDefendTx(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
value := common.Hash{0xaa} value := common.Hash{0xaa}
stubRpc.SetResponse(methodDefend, batching.BlockLatest, []interface{}{big.NewInt(111), value}, nil) stubRpc.SetResponse(fdgAddr, methodDefend, batching.BlockLatest, []interface{}{big.NewInt(111), value}, nil)
tx, err := game.DefendTx(111, value) tx, err := game.DefendTx(111, value)
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
...@@ -228,14 +234,55 @@ func TestStepTx(t *testing.T) { ...@@ -228,14 +234,55 @@ func TestStepTx(t *testing.T) {
stubRpc, game := setup(t) stubRpc, game := setup(t)
stateData := []byte{1, 2, 3} stateData := []byte{1, 2, 3}
proofData := []byte{4, 5, 6, 7, 8, 9} proofData := []byte{4, 5, 6, 7, 8, 9}
stubRpc.SetResponse(methodStep, batching.BlockLatest, []interface{}{big.NewInt(111), true, stateData, proofData}, nil) stubRpc.SetResponse(fdgAddr, methodStep, batching.BlockLatest, []interface{}{big.NewInt(111), true, stateData, proofData}, nil)
tx, err := game.StepTx(111, true, stateData, proofData) tx, err := game.StepTx(111, true, stateData, proofData)
require.NoError(t, err) require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx) stubRpc.VerifyTxCandidate(tx)
} }
func TestUpdateOracleTx(t *testing.T) {
t.Run("Local", func(t *testing.T) {
stubRpc, game := setup(t)
data := &faultTypes.PreimageOracleData{
IsLocal: true,
LocalContext: 2,
OracleKey: common.Hash{0xbc}.Bytes(),
OracleData: []byte{1, 2, 3, 4, 5, 6, 7},
OracleOffset: 16,
}
stubRpc.SetResponse(fdgAddr, methodAddLocalData, batching.BlockLatest, []interface{}{
data.GetIdent(),
new(big.Int).SetUint64(data.LocalContext),
new(big.Int).SetUint64(uint64(data.OracleOffset)),
}, nil)
tx, err := game.UpdateOracleTx(context.Background(), data)
require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx)
})
t.Run("Global", func(t *testing.T) {
stubRpc, game := setup(t)
data := &faultTypes.PreimageOracleData{
IsLocal: false,
OracleKey: common.Hash{0xbc}.Bytes(),
OracleData: []byte{1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15},
OracleOffset: 16,
}
stubRpc.SetResponse(fdgAddr, methodVM, batching.BlockLatest, nil, []interface{}{vmAddr})
stubRpc.SetResponse(vmAddr, methodOracle, batching.BlockLatest, nil, []interface{}{oracleAddr})
stubRpc.SetResponse(oracleAddr, methodLoadKeccak256PreimagePart, batching.BlockLatest, []interface{}{
new(big.Int).SetUint64(uint64(data.OracleOffset)),
data.GetPreimageWithoutSize(),
}, nil)
tx, err := game.UpdateOracleTx(context.Background(), data)
require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx)
})
}
func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) { func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) {
stubRpc.SetResponse( stubRpc.SetResponse(
fdgAddr,
methodClaim, methodClaim,
batching.BlockLatest, batching.BlockLatest,
[]interface{}{big.NewInt(int64(claim.ContractIndex))}, []interface{}{big.NewInt(int64(claim.ContractIndex))},
...@@ -251,11 +298,17 @@ func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) { ...@@ -251,11 +298,17 @@ func expectGetClaim(stubRpc *batchingTest.AbiBasedRpc, claim faultTypes.Claim) {
func setup(t *testing.T) (*batchingTest.AbiBasedRpc, *FaultDisputeGameContract) { func setup(t *testing.T) (*batchingTest.AbiBasedRpc, *FaultDisputeGameContract) {
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi() fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
require.NoError(t, err) require.NoError(t, err)
address := common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB")
stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAbi, address) vmAbi, err := bindings.MIPSMetaData.GetAbi()
caller := batching.NewMultiCaller(stubRpc, 100) require.NoError(t, err)
game, err := NewFaultDisputeGameContract(address, caller) oracleAbi, err := bindings.PreimageOracleMetaData.GetAbi()
require.NoError(t, err)
stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAddr, fdgAbi)
stubRpc.AddContract(vmAddr, vmAbi)
stubRpc.AddContract(oracleAddr, oracleAbi)
caller := batching.NewMultiCaller(stubRpc, batching.DefaultBatchSize)
game, err := NewFaultDisputeGameContract(fdgAddr, caller)
require.NoError(t, err) require.NoError(t, err)
return stubRpc, game return stubRpc, game
} }
...@@ -13,6 +13,10 @@ import ( ...@@ -13,6 +13,10 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
var (
factoryAddr = common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB")
)
func TestDisputeGameFactorySimpleGetters(t *testing.T) { func TestDisputeGameFactorySimpleGetters(t *testing.T) {
blockNum := uint64(23) blockNum := uint64(23)
tests := []struct { tests := []struct {
...@@ -35,7 +39,7 @@ func TestDisputeGameFactorySimpleGetters(t *testing.T) { ...@@ -35,7 +39,7 @@ func TestDisputeGameFactorySimpleGetters(t *testing.T) {
test := test test := test
t.Run(test.method, func(t *testing.T) { t.Run(test.method, func(t *testing.T) {
stubRpc, factory := setupDisputeGameFactoryTest(t) stubRpc, factory := setupDisputeGameFactoryTest(t)
stubRpc.SetResponse(test.method, batching.BlockByNumber(blockNum), nil, []interface{}{test.result}) stubRpc.SetResponse(factoryAddr, test.method, batching.BlockByNumber(blockNum), nil, []interface{}{test.result})
status, err := test.call(factory) status, err := test.call(factory)
require.NoError(t, err) require.NoError(t, err)
expected := test.expected expected := test.expected
...@@ -76,6 +80,7 @@ func TestLoadGame(t *testing.T) { ...@@ -76,6 +80,7 @@ func TestLoadGame(t *testing.T) {
func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, game types.GameMetadata) { func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, game types.GameMetadata) {
stubRpc.SetResponse( stubRpc.SetResponse(
factoryAddr,
methodGameAtIndex, methodGameAtIndex,
batching.BlockByNumber(blockNum), batching.BlockByNumber(blockNum),
[]interface{}{big.NewInt(int64(idx))}, []interface{}{big.NewInt(int64(idx))},
...@@ -89,11 +94,10 @@ func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64, ...@@ -89,11 +94,10 @@ func expectGetGame(stubRpc *batchingTest.AbiBasedRpc, idx int, blockNum uint64,
func setupDisputeGameFactoryTest(t *testing.T) (*batchingTest.AbiBasedRpc, *DisputeGameFactoryContract) { func setupDisputeGameFactoryTest(t *testing.T) (*batchingTest.AbiBasedRpc, *DisputeGameFactoryContract) {
fdgAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi() fdgAbi, err := bindings.DisputeGameFactoryMetaData.GetAbi()
require.NoError(t, err) require.NoError(t, err)
address := common.HexToAddress("0x24112842371dFC380576ebb09Ae16Cb6B6caD7CB")
stubRpc := batchingTest.NewAbiBasedRpc(t, fdgAbi, address) stubRpc := batchingTest.NewAbiBasedRpc(t, factoryAddr, fdgAbi)
caller := batching.NewMultiCaller(stubRpc, 100) caller := batching.NewMultiCaller(stubRpc, 100)
factory, err := NewDisputeGameFactoryContract(address, caller) factory, err := NewDisputeGameFactoryContract(factoryAddr, caller)
require.NoError(t, err) require.NoError(t, err)
return stubRpc, factory return stubRpc, factory
} }
package contracts
import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/common"
)
const (
methodLoadKeccak256PreimagePart = "loadKeccak256PreimagePart"
)
// PreimageOracleContract is a binding that works with contracts implementing the IPreimageOracle interface
type PreimageOracleContract struct {
multiCaller *batching.MultiCaller
contract *batching.BoundContract
}
func NewPreimageOracleContract(addr common.Address, caller *batching.MultiCaller) (*PreimageOracleContract, error) {
mipsAbi, err := bindings.PreimageOracleMetaData.GetAbi()
if err != nil {
return nil, fmt.Errorf("failed to load preimage oracle ABI: %w", err)
}
return &PreimageOracleContract{
multiCaller: caller,
contract: batching.NewBoundContract(mipsAbi, addr),
}, nil
}
func (c PreimageOracleContract) AddGlobalDataTx(data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
call := c.contract.Call(methodLoadKeccak256PreimagePart, new(big.Int).SetUint64(uint64(data.OracleOffset)), data.GetPreimageWithoutSize())
return call.ToTxCandidate()
}
package contracts
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
func TestPreimageOracleContract_LoadKeccak256(t *testing.T) {
oracleAbi, err := bindings.PreimageOracleMetaData.GetAbi()
require.NoError(t, err)
stubRpc := batchingTest.NewAbiBasedRpc(t, oracleAddr, oracleAbi)
oracleContract, err := NewPreimageOracleContract(oracleAddr, batching.NewMultiCaller(stubRpc, batching.DefaultBatchSize))
require.NoError(t, err)
data := &types.PreimageOracleData{
OracleKey: common.Hash{0xcc}.Bytes(),
OracleData: make([]byte, 20),
OracleOffset: 545,
}
stubRpc.SetResponse(oracleAddr, methodLoadKeccak256PreimagePart, batching.BlockLatest, []interface{}{
new(big.Int).SetUint64(uint64(data.OracleOffset)),
data.GetPreimageWithoutSize(),
}, nil)
tx, err := oracleContract.AddGlobalDataTx(data)
require.NoError(t, err)
stubRpc.VerifyTxCandidate(tx)
}
package contracts
import (
"context"
"fmt"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum/go-ethereum/common"
)
const (
methodOracle = "oracle"
)
// VMContract is a binding that works with contracts implementing the IBigStepper interface
type VMContract struct {
multiCaller *batching.MultiCaller
contract *batching.BoundContract
}
func NewVMContract(addr common.Address, caller *batching.MultiCaller) (*VMContract, error) {
mipsAbi, err := bindings.MIPSMetaData.GetAbi()
if err != nil {
return nil, fmt.Errorf("failed to load VM ABI: %w", err)
}
return &VMContract{
multiCaller: caller,
contract: batching.NewBoundContract(mipsAbi, addr),
}, nil
}
func (c *VMContract) Oracle(ctx context.Context) (*PreimageOracleContract, error) {
results, err := c.multiCaller.SingleCall(ctx, batching.BlockLatest, c.contract.Call(methodOracle))
if err != nil {
return nil, fmt.Errorf("failed to load oracle address: %w", err)
}
return NewPreimageOracleContract(results.GetAddress(0), c.multiCaller)
}
package contracts
import (
"context"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
batchingTest "github.com/ethereum-optimism/optimism/op-service/sources/batching/test"
"github.com/stretchr/testify/require"
)
func TestVMContract_Oracle(t *testing.T) {
vmAbi, err := bindings.MIPSMetaData.GetAbi()
require.NoError(t, err)
stubRpc := batchingTest.NewAbiBasedRpc(t, vmAddr, vmAbi)
vmContract, err := NewVMContract(vmAddr, batching.NewMultiCaller(stubRpc, batching.DefaultBatchSize))
require.NoError(t, err)
stubRpc.SetResponse(vmAddr, methodOracle, batching.BlockLatest, nil, []interface{}{oracleAddr})
oracleContract, err := vmContract.Oracle(context.Background())
require.NoError(t, err)
tx, err := oracleContract.AddGlobalDataTx(&types.PreimageOracleData{
OracleData: make([]byte, 20),
})
require.NoError(t, err)
// This test doesn't care about all the tx details, we just want to confirm the contract binding is using the
// correct address
require.Equal(t, &oracleAddr, tx.To)
}
...@@ -37,7 +37,7 @@ type GamePlayer struct { ...@@ -37,7 +37,7 @@ type GamePlayer struct {
status gameTypes.GameStatus status gameTypes.GameStatus
} }
type resourceCreator func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (types.TraceAccessor, types.OracleUpdater, gameValidator, error) type resourceCreator func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (types.TraceAccessor, gameValidator, error)
func NewGamePlayer( func NewGamePlayer(
ctx context.Context, ctx context.Context,
...@@ -51,6 +51,7 @@ func NewGamePlayer( ...@@ -51,6 +51,7 @@ func NewGamePlayer(
creator resourceCreator, creator resourceCreator,
) (*GamePlayer, error) { ) (*GamePlayer, error) {
logger = logger.New("game", addr) logger = logger.New("game", addr)
loader, err := contracts.NewFaultDisputeGameContract(addr, batching.NewMultiCaller(client.Client(), batching.DefaultBatchSize)) loader, err := contracts.NewFaultDisputeGameContract(addr, batching.NewMultiCaller(client.Client(), batching.DefaultBatchSize))
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create fault dispute game contract wrapper: %w", err) return nil, fmt.Errorf("failed to create fault dispute game contract wrapper: %w", err)
...@@ -80,7 +81,7 @@ func NewGamePlayer( ...@@ -80,7 +81,7 @@ func NewGamePlayer(
return nil, fmt.Errorf("failed to fetch the game depth: %w", err) return nil, fmt.Errorf("failed to fetch the game depth: %w", err)
} }
accessor, updater, validator, err := creator(addr, loader, gameDepth, dir) accessor, validator, err := creator(addr, loader, gameDepth, dir)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create trace accessor: %w", err) return nil, fmt.Errorf("failed to create trace accessor: %w", err)
} }
...@@ -94,7 +95,7 @@ func NewGamePlayer( ...@@ -94,7 +95,7 @@ func NewGamePlayer(
return nil, fmt.Errorf("failed to create the responder: %w", err) return nil, fmt.Errorf("failed to create the responder: %w", err)
} }
agent := NewAgent(m, loader, int(gameDepth), accessor, responder, updater, cfg.AgreeWithProposedOutput, logger) agent := NewAgent(m, loader, int(gameDepth), accessor, responder, cfg.AgreeWithProposedOutput, logger)
return &GamePlayer{ return &GamePlayer{
act: agent.Act, act: agent.Act,
agreeWithProposedOutput: cfg.AgreeWithProposedOutput, agreeWithProposedOutput: cfg.AgreeWithProposedOutput,
......
...@@ -58,25 +58,22 @@ func registerOutputCannon( ...@@ -58,25 +58,22 @@ func registerOutputCannon(
cfg *config.Config, cfg *config.Config,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client) { client *ethclient.Client) {
resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, faultTypes.OracleUpdater, gameValidator, error) { resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) {
logger := logger.New("game", addr)
// TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks // TODO(client-pod#43): Updated contracts should expose this as the pre and post state blocks
agreed, disputed, err := contract.GetProposals(ctx) agreed, disputed, err := contract.GetProposals(ctx)
if err != nil { if err != nil {
return nil, nil, nil, err 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, cfg.RollupRpc, gameDepth, agreed.L2BlockNumber.Uint64(), disputed.L2BlockNumber.Uint64())
if err != nil { if err != nil {
return nil, nil, nil, err return nil, nil, err
}
updater, err := cannon.NewOracleUpdater(ctx, logger, txMgr, addr, client)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to create the cannon updater: %w", err)
} }
// TODO(client-pod#44): Validate absolute pre-state for split games // TODO(client-pod#44): Validate absolute pre-state for split games
noopValidator := func(ctx context.Context, gameContract *contracts.FaultDisputeGameContract) error { noopValidator := func(ctx context.Context, gameContract *contracts.FaultDisputeGameContract) error {
return nil return nil
} }
return accessor, updater, noopValidator, nil return accessor, noopValidator, nil
} }
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
return NewGamePlayer(ctx, logger, m, cfg, dir, game.Proxy, txMgr, client, resourceCreator) return NewGamePlayer(ctx, logger, m, cfg, dir, game.Proxy, txMgr, client, resourceCreator)
...@@ -92,19 +89,16 @@ func registerCannon( ...@@ -92,19 +89,16 @@ func registerCannon(
cfg *config.Config, cfg *config.Config,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client) { client *ethclient.Client) {
resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, faultTypes.OracleUpdater, gameValidator, error) { resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) {
logger := logger.New("game", addr)
provider, err := cannon.NewTraceProvider(ctx, logger, m, cfg, contract, dir, gameDepth) provider, err := cannon.NewTraceProvider(ctx, logger, m, cfg, contract, dir, gameDepth)
if err != nil { if err != nil {
return nil, nil, nil, fmt.Errorf("create cannon trace provider: %w", err) return nil, nil, fmt.Errorf("create cannon trace provider: %w", err)
}
updater, err := cannon.NewOracleUpdater(ctx, logger, txMgr, addr, client)
if err != nil {
return nil, nil, nil, fmt.Errorf("failed to create the cannon updater: %w", err)
} }
validator := func(ctx context.Context, contract *contracts.FaultDisputeGameContract) error { validator := func(ctx context.Context, contract *contracts.FaultDisputeGameContract) error {
return ValidateAbsolutePrestate(ctx, provider, contract) return ValidateAbsolutePrestate(ctx, provider, contract)
} }
return trace.NewSimpleTraceAccessor(provider), updater, validator, nil return trace.NewSimpleTraceAccessor(provider), validator, nil
} }
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
return NewGamePlayer(ctx, logger, m, cfg, dir, game.Proxy, txMgr, client, resourceCreator) return NewGamePlayer(ctx, logger, m, cfg, dir, game.Proxy, txMgr, client, resourceCreator)
...@@ -120,13 +114,12 @@ func registerAlphabet( ...@@ -120,13 +114,12 @@ func registerAlphabet(
cfg *config.Config, cfg *config.Config,
txMgr txmgr.TxManager, txMgr txmgr.TxManager,
client *ethclient.Client) { client *ethclient.Client) {
resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, faultTypes.OracleUpdater, gameValidator, error) { resourceCreator := func(addr common.Address, contract *contracts.FaultDisputeGameContract, gameDepth uint64, dir string) (faultTypes.TraceAccessor, gameValidator, error) {
provider := alphabet.NewTraceProvider(cfg.AlphabetTrace, gameDepth) provider := alphabet.NewTraceProvider(cfg.AlphabetTrace, gameDepth)
updater := alphabet.NewOracleUpdater(logger)
validator := func(ctx context.Context, contract *contracts.FaultDisputeGameContract) error { validator := func(ctx context.Context, contract *contracts.FaultDisputeGameContract) error {
return ValidateAbsolutePrestate(ctx, provider, contract) return ValidateAbsolutePrestate(ctx, provider, contract)
} }
return trace.NewSimpleTraceAccessor(provider), updater, validator, nil return trace.NewSimpleTraceAccessor(provider), validator, nil
} }
playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) { playerCreator := func(game types.GameMetadata, dir string) (scheduler.GamePlayer, error) {
return NewGamePlayer(ctx, logger, m, cfg, dir, game.Proxy, txMgr, client, resourceCreator) return NewGamePlayer(ctx, logger, m, cfg, dir, game.Proxy, txMgr, client, resourceCreator)
......
...@@ -2,6 +2,7 @@ package responder ...@@ -2,6 +2,7 @@ package responder
import ( import (
"context" "context"
"fmt"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types" "github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types" gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
...@@ -20,6 +21,7 @@ type GameContract interface { ...@@ -20,6 +21,7 @@ type GameContract interface {
AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) AttackTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error)
DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error) DefendTx(parentContractIndex uint64, pivot common.Hash) (txmgr.TxCandidate, error)
StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error) StepTx(claimIdx uint64, isAttack bool, stateData []byte, proof []byte) (txmgr.TxCandidate, error)
UpdateOracleTx(ctx context.Context, data *types.PreimageOracleData) (txmgr.TxCandidate, error)
} }
// FaultResponder implements the [Responder] interface to send onchain transactions. // FaultResponder implements the [Responder] interface to send onchain transactions.
...@@ -71,6 +73,16 @@ func (r *FaultResponder) ResolveClaim(ctx context.Context, claimIdx uint64) erro ...@@ -71,6 +73,16 @@ func (r *FaultResponder) ResolveClaim(ctx context.Context, claimIdx uint64) erro
} }
func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) error { func (r *FaultResponder) PerformAction(ctx context.Context, action types.Action) error {
if action.OracleData != nil {
r.log.Info("Updating oracle data", "key", action.OracleData.OracleKey)
candidate, err := r.contract.UpdateOracleTx(ctx, action.OracleData)
if err != nil {
return fmt.Errorf("failed to create pre-image oracle tx: %w", err)
}
if err := r.sendTxAndWait(ctx, candidate); err != nil {
return fmt.Errorf("failed to populate pre-image oracle: %w", err)
}
}
var candidate txmgr.TxCandidate var candidate txmgr.TxCandidate
var err error var err error
switch action.Type { switch action.Type {
......
...@@ -169,6 +169,30 @@ func TestPerformAction(t *testing.T) { ...@@ -169,6 +169,30 @@ func TestPerformAction(t *testing.T) {
require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs) require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs)
require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData) require.Equal(t, ([]byte)("step"), mockTxMgr.sent[0].TxData)
}) })
t.Run("stepWithOracleData", func(t *testing.T) {
responder, mockTxMgr, contract := newTestFaultResponder(t)
action := types.Action{
Type: types.ActionTypeStep,
ParentIdx: 123,
IsAttack: true,
PreState: []byte{1, 2, 3},
ProofData: []byte{4, 5, 6},
OracleData: &types.PreimageOracleData{
IsLocal: true,
LocalContext: 6,
},
}
err := responder.PerformAction(context.Background(), action)
require.NoError(t, err)
require.Len(t, mockTxMgr.sent, 2)
require.EqualValues(t, action.OracleData, contract.updateOracleArgs)
require.EqualValues(t, []interface{}{uint64(action.ParentIdx), action.IsAttack, action.PreState, action.ProofData}, contract.stepArgs)
// Important that the oracle is updated first
require.Equal(t, ([]byte)("updateOracle"), mockTxMgr.sent[0].TxData)
require.Equal(t, ([]byte)("step"), mockTxMgr.sent[1].TxData)
})
} }
func newTestFaultResponder(t *testing.T) (*FaultResponder, *mockTxManager, *mockContract) { func newTestFaultResponder(t *testing.T) (*FaultResponder, *mockTxManager, *mockContract) {
...@@ -209,11 +233,12 @@ func (m *mockTxManager) From() common.Address { ...@@ -209,11 +233,12 @@ func (m *mockTxManager) From() common.Address {
} }
type mockContract struct { type mockContract struct {
calls int calls int
callFails bool callFails bool
attackArgs []interface{} attackArgs []interface{}
defendArgs []interface{} defendArgs []interface{}
stepArgs []interface{} stepArgs []interface{}
updateOracleArgs *types.PreimageOracleData
} }
func (m *mockContract) CallResolve(_ context.Context) (gameTypes.GameStatus, error) { func (m *mockContract) CallResolve(_ context.Context) (gameTypes.GameStatus, error) {
...@@ -254,3 +279,8 @@ func (m *mockContract) StepTx(claimIdx uint64, isAttack bool, stateData []byte, ...@@ -254,3 +279,8 @@ func (m *mockContract) StepTx(claimIdx uint64, isAttack bool, stateData []byte,
m.stepArgs = []interface{}{claimIdx, isAttack, stateData, proofData} m.stepArgs = []interface{}{claimIdx, isAttack, stateData, proofData}
return txmgr.TxCandidate{TxData: ([]byte)("step")}, nil return txmgr.TxCandidate{TxData: ([]byte)("step")}, nil
} }
func (m *mockContract) UpdateOracleTx(_ context.Context, data *types.PreimageOracleData) (txmgr.TxCandidate, error) {
m.updateOracleArgs = data
return txmgr.TxCandidate{TxData: ([]byte)("updateOracle")}, nil
}
package alphabet
import (
"context"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum/go-ethereum/log"
)
// alphabetUpdater is a [types.OracleUpdater] that exposes a
// method to update onchain oracles with required data.
type alphabetUpdater struct {
logger log.Logger
}
// NewOracleUpdater returns a new updater.
func NewOracleUpdater(logger log.Logger) *alphabetUpdater {
return &alphabetUpdater{
logger: logger,
}
}
// UpdateOracle updates the oracle with the given data.
func (u *alphabetUpdater) UpdateOracle(ctx context.Context, data *types.PreimageOracleData) error {
u.logger.Info("alphabet oracle updater called")
return nil
}
package alphabet
import (
"context"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
// TestAlphabetUpdater tests the [alphabetUpdater].
func TestAlphabetUpdater(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo)
updater := NewOracleUpdater(logger)
require.Nil(t, updater.UpdateOracle(context.Background(), &types.PreimageOracleData{}))
}
package cannon
import (
"context"
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
)
// cannonUpdater is a [types.OracleUpdater] that exposes a method
// to update onchain cannon oracles with required data.
type cannonUpdater struct {
log log.Logger
txMgr txmgr.TxManager
fdgAbi abi.ABI
fdgAddr common.Address
preimageOracleAbi abi.ABI
preimageOracleAddr common.Address
}
// NewOracleUpdater returns a new updater. The pre-image oracle address is loaded from the fault dispute game.
func NewOracleUpdater(
ctx context.Context,
logger log.Logger,
txMgr txmgr.TxManager,
fdgAddr common.Address,
client bind.ContractCaller,
) (*cannonUpdater, error) {
gameCaller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client)
if err != nil {
return nil, fmt.Errorf("create caller for game %v: %w", fdgAddr, err)
}
opts := &bind.CallOpts{Context: ctx}
vm, err := gameCaller.VM(opts)
if err != nil {
return nil, fmt.Errorf("failed to load VM address from game %v: %w", fdgAddr, err)
}
mipsCaller, err := bindings.NewMIPSCaller(vm, client)
if err != nil {
return nil, fmt.Errorf("failed to create MIPS caller for address %v: %w", vm, err)
}
oracleAddr, err := mipsCaller.Oracle(opts)
if err != nil {
return nil, fmt.Errorf("failed to load pre-image oracle address from game %v: %w", fdgAddr, err)
}
return NewOracleUpdaterWithOracle(logger, txMgr, fdgAddr, oracleAddr)
}
// NewOracleUpdaterWithOracle returns a new updater using a specified pre-image oracle address.
func NewOracleUpdaterWithOracle(
logger log.Logger,
txMgr txmgr.TxManager,
fdgAddr common.Address,
preimageOracleAddr common.Address,
) (*cannonUpdater, error) {
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
if err != nil {
return nil, err
}
preimageOracleAbi, err := bindings.PreimageOracleMetaData.GetAbi()
if err != nil {
return nil, err
}
return &cannonUpdater{
log: logger,
txMgr: txMgr,
fdgAbi: *fdgAbi,
fdgAddr: fdgAddr,
preimageOracleAbi: *preimageOracleAbi,
preimageOracleAddr: preimageOracleAddr,
}, nil
}
// UpdateOracle updates the oracle with the given data.
func (u *cannonUpdater) UpdateOracle(ctx context.Context, data *types.PreimageOracleData) error {
if data.IsLocal {
return u.sendLocalOracleData(ctx, data)
}
return u.sendGlobalOracleData(ctx, data)
}
// sendLocalOracleData sends the local oracle data to the [txmgr].
func (u *cannonUpdater) sendLocalOracleData(ctx context.Context, data *types.PreimageOracleData) error {
txData, err := u.BuildLocalOracleData(data)
if err != nil {
return fmt.Errorf("local oracle tx data build: %w", err)
}
return u.sendTxAndWait(ctx, u.fdgAddr, txData)
}
// sendGlobalOracleData sends the global oracle data to the [txmgr].
func (u *cannonUpdater) sendGlobalOracleData(ctx context.Context, data *types.PreimageOracleData) error {
txData, err := u.BuildGlobalOracleData(data)
if err != nil {
return fmt.Errorf("global oracle tx data build: %w", err)
}
return u.sendTxAndWait(ctx, u.fdgAddr, txData)
}
// BuildLocalOracleData takes the local preimage key and data
// and creates tx data to load the key, data pair into the
// PreimageOracle contract from the FaultDisputeGame contract call.
func (u *cannonUpdater) BuildLocalOracleData(data *types.PreimageOracleData) ([]byte, error) {
return u.fdgAbi.Pack(
"addLocalData",
data.GetIdent(),
big.NewInt(int64(data.LocalContext)),
big.NewInt(int64(data.OracleOffset)),
)
}
// BuildGlobalOracleData takes the global preimage key and data
// and creates tx data to load the key, data pair into the
// PreimageOracle contract.
func (u *cannonUpdater) BuildGlobalOracleData(data *types.PreimageOracleData) ([]byte, error) {
return u.preimageOracleAbi.Pack(
"loadKeccak256PreimagePart",
big.NewInt(int64(data.OracleOffset)),
data.GetPreimageWithoutSize(),
)
}
// sendTxAndWait sends a transaction through the [txmgr] and waits for a receipt.
// This sets the tx GasLimit to 0, performing gas estimation online through the [txmgr].
func (u *cannonUpdater) sendTxAndWait(ctx context.Context, addr common.Address, txData []byte) error {
receipt, err := u.txMgr.Send(ctx, txmgr.TxCandidate{
To: &addr,
TxData: txData,
GasLimit: 0,
})
if err != nil {
return err
}
if receipt.Status == ethtypes.ReceiptStatusFailed {
u.log.Error("Responder tx successfully published but reverted", "tx_hash", receipt.TxHash)
} else {
u.log.Debug("Responder tx successfully published", "tx_hash", receipt.TxHash)
}
return nil
}
package cannon
import (
"context"
"errors"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum-optimism/optimism/op-service/txmgr"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/stretchr/testify/require"
)
var (
mockFdgAddress = common.HexToAddress("0x1234")
mockPreimageOracleAddress = common.HexToAddress("0x12345")
mockSendError = errors.New("mock send error")
)
type mockTxManager struct {
from common.Address
sends int
failedSends int
sendFails bool
}
func (m *mockTxManager) Send(ctx context.Context, candidate txmgr.TxCandidate) (*ethtypes.Receipt, error) {
if m.sendFails {
m.failedSends++
return nil, mockSendError
}
m.sends++
return ethtypes.NewReceipt(
[]byte{},
false,
0,
), nil
}
func (m *mockTxManager) BlockNumber(ctx context.Context) (uint64, error) {
panic("not implemented")
}
func (m *mockTxManager) From() common.Address {
return m.from
}
func newTestCannonUpdater(t *testing.T, sendFails bool) (*cannonUpdater, *mockTxManager) {
logger := testlog.Logger(t, log.LvlInfo)
txMgr := &mockTxManager{
from: mockFdgAddress,
sendFails: sendFails,
}
updater, err := NewOracleUpdaterWithOracle(logger, txMgr, mockFdgAddress, mockPreimageOracleAddress)
require.NoError(t, err)
return updater, txMgr
}
// TestCannonUpdater_UpdateOracle tests the [cannonUpdater]
// UpdateOracle function.
func TestCannonUpdater_UpdateOracle(t *testing.T) {
t.Run("succeeds", func(t *testing.T) {
updater, mockTxMgr := newTestCannonUpdater(t, false)
require.NoError(t, updater.UpdateOracle(context.Background(), &types.PreimageOracleData{
OracleKey: common.Hash{0xaa}.Bytes(),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
}))
require.Equal(t, 1, mockTxMgr.sends)
})
t.Run("send fails", func(t *testing.T) {
updater, mockTxMgr := newTestCannonUpdater(t, true)
require.Error(t, updater.UpdateOracle(context.Background(), &types.PreimageOracleData{
OracleKey: common.Hash{0xaa}.Bytes(),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
}))
require.Equal(t, 1, mockTxMgr.failedSends)
})
}
// TestCannonUpdater_BuildLocalOracleData tests the [cannonUpdater]
// builds a valid tx candidate for a local oracle update.
func TestCannonUpdater_BuildLocalOracleData(t *testing.T) {
updater, _ := newTestCannonUpdater(t, false)
oracleData := &types.PreimageOracleData{
OracleKey: common.Hex2Bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
OracleOffset: 7,
}
txData, err := updater.BuildLocalOracleData(oracleData)
require.NoError(t, err)
fdgAbi, err := bindings.FaultDisputeGameMetaData.GetAbi()
require.NoError(t, err)
addLocalDataBytes4 := fdgAbi.Methods["addLocalData"].ID[:4]
// Pack the tx data manually.
var expected []byte
expected = append(expected, addLocalDataBytes4...)
expected = append(expected, common.Hex2Bytes("00aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")...)
expected = append(expected, common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000000")...)
expected = append(expected, common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000007")...)
require.Equal(t, expected, txData)
}
// TestCannonUpdater_BuildGlobalOracleData tests the [cannonUpdater]
// builds a valid tx candidate for a global oracle update.
func TestCannonUpdater_BuildGlobalOracleData(t *testing.T) {
updater, _ := newTestCannonUpdater(t, false)
oracleData := &types.PreimageOracleData{
OracleKey: common.Hex2Bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
OracleOffset: 7,
}
txData, err := updater.BuildGlobalOracleData(oracleData)
require.NoError(t, err)
var loadKeccak256PreimagePartBytes4 = crypto.Keccak256([]byte("loadKeccak256PreimagePart(uint256,bytes)"))[:4]
// Pack the tx data manually.
var expected []byte
expected = append(expected, loadKeccak256PreimagePartBytes4...)
expected = append(expected, common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000007")...)
expected = append(expected, common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000040")...)
expected = append(expected, common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000018")...)
expected = append(expected, common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccc0000000000000000")...)
require.Equal(t, expected, txData)
}
...@@ -51,12 +51,6 @@ type StepCallData struct { ...@@ -51,12 +51,6 @@ type StepCallData struct {
Proof []byte Proof []byte
} }
// OracleUpdater is a generic interface for updating oracles.
type OracleUpdater interface {
// UpdateOracle updates the oracle with the given data.
UpdateOracle(ctx context.Context, data *PreimageOracleData) error
}
// TraceAccessor defines an interface to request data from a TraceProvider with additional context for the game position. // TraceAccessor defines an interface to request data from a TraceProvider with additional context for the game position.
// This can be used to implement split games where lower layers of the game may have different values depending on claims // This can be used to implement split games where lower layers of the game may have different values depending on claims
// at higher levels in the game. // at higher levels in the game.
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
) )
type expectedCall struct { type expectedCall struct {
to common.Address
block batching.Block block batching.Block
args []interface{} args []interface{}
packedArgs []byte packedArgs []byte
...@@ -26,38 +27,49 @@ type expectedCall struct { ...@@ -26,38 +27,49 @@ type expectedCall struct {
} }
func (e *expectedCall) String() string { func (e *expectedCall) String() string {
return fmt.Sprintf("{block: %v, args: %v, outputs: %v}", e.block, e.args, e.outputs) return fmt.Sprintf("{to: %v, block: %v, args: %v, outputs: %v}", e.to, e.block, e.args, e.outputs)
} }
type AbiBasedRpc struct { type AbiBasedRpc struct {
t *testing.T t *testing.T
abi *abi.ABI abis map[common.Address]*abi.ABI
addr common.Address
expectedCalls map[string][]*expectedCall expectedCalls map[string][]*expectedCall
} }
func NewAbiBasedRpc(t *testing.T, contractAbi *abi.ABI, addr common.Address) *AbiBasedRpc { func NewAbiBasedRpc(t *testing.T, to common.Address, contractAbi *abi.ABI) *AbiBasedRpc {
abis := make(map[common.Address]*abi.ABI)
abis[to] = contractAbi
return &AbiBasedRpc{ return &AbiBasedRpc{
t: t, t: t,
abi: contractAbi, abis: abis,
addr: addr,
expectedCalls: make(map[string][]*expectedCall), expectedCalls: make(map[string][]*expectedCall),
} }
} }
func (l *AbiBasedRpc) SetResponse(method string, block batching.Block, expected []interface{}, output []interface{}) { func (l *AbiBasedRpc) AddContract(to common.Address, contractAbi *abi.ABI) {
l.abis[to] = contractAbi
}
func (l *AbiBasedRpc) abi(to common.Address) *abi.ABI {
abi, ok := l.abis[to]
require.Truef(l.t, ok, "Missing ABI for %v", to)
return abi
}
func (l *AbiBasedRpc) SetResponse(to common.Address, method string, block batching.Block, expected []interface{}, output []interface{}) {
if expected == nil { if expected == nil {
expected = []interface{}{} expected = []interface{}{}
} }
if output == nil { if output == nil {
output = []interface{}{} output = []interface{}{}
} }
abiMethod, ok := l.abi.Methods[method] abiMethod, ok := l.abi(to).Methods[method]
require.Truef(l.t, ok, "No method: %v", method) require.Truef(l.t, ok, "No method: %v", method)
packedArgs, err := abiMethod.Inputs.Pack(expected...) packedArgs, err := abiMethod.Inputs.Pack(expected...)
require.NoErrorf(l.t, err, "Invalid expected arguments for method %v: %v", method, expected) require.NoErrorf(l.t, err, "Invalid expected arguments for method %v: %v", method, expected)
l.expectedCalls[method] = append(l.expectedCalls[method], &expectedCall{ l.expectedCalls[method] = append(l.expectedCalls[method], &expectedCall{
to: to,
block: block, block: block,
args: expected, args: expected,
packedArgs: packedArgs, packedArgs: packedArgs,
...@@ -75,8 +87,8 @@ func (l *AbiBasedRpc) BatchCallContext(ctx context.Context, b []rpc.BatchElem) e ...@@ -75,8 +87,8 @@ func (l *AbiBasedRpc) BatchCallContext(ctx context.Context, b []rpc.BatchElem) e
} }
func (l *AbiBasedRpc) VerifyTxCandidate(candidate txmgr.TxCandidate) { func (l *AbiBasedRpc) VerifyTxCandidate(candidate txmgr.TxCandidate) {
require.EqualValues(l.t, &l.addr, candidate.To, "Incorrect To address") require.NotNil(l.t, candidate.To)
l.findExpectedCall(candidate.TxData, batching.BlockLatest.ArgValue()) l.findExpectedCall(*candidate.To, candidate.TxData, batching.BlockLatest.ArgValue())
} }
func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method string, args ...interface{}) error { func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method string, args ...interface{}) error {
...@@ -85,11 +97,13 @@ func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method str ...@@ -85,11 +97,13 @@ func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method str
actualBlockRef := args[1] actualBlockRef := args[1]
callOpts, ok := args[0].(map[string]any) callOpts, ok := args[0].(map[string]any)
require.True(l.t, ok) require.True(l.t, ok)
require.Equal(l.t, &l.addr, callOpts["to"]) to, ok := callOpts["to"].(*common.Address)
require.True(l.t, ok)
require.NotNil(l.t, to)
data, ok := callOpts["input"].(hexutil.Bytes) data, ok := callOpts["input"].(hexutil.Bytes)
require.True(l.t, ok) require.True(l.t, ok)
call, abiMethod := l.findExpectedCall(data, actualBlockRef) call, abiMethod := l.findExpectedCall(*to, data, actualBlockRef)
output, err := abiMethod.Outputs.Pack(call.outputs...) output, err := abiMethod.Outputs.Pack(call.outputs...)
require.NoErrorf(l.t, err, "Invalid outputs for method %v: %v", abiMethod.Name, call.outputs) require.NoErrorf(l.t, err, "Invalid outputs for method %v: %v", abiMethod.Name, call.outputs)
...@@ -102,9 +116,9 @@ func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method str ...@@ -102,9 +116,9 @@ func (l *AbiBasedRpc) CallContext(_ context.Context, out interface{}, method str
return nil return nil
} }
func (l *AbiBasedRpc) findExpectedCall(data []byte, actualBlockRef interface{}) (*expectedCall, *abi.Method) { func (l *AbiBasedRpc) findExpectedCall(to common.Address, data []byte, actualBlockRef interface{}) (*expectedCall, *abi.Method) {
abiMethod, err := l.abi.MethodById(data[0:4]) abiMethod, err := l.abi(to).MethodById(data[0:4])
require.NoError(l.t, err) require.NoError(l.t, err)
argData := data[4:] argData := data[4:]
...@@ -116,11 +130,14 @@ func (l *AbiBasedRpc) findExpectedCall(data []byte, actualBlockRef interface{}) ...@@ -116,11 +130,14 @@ func (l *AbiBasedRpc) findExpectedCall(data []byte, actualBlockRef interface{})
require.Truef(l.t, ok, "Unexpected call to %v", abiMethod.Name) require.Truef(l.t, ok, "Unexpected call to %v", abiMethod.Name)
var call *expectedCall var call *expectedCall
for _, candidate := range expectedCalls { for _, candidate := range expectedCalls {
if slices.Equal(candidate.packedArgs, argData) && assert.ObjectsAreEqualValues(candidate.block.ArgValue(), actualBlockRef) { if to == candidate.to &&
slices.Equal(candidate.packedArgs, argData) &&
assert.ObjectsAreEqualValues(candidate.block.ArgValue(), actualBlockRef) {
call = candidate call = candidate
break break
} }
} }
require.NotNilf(l.t, call, "No expected calls to %v at block %v with arguments: %v\nExpected calls: %v", abiMethod.Name, actualBlockRef, args, expectedCalls) require.NotNilf(l.t, call, "No expected calls to %v at block %v with to: %v, arguments: %v\nExpected calls: %v",
to, abiMethod.Name, actualBlockRef, args, expectedCalls)
return call, abiMethod return call, abiMethod
} }
...@@ -8,7 +8,7 @@ RUN apt-get update && \ ...@@ -8,7 +8,7 @@ RUN apt-get update && \
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \ RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh && \
chmod +x ./rustup.sh && \ chmod +x ./rustup.sh && \
./rustup.sh -y sh rustup.sh -y
# Install nightly toolchain # Install nightly toolchain
RUN source $HOME/.profile && rustup update nightly RUN source $HOME/.profile && rustup update nightly
...@@ -24,6 +24,10 @@ COPY ./ops/scripts/install-foundry.sh ./install-foundry.sh ...@@ -24,6 +24,10 @@ COPY ./ops/scripts/install-foundry.sh ./install-foundry.sh
RUN curl -L https://foundry.paradigm.xyz | bash RUN curl -L https://foundry.paradigm.xyz | bash
RUN source $HOME/.profile && ./install-foundry.sh RUN source $HOME/.profile && ./install-foundry.sh
RUN strip /root/.foundry/bin/forge && \
strip /root/.foundry/bin/cast && \
strip /root/.foundry/bin/anvil
FROM --platform=linux/amd64 ghcr.io/crytic/echidna/echidna:v2.0.4 as echidna-test FROM --platform=linux/amd64 ghcr.io/crytic/echidna/echidna:v2.0.4 as echidna-test
FROM --platform=linux/amd64 debian:bullseye-slim as go-build FROM --platform=linux/amd64 debian:bullseye-slim as go-build
......
# @eth-optimism/drippie-mon # @eth-optimism/drippie-mon
## 0.5.3
### Patch Changes
- Updated dependencies [[`2534eabb5`](https://github.com/ethereum-optimism/optimism/commit/2534eabb50afe76f176407f83cc1f1c606e6de69)]:
- @eth-optimism/sdk@3.1.5
## 0.5.2 ## 0.5.2
### Patch Changes ### Patch Changes
......
{ {
"private": true, "private": true,
"name": "@eth-optimism/chain-mon", "name": "@eth-optimism/chain-mon",
"version": "0.5.2", "version": "0.5.3",
"description": "[Optimism] Chain monitoring services", "description": "[Optimism] Chain monitoring services",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
"dev:replica-mon": "tsx watch ./src/replica-mon/service.ts", "dev:replica-mon": "tsx watch ./src/replica-mon/service.ts",
"dev:wallet-mon": "tsx watch ./src/wallet-mon/service.ts", "dev:wallet-mon": "tsx watch ./src/wallet-mon/service.ts",
"dev:wd-mon": "tsx watch ./src/wd-mon/service.ts", "dev:wd-mon": "tsx watch ./src/wd-mon/service.ts",
"start:balance-mon": "tsx ./src/balance-mon/service.ts", "start:balance-mon": "tsx ./src/balance-mon/service.ts",
"start:drippie-mon": "tsx ./src/drippie-mon/service.ts", "start:drippie-mon": "tsx ./src/drippie-mon/service.ts",
"start:fault-mon": "tsx ./src/fault-mon/service.ts", "start:fault-mon": "tsx ./src/fault-mon/service.ts",
...@@ -24,7 +23,6 @@ ...@@ -24,7 +23,6 @@
"start:replica-mon": "tsx ./src/replica-mon/service.ts", "start:replica-mon": "tsx ./src/replica-mon/service.ts",
"start:wallet-mon": "tsx ./src/wallet-mon/service.ts", "start:wallet-mon": "tsx ./src/wallet-mon/service.ts",
"start:wd-mon": "tsx ./src/wd-mon/service.ts", "start:wd-mon": "tsx ./src/wd-mon/service.ts",
"test": "hardhat test", "test": "hardhat test",
"test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json", "test:coverage": "nyc hardhat test && nyc merge .nyc_output coverage.json",
"build": "tsc -p ./tsconfig.json", "build": "tsc -p ./tsconfig.json",
...@@ -65,6 +63,6 @@ ...@@ -65,6 +63,6 @@
"@nomiclabs/hardhat-waffle": "^2.0.6", "@nomiclabs/hardhat-waffle": "^2.0.6",
"hardhat": "^2.19.0", "hardhat": "^2.19.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsx": "^3.14.0" "tsx": "^4.1.1"
} }
} }
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
}, },
"dependencies": { "dependencies": {
"@eth-optimism/core-utils": "workspace:*", "@eth-optimism/core-utils": "workspace:*",
"@sentry/node": "^7.77.0", "@sentry/node": "^7.80.0",
"bcfg": "^0.2.1", "bcfg": "^0.2.1",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"commander": "^11.1.0", "commander": "^11.1.0",
......
...@@ -44,9 +44,9 @@ ...@@ -44,9 +44,9 @@
"lint": "pnpm lint:fix && pnpm lint:check" "lint": "pnpm lint:fix && pnpm lint:check"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/eslint-plugin": "^6.11.0",
"@typescript-eslint/parser": "^6.9.1", "@typescript-eslint/parser": "^6.11.0",
"tsx": "^3.14.0", "tsx": "^4.1.1",
"typescript": "^5.2.2" "typescript": "^5.2.2"
} }
} }
# @eth-optimism/sdk # @eth-optimism/sdk
## 3.1.5
### Patch Changes
- [#8155](https://github.com/ethereum-optimism/optimism/pull/8155) [`2534eabb5`](https://github.com/ethereum-optimism/optimism/commit/2534eabb50afe76f176407f83cc1f1c606e6de69) Thanks [@smartcontracts](https://github.com/smartcontracts)! - Fixed bug with tokenBridge checks throwing
## 3.1.4 ## 3.1.4
### Patch Changes ### Patch Changes
......
{ {
"name": "@eth-optimism/sdk", "name": "@eth-optimism/sdk",
"version": "3.1.4", "version": "3.1.5",
"description": "[Optimism] Tools for working with Optimism", "description": "[Optimism] Tools for working with Optimism",
"main": "dist/index", "main": "dist/index",
"types": "dist/index", "types": "dist/index",
......
...@@ -156,46 +156,33 @@ export class StandardBridgeAdapter implements IBridgeAdapter { ...@@ -156,46 +156,33 @@ export class StandardBridgeAdapter implements IBridgeAdapter {
l1Token: AddressLike, l1Token: AddressLike,
l2Token: AddressLike l2Token: AddressLike
): Promise<boolean> { ): Promise<boolean> {
try { const contract = new Contract(
const contract = new Contract( toAddress(l2Token),
toAddress(l2Token), optimismMintableERC20.abi,
optimismMintableERC20.abi, this.messenger.l2Provider
this.messenger.l2Provider )
) // Don't support ETH deposits or withdrawals via this bridge.
// Don't support ETH deposits or withdrawals via this bridge. if (
if ( hexStringEquals(toAddress(l1Token), ethers.constants.AddressZero) ||
hexStringEquals(toAddress(l1Token), ethers.constants.AddressZero) || hexStringEquals(toAddress(l2Token), predeploys.OVM_ETH)
hexStringEquals(toAddress(l2Token), predeploys.OVM_ETH) ) {
) { return false
return false }
}
// Make sure the L1 token matches.
const remoteL1Token = await contract.l1Token()
if (!hexStringEquals(remoteL1Token, toAddress(l1Token))) { // Make sure the L1 token matches.
return false const remoteL1Token = await contract.l1Token()
}
// Make sure the L2 bridge matches. if (!hexStringEquals(remoteL1Token, toAddress(l1Token))) {
const remoteL2Bridge = await contract.l2Bridge() return false
if (!hexStringEquals(remoteL2Bridge, this.l2Bridge.address)) { }
return false
}
return true // Make sure the L2 bridge matches.
} catch (err) { const remoteL2Bridge = await contract.l2Bridge()
// If the L2 token is not an L2StandardERC20, it may throw an error. If there's a call if (!hexStringEquals(remoteL2Bridge, this.l2Bridge.address)) {
// exception then we assume that the token is not supported. Other errors are thrown. Since
// the JSON-RPC API is not well-specified, we need to handle multiple possible error codes.
if (
!err?.message?.toString().includes('CALL_EXCEPTION') &&
!err?.stack?.toString().includes('execution reverted')
) {
console.error('Unexpected error when checking bridge', err)
}
return false return false
} }
return true
} }
public async approval( public async approval(
......
...@@ -490,8 +490,17 @@ export class CrossChainMessenger { ...@@ -490,8 +490,17 @@ export class CrossChainMessenger {
): Promise<IBridgeAdapter> { ): Promise<IBridgeAdapter> {
const bridges: IBridgeAdapter[] = [] const bridges: IBridgeAdapter[] = []
for (const bridge of Object.values(this.bridges)) { for (const bridge of Object.values(this.bridges)) {
if (await bridge.supportsTokenPair(l1Token, l2Token)) { try {
bridges.push(bridge) if (await bridge.supportsTokenPair(l1Token, l2Token)) {
bridges.push(bridge)
}
} catch (err) {
if (
!err?.message?.toString().includes('CALL_EXCEPTION') &&
!err?.stack?.toString().includes('execution reverted')
) {
console.error('Unexpected error when checking bridge', err)
}
} }
} }
......
...@@ -34,11 +34,11 @@ importers: ...@@ -34,11 +34,11 @@ importers:
specifier: ^20.9.0 specifier: ^20.9.0
version: 20.9.0 version: 20.9.0
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^6.10.0 specifier: ^6.11.0
version: 6.10.0(@typescript-eslint/parser@6.9.1)(eslint@8.53.0)(typescript@5.2.2) version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^6.9.1 specifier: ^6.11.0
version: 6.9.1(eslint@8.53.0)(typescript@5.2.2) version: 6.11.0(eslint@8.53.0)(typescript@5.2.2)
chai: chai:
specifier: ^4.3.10 specifier: ^4.3.10
version: 4.3.10 version: 4.3.10
...@@ -59,7 +59,7 @@ importers: ...@@ -59,7 +59,7 @@ importers:
version: 16.0.3(eslint-plugin-import@2.29.0)(eslint-plugin-node@11.1.0)(eslint-plugin-promise@5.2.0)(eslint@8.53.0) version: 16.0.3(eslint-plugin-import@2.29.0)(eslint-plugin-node@11.1.0)(eslint-plugin-promise@5.2.0)(eslint@8.53.0)
eslint-plugin-import: eslint-plugin-import:
specifier: ^2.29.0 specifier: ^2.29.0
version: 2.29.0(@typescript-eslint/parser@6.9.1)(eslint@8.53.0) version: 2.29.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)
eslint-plugin-jsdoc: eslint-plugin-jsdoc:
specifier: ^35.1.2 specifier: ^35.1.2
version: 35.5.1(eslint@8.53.0) version: 35.5.1(eslint@8.53.0)
...@@ -111,9 +111,6 @@ importers: ...@@ -111,9 +111,6 @@ importers:
prettier: prettier:
specifier: ^2.8.0 specifier: ^2.8.0
version: 2.8.8 version: 2.8.8
prettier-plugin-solidity:
specifier: ^1.0.0-beta.13
version: 1.0.0-beta.18(prettier@2.8.8)
rimraf: rimraf:
specifier: ^5.0.5 specifier: ^5.0.5
version: 5.0.5 version: 5.0.5
...@@ -186,8 +183,8 @@ importers: ...@@ -186,8 +183,8 @@ importers:
specifier: ^10.9.1 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.0)(typescript@5.2.2)
tsx: tsx:
specifier: ^3.14.0 specifier: ^4.1.1
version: 3.14.0 version: 4.1.1
packages/common-ts: packages/common-ts:
dependencies: dependencies:
...@@ -195,8 +192,8 @@ importers: ...@@ -195,8 +192,8 @@ importers:
specifier: workspace:* specifier: workspace:*
version: link:../core-utils version: link:../core-utils
'@sentry/node': '@sentry/node':
specifier: ^7.77.0 specifier: ^7.80.0
version: 7.77.0 version: 7.80.0
bcfg: bcfg:
specifier: ^0.2.1 specifier: ^0.2.1
version: 0.2.1 version: 0.2.1
...@@ -268,14 +265,14 @@ importers: ...@@ -268,14 +265,14 @@ importers:
packages/contracts-bedrock: packages/contracts-bedrock:
devDependencies: devDependencies:
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: ^6.10.0 specifier: ^6.11.0
version: 6.10.0(@typescript-eslint/parser@6.9.1)(eslint@8.53.0)(typescript@5.2.2) version: 6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: ^6.9.1 specifier: ^6.11.0
version: 6.9.1(eslint@8.53.0)(typescript@5.2.2) version: 6.11.0(eslint@8.53.0)(typescript@5.2.2)
tsx: tsx:
specifier: ^3.14.0 specifier: ^4.1.1
version: 3.14.0 version: 4.1.1
typescript: typescript:
specifier: ^5.2.2 specifier: ^5.2.2
version: 5.2.2 version: 5.2.2
...@@ -3251,13 +3248,13 @@ packages: ...@@ -3251,13 +3248,13 @@ packages:
'@noble/hashes': 1.3.2 '@noble/hashes': 1.3.2
'@scure/base': 1.1.3 '@scure/base': 1.1.3
/@sentry-internal/tracing@7.77.0: /@sentry-internal/tracing@7.80.0:
resolution: {integrity: sha512-8HRF1rdqWwtINqGEdx8Iqs9UOP/n8E0vXUu3Nmbqj4p5sQPA7vvCfq+4Y4rTqZFc7sNdFpDsRION5iQEh8zfZw==} resolution: {integrity: sha512-P1Ab9gamHLsbH9D82i1HY8xfq9dP8runvc4g50AAd6OXRKaJ45f2KGRZUmnMEVqBQ7YoPYp2LFMkrhNYbcZEoQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
'@sentry/core': 7.77.0 '@sentry/core': 7.80.0
'@sentry/types': 7.77.0 '@sentry/types': 7.80.0
'@sentry/utils': 7.77.0 '@sentry/utils': 7.80.0
dev: false dev: false
/@sentry/core@5.30.0: /@sentry/core@5.30.0:
...@@ -3271,12 +3268,12 @@ packages: ...@@ -3271,12 +3268,12 @@ packages:
tslib: 1.14.1 tslib: 1.14.1
dev: true dev: true
/@sentry/core@7.77.0: /@sentry/core@7.80.0:
resolution: {integrity: sha512-Tj8oTYFZ/ZD+xW8IGIsU6gcFXD/gfE+FUxUaeSosd9KHwBQNOLhZSsYo/tTVf/rnQI/dQnsd4onPZLiL+27aTg==} resolution: {integrity: sha512-nJiiymdTSEyI035/rdD3VOq6FlOZ2wWLR5bit9LK8a3rzHU3UXkwScvEo6zYgs0Xp1sC0yu1S9+0BEiYkmi29A==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
'@sentry/types': 7.77.0 '@sentry/types': 7.80.0
'@sentry/utils': 7.77.0 '@sentry/utils': 7.80.0
dev: false dev: false
/@sentry/hub@5.30.0: /@sentry/hub@5.30.0:
...@@ -3314,14 +3311,14 @@ packages: ...@@ -3314,14 +3311,14 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@sentry/node@7.77.0: /@sentry/node@7.80.0:
resolution: {integrity: sha512-Ob5tgaJOj0OYMwnocc6G/CDLWC7hXfVvKX/ofkF98+BbN/tQa5poL+OwgFn9BA8ud8xKzyGPxGU6LdZ8Oh3z/g==} resolution: {integrity: sha512-J35fqe8J5ac/17ZXT0ML3opYGTOclqYNE9Sybs1y9n6BqacHyzH8By72YrdI03F7JJDHwrcGw+/H8hGpkCwi0Q==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
'@sentry-internal/tracing': 7.77.0 '@sentry-internal/tracing': 7.80.0
'@sentry/core': 7.77.0 '@sentry/core': 7.80.0
'@sentry/types': 7.77.0 '@sentry/types': 7.80.0
'@sentry/utils': 7.77.0 '@sentry/utils': 7.80.0
https-proxy-agent: 5.0.1 https-proxy-agent: 5.0.1
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
...@@ -3343,8 +3340,8 @@ packages: ...@@ -3343,8 +3340,8 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true dev: true
/@sentry/types@7.77.0: /@sentry/types@7.80.0:
resolution: {integrity: sha512-nfb00XRJVi0QpDHg+JkqrmEBHsqBnxJu191Ded+Cs1OJ5oPXEW6F59LVcBScGvMqe+WEk1a73eH8XezwfgrTsA==} resolution: {integrity: sha512-4bpMO+2jWiWLDa8zbTASWWNLWe6yhjfPsa7/6VH5y9x1NGtL8oRbqUsTgsvjF3nmeHEMkHQsC8NHPaQ/ibFmZQ==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: false dev: false
...@@ -3356,11 +3353,11 @@ packages: ...@@ -3356,11 +3353,11 @@ packages:
tslib: 1.14.1 tslib: 1.14.1
dev: true dev: true
/@sentry/utils@7.77.0: /@sentry/utils@7.80.0:
resolution: {integrity: sha512-NmM2kDOqVchrey3N5WSzdQoCsyDkQkiRxExPaNI2oKQ/jMWHs9yt0tSy7otPBcXs0AP59ihl75Bvm1tDRcsp5g==} resolution: {integrity: sha512-XbBCEl6uLvE50ftKwrEo6XWdDaZXHXu+kkHXTPWQEcnbvfZKLuG9V0Hxtxxq3xQgyWmuF05OH1GcqYqiO+v5Yg==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
'@sentry/types': 7.77.0 '@sentry/types': 7.80.0
dev: false dev: false
/@sinclair/typebox@0.27.8: /@sinclair/typebox@0.27.8:
...@@ -3409,12 +3406,6 @@ packages: ...@@ -3409,12 +3406,6 @@ packages:
- supports-color - supports-color
- utf-8-validate - utf-8-validate
/@solidity-parser/parser@0.13.2:
resolution: {integrity: sha512-RwHnpRnfrnD2MSPveYoPh8nhofEvX7fgjHk1Oq+NNvCcLx4r1js91CO9o+F/F3fBzOCyvm8kKRTriFICX/odWw==}
dependencies:
antlr4ts: 0.5.0-alpha.4
dev: true
/@stablelib/aead@1.0.1: /@stablelib/aead@1.0.1:
resolution: {integrity: sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==} resolution: {integrity: sha512-q39ik6sxGHewqtO0nP4BuSe3db5G1fEJE8ukvngS2gLkBXyy6E7pLubhbYgnkDFv6V8cWaxcE4Xn0t6LWcJkyg==}
...@@ -4201,8 +4192,8 @@ packages: ...@@ -4201,8 +4192,8 @@ packages:
'@types/node': 20.9.0 '@types/node': 20.9.0
dev: false dev: false
/@typescript-eslint/eslint-plugin@6.10.0(@typescript-eslint/parser@6.9.1)(eslint@8.53.0)(typescript@5.2.2): /@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==} resolution: {integrity: sha512-uXnpZDc4VRjY4iuypDBKzW1rz9T5YBBK0snMn8MaTSNd2kMlj50LnLBABELjJiOL5YHk7ZD8hbSpI9ubzqYI0w==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
'@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha
...@@ -4213,11 +4204,11 @@ packages: ...@@ -4213,11 +4204,11 @@ packages:
optional: true optional: true
dependencies: dependencies:
'@eslint-community/regexpp': 4.6.2 '@eslint-community/regexpp': 4.6.2
'@typescript-eslint/parser': 6.9.1(eslint@8.53.0)(typescript@5.2.2) '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/scope-manager': 6.10.0 '@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/type-utils': 6.10.0(eslint@8.53.0)(typescript@5.2.2) '@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
'@typescript-eslint/utils': 6.10.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.10.0 '@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.53.0 eslint: 8.53.0
graphemer: 1.4.0 graphemer: 1.4.0
...@@ -4230,8 +4221,8 @@ packages: ...@@ -4230,8 +4221,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/parser@6.9.1(eslint@8.53.0)(typescript@5.2.2): /@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-C7AK2wn43GSaCUZ9do6Ksgi2g3mwFkMO3Cis96kzmgudoVaKyt62yNzJOktP0HDLb/iO2O0n2lBOzJgr6Q/cyg==} resolution: {integrity: sha512-+whEdjk+d5do5nxfxx73oanLL9ghKO3EwM9kBCkUtWMRwWuPaFv9ScuqlYfQ6pAD6ZiJhky7TZ2ZYhrMsfMxVQ==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
...@@ -4240,10 +4231,10 @@ packages: ...@@ -4240,10 +4231,10 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/scope-manager': 6.9.1 '@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.9.1 '@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.9.1(typescript@5.2.2) '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/visitor-keys': 6.9.1 '@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.53.0 eslint: 8.53.0
typescript: 5.2.2 typescript: 5.2.2
...@@ -4251,24 +4242,16 @@ packages: ...@@ -4251,24 +4242,16 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/scope-manager@6.10.0: /@typescript-eslint/scope-manager@6.11.0:
resolution: {integrity: sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==} resolution: {integrity: sha512-0A8KoVvIURG4uhxAdjSaxy8RdRE//HztaZdG8KiHLP8WOXSk0vlF7Pvogv+vlJA5Rnjj/wDcFENvDaHb+gKd1A==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/visitor-keys': 6.10.0
dev: true
/@typescript-eslint/scope-manager@6.9.1:
resolution: {integrity: sha512-38IxvKB6NAne3g/+MyXMs2Cda/Sz+CEpmm+KLGEM8hx/CvnSRuw51i8ukfwB/B/sESdeTGet1NH1Wj7I0YXswg==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
dependencies: dependencies:
'@typescript-eslint/types': 6.9.1 '@typescript-eslint/types': 6.11.0
'@typescript-eslint/visitor-keys': 6.9.1 '@typescript-eslint/visitor-keys': 6.11.0
dev: true dev: true
/@typescript-eslint/type-utils@6.10.0(eslint@8.53.0)(typescript@5.2.2): /@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==} resolution: {integrity: sha512-nA4IOXwZtqBjIoYrJcYxLRO+F9ri+leVGoJcMW1uqr4r1Hq7vW5cyWrA43lFbpRvQ9XgNrnfLpIkO3i1emDBIA==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
...@@ -4277,8 +4260,8 @@ packages: ...@@ -4277,8 +4260,8 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 6.10.0(typescript@5.2.2) '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
'@typescript-eslint/utils': 6.10.0(eslint@8.53.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) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.53.0 eslint: 8.53.0
ts-api-utils: 1.0.1(typescript@5.2.2) ts-api-utils: 1.0.1(typescript@5.2.2)
...@@ -4287,39 +4270,13 @@ packages: ...@@ -4287,39 +4270,13 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/types@6.10.0: /@typescript-eslint/types@6.11.0:
resolution: {integrity: sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==} resolution: {integrity: sha512-ZbEzuD4DwEJxwPqhv3QULlRj8KYTAnNsXxmfuUXFCxZmO6CF2gM/y+ugBSAQhrqaJL3M+oe4owdWunaHM6beqA==}
engines: {node: ^16.0.0 || >=18.0.0}
dev: true
/@typescript-eslint/types@6.9.1:
resolution: {integrity: sha512-BUGslGOb14zUHOUmDB2FfT6SI1CcZEJYfF3qFwBeUrU6srJfzANonwRYHDpLBuzbq3HaoF2XL2hcr01c8f8OaQ==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
dev: true dev: true
/@typescript-eslint/typescript-estree@6.10.0(typescript@5.2.2): /@typescript-eslint/typescript-estree@6.11.0(typescript@5.2.2):
resolution: {integrity: sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==} resolution: {integrity: sha512-Aezzv1o2tWJwvZhedzvD5Yv7+Lpu1by/U1LZ5gLc4tCx8jUmuSCMioPFRjliN/6SJIvY6HpTtJIWubKuYYYesQ==}
engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 6.10.0
'@typescript-eslint/visitor-keys': 6.10.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
dev: true
/@typescript-eslint/typescript-estree@6.9.1(typescript@5.2.2):
resolution: {integrity: sha512-U+mUylTHfcqeO7mLWVQ5W/tMLXqVpRv61wm9ZtfE5egz7gtnmqVIw9ryh0mgIlkKk9rZLY3UHygsBSdB9/ftyw==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
typescript: '*' typescript: '*'
...@@ -4327,8 +4284,8 @@ packages: ...@@ -4327,8 +4284,8 @@ packages:
typescript: typescript:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/types': 6.9.1 '@typescript-eslint/types': 6.11.0
'@typescript-eslint/visitor-keys': 6.9.1 '@typescript-eslint/visitor-keys': 6.11.0
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
globby: 11.1.0 globby: 11.1.0
is-glob: 4.0.3 is-glob: 4.0.3
...@@ -4339,8 +4296,8 @@ packages: ...@@ -4339,8 +4296,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/@typescript-eslint/utils@6.10.0(eslint@8.53.0)(typescript@5.2.2): /@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.2.2):
resolution: {integrity: sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==} resolution: {integrity: sha512-p23ibf68fxoZy605dc0dQAEoUsoiNoP3MD9WQGiHLDuTSOuqoTsa4oAy+h3KDkTcxbbfOtUjb9h3Ta0gT4ug2g==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
peerDependencies: peerDependencies:
eslint: ^7.0.0 || ^8.0.0 eslint: ^7.0.0 || ^8.0.0
...@@ -4348,9 +4305,9 @@ packages: ...@@ -4348,9 +4305,9 @@ packages:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0)
'@types/json-schema': 7.0.12 '@types/json-schema': 7.0.12
'@types/semver': 7.5.0 '@types/semver': 7.5.0
'@typescript-eslint/scope-manager': 6.10.0 '@typescript-eslint/scope-manager': 6.11.0
'@typescript-eslint/types': 6.10.0 '@typescript-eslint/types': 6.11.0
'@typescript-eslint/typescript-estree': 6.10.0(typescript@5.2.2) '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.2.2)
eslint: 8.53.0 eslint: 8.53.0
semver: 7.5.4 semver: 7.5.4
transitivePeerDependencies: transitivePeerDependencies:
...@@ -4358,19 +4315,11 @@ packages: ...@@ -4358,19 +4315,11 @@ packages:
- typescript - typescript
dev: true dev: true
/@typescript-eslint/visitor-keys@6.10.0: /@typescript-eslint/visitor-keys@6.11.0:
resolution: {integrity: sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==} resolution: {integrity: sha512-+SUN/W7WjBr05uRxPggJPSzyB8zUpaYo2hByKasWbqr3PM8AXfZt8UHdNpBS1v9SA62qnSSMF3380SwDqqprgQ==}
engines: {node: ^16.0.0 || >=18.0.0}
dependencies:
'@typescript-eslint/types': 6.10.0
eslint-visitor-keys: 3.4.3
dev: true
/@typescript-eslint/visitor-keys@6.9.1:
resolution: {integrity: sha512-MUaPUe/QRLEffARsmNfmpghuQkW436DvESW+h+M52w0coICHRfD6Np9/K6PdACwnrq1HmuLl+cSPZaJmeVPkSw==}
engines: {node: ^16.0.0 || >=18.0.0} engines: {node: ^16.0.0 || >=18.0.0}
dependencies: dependencies:
'@typescript-eslint/types': 6.9.1 '@typescript-eslint/types': 6.11.0
eslint-visitor-keys: 3.4.3 eslint-visitor-keys: 3.4.3
dev: true dev: true
...@@ -5560,10 +5509,6 @@ packages: ...@@ -5560,10 +5509,6 @@ packages:
resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==}
dev: false dev: false
/antlr4ts@0.5.0-alpha.4:
resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==}
dev: true
/any-promise@1.3.0: /any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
dev: true dev: true
...@@ -7517,7 +7462,7 @@ packages: ...@@ -7517,7 +7462,7 @@ packages:
eslint-plugin-promise: ^4.2.1 || ^5.0.0 eslint-plugin-promise: ^4.2.1 || ^5.0.0
dependencies: dependencies:
eslint: 8.53.0 eslint: 8.53.0
eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.1)(eslint@8.53.0) eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0)
eslint-plugin-node: 11.1.0(eslint@8.53.0) eslint-plugin-node: 11.1.0(eslint@8.53.0)
eslint-plugin-promise: 5.2.0(eslint@8.53.0) eslint-plugin-promise: 5.2.0(eslint@8.53.0)
dev: true dev: true
...@@ -7532,7 +7477,7 @@ packages: ...@@ -7532,7 +7477,7 @@ packages:
- supports-color - supports-color
dev: true dev: true
/eslint-module-utils@2.8.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-node@0.3.9)(eslint@8.53.0): /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint@8.53.0):
resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
...@@ -7553,7 +7498,7 @@ packages: ...@@ -7553,7 +7498,7 @@ packages:
eslint-import-resolver-webpack: eslint-import-resolver-webpack:
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 6.9.1(eslint@8.53.0)(typescript@5.2.2) '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
debug: 3.2.7 debug: 3.2.7
eslint: 8.53.0 eslint: 8.53.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
...@@ -7572,7 +7517,7 @@ packages: ...@@ -7572,7 +7517,7 @@ packages:
regexpp: 3.2.0 regexpp: 3.2.0
dev: true dev: true
/eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.1)(eslint@8.53.0): /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.11.0)(eslint@8.53.0):
resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==} resolution: {integrity: sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==}
engines: {node: '>=4'} engines: {node: '>=4'}
peerDependencies: peerDependencies:
...@@ -7582,7 +7527,7 @@ packages: ...@@ -7582,7 +7527,7 @@ packages:
'@typescript-eslint/parser': '@typescript-eslint/parser':
optional: true optional: true
dependencies: dependencies:
'@typescript-eslint/parser': 6.9.1(eslint@8.53.0)(typescript@5.2.2) '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.2.2)
array-includes: 3.1.7 array-includes: 3.1.7
array.prototype.findlastindex: 1.2.3 array.prototype.findlastindex: 1.2.3
array.prototype.flat: 1.3.2 array.prototype.flat: 1.3.2
...@@ -7591,7 +7536,7 @@ packages: ...@@ -7591,7 +7536,7 @@ packages:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.53.0 eslint: 8.53.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-node@0.3.9)(eslint@8.53.0) eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.11.0)(eslint-import-resolver-node@0.3.9)(eslint@8.53.0)
hasown: 2.0.0 hasown: 2.0.0
is-core-module: 2.13.1 is-core-module: 2.13.1
is-glob: 4.0.3 is-glob: 4.0.3
...@@ -11968,7 +11913,7 @@ packages: ...@@ -11968,7 +11913,7 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
dependencies: dependencies:
'@sentry/node': 7.77.0 '@sentry/node': 7.80.0
commander: 2.20.3 commander: 2.20.3
pumpify: 2.0.1 pumpify: 2.0.1
split2: 3.2.2 split2: 3.2.2
...@@ -12099,21 +12044,6 @@ packages: ...@@ -12099,21 +12044,6 @@ packages:
fast-diff: 1.2.0 fast-diff: 1.2.0
dev: true dev: true
/prettier-plugin-solidity@1.0.0-beta.18(prettier@2.8.8):
resolution: {integrity: sha512-ezWdsG/jIeClmYBzg8V9Voy8jujt+VxWF8OS3Vld+C3c+3cPVib8D9l8ahTod7O5Df1anK9zo+WiiS5wb1mLmg==}
engines: {node: '>=12'}
peerDependencies:
prettier: ^2.3.0
dependencies:
'@solidity-parser/parser': 0.13.2
emoji-regex: 9.2.2
escape-string-regexp: 4.0.0
prettier: 2.8.8
semver: 7.5.4
solidity-comments-extractor: 0.0.7
string-width: 4.2.3
dev: true
/prettier@2.8.8: /prettier@2.8.8:
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
engines: {node: '>=10.13.0'} engines: {node: '>=10.13.0'}
...@@ -13094,10 +13024,6 @@ packages: ...@@ -13094,10 +13024,6 @@ packages:
- debug - debug
dev: true dev: true
/solidity-comments-extractor@0.0.7:
resolution: {integrity: sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==}
dev: true
/sonic-boom@2.8.0: /sonic-boom@2.8.0:
resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==} resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==}
dependencies: dependencies:
...@@ -13882,8 +13808,9 @@ packages: ...@@ -13882,8 +13808,9 @@ packages:
- ts-node - ts-node
dev: true dev: true
/tsx@3.14.0: /tsx@4.1.1:
resolution: {integrity: sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==} resolution: {integrity: sha512-zyPn5BFMB0TB5kMLbYPNx4x/oL/oSlaecdKCv6WeJ0TeSEfx8RTJWjuB5TZ2dSewktgfBsBO/HNA9mrMWqLXMA==}
engines: {node: '>=18.0.0'}
hasBin: true hasBin: true
dependencies: dependencies:
esbuild: 0.18.20 esbuild: 0.18.20
......
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