Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions op-challenger/game/fault/contracts/faultdisputegame.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ func (f *FaultDisputeGameContractLatest) getDelayedWETH(ctx context.Context, blo

func (f *FaultDisputeGameContractLatest) GetOracle(ctx context.Context) (*PreimageOracleContract, error) {
defer f.metrics.StartContractRequest("GetOracle")()
vm, err := f.vm(ctx)
vm, err := f.Vm(ctx)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -458,7 +458,7 @@ func (f *FaultDisputeGameContractLatest) IsResolved(ctx context.Context, block r
return resolved, nil
}

func (f *FaultDisputeGameContractLatest) vm(ctx context.Context) (*VMContract, error) {
func (f *FaultDisputeGameContractLatest) Vm(ctx context.Context) (*VMContract, error) {
result, err := f.multiCaller.SingleCall(ctx, rpcblock.Latest, f.contract.Call(methodVM))
if err != nil {
return nil, fmt.Errorf("failed to fetch VM addr: %w", err)
Expand Down Expand Up @@ -623,4 +623,5 @@ type FaultDisputeGameContract interface {
ResolveClaimTx(claimIdx uint64) (txmgr.TxCandidate, error)
CallResolve(ctx context.Context) (gameTypes.GameStatus, error)
ResolveTx() (txmgr.TxCandidate, error)
Vm(ctx context.Context) (*VMContract, error)
}
4 changes: 4 additions & 0 deletions op-challenger/game/fault/contracts/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ func NewVMContract(addr common.Address, caller *batching.MultiCaller) *VMContrac
}
}

func (c *VMContract) Addr() common.Address {
return c.contract.Addr()
}

func (c *VMContract) Oracle(ctx context.Context) (*PreimageOracleContract, error) {
results, err := c.multiCaller.SingleCall(ctx, rpcblock.Latest, c.contract.Call(methodOracle))
if err != nil {
Expand Down
14 changes: 7 additions & 7 deletions op-e2e/e2eutils/disputegame/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package disputegame

import (
"context"
"crypto/ecdsa"
"encoding/binary"
"math/big"
"testing"
Expand Down Expand Up @@ -88,6 +89,7 @@ type FactoryHelper struct {
System DisputeSystem
Client *ethclient.Client
Opts *bind.TransactOpts
PrivKey *ecdsa.PrivateKey
FactoryAddr common.Address
Factory *bindings.DisputeGameFactory
}
Expand All @@ -97,7 +99,8 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) *
client := system.NodeClient("l1")
chainID, err := client.ChainID(ctx)
require.NoError(err)
opts, err := bind.NewKeyedTransactorWithChainID(TestKey, chainID)
privKey := TestKey
opts, err := bind.NewKeyedTransactorWithChainID(privKey, chainID)
require.NoError(err)

l1Deployments := system.L1Deployments()
Expand All @@ -111,6 +114,7 @@ func NewFactoryHelper(t *testing.T, ctx context.Context, system DisputeSystem) *
System: system,
Client: client,
Opts: opts,
PrivKey: privKey,
Factory: factory,
FactoryAddr: factoryAddr,
}
Expand Down Expand Up @@ -167,8 +171,6 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string
h.Require.Len(rcpt.Logs, 2, "should have emitted a single DisputeGameCreated event")
createdEvent, err := h.Factory.ParseDisputeGameCreated(*rcpt.Logs[1])
h.Require.NoError(err)
gameBindings, err := bindings.NewFaultDisputeGame(createdEvent.DisputeProxy, h.Client)
h.Require.NoError(err)
game, err := contracts.NewFaultDisputeGameContract(ctx, metrics.NoopContractMetrics, createdEvent.DisputeProxy, batching.NewMultiCaller(h.Client.Client(), batching.DefaultBatchSize))
h.Require.NoError(err)

Expand All @@ -182,7 +184,7 @@ func (h *FactoryHelper) StartOutputCannonGame(ctx context.Context, l2Node string
provider := outputs.NewTraceProvider(logger, prestateProvider, rollupClient, l2Client, l1Head, splitDepth, prestateBlock, poststateBlock)

return &OutputCannonGameHelper{
OutputGameHelper: *NewOutputGameHelper(h.T, h.Require, h.Client, h.Opts, game, gameBindings, h.FactoryAddr, createdEvent.DisputeProxy, provider, h.System),
OutputGameHelper: *NewOutputGameHelper(h.T, h.Require, h.Client, h.Opts, h.PrivKey, game, h.FactoryAddr, createdEvent.DisputeProxy, provider, h.System),
}
}

Expand Down Expand Up @@ -223,8 +225,6 @@ func (h *FactoryHelper) StartOutputAlphabetGame(ctx context.Context, l2Node stri
h.Require.Len(rcpt.Logs, 2, "should have emitted a single DisputeGameCreated event")
createdEvent, err := h.Factory.ParseDisputeGameCreated(*rcpt.Logs[1])
h.Require.NoError(err)
gameBindings, err := bindings.NewFaultDisputeGame(createdEvent.DisputeProxy, h.Client)
h.Require.NoError(err)
game, err := contracts.NewFaultDisputeGameContract(ctx, metrics.NoopContractMetrics, createdEvent.DisputeProxy, batching.NewMultiCaller(h.Client.Client(), batching.DefaultBatchSize))
h.Require.NoError(err)

Expand All @@ -238,7 +238,7 @@ func (h *FactoryHelper) StartOutputAlphabetGame(ctx context.Context, l2Node stri
provider := outputs.NewTraceProvider(logger, prestateProvider, rollupClient, l2Client, l1Head, splitDepth, prestateBlock, poststateBlock)

return &OutputAlphabetGameHelper{
OutputGameHelper: *NewOutputGameHelper(h.T, h.Require, h.Client, h.Opts, game, gameBindings, h.FactoryAddr, createdEvent.DisputeProxy, provider, h.System),
OutputGameHelper: *NewOutputGameHelper(h.T, h.Require, h.Client, h.Opts, h.PrivKey, game, h.FactoryAddr, createdEvent.DisputeProxy, provider, h.System),
}
}

Expand Down
17 changes: 6 additions & 11 deletions op-e2e/e2eutils/disputegame/output_cannon_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ import (
"github.com/ethereum-optimism/optimism/op-challenger/metrics"
"github.com/ethereum-optimism/optimism/op-e2e/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock"
"github.com/ethereum-optimism/optimism/op-service/testlog"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
)
Expand Down Expand Up @@ -233,27 +233,22 @@ func (g *OutputCannonGameHelper) VerifyPreimage(ctx context.Context, outputRootC
g.Require.NotNil(oracleData, "Should have had required preimage oracle data")
g.Require.Equal(common.Hash(preimageKey.PreimageKey()).Bytes(), oracleData.OracleKey, "Must have correct preimage key")

tx, err := g.GameBindings.AddLocalData(g.Opts,
oracleData.GetIdent(),
big.NewInt(outputRootClaim.Index),
new(big.Int).SetUint64(uint64(oracleData.OracleOffset)))
g.Require.NoError(err)
_, err = wait.ForReceiptOK(ctx, g.Client, tx.Hash())
g.Require.NoError(err)
candidate, err := g.Game.UpdateOracleTx(ctx, uint64(outputRootClaim.Index), oracleData)
g.Require.NoError(err, "failed to get oracle")
transactions.RequireSendTx(g.T, ctx, g.Client, candidate, g.PrivKey)

expectedPostState, err := provider.Get(ctx, pos)
g.Require.NoError(err, "Failed to get expected post state")

callOpts := &bind.CallOpts{Context: ctx}
vmAddr, err := g.GameBindings.Vm(callOpts)
vm, err := g.Game.Vm(ctx)
g.Require.NoError(err, "Failed to get VM address")

abi, err := bindings.MIPSMetaData.GetAbi()
g.Require.NoError(err, "Failed to load MIPS ABI")
caller := batching.NewMultiCaller(g.Client.Client(), batching.DefaultBatchSize)
result, err := caller.SingleCall(ctx, rpcblock.Latest, &batching.ContractCall{
Abi: abi,
Addr: vmAddr,
Addr: vm.Addr(),
Method: "step",
Args: []interface{}{
prestate, proof, localContext,
Expand Down
82 changes: 27 additions & 55 deletions op-e2e/e2eutils/disputegame/output_game_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package disputegame
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"testing"
Expand All @@ -15,6 +16,7 @@ import (
keccakTypes "github.com/ethereum-optimism/optimism/op-challenger/game/keccak/types"
gameTypes "github.com/ethereum-optimism/optimism/op-challenger/game/types"
"github.com/ethereum-optimism/optimism/op-e2e/bindings"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/wait"
preimage "github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-service/eth"
Expand All @@ -33,23 +35,23 @@ type OutputGameHelper struct {
Require *require.Assertions
Client *ethclient.Client
Opts *bind.TransactOpts
PrivKey *ecdsa.PrivateKey
Game contracts.FaultDisputeGameContract
GameBindings *bindings.FaultDisputeGame
FactoryAddr common.Address
Addr common.Address
CorrectOutputProvider *outputs.OutputTraceProvider
System DisputeSystem
}

func NewOutputGameHelper(t *testing.T, require *require.Assertions, client *ethclient.Client, opts *bind.TransactOpts,
game contracts.FaultDisputeGameContract, gameBindings *bindings.FaultDisputeGame, factoryAddr common.Address, addr common.Address, correctOutputProvider *outputs.OutputTraceProvider, system DisputeSystem) *OutputGameHelper {
func NewOutputGameHelper(t *testing.T, require *require.Assertions, client *ethclient.Client, opts *bind.TransactOpts, privKey *ecdsa.PrivateKey,
game contracts.FaultDisputeGameContract, factoryAddr common.Address, addr common.Address, correctOutputProvider *outputs.OutputTraceProvider, system DisputeSystem) *OutputGameHelper {
return &OutputGameHelper{
T: t,
Require: require,
Client: client,
Opts: opts,
PrivKey: privKey,
Game: game,
GameBindings: gameBindings,
FactoryAddr: factoryAddr,
Addr: addr,
CorrectOutputProvider: correctOutputProvider,
Expand Down Expand Up @@ -203,22 +205,13 @@ func (g *OutputGameHelper) AvailableCredit(ctx context.Context, addr common.Addr
}

func (g *OutputGameHelper) CreditUnlockDuration(ctx context.Context) time.Duration {
weth, err := g.GameBindings.Weth(&bind.CallOpts{Context: ctx})
g.Require.NoError(err, "Failed to get WETH contract")
contract, err := bindings.NewDelayedWETH(weth, g.Client)
g.Require.NoError(err)
period, err := contract.Delay(&bind.CallOpts{Context: ctx})
g.Require.NoError(err, "Failed to get WETH unlock period")
float, _ := period.Float64()
return time.Duration(float) * time.Second
_, delay, _, err := g.Game.GetBalanceAndDelay(ctx, rpcblock.Latest)
g.Require.NoError(err, "Failed to get withdrawal delay")
return delay
}

func (g *OutputGameHelper) WethBalance(ctx context.Context, addr common.Address) *big.Int {
weth, err := g.GameBindings.Weth(&bind.CallOpts{Context: ctx})
g.Require.NoError(err, "Failed to get WETH contract")
contract, err := bindings.NewDelayedWETH(weth, g.Client)
g.Require.NoError(err)
balance, err := contract.BalanceOf(&bind.CallOpts{Context: ctx}, addr)
balance, _, _, err := g.Game.GetBalanceAndDelay(ctx, rpcblock.Latest)
g.Require.NoError(err, "Failed to get WETH balance")
return balance
}
Expand Down Expand Up @@ -363,10 +356,9 @@ func (g *OutputGameHelper) WaitForAllClaimsCountered(ctx context.Context) {
func (g *OutputGameHelper) Resolve(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
tx, err := g.GameBindings.Resolve(g.Opts)
g.Require.NoError(err)
_, err = wait.ForReceiptOK(ctx, g.Client, tx.Hash())
candidate, err := g.Game.ResolveTx()
g.Require.NoError(err)
transactions.RequireSendTx(g.T, ctx, g.Client, candidate, g.PrivKey)
}

func (g *OutputGameHelper) Status(ctx context.Context) gameTypes.GameStatus {
Expand Down Expand Up @@ -545,11 +537,10 @@ func (g *OutputGameHelper) Attack(ctx context.Context, claimIdx int64, claim com
claimData, err := g.Game.GetClaim(ctx, uint64(claimIdx))
g.Require.NoError(err, "Failed to get claim data")
attackPos := claimData.Position.Attack()
transactOpts := g.makeBondedTransactOpts(ctx, claimData.Position.Attack().ToGIndex(), cfg.Opts)

err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) {
return g.GameBindings.Attack(transactOpts, claimData.Value, big.NewInt(claimIdx), claim)
})
candidate, err := g.Game.AttackTx(ctx, claimData, claim)
g.Require.NoError(err, "Failed to create tx candidate")
_, _, err = transactions.SendTx(ctx, g.Client, candidate, g.PrivKey)
if err != nil {
if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, attackPos, claim) {
return
Expand All @@ -565,11 +556,10 @@ func (g *OutputGameHelper) Defend(ctx context.Context, claimIdx int64, claim com
claimData, err := g.Game.GetClaim(ctx, uint64(claimIdx))
g.Require.NoError(err, "Failed to get claim data")
defendPos := claimData.Position.Defend()
transactOpts := g.makeBondedTransactOpts(ctx, defendPos.ToGIndex(), cfg.Opts)

err = g.sendMove(ctx, func() (*gethtypes.Transaction, error) {
return g.GameBindings.Defend(transactOpts, claimData.Value, big.NewInt(claimIdx), claim)
})
candidate, err := g.Game.DefendTx(ctx, claimData, claim)
g.Require.NoError(err, "Failed to create tx candidate")
_, _, err = transactions.SendTx(ctx, g.Client, candidate, g.PrivKey)
if err != nil {
if cfg.ignoreDupes && g.hasClaim(ctx, claimIdx, defendPos, claim) {
return
Expand All @@ -588,45 +578,27 @@ func (g *OutputGameHelper) hasClaim(ctx context.Context, parentIdx int64, pos ty
return false
}

func (g *OutputGameHelper) sendMove(ctx context.Context, send func() (*gethtypes.Transaction, error)) error {
tx, err := send()
if err != nil {
return fmt.Errorf("transaction did not send: %w", err)
}
_, err = wait.ForReceiptOK(ctx, g.Client, tx.Hash())
if err != nil {
return fmt.Errorf("transaction was not ok: %w", err)
}
return nil
}

func (g *OutputGameHelper) makeBondedTransactOpts(ctx context.Context, pos *big.Int, Opts *bind.TransactOpts) *bind.TransactOpts {
bOpts := *Opts
bond, err := g.GameBindings.GetRequiredBond(&bind.CallOpts{Context: ctx}, pos)
g.Require.NoError(err, "Failed to get required bond")
bOpts.Value = bond
return &bOpts
}

type ErrWithData interface {
ErrorData() interface{}
}

// StepFails attempts to call step and verifies that it fails with ValidStep()
func (g *OutputGameHelper) StepFails(claimIdx int64, isAttack bool, stateData []byte, proof []byte) {
func (g *OutputGameHelper) StepFails(ctx context.Context, claimIdx int64, isAttack bool, stateData []byte, proof []byte) {
g.T.Logf("Attempting step against claim %v isAttack: %v", claimIdx, isAttack)
_, err := g.GameBindings.Step(g.Opts, big.NewInt(claimIdx), isAttack, stateData, proof)
errData, ok := err.(ErrWithData)
candidate, err := g.Game.StepTx(uint64(claimIdx), isAttack, stateData, proof)
g.Require.NoError(err, "Failed to create tx candidate")
_, _, err = transactions.SendTx(ctx, g.Client, candidate, g.PrivKey, transactions.WithReceiptFail())
var errData ErrWithData
ok := errors.As(err, &errData)
g.Require.Truef(ok, "Error should provide ErrorData method: %v", err)
g.Require.Equal("0xfb4e40dd", errData.ErrorData(), "Revert reason should be abi encoded ValidStep()")
}

// ResolveClaim resolves a single subgame
func (g *OutputGameHelper) ResolveClaim(ctx context.Context, claimIdx int64) {
tx, err := g.GameBindings.ResolveClaim(g.Opts, big.NewInt(claimIdx), common.Big0)
g.Require.NoError(err, "ResolveClaim transaction did not send")
_, err = wait.ForReceiptOK(ctx, g.Client, tx.Hash())
g.Require.NoError(err, "ResolveClaim transaction was not OK")
candidate, err := g.Game.ResolveClaimTx(uint64(claimIdx))
g.Require.NoError(err, "Failed to create resolve claim candidate tx")
transactions.RequireSendTx(g.T, ctx, g.Client, candidate, g.PrivKey)
}

// ChallengePeriod returns the challenge period fetched from the PreimageOracle contract.
Expand Down
2 changes: 1 addition & 1 deletion op-e2e/e2eutils/disputegame/output_honest_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ func (h *OutputHonestHelper) StepFails(ctx context.Context, claimIdx int64, isAt
}
prestate, proofData, _, err := h.correctTrace.GetStepData(ctx, game, claim, pos)
h.require.NoError(err, "Get step data")
h.game.StepFails(claimIdx, isAttack, prestate, proofData)
h.game.StepFails(ctx, claimIdx, isAttack, prestate, proofData)
}

func (h *OutputHonestHelper) loadState(ctx context.Context, claimIdx int64) (types.Game, types.Claim) {
Expand Down
Loading