Commit 251a4f62 authored by Adrian Sutton's avatar Adrian Sutton

Merge branch 'develop' into aj/remove-more-bindings

parents c2eb3847 57413031
......@@ -433,7 +433,7 @@ jobs:
contracts-bedrock-slither:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: large
resource_class: xlarge
steps:
- checkout
- check-changed:
......@@ -446,6 +446,7 @@ jobs:
contracts-bedrock-validate-spaces:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: xlarge
steps:
- checkout
- attach_workspace: { at: "." }
......@@ -467,7 +468,7 @@ jobs:
op-bindings-build:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: large
resource_class: xlarge
steps:
- checkout
- run:
......@@ -876,7 +877,7 @@ jobs:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
- image: cimg/postgres:14.1
resource_class: large
resource_class: xlarge
steps:
- checkout
- check-changed:
......@@ -952,6 +953,7 @@ jobs:
devnet-allocs:
docker:
- image: us-docker.pkg.dev/oplabs-tools-artifacts/images/ci-builder:latest
resource_class: xlarge
steps:
- checkout
- restore_cache:
......
ee5d02c3ef5f55a06b069e4a70a820661a9130c8
d85718785859dc0b5a095d2302d1a20ec06ab77a
......@@ -23,10 +23,10 @@ require (
github.com/ipfs/go-datastore v0.6.0
github.com/ipfs/go-ds-leveldb v0.5.0
github.com/jackc/pgtype v1.14.0
github.com/jackc/pgx/v5 v5.4.3
github.com/libp2p/go-libp2p v0.31.0
github.com/jackc/pgx/v5 v5.5.0
github.com/libp2p/go-libp2p v0.32.0
github.com/libp2p/go-libp2p-mplex v0.9.0
github.com/libp2p/go-libp2p-pubsub v0.9.3
github.com/libp2p/go-libp2p-pubsub v0.10.0
github.com/libp2p/go-libp2p-testing v0.12.0
github.com/mattn/go-isatty v0.0.20
github.com/multiformats/go-base32 v0.1.0
......@@ -40,10 +40,10 @@ require (
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.25.7
golang.org/x/crypto v0.14.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/sync v0.4.0
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
golang.org/x/sync v0.5.0
golang.org/x/term v0.13.0
golang.org/x/time v0.3.0
golang.org/x/time v0.4.0
gorm.io/driver/postgres v1.5.4
gorm.io/gorm v1.25.5
)
......@@ -98,10 +98,9 @@ require (
github.com/gofrs/flock v0.8.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/pprof v0.0.0-20230817174616-7a8ec2ada47b // indirect
github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/graph-gophers/graphql-go v1.3.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
......@@ -118,6 +117,7 @@ require (
github.com/jackc/pgio v1.0.0 // indirect
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
github.com/jbenet/goprocess v0.1.4 // indirect
......@@ -125,7 +125,7 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/karalabe/usb v0.0.3-0.20230711191512-61db3e06439c // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/compress v1.17.2 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/koron/go-ssdp v0.0.4 // indirect
github.com/kr/pretty v0.3.1 // indirect
......@@ -145,7 +145,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/miekg/dns v1.1.55 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
......@@ -158,7 +158,7 @@ require (
github.com/multiformats/go-multibase v0.2.0 // indirect
github.com/multiformats/go-multicodec v0.9.0 // indirect
github.com/multiformats/go-multihash v0.2.3 // indirect
github.com/multiformats/go-multistream v0.4.1 // indirect
github.com/multiformats/go-multistream v0.5.0 // indirect
github.com/multiformats/go-varint v0.0.7 // indirect
github.com/naoina/go-stringutil v0.1.0 // indirect
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 // indirect
......@@ -172,9 +172,9 @@ require (
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.3.3 // indirect
github.com/quic-go/quic-go v0.38.1 // indirect
github.com/quic-go/webtransport-go v0.5.3 // indirect
github.com/quic-go/qtls-go1-20 v0.3.4 // indirect
github.com/quic-go/quic-go v0.39.3 // indirect
github.com/quic-go/webtransport-go v0.6.0 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
......@@ -192,15 +192,16 @@ require (
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/automaxprocs v1.5.2 // indirect
go.uber.org/dig v1.17.0 // indirect
go.uber.org/fx v1.20.0 // indirect
go.uber.org/dig v1.17.1 // indirect
go.uber.org/fx v1.20.1 // indirect
go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/mod v0.12.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/tools v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
package fault
import (
"context"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
)
// MinimalFaultDisputeGameCaller is a minimal interface around [bindings.FaultDisputeGameCaller].
// This needs to be updated if the [bindings.FaultDisputeGameCaller] interface changes.
type MinimalFaultDisputeGameCaller interface {
ClaimData(opts *bind.CallOpts, arg0 *big.Int) (struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}, error)
Status(opts *bind.CallOpts) (uint8, error)
ClaimDataLen(opts *bind.CallOpts) (*big.Int, error)
MAXGAMEDEPTH(opts *bind.CallOpts) (*big.Int, error)
ABSOLUTEPRESTATE(opts *bind.CallOpts) ([32]byte, error)
}
// loader pulls in fault dispute game claim data periodically and over subscriptions.
type loader struct {
caller MinimalFaultDisputeGameCaller
}
// NewLoader creates a new [loader].
func NewLoader(caller MinimalFaultDisputeGameCaller) *loader {
return &loader{
caller: caller,
}
}
// NewLoaderFromBindings creates a new [loader] from a [bindings.FaultDisputeGameCaller].
func NewLoaderFromBindings(fdgAddr common.Address, client bind.ContractCaller) (*loader, error) {
caller, err := bindings.NewFaultDisputeGameCaller(fdgAddr, client)
if err != nil {
return nil, err
}
return NewLoader(caller), nil
}
// GetGameStatus returns the current game status.
func (l *loader) GetGameStatus(ctx context.Context) (gameTypes.GameStatus, error) {
status, err := l.caller.Status(&bind.CallOpts{Context: ctx})
return gameTypes.GameStatus(status), err
}
// GetClaimCount returns the number of claims in the game.
func (l *loader) GetClaimCount(ctx context.Context) (uint64, error) {
count, err := l.caller.ClaimDataLen(&bind.CallOpts{Context: ctx})
if err != nil {
return 0, err
}
return count.Uint64(), nil
}
// FetchGameDepth fetches the game depth from the fault dispute game.
func (l *loader) FetchGameDepth(ctx context.Context) (uint64, error) {
callOpts := bind.CallOpts{
Context: ctx,
}
gameDepth, err := l.caller.MAXGAMEDEPTH(&callOpts)
if err != nil {
return 0, err
}
return gameDepth.Uint64(), nil
}
// fetchClaim fetches a single [Claim] with a hydrated parent.
func (l *loader) fetchClaim(ctx context.Context, arrIndex uint64) (types.Claim, error) {
callOpts := bind.CallOpts{
Context: ctx,
}
fetchedClaim, err := l.caller.ClaimData(&callOpts, new(big.Int).SetUint64(arrIndex))
if err != nil {
return types.Claim{}, err
}
claim := types.Claim{
ClaimData: types.ClaimData{
Value: fetchedClaim.Claim,
Position: types.NewPositionFromGIndex(fetchedClaim.Position),
},
Countered: fetchedClaim.Countered,
Clock: fetchedClaim.Clock.Uint64(),
ContractIndex: int(arrIndex),
ParentContractIndex: int(fetchedClaim.ParentIndex),
}
return claim, nil
}
// FetchClaims fetches all claims from the fault dispute game.
func (l *loader) FetchClaims(ctx context.Context) ([]types.Claim, error) {
// Get the current claim count.
claimCount, err := l.caller.ClaimDataLen(&bind.CallOpts{
Context: ctx,
})
if err != nil {
return nil, err
}
// Fetch each claim and build a list.
claimList := make([]types.Claim, claimCount.Uint64())
for i := uint64(0); i < claimCount.Uint64(); i++ {
claim, err := l.fetchClaim(ctx, i)
if err != nil {
return nil, err
}
claimList[i] = claim
}
return claimList, nil
}
// FetchAbsolutePrestateHash fetches the hashed absolute prestate from the fault dispute game.
func (l *loader) FetchAbsolutePrestateHash(ctx context.Context) (common.Hash, error) {
callOpts := bind.CallOpts{
Context: ctx,
}
absolutePrestate, err := l.caller.ABSOLUTEPRESTATE(&callOpts)
if err != nil {
return common.Hash{}, err
}
return absolutePrestate, nil
}
package fault
import (
"context"
"fmt"
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
)
var (
mockClaimDataError = fmt.Errorf("claim data errored")
mockClaimLenError = fmt.Errorf("claim len errored")
mockMaxGameDepthError = fmt.Errorf("max game depth errored")
mockPrestateError = fmt.Errorf("prestate errored")
mockStatusError = fmt.Errorf("status errored")
)
// TestLoader_GetGameStatus tests fetching the game status.
func TestLoader_GetGameStatus(t *testing.T) {
tests := []struct {
name string
status uint8
expectedError bool
}{
{
name: "challenger won status",
status: uint8(gameTypes.GameStatusChallengerWon),
},
{
name: "defender won status",
status: uint8(gameTypes.GameStatusDefenderWon),
},
{
name: "in progress status",
status: uint8(gameTypes.GameStatusInProgress),
},
{
name: "error bubbled up",
expectedError: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
mockCaller := newMockCaller()
mockCaller.status = test.status
mockCaller.statusError = test.expectedError
loader := NewLoader(mockCaller)
status, err := loader.GetGameStatus(context.Background())
if test.expectedError {
require.ErrorIs(t, err, mockStatusError)
} else {
require.NoError(t, err)
require.Equal(t, gameTypes.GameStatus(test.status), status)
}
})
}
}
// TestLoader_FetchGameDepth tests fetching the game depth.
func TestLoader_FetchGameDepth(t *testing.T) {
t.Run("Succeeds", func(t *testing.T) {
mockCaller := newMockCaller()
mockCaller.maxGameDepth = 10
loader := NewLoader(mockCaller)
depth, err := loader.FetchGameDepth(context.Background())
require.NoError(t, err)
require.Equal(t, uint64(10), depth)
})
t.Run("Errors", func(t *testing.T) {
mockCaller := newMockCaller()
mockCaller.maxGameDepthError = true
loader := NewLoader(mockCaller)
depth, err := loader.FetchGameDepth(context.Background())
require.ErrorIs(t, mockMaxGameDepthError, err)
require.Equal(t, depth, uint64(0))
})
}
// TestLoader_FetchAbsolutePrestateHash tests fetching the absolute prestate hash.
func TestLoader_FetchAbsolutePrestateHash(t *testing.T) {
t.Run("Succeeds", func(t *testing.T) {
mockCaller := newMockCaller()
loader := NewLoader(mockCaller)
prestate, err := loader.FetchAbsolutePrestateHash(context.Background())
require.NoError(t, err)
require.ElementsMatch(t, common.HexToHash("0xdEad"), prestate)
})
t.Run("Errors", func(t *testing.T) {
mockCaller := newMockCaller()
mockCaller.prestateError = true
loader := NewLoader(mockCaller)
prestate, err := loader.FetchAbsolutePrestateHash(context.Background())
require.Error(t, err)
require.ElementsMatch(t, common.Hash{}, prestate)
})
}
// TestLoader_FetchClaims tests fetching claims.
func TestLoader_FetchClaims(t *testing.T) {
t.Run("Succeeds", func(t *testing.T) {
mockCaller := newMockCaller()
expectedClaims := mockCaller.returnClaims
loader := NewLoader(mockCaller)
claims, err := loader.FetchClaims(context.Background())
require.NoError(t, err)
require.ElementsMatch(t, []types.Claim{
{
ClaimData: types.ClaimData{
Value: expectedClaims[0].Claim,
Position: types.NewPositionFromGIndex(expectedClaims[0].Position),
},
Countered: false,
Clock: uint64(0),
ContractIndex: 0,
},
{
ClaimData: types.ClaimData{
Value: expectedClaims[1].Claim,
Position: types.NewPositionFromGIndex(expectedClaims[1].Position),
},
Countered: false,
Clock: uint64(0),
ContractIndex: 1,
ParentContractIndex: 0,
},
{
ClaimData: types.ClaimData{
Value: expectedClaims[2].Claim,
Position: types.NewPositionFromGIndex(expectedClaims[2].Position),
},
Countered: false,
Clock: uint64(0),
ContractIndex: 2,
ParentContractIndex: 1,
},
}, claims)
})
t.Run("Claim Data Errors", func(t *testing.T) {
mockCaller := newMockCaller()
mockCaller.claimDataError = true
loader := NewLoader(mockCaller)
claims, err := loader.FetchClaims(context.Background())
require.ErrorIs(t, err, mockClaimDataError)
require.Empty(t, claims)
})
t.Run("Claim Len Errors", func(t *testing.T) {
mockCaller := newMockCaller()
mockCaller.claimLenError = true
loader := NewLoader(mockCaller)
claims, err := loader.FetchClaims(context.Background())
require.ErrorIs(t, err, mockClaimLenError)
require.Empty(t, claims)
})
}
type mockCaller struct {
claimDataError bool
claimLenError bool
maxGameDepthError bool
prestateError bool
statusError bool
maxGameDepth uint64
currentIndex uint64
status uint8
returnClaims []struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}
}
func newMockCaller() *mockCaller {
return &mockCaller{
returnClaims: []struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}{
{
Claim: [32]byte{0x00},
Position: big.NewInt(1),
Countered: false,
Clock: big.NewInt(0),
},
{
Claim: [32]byte{0x01},
Position: big.NewInt(2),
Countered: false,
Clock: big.NewInt(0),
ParentIndex: 0,
},
{
Claim: [32]byte{0x02},
Position: big.NewInt(3),
Countered: false,
Clock: big.NewInt(0),
ParentIndex: 1,
},
},
}
}
func (m *mockCaller) ClaimData(opts *bind.CallOpts, arg0 *big.Int) (struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}, error) {
if m.claimDataError {
return struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}{}, mockClaimDataError
}
returnClaim := m.returnClaims[arg0.Uint64()]
m.currentIndex++
return returnClaim, nil
}
func (m *mockCaller) Status(opts *bind.CallOpts) (uint8, error) {
if m.statusError {
return 0, mockStatusError
}
return m.status, nil
}
func (m *mockCaller) ClaimDataLen(opts *bind.CallOpts) (*big.Int, error) {
if m.claimLenError {
return big.NewInt(0), mockClaimLenError
}
return big.NewInt(int64(len(m.returnClaims))), nil
}
func (m *mockCaller) MAXGAMEDEPTH(opts *bind.CallOpts) (*big.Int, error) {
if m.maxGameDepthError {
return nil, mockMaxGameDepthError
}
return big.NewInt(int64(m.maxGameDepth)), nil
}
func (m *mockCaller) ABSOLUTEPRESTATE(opts *bind.CallOpts) ([32]byte, error) {
if m.prestateError {
return [32]byte{}, mockPrestateError
}
return common.HexToHash("0xdEad"), nil
}
......@@ -14,6 +14,7 @@ import (
var (
ErrIndexTooLarge = errors.New("index is larger than the maximum index")
absolutePrestate = common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060")
)
// AlphabetTraceProvider is a [TraceProvider] that provides claims for specific
......@@ -36,11 +37,7 @@ func NewTraceProvider(state string, depth uint64) *AlphabetTraceProvider {
func (ap *AlphabetTraceProvider) GetStepData(ctx context.Context, i types.Position) ([]byte, []byte, *types.PreimageOracleData, error) {
traceIndex := i.TraceIndex(int(ap.depth))
if traceIndex.Cmp(common.Big0) == 0 {
prestate, err := ap.AbsolutePreState(ctx)
if err != nil {
return nil, nil, nil, err
}
return prestate, []byte{}, nil, nil
return absolutePrestate, []byte{}, nil, nil
}
// We want the pre-state which is the value prior to the one requested
traceIndex = traceIndex.Sub(traceIndex, big.NewInt(1))
......@@ -67,17 +64,8 @@ func (ap *AlphabetTraceProvider) Get(ctx context.Context, i types.Position) (com
return alphabetStateHash(claimBytes), nil
}
// AbsolutePreState returns the absolute pre-state for the alphabet trace.
func (ap *AlphabetTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, error) {
return common.Hex2Bytes("0000000000000000000000000000000000000000000000000000000000000060"), nil
}
func (ap *AlphabetTraceProvider) AbsolutePreStateCommitment(ctx context.Context) (common.Hash, error) {
prestate, err := ap.AbsolutePreState(ctx)
if err != nil {
return common.Hash{}, err
}
hash := common.BytesToHash(crypto.Keccak256(prestate))
func (ap *AlphabetTraceProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) {
hash := common.BytesToHash(crypto.Keccak256(absolutePrestate))
hash[0] = mipsevm.VMStatusUnfinished
return hash, nil
}
......
......@@ -124,7 +124,7 @@ func (p *CannonTraceProvider) GetStepData(ctx context.Context, pos types.Positio
return value, data, oracleData, nil
}
func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, error) {
func (p *CannonTraceProvider) absolutePreState() ([]byte, error) {
state, err := parseState(p.prestate)
if err != nil {
return nil, fmt.Errorf("cannot load absolute pre-state: %w", err)
......@@ -132,8 +132,8 @@ func (p *CannonTraceProvider) AbsolutePreState(ctx context.Context) ([]byte, err
return state.EncodeWitness(), nil
}
func (p *CannonTraceProvider) AbsolutePreStateCommitment(ctx context.Context) (common.Hash, error) {
state, err := p.AbsolutePreState(ctx)
func (p *CannonTraceProvider) AbsolutePreStateCommitment(_ context.Context) (common.Hash, error) {
state, err := p.absolutePreState()
if err != nil {
return common.Hash{}, fmt.Errorf("cannot load absolute pre-state: %w", err)
}
......
......@@ -216,28 +216,28 @@ func TestGetStepData(t *testing.T) {
})
}
func TestAbsolutePreState(t *testing.T) {
func TestAbsolutePreStateCommitment(t *testing.T) {
dataDir := t.TempDir()
prestate := "state.json"
t.Run("StateUnavailable", func(t *testing.T) {
provider, _ := setupWithTestData(t, "/dir/does/not/exist", prestate)
_, err := provider.AbsolutePreState(context.Background())
_, err := provider.AbsolutePreStateCommitment(context.Background())
require.ErrorIs(t, err, os.ErrNotExist)
})
t.Run("InvalidStateFile", func(t *testing.T) {
setupPreState(t, dataDir, "invalid.json")
provider, _ := setupWithTestData(t, dataDir, prestate)
_, err := provider.AbsolutePreState(context.Background())
_, err := provider.AbsolutePreStateCommitment(context.Background())
require.ErrorContains(t, err, "invalid mipsevm state")
})
t.Run("ExpectedAbsolutePreState", func(t *testing.T) {
setupPreState(t, dataDir, "state.json")
provider, _ := setupWithTestData(t, dataDir, prestate)
preState, err := provider.AbsolutePreState(context.Background())
actual, err := provider.AbsolutePreStateCommitment(context.Background())
require.NoError(t, err)
state := mipsevm.State{
Memory: mipsevm.NewMemory(),
......@@ -253,7 +253,9 @@ func TestAbsolutePreState(t *testing.T) {
Step: 0,
Registers: [32]uint32{},
}
require.Equal(t, []byte(state.EncodeWitness()), preState)
expected, err := state.EncodeWitness().StateHash()
require.NoError(t, err)
require.Equal(t, expected, actual)
})
}
......
......@@ -56,11 +56,6 @@ func (s *SplitTraceProvider) AbsolutePreStateCommitment(ctx context.Context) (ha
return s.bottomProvider.AbsolutePreStateCommitment(ctx)
}
// AbsolutePreState routes the AbsolutePreState request to the lowest internal [types.TraceProvider].
func (s *SplitTraceProvider) AbsolutePreState(ctx context.Context) (preimage []byte, err error) {
return s.bottomProvider.AbsolutePreState(ctx)
}
// GetStepData routes the GetStepData request to the lowest internal [types.TraceProvider].
func (s *SplitTraceProvider) GetStepData(ctx context.Context, pos types.Position) (prestate []byte, proofData []byte, preimageData *types.PreimageOracleData, err error) {
ancestorDepth, provider := s.providerForDepth(uint64(pos.Depth()))
......
......@@ -64,24 +64,6 @@ func TestAbsolutePreStateCommitment(t *testing.T) {
})
}
func TestAbsolutePreState(t *testing.T) {
t.Run("ErrorBubblesUp", func(t *testing.T) {
mockOutputProvider := mockTraceProvider{absolutePreStateError: mockGetError}
splitProvider := newSplitTraceProvider(t, nil, &mockOutputProvider, 40)
_, err := splitProvider.AbsolutePreState(context.Background())
require.ErrorIs(t, err, mockGetError)
})
t.Run("ReturnsCorrectPreimageData", func(t *testing.T) {
expectedPreimage := []byte{1, 2, 3, 4}
mockOutputProvider := mockTraceProvider{preImageData: expectedPreimage}
splitProvider := newSplitTraceProvider(t, nil, &mockOutputProvider, 40)
output, err := splitProvider.AbsolutePreState(context.Background())
require.NoError(t, err)
require.Equal(t, expectedPreimage, output)
})
}
func TestGetStepData(t *testing.T) {
t.Run("ErrorBubblesUp", func(t *testing.T) {
mockOutputProvider := mockTraceProvider{getStepDataError: mockGetError}
......
......@@ -69,9 +69,6 @@ type TraceProvider interface {
// The prestate returned from GetStepData for trace 10 should be the pre-image of the claim from trace 9
GetStepData(ctx context.Context, i Position) (prestate []byte, proofData []byte, preimageData *PreimageOracleData, err error)
// AbsolutePreState is the pre-image value of the trace that transitions to the trace value at index 0
AbsolutePreState(ctx context.Context) (preimage []byte, err error)
// AbsolutePreStateCommitment is the commitment of the pre-image value of the trace that transitions to the trace value at index 0
AbsolutePreStateCommitment(ctx context.Context) (hash common.Hash, err error)
}
......
......@@ -8,7 +8,6 @@ import (
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/types"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
......@@ -356,25 +355,6 @@ func (g *FaultGameHelper) ResolveClaim(ctx context.Context, claimIdx int64) {
g.require.NoError(err, "ResolveClaim transaction was not OK")
}
// ResolveAllClaims resolves all subgames
// This function does not resolve the game. That's the responsibility of challengers
func (g *FaultGameHelper) ResolveAllClaims(ctx context.Context) {
loader := fault.NewLoader(g.game)
claims, err := loader.FetchClaims(ctx)
g.require.NoError(err, "Failed to fetch claims")
subgames := make(map[int]bool)
for i := len(claims) - 1; i > 0; i-- {
subgames[claims[i].ParentContractIndex] = true
// Subgames containing only one node are implicitly resolved
// i.e. uncountered and claims at MAX_DEPTH
if !subgames[i] {
continue
}
g.ResolveClaim(ctx, int64(i))
}
g.ResolveClaim(ctx, 0)
}
func (g *FaultGameHelper) gameData(ctx context.Context) string {
opts := &bind.CallOpts{Context: ctx}
maxDepth := int(g.MaxDepth(ctx))
......
......@@ -142,7 +142,7 @@ func (n *NodeP2P) init(resourcesCtx context.Context, rollupCfg *rollup.Config, l
if err != nil {
return fmt.Errorf("failed to join blocks gossip topic: %w", err)
}
log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().Pretty())
log.Info("started p2p host", "addrs", n.host.Addrs(), "peerID", n.host.ID().String())
tcpPort, err := FindActiveTCPPort(n.host)
if err != nil {
......
This diff is collapsed.
......@@ -59,4 +59,3 @@ runs = 512
[profile.lite]
optimizer = false
# `CrossDomainMessenger` Invariants
## A call to `relayMessage` should succeed if at least the minimum gas limit can be supplied to the target context, there is enough gas to complete execution of `relayMessage` after the target context's execution is finished, and the target context did not revert.
**Test:** [`CrossDomainMessenger.t.sol#L136`](../test/invariants/CrossDomainMessenger.t.sol#L136)
**Test:** [`CrossDomainMessenger.t.sol#L137`](../test/invariants/CrossDomainMessenger.t.sol#L137)
There are two minimum gas limits here:
- The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit.
- The inner min gas limit is for the call from the `L1CrossDomainMessenger` to the target contract.
## A call to `relayMessage` should assign the message hash to the `failedMessages` mapping if not enough gas is supplied to forward `minGasLimit` to the target context or if there is not enough gas to complete execution of `relayMessage` after the target context's execution is finished.
**Test:** [`CrossDomainMessenger.t.sol#L169`](../test/invariants/CrossDomainMessenger.t.sol#L169)
**Test:** [`CrossDomainMessenger.t.sol#L170`](../test/invariants/CrossDomainMessenger.t.sol#L170)
There are two minimum gas limits here:
- The outer min gas limit is for the call from the `OptimismPortal` to the `L1CrossDomainMessenger`, and it can be retrieved by calling the xdm's `baseGas` function with the `message` and inner limit.
......
# `OptimismPortal` Invariants
## Deposits of any value should always succeed unless `_to` = `address(0)` or `_isCreation` = `true`.
**Test:** [`OptimismPortal.t.sol#L148`](../test/invariants/OptimismPortal.t.sol#L148)
**Test:** [`OptimismPortal.t.sol#L151`](../test/invariants/OptimismPortal.t.sol#L151)
All deposits, barring creation transactions and transactions sent to `address(0)`, should always succeed.
## `finalizeWithdrawalTransaction` should revert if the finalization period has not elapsed.
**Test:** [`OptimismPortal.t.sol#L171`](../test/invariants/OptimismPortal.t.sol#L171)
**Test:** [`OptimismPortal.t.sol#L174`](../test/invariants/OptimismPortal.t.sol#L174)
A withdrawal that has been proven should not be able to be finalized until after the finalization period has elapsed.
## `finalizeWithdrawalTransaction` should revert if the withdrawal has already been finalized.
**Test:** [`OptimismPortal.t.sol#L201`](../test/invariants/OptimismPortal.t.sol#L201)
**Test:** [`OptimismPortal.t.sol#L204`](../test/invariants/OptimismPortal.t.sol#L204)
Ensures that there is no chain of calls that can be made that allows a withdrawal to be finalized twice.
## A withdrawal should **always** be able to be finalized `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
**Test:** [`OptimismPortal.t.sol#L230`](../test/invariants/OptimismPortal.t.sol#L230)
**Test:** [`OptimismPortal.t.sol#L233`](../test/invariants/OptimismPortal.t.sol#L233)
This invariant asserts that there is no chain of calls that can be made that will prevent a withdrawal from being finalized exactly `FINALIZATION_PERIOD_SECONDS` after it was successfully proven.
\ No newline at end of file
This diff is collapsed.
......@@ -3,28 +3,28 @@ pragma solidity 0.8.15;
// Testing utilities
import { Test } from "forge-std/Test.sol";
import { Messenger_Initializer, Test } from "test/CommonTest.t.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
import { Reverter, CallerCaller } from "test/mocks/Callers.sol";
import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
import { CallerCaller, Reverter } from "test/mocks/Callers.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Hashing } from "src/libraries/Hashing.sol";
import { Encoding } from "src/libraries/Encoding.sol";
import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
// CrossDomainMessenger_Test is for testing functionality which is common to both the L1 and L2
// CrossDomainMessenger contracts. For simplicity, we use the L1 Messenger as the test contract.
contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
contract CrossDomainMessenger_BaseGas_Test is Bridge_Initializer {
/// @dev Ensure that baseGas passes for the max value of _minGasLimit,
/// this is about 4 Billion.
function test_baseGas_succeeds() external view {
L1Messenger.baseGas(hex"ff", type(uint32).max);
l1CrossDomainMessenger.baseGas(hex"ff", type(uint32).max);
}
/// @dev Fuzz for other values which might cause a revert in baseGas.
function testFuzz_baseGas_succeeds(uint32 _minGasLimit) external view {
L1Messenger.baseGas(hex"ff", _minGasLimit);
l1CrossDomainMessenger.baseGas(hex"ff", _minGasLimit);
}
/// @notice The baseGas function should always return a value greater than
......@@ -33,8 +33,8 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
/// gas to the OptimismPortal.
function testFuzz_baseGas_portalMinGasLimit_succeeds(bytes memory _data, uint32 _minGasLimit) external {
vm.assume(_data.length <= type(uint64).max);
uint64 baseGas = L1Messenger.baseGas(_data, _minGasLimit);
uint64 minGasLimit = op.minimumGasLimit(uint64(_data.length));
uint64 baseGas = l1CrossDomainMessenger.baseGas(_data, _minGasLimit);
uint64 minGasLimit = optimismPortal.minimumGasLimit(uint64(_data.length));
assertTrue(baseGas >= minGasLimit);
}
}
......@@ -45,18 +45,18 @@ contract CrossDomainMessenger_BaseGas_Test is Messenger_Initializer {
contract ExternalRelay is Test {
address internal op;
address internal fuzzedSender;
L1CrossDomainMessenger internal L1Messenger;
L1CrossDomainMessenger internal l1CrossDomainMessenger;
event FailedRelayedMessage(bytes32 indexed msgHash);
constructor(L1CrossDomainMessenger _l1Messenger, address _op) {
L1Messenger = _l1Messenger;
l1CrossDomainMessenger = _l1Messenger;
op = _op;
}
/// @notice Internal helper function to relay a message and perform assertions.
function _internalRelay(address _innerSender) internal {
address initialSender = L1Messenger.xDomainMessageSender();
address initialSender = l1CrossDomainMessenger.xDomainMessageSender();
bytes memory callMessage = getCallData();
......@@ -73,7 +73,7 @@ contract ExternalRelay is Test {
emit FailedRelayedMessage(hash);
vm.prank(address(op));
L1Messenger.relayMessage({
l1CrossDomainMessenger.relayMessage({
_nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),
_sender: _innerSender,
_target: address(this),
......@@ -82,9 +82,9 @@ contract ExternalRelay is Test {
_message: callMessage
});
assertTrue(L1Messenger.failedMessages(hash));
assertFalse(L1Messenger.successfulMessages(hash));
assertEq(initialSender, L1Messenger.xDomainMessageSender());
assertTrue(l1CrossDomainMessenger.failedMessages(hash));
assertFalse(l1CrossDomainMessenger.successfulMessages(hash));
assertEq(initialSender, l1CrossDomainMessenger.xDomainMessageSender());
}
/// @notice externalCallWithMinGas is called by the CrossDomainMessenger.
......@@ -111,7 +111,7 @@ contract ExternalRelay is Test {
/// @title CrossDomainMessenger_RelayMessage_Test
/// @notice Fuzz tests re-entrancy into the CrossDomainMessenger relayMessage function.
contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
contract CrossDomainMessenger_RelayMessage_Test is Bridge_Initializer {
// Storage slot of the l2Sender
uint256 constant senderSlotIndex = 50;
......@@ -119,7 +119,7 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
function setUp() public override {
super.setUp();
er = new ExternalRelay(L1Messenger, address(op));
er = new ExternalRelay(l1CrossDomainMessenger, address(optimismPortal));
}
/// @dev This test mocks an OptimismPortal call to the L1CrossDomainMessenger via
......@@ -151,9 +151,9 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
});
// set the value of op.l2Sender() to be the L2 Cross Domain Messenger.
vm.store(address(op), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(op));
L1Messenger.relayMessage({
vm.store(address(optimismPortal), bytes32(senderSlotIndex), bytes32(abi.encode(sender)));
vm.prank(address(optimismPortal));
l1CrossDomainMessenger.relayMessage({
_nonce: Encoding.encodeVersionedNonce({ _nonce: 0, _version: 1 }),
_sender: sender,
_target: target,
......@@ -162,11 +162,11 @@ contract CrossDomainMessenger_RelayMessage_Test is Messenger_Initializer {
_message: callMessage
});
assertTrue(L1Messenger.successfulMessages(hash));
assertEq(L1Messenger.failedMessages(hash), false);
assertTrue(l1CrossDomainMessenger.successfulMessages(hash));
assertEq(l1CrossDomainMessenger.failedMessages(hash), false);
// Ensures that the `xDomainMsgSender` is set back to `Predeploys.L2_CROSS_DOMAIN_MESSENGER`
vm.expectRevert("CrossDomainMessenger: xDomainMessageSender is not set");
L1Messenger.xDomainMessageSender();
l1CrossDomainMessenger.xDomainMessageSender();
}
}
......@@ -4,7 +4,7 @@ pragma solidity 0.8.15;
// Testing utilities
import { VmSafe } from "forge-std/Vm.sol";
import { Test } from "forge-std/Test.sol";
import { Portal_Initializer } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
// Libraries
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
......@@ -46,7 +46,7 @@ contract CrossDomainOwnable_Test is Test {
}
}
contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {
contract CrossDomainOwnableThroughPortal_Test is CommonTest {
XDomainSetter setter;
/// @dev Sets up the test suite.
......@@ -63,7 +63,7 @@ contract CrossDomainOwnableThroughPortal_Test is Portal_Initializer {
vm.recordLogs();
vm.prank(alice);
op.depositTransaction({
optimismPortal.depositTransaction({
_to: address(setter),
_value: 0,
_gasLimit: 30_000,
......
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest, Messenger_Initializer } from "test/CommonTest.t.sol";
import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
// Libraries
import { Hashing } from "src/libraries/Hashing.sol";
......@@ -10,10 +10,10 @@ import { Encoding } from "src/libraries/Encoding.sol";
import { Bytes32AddressLib } from "@rari-capital/solmate/src/utils/Bytes32AddressLib.sol";
// Target contract dependencies
import { AddressAliasHelper } from "../src/vendor/AddressAliasHelper.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
// Target contract
import { CrossDomainOwnable2 } from "../src/L2/CrossDomainOwnable2.sol";
import { CrossDomainOwnable2 } from "src/L2/CrossDomainOwnable2.sol";
contract XDomainSetter2 is CrossDomainOwnable2 {
uint256 public value;
......@@ -23,7 +23,7 @@ contract XDomainSetter2 is CrossDomainOwnable2 {
}
}
contract CrossDomainOwnable2_Test is Messenger_Initializer {
contract CrossDomainOwnable2_Test is Bridge_Initializer {
XDomainSetter2 setter;
/// @dev Sets up the test suite.
......@@ -44,9 +44,9 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
// set the xDomainMsgSender storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(address(alice));
vm.store(address(L2Messenger), key, value);
vm.store(address(l2CrossDomainMessenger), key, value);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("CrossDomainOwnable2: caller is not the owner");
setter.set(1);
}
......@@ -69,8 +69,10 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
vm.expectEmit(true, true, true, true);
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
);
assertEq(setter.value(), 0);
}
......@@ -81,8 +83,8 @@ contract CrossDomainOwnable2_Test is Messenger_Initializer {
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
owner,
address(setter),
......
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest, Messenger_Initializer } from "test/CommonTest.t.sol";
import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
// Libraries
import { Hashing } from "src/libraries/Hashing.sol";
......@@ -23,7 +23,7 @@ contract XDomainSetter3 is CrossDomainOwnable3 {
}
}
contract CrossDomainOwnable3_Test is Messenger_Initializer {
contract CrossDomainOwnable3_Test is Bridge_Initializer {
XDomainSetter3 setter;
/// @dev CrossDomainOwnable3.sol transferOwnership event
......@@ -73,9 +73,9 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// set the xDomainMsgSender storage slot
bytes32 key = bytes32(uint256(204));
bytes32 value = Bytes32AddressLib.fillLast12Bytes(bob);
vm.store(address(L2Messenger), key, value);
vm.store(address(l2CrossDomainMessenger), key, value);
vm.prank(address(L2Messenger));
vm.prank(address(l2CrossDomainMessenger));
vm.expectRevert("CrossDomainOwnable3: caller is not the owner");
setter.set(1);
}
......@@ -109,11 +109,13 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// It should be a failed message. The revert is caught,
// so we cannot expectRevert here.
vm.expectEmit(true, true, true, true, address(L2Messenger));
vm.expectEmit(true, true, true, true, address(l2CrossDomainMessenger));
emit FailedRelayedMessage(hash);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message);
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(nonce, 1), sender, target, value, minGasLimit, message
);
assertEq(setter.value(), 0);
}
......@@ -212,8 +214,8 @@ contract CrossDomainOwnable3_Test is Messenger_Initializer {
// Simulate the L2 execution where the call is coming from
// the L1CrossDomainMessenger
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(L1Messenger)));
L2Messenger.relayMessage(
vm.prank(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)));
l2CrossDomainMessenger.relayMessage(
Encoding.encodeVersionedNonce(1, 1),
bob,
address(setter),
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { CommonTest } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
import { DelayedVetoable } from "src/L1/DelayedVetoable.sol";
contract DelayedVetoable_Init is CommonTest {
......@@ -146,7 +146,7 @@ contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init {
/// @dev Only the initiator can initiate a call.
function test_handleCall_unauthorizedInitiation_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(bool success,) = address(delayedVetoable).call(NON_ZERO_DATA);
(bool success,) = address(delayedVetoable).call(hex"00001234");
assertTrue(success);
}
......
......@@ -8,9 +8,9 @@ import { Test } from "forge-std/Test.sol";
import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { Proxy } from "src/universal/Proxy.sol";
import { L2OutputOracle_Initializer } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
contract DisputeGameFactory_Init is L2OutputOracle_Initializer {
contract DisputeGameFactory_Init is CommonTest {
DisputeGameFactory factory;
FakeClone fakeClone;
......
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
// Libraries
import { Types } from "src/libraries/Types.sol";
......
......@@ -37,9 +37,9 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
vm.warp(1690906994);
// Propose 2 mock outputs
vm.startPrank(oracle.PROPOSER());
vm.startPrank(l2OutputOracle.PROPOSER());
for (uint256 i; i < 2; i++) {
oracle.proposeL2Output(bytes32(i + 1), oracle.nextBlockNumber(), blockhash(i), i);
l2OutputOracle.proposeL2Output(bytes32(i + 1), l2OutputOracle.nextBlockNumber(), blockhash(i), i);
// Advance 1 block
vm.roll(block.number + 1);
......@@ -52,7 +52,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
blockOracle.checkpoint();
// Set the extra data for the game creation
extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
// Deploy an implementation of the fault game
gameImpl = new FaultDisputeGame(
......@@ -61,7 +61,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
4,
Duration.wrap(7 days),
new AlphabetVM(absolutePrestate),
oracle,
l2OutputOracle,
blockOracle
);
// Register the game implementation with the factory.
......@@ -127,7 +127,7 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
function test_initialize_l1HeadTooOld_reverts() public {
// Store a mock block hash for the genesis block. The timestamp will default to 0.
vm.store(address(gameImpl.BLOCK_ORACLE()), keccak256(abi.encode(0, 0)), bytes32(uint256(1)));
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, 0);
bytes memory _extraData = abi.encode(l2OutputOracle.SUBMISSION_INTERVAL() * 2, 0);
vm.expectRevert(L1HeadTooOld.selector);
factory.create(GAME_TYPE, ROOT_CLAIM, _extraData);
......@@ -139,8 +139,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// For now, it is critical that the first proposed output root of an OP stack
/// chain is done so by an honest party.
function test_initialize_firstOutput_reverts() public {
uint256 submissionInterval = l2OutputOracle.submissionInterval();
vm.expectRevert(abi.encodeWithSignature("Panic(uint256)", 0x11));
factory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(1800, block.number - 1));
factory.create(GAME_TYPE, ROOT_CLAIM, abi.encode(submissionInterval, block.number - 1));
}
/// @dev Tests that the `create` function reverts when the rootClaim does not disagree with the outcome.
......@@ -159,12 +160,12 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
// Starting
(FaultDisputeGame.OutputProposal memory startingProp, FaultDisputeGame.OutputProposal memory disputedProp) =
gameProxy.proposals();
Types.OutputProposal memory starting = oracle.getL2Output(startingProp.index);
Types.OutputProposal memory starting = l2OutputOracle.getL2Output(startingProp.index);
assertEq(startingProp.index, 0);
assertEq(startingProp.l2BlockNumber, starting.l2BlockNumber);
assertEq(Hash.unwrap(startingProp.outputRoot), starting.outputRoot);
// Disputed
Types.OutputProposal memory disputed = oracle.getL2Output(disputedProp.index);
Types.OutputProposal memory disputed = l2OutputOracle.getL2Output(disputedProp.index);
assertEq(disputedProp.index, 1);
assertEq(disputedProp.l2BlockNumber, disputed.l2BlockNumber);
assertEq(Hash.unwrap(disputedProp.outputRoot), disputed.outputRoot);
......
......@@ -2,49 +2,24 @@
pragma solidity 0.8.15;
// Testing utilities
import { Bridge_Initializer } from "test/CommonTest.t.sol";
import { BaseFeeVault } from "src/L2/BaseFeeVault.sol";
import { StandardBridge } from "src/universal/StandardBridge.sol";
// Libraries
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract dependencies
import { FeeVault } from "src/universal/FeeVault.sol";
import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
// Target contract
import { L1FeeVault } from "src/L2/L1FeeVault.sol";
import { FeeVault } from "src/universal/FeeVault.sol";
// Test the implementations of the FeeVault
contract FeeVault_Test is Bridge_Initializer {
BaseFeeVault baseFeeVault = BaseFeeVault(payable(Predeploys.BASE_FEE_VAULT));
L1FeeVault l1FeeVault = L1FeeVault(payable(Predeploys.L1_FEE_VAULT));
uint256 constant otherMinimumWithdrawalAmount = 10 ether;
/// @dev Sets up the test suite.
function setUp() public override {
super.setUp();
vm.etch(
Predeploys.BASE_FEE_VAULT,
address(new BaseFeeVault(alice, NON_ZERO_VALUE, FeeVault.WithdrawalNetwork.L1)).code
);
vm.etch(
Predeploys.L1_FEE_VAULT,
address(new L1FeeVault(bob, otherMinimumWithdrawalAmount, FeeVault.WithdrawalNetwork.L2)).code
);
vm.label(Predeploys.BASE_FEE_VAULT, "BaseFeeVault");
vm.label(Predeploys.L1_FEE_VAULT, "L1FeeVault");
/// @dev Tests that the constructor sets the correct values.
function test_constructor_l1FeeVault_succeeds() external {
assertEq(l1FeeVault.RECIPIENT(), cfg.l1FeeVaultRecipient());
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.l1FeeVaultMinimumWithdrawalAmount());
assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
}
/// @dev Tests that the constructor sets the correct values.
function test_constructor_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), alice);
assertEq(l1FeeVault.RECIPIENT(), bob);
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), NON_ZERO_VALUE);
assertEq(l1FeeVault.MIN_WITHDRAWAL_AMOUNT(), otherMinimumWithdrawalAmount);
function test_constructor_baseFeeVault_succeeds() external {
assertEq(baseFeeVault.RECIPIENT(), cfg.baseFeeVaultRecipient());
assertEq(baseFeeVault.MIN_WITHDRAWAL_AMOUNT(), cfg.baseFeeVaultMinimumWithdrawalAmount());
assertEq(uint8(baseFeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L1));
assertEq(uint8(l1FeeVault.WITHDRAWAL_NETWORK()), uint8(FeeVault.WithdrawalNetwork.L2));
}
}
......@@ -2,22 +2,13 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Target contract dependencies
import { L1Block } from "src/L2/L1Block.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
// Target contract
import { GasPriceOracle } from "src/L2/GasPriceOracle.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
contract GasPriceOracle_Test is CommonTest {
event OverheadUpdated(uint256);
event ScalarUpdated(uint256);
event DecimalsUpdated(uint256);
GasPriceOracle gasOracle;
L1Block l1Block;
address depositor;
// The initial L1 context values
......@@ -33,17 +24,9 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
// place the L1Block contract at the predeploy address
vm.etch(Predeploys.L1_BLOCK_ATTRIBUTES, address(new L1Block()).code);
l1Block = L1Block(Predeploys.L1_BLOCK_ATTRIBUTES);
depositor = l1Block.DEPOSITOR_ACCOUNT();
// We are not setting the gas oracle at its predeploy
// address for simplicity purposes. Nothing in this test
// requires it to be at a particular address
gasOracle = new GasPriceOracle();
vm.prank(depositor);
l1Block.setL1BlockValues({
_number: number,
......@@ -59,43 +42,43 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Tests that `l1BaseFee` is set correctly.
function test_l1BaseFee_succeeds() external {
assertEq(gasOracle.l1BaseFee(), basefee);
assertEq(gasPriceOracle.l1BaseFee(), basefee);
}
/// @dev Tests that `gasPrice` is set correctly.
function test_gasPrice_succeeds() external {
vm.fee(100);
uint256 gasPrice = gasOracle.gasPrice();
uint256 gasPrice = gasPriceOracle.gasPrice();
assertEq(gasPrice, 100);
}
/// @dev Tests that `baseFee` is set correctly.
function test_baseFee_succeeds() external {
vm.fee(64);
uint256 gasPrice = gasOracle.baseFee();
uint256 gasPrice = gasPriceOracle.baseFee();
assertEq(gasPrice, 64);
}
/// @dev Tests that `scalar` is set correctly.
function test_scalar_succeeds() external {
assertEq(gasOracle.scalar(), l1FeeScalar);
assertEq(gasPriceOracle.scalar(), l1FeeScalar);
}
/// @dev Tests that `overhead` is set correctly.
function test_overhead_succeeds() external {
assertEq(gasOracle.overhead(), l1FeeOverhead);
assertEq(gasPriceOracle.overhead(), l1FeeOverhead);
}
/// @dev Tests that `decimals` is set correctly.
function test_decimals_succeeds() external {
assertEq(gasOracle.decimals(), 6);
assertEq(gasOracle.DECIMALS(), 6);
assertEq(gasPriceOracle.decimals(), 6);
assertEq(gasPriceOracle.DECIMALS(), 6);
}
/// @dev Tests that `setGasPrice` reverts since it was removed in bedrock.
function test_setGasPrice_doesNotExist_reverts() external {
(bool success, bytes memory returndata) =
address(gasOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1));
address(gasPriceOracle).call(abi.encodeWithSignature("setGasPrice(uint256)", 1));
assertEq(success, false);
assertEq(returndata, hex"");
......@@ -104,7 +87,7 @@ contract GasPriceOracle_Test is CommonTest {
/// @dev Tests that `setL1BaseFee` reverts since it was removed in bedrock.
function test_setL1BaseFee_doesNotExist_reverts() external {
(bool success, bytes memory returndata) =
address(gasOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1));
address(gasPriceOracle).call(abi.encodeWithSignature("setL1BaseFee(uint256)", 1));
assertEq(success, false);
assertEq(returndata, hex"");
......
......@@ -2,41 +2,37 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
// Target contract
import { GovernanceToken } from "src/governance/GovernanceToken.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
contract GovernanceToken_Test is CommonTest {
address constant owner = address(0x1234);
address constant rando = address(0x5678);
GovernanceToken internal gov;
address owner;
address rando;
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
vm.prank(owner);
gov = new GovernanceToken();
owner = governanceToken.owner();
rando = makeAddr("rando");
}
/// @dev Tests that the constructor sets the correct initial state.
function test_constructor_succeeds() external {
assertEq(gov.owner(), owner);
assertEq(gov.name(), "Optimism");
assertEq(gov.symbol(), "OP");
assertEq(gov.decimals(), 18);
assertEq(gov.totalSupply(), 0);
assertEq(governanceToken.owner(), owner);
assertEq(governanceToken.name(), "Optimism");
assertEq(governanceToken.symbol(), "OP");
assertEq(governanceToken.decimals(), 18);
assertEq(governanceToken.totalSupply(), 0);
}
/// @dev Tests that the owner can successfully call `mint`.
function test_mint_fromOwner_succeeds() external {
// Mint 100 tokens.
vm.prank(owner);
gov.mint(owner, 100);
governanceToken.mint(owner, 100);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 100);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 100);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `mint` reverts when called by a non-owner.
......@@ -44,130 +40,130 @@ contract GovernanceToken_Test is CommonTest {
// Mint 100 tokens as rando.
vm.prank(rando);
vm.expectRevert("Ownable: caller is not the owner");
gov.mint(owner, 100);
governanceToken.mint(owner, 100);
// Balance does not update.
assertEq(gov.balanceOf(owner), 0);
assertEq(gov.totalSupply(), 0);
assertEq(governanceToken.balanceOf(owner), 0);
assertEq(governanceToken.totalSupply(), 0);
}
/// @dev Tests that the owner can successfully call `burn`.
function test_burn_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando burns their tokens.
vm.prank(rando);
gov.burn(50);
governanceToken.burn(50);
// Balances have updated correctly.
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 50);
}
/// @dev Tests that the owner can successfully call `burnFrom`.
function test_burnFrom_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to burn 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Owner burns 50 tokens from rando.
vm.prank(owner);
gov.burnFrom(rando, 50);
governanceToken.burnFrom(rando, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 50);
}
/// @dev Tests that `transfer` correctly transfers tokens.
function test_transfer_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando transfers 50 tokens to owner.
vm.prank(rando);
gov.transfer(owner, 50);
governanceToken.transfer(owner, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 50);
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `approve` correctly sets allowances.
function test_approve_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 50);
assertEq(governanceToken.allowance(rando, owner), 50);
}
/// @dev Tests that `transferFrom` correctly transfers tokens.
function test_transferFrom_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Owner transfers 50 tokens from rando to owner.
vm.prank(owner);
gov.transferFrom(rando, owner, 50);
governanceToken.transferFrom(rando, owner, 50);
// Balances have updated correctly.
assertEq(gov.balanceOf(owner), 50);
assertEq(gov.balanceOf(rando), 50);
assertEq(gov.totalSupply(), 100);
assertEq(governanceToken.balanceOf(owner), 50);
assertEq(governanceToken.balanceOf(rando), 50);
assertEq(governanceToken.totalSupply(), 100);
}
/// @dev Tests that `increaseAllowance` correctly increases allowances.
function test_increaseAllowance_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 50 tokens.
vm.prank(rando);
gov.approve(owner, 50);
governanceToken.approve(owner, 50);
// Rando increases allowance by 50 tokens.
vm.prank(rando);
gov.increaseAllowance(owner, 50);
governanceToken.increaseAllowance(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 100);
assertEq(governanceToken.allowance(rando, owner), 100);
}
/// @dev Tests that `decreaseAllowance` correctly decreases allowances.
function test_decreaseAllowance_succeeds() external {
// Mint 100 tokens to rando.
vm.prank(owner);
gov.mint(rando, 100);
governanceToken.mint(rando, 100);
// Rando approves owner to spend 100 tokens.
vm.prank(rando);
gov.approve(owner, 100);
governanceToken.approve(owner, 100);
// Rando decreases allowance by 50 tokens.
vm.prank(rando);
gov.decreaseAllowance(owner, 50);
governanceToken.decreaseAllowance(owner, 50);
// Allowances have updated.
assertEq(gov.allowance(rando, owner), 50);
assertEq(governanceToken.allowance(rando, owner), 50);
}
}
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
// Libraries
import { Types } from "src/libraries/Types.sol";
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ERC721Bridge_Initializer } from "test/CommonTest.t.sol";
import { console } from "forge-std/console.sol";
import { Bridge_Initializer } from "test/setup/Bridge_Initializer.sol";
import { CrossDomainMessenger } from "src/universal/CrossDomainMessenger.sol";
import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
import { SystemConfig } from "src/L1/SystemConfig.sol";
......@@ -13,19 +12,19 @@ import { OptimismPortal } from "src/L1/OptimismPortal.sol";
/// @dev Ensures that the `initialize()` function on contracts cannot be called more than
/// once. This contract inherits from `ERC721Bridge_Initializer` because it is the
/// deepest contract in the inheritance chain for setting up the system contracts.
contract Initializer_Test is ERC721Bridge_Initializer {
contract Initializer_Test is Bridge_Initializer {
function test_cannotReinitializeL1_succeeds() public {
vm.expectRevert("Initializable: contract is already initialized");
L1Messenger.initialize(OptimismPortal(payable(address(0))));
l1CrossDomainMessenger.initialize(OptimismPortal(payable(address(0))));
vm.expectRevert("Initializable: contract is already initialized");
L1Bridge.initialize(CrossDomainMessenger(address(0)));
l1StandardBridge.initialize(CrossDomainMessenger(address(0)));
vm.expectRevert("Initializable: contract is already initialized");
oracle.initialize(0, 0, address(0), address(0));
l2OutputOracle.initialize(0, 0, address(0), address(0));
vm.expectRevert("Initializable: contract is already initialized");
op.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false);
optimismPortal.initialize(L2OutputOracle(address(0)), address(0), SystemConfig(address(0)), false);
vm.expectRevert("Initializable: contract is already initialized");
systemConfig.initialize({
......@@ -56,6 +55,6 @@ contract Initializer_Test is ERC721Bridge_Initializer {
});
vm.expectRevert("Initializable: contract is already initialized");
L1NFTBridge.initialize(CrossDomainMessenger(address(0)));
l1ERC721Bridge.initialize(CrossDomainMessenger(address(0)));
}
}
......@@ -2,27 +2,25 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
// Target contract
import { L1Block } from "src/L2/L1Block.sol";
contract L1BlockTest is CommonTest {
L1Block lb;
address depositor;
bytes32 immutable NON_ZERO_HASH = keccak256(abi.encode(1));
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
lb = new L1Block();
depositor = lb.DEPOSITOR_ACCOUNT();
depositor = l1Block.DEPOSITOR_ACCOUNT();
vm.prank(depositor);
lb.setL1BlockValues({
l1Block.setL1BlockValues({
_number: uint64(1),
_timestamp: uint64(2),
_basefee: 3,
_hash: NON_ZERO_HASH,
_hash: keccak256(abi.encode(block.number)),
_sequenceNumber: uint64(4),
_batcherHash: bytes32(0),
_l1FeeOverhead: 2,
......@@ -44,46 +42,46 @@ contract L1BlockTest is CommonTest {
external
{
vm.prank(depositor);
lb.setL1BlockValues(n, t, b, h, s, bt, fo, fs);
assertEq(lb.number(), n);
assertEq(lb.timestamp(), t);
assertEq(lb.basefee(), b);
assertEq(lb.hash(), h);
assertEq(lb.sequenceNumber(), s);
assertEq(lb.batcherHash(), bt);
assertEq(lb.l1FeeOverhead(), fo);
assertEq(lb.l1FeeScalar(), fs);
l1Block.setL1BlockValues(n, t, b, h, s, bt, fo, fs);
assertEq(l1Block.number(), n);
assertEq(l1Block.timestamp(), t);
assertEq(l1Block.basefee(), b);
assertEq(l1Block.hash(), h);
assertEq(l1Block.sequenceNumber(), s);
assertEq(l1Block.batcherHash(), bt);
assertEq(l1Block.l1FeeOverhead(), fo);
assertEq(l1Block.l1FeeScalar(), fs);
}
/// @dev Tests that `number` returns the correct value.
function test_number_succeeds() external {
assertEq(lb.number(), uint64(1));
assertEq(l1Block.number(), uint64(1));
}
/// @dev Tests that `timestamp` returns the correct value.
function test_timestamp_succeeds() external {
assertEq(lb.timestamp(), uint64(2));
assertEq(l1Block.timestamp(), uint64(2));
}
/// @dev Tests that `basefee` returns the correct value.
function test_basefee_succeeds() external {
assertEq(lb.basefee(), 3);
assertEq(l1Block.basefee(), 3);
}
/// @dev Tests that `hash` returns the correct value.
function test_hash_succeeds() external {
assertEq(lb.hash(), NON_ZERO_HASH);
assertEq(l1Block.hash(), keccak256(abi.encode(block.number)));
}
/// @dev Tests that `sequenceNumber` returns the correct value.
function test_sequenceNumber_succeeds() external {
assertEq(lb.sequenceNumber(), uint64(4));
assertEq(l1Block.sequenceNumber(), uint64(4));
}
/// @dev Tests that `setL1BlockValues` can set max values.
function test_updateValues_succeeds() external {
vm.prank(depositor);
lb.setL1BlockValues({
l1Block.setL1BlockValues({
_number: type(uint64).max,
_timestamp: type(uint64).max,
_basefee: type(uint256).max,
......
......@@ -2,36 +2,13 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
// Libraries
import { Types } from "src/libraries/Types.sol";
import { Hashing } from "src/libraries/Hashing.sol";
// Target contract
import { L2ToL1MessagePasser } from "src/L2/L2ToL1MessagePasser.sol";
contract L2ToL1MessagePasserTest is CommonTest {
L2ToL1MessagePasser messagePasser;
event MessagePassed(
uint256 indexed nonce,
address indexed sender,
address indexed target,
uint256 value,
uint256 gasLimit,
bytes data,
bytes32 withdrawalHash
);
event WithdrawerBalanceBurnt(uint256 indexed amount);
/// @dev Sets up the test suite.
function setUp() public virtual override {
super.setUp();
messagePasser = new L2ToL1MessagePasser();
}
/// @dev Tests that `initiateWithdrawal` succeeds and correctly sets the state
/// of the message passer for the withdrawal hash.
function testFuzz_initiateWithdrawal_succeeds(
......@@ -43,7 +20,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
)
external
{
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
......@@ -56,18 +33,18 @@ contract L2ToL1MessagePasserTest is CommonTest {
})
);
vm.expectEmit(true, true, true, true);
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(nonce, _sender, _target, _value, _gasLimit, _data, withdrawalHash);
vm.deal(_sender, _value);
vm.prank(_sender);
messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
assertEq(messagePasser.sentMessages(withdrawalHash), true);
assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true);
bytes32 slot = keccak256(bytes.concat(withdrawalHash, bytes32(0)));
assertEq(vm.load(address(messagePasser), slot), bytes32(uint256(1)));
assertEq(vm.load(address(l2ToL1MessagePasser), slot), bytes32(uint256(1)));
}
/// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed
......@@ -82,7 +59,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
{
bytes32 withdrawalHash = Hashing.hashWithdrawal(
Types.WithdrawalTransaction({
nonce: messagePasser.messageNonce(),
nonce: l2ToL1MessagePasser.messageNonce(),
sender: address(this),
target: _target,
value: _value,
......@@ -91,13 +68,13 @@ contract L2ToL1MessagePasserTest is CommonTest {
})
);
vm.expectEmit(address(messagePasser));
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(
messagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash
l2ToL1MessagePasser.messageNonce(), address(this), _target, _value, _gasLimit, _data, withdrawalHash
);
vm.deal(address(this), _value);
messagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }(_target, _gasLimit, _data);
}
/// @dev Tests that `initiateWithdrawal` succeeds and emits the correct MessagePassed
......@@ -110,7 +87,7 @@ contract L2ToL1MessagePasserTest is CommonTest {
)
external
{
uint256 nonce = messagePasser.messageNonce();
uint256 nonce = l2ToL1MessagePasser.messageNonce();
// EOA emulation
vm.prank(alice, alice);
......@@ -118,29 +95,28 @@ contract L2ToL1MessagePasserTest is CommonTest {
bytes32 withdrawalHash =
Hashing.hashWithdrawal(Types.WithdrawalTransaction(nonce, alice, _target, _value, _gasLimit, _data));
vm.expectEmit(address(messagePasser));
vm.expectEmit(address(l2ToL1MessagePasser));
emit MessagePassed(nonce, alice, _target, _value, _gasLimit, _data, withdrawalHash);
messagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
// the sent messages mapping is filled
assertEq(messagePasser.sentMessages(withdrawalHash), true);
assertEq(l2ToL1MessagePasser.sentMessages(withdrawalHash), true);
// the nonce increments
assertEq(nonce + 1, messagePasser.messageNonce());
assertEq(nonce + 1, l2ToL1MessagePasser.messageNonce());
}
/// @dev Tests that `burn` succeeds and destroys the ETH held in the contract.
function testFuzz_burn_succeeds(uint256 _value, address _target, uint256 _gasLimit, bytes memory _data) external {
vm.deal(address(this), _value);
messagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
l2ToL1MessagePasser.initiateWithdrawal{ value: _value }({ _target: _target, _gasLimit: _gasLimit, _data: _data });
assertEq(address(messagePasser).balance, _value);
vm.expectEmit(true, false, false, false);
assertEq(address(l2ToL1MessagePasser).balance, _value);
emit WithdrawerBalanceBurnt(_value);
messagePasser.burn();
l2ToL1MessagePasser.burn();
// The Withdrawer should have no balance
assertEq(address(messagePasser).balance, 0);
assertEq(address(l2ToL1MessagePasser).balance, 0);
}
}
......@@ -2,7 +2,7 @@
pragma solidity 0.8.15;
// Testing utilities
import { CommonTest } from "test/CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
// Target contract dependencies
import { Predeploys } from "src/libraries/Predeploys.sol";
......
......@@ -2,7 +2,7 @@
pragma solidity ^0.8.15;
import { Test } from "forge-std/Test.sol";
import { LibPosition } from "../src/dispute/lib/LibPosition.sol";
import { LibPosition } from "src/dispute/lib/LibPosition.sol";
import "src/libraries/DisputeTypes.sol";
/// @notice Tests for `LibPosition`
......
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { CommonTest } from "./CommonTest.t.sol";
import { CommonTest } from "test/setup/CommonTest.sol";
import { MIPS } from "src/cannon/MIPS.sol";
import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
import "src/libraries/DisputeTypes.sol";
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment