Skip to content

Commit

Permalink
feat: interop invariant checks
Browse files Browse the repository at this point in the history
  • Loading branch information
tremarkley committed Aug 2, 2024
1 parent 5065c26 commit d518988
Show file tree
Hide file tree
Showing 12 changed files with 624 additions and 13 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ Supersim allows developers to start multiple local evm nodes with one command, a
Supersim is a lightweight tool that simulates an interoperable Superchain environment locally. It does not require a complicated devnet setup and is run using cli commands with configuration options that fall back to sensible defaults if they are not specified. Each chain is an instance of [anvil](https://book.getfoundry.sh/reference/anvil/), though future versions may support other local testing tools.

## Getting started
### Installation
TODO
### Running Locally
1. build the binary by running:
```
go build cmd/main.go
```
2. start supersim in vanilla mode by running:
```
./main
```

## Features
### Vanilla mode
Expand Down
18 changes: 18 additions & 0 deletions anvil/anvil.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
"io"
"math/big"
"os"
"os/exec"
"strconv"
Expand Down Expand Up @@ -283,7 +284,24 @@ func (a *Anvil) EthSendTransaction(ctx context.Context, tx *types.Transaction) e
return a.ethClient.SendTransaction(ctx, tx)
}

func (a *Anvil) EthBlockByNumber(ctx context.Context, blockHeight *big.Int) (*types.Block, error) {
return a.ethClient.BlockByNumber(ctx, blockHeight)
}

// subscription API
func (a *Anvil) SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error) {
return a.ethClient.SubscribeFilterLogs(ctx, q, ch)
}

func (a *Anvil) DebugTraceCall(ctx context.Context, txArgs config.TransactionArgs) (config.TraceCallRaw, error) {
var result config.TraceCallRaw
if err := a.rpcClient.CallContext(ctx, &result, "debug_traceCall", txArgs, "latest", map[string]interface{}{
"tracer": "callTracer",
"tracerConfig": map[string]interface{}{
"withLog": true,
},
}); err != nil {
return config.TraceCallRaw{}, err
}
return result, nil
}
34 changes: 34 additions & 0 deletions config/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
import (
"context"
"fmt"
"math/big"
"strings"

registry "github.com/ethereum-optimism/superchain-registry/superchain"
Expand All @@ -12,6 +13,7 @@ import (
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
Expand Down Expand Up @@ -96,6 +98,35 @@ type NetworkConfig struct {
L2Configs []ChainConfig
}

type TransactionArgs struct {
From common.Address `json:"from"`
To *common.Address `json:"to"`
Gas hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
Data hexutil.Bytes `json:"data"`
Value *hexutil.Big `json:"value"`
}

type TraceCallRaw struct {
Error *string `json:"error,omitempty"`
Type string `json:"type"`
From string `json:"from"`
To string `json:"to"`
Value string `json:"value"`
Gas string `json:"gas"`
GasUsed string `json:"gasUsed"`
Input string `json:"input"`
Output string `json:"output"`
Logs []*TraceCallRawLog `json:"logs"`
Calls []TraceCallRaw `json:"calls"`
}

type TraceCallRawLog struct {
Address common.Address `json:"address"`
Topics []common.Hash `json:"topics"`
Data string `json:"data"`
}

type Chain interface {
Name() string
Endpoint() string
Expand All @@ -109,7 +140,10 @@ type Chain interface {
EthGetCode(ctx context.Context, account common.Address) ([]byte, error)
EthGetLogs(ctx context.Context, q ethereum.FilterQuery) ([]types.Log, error)
EthSendTransaction(ctx context.Context, tx *types.Transaction) error
EthBlockByNumber(ctx context.Context, blockHeight *big.Int) (*types.Block, error)

SubscribeFilterLogs(ctx context.Context, q ethereum.FilterQuery, ch chan<- types.Log) (ethereum.Subscription, error)
DebugTraceCall(ctx context.Context, txArgs TransactionArgs) (TraceCallRaw, error)
}

// Note: The default secrets config is used everywhere
Expand Down
2 changes: 2 additions & 0 deletions contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ out/
# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/*/901/
/broadcast/*/902/
/broadcast/**/dry-run/

# Docs
Expand Down
170 changes: 170 additions & 0 deletions crossl2inbox/CrossL2Inbox.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
[
{
"inputs": [],
"name": "blockNumber",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "chainId",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"internalType": "address",
"name": "origin",
"type": "address"
},
{
"internalType": "uint256",
"name": "blockNumber",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "logIndex",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "timestamp",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "chainId",
"type": "uint256"
}
],
"internalType": "struct ICrossL2Inbox.Identifier",
"name": "_id",
"type": "tuple"
},
{
"internalType": "address",
"name": "_target",
"type": "address"
},
{
"internalType": "bytes",
"name": "_message",
"type": "bytes"
}
],
"name": "executeMessage",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "logIndex",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "origin",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "timestamp",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "version",
"outputs": [
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "bytes",
"name": "encodedId",
"type": "bytes"
},
{
"indexed": false,
"internalType": "bytes",
"name": "message",
"type": "bytes"
}
],
"name": "ExecutingMessage",
"type": "event"
},
{
"inputs": [],
"name": "InvalidChainId",
"type": "error"
},
{
"inputs": [],
"name": "InvalidTimestamp",
"type": "error"
},
{
"inputs": [],
"name": "NotEntered",
"type": "error"
},
{
"inputs": [],
"name": "TargetCallFailed",
"type": "error"
}
]

Loading

0 comments on commit d518988

Please sign in to comment.