Skip to content

Commit

Permalink
challenger: Add subcommand to list the credits in a game and when the…
Browse files Browse the repository at this point in the history
  • Loading branch information
ajsutton authored Jun 6, 2024
1 parent c4a5003 commit 2a01915
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 6 deletions.
117 changes: 117 additions & 0 deletions op-challenger/cmd/credits.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package main

import (
"context"
"fmt"
"math/big"
"time"

"github.com/ethereum-optimism/optimism/op-challenger/flags"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts"
"github.com/ethereum-optimism/optimism/op-challenger/game/fault/contracts/metrics"
opservice "github.com/ethereum-optimism/optimism/op-service"
"github.com/ethereum-optimism/optimism/op-service/dial"
"github.com/ethereum-optimism/optimism/op-service/eth"
oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/sources/batching"
"github.com/ethereum-optimism/optimism/op-service/sources/batching/rpcblock"
"github.com/ethereum/go-ethereum/common"
"github.com/urfave/cli/v2"
"golang.org/x/exp/maps"
)

func ListCredits(ctx *cli.Context) error {
logger, err := setupLogging(ctx)
if err != nil {
return err
}
rpcUrl := ctx.String(flags.L1EthRpcFlag.Name)
if rpcUrl == "" {
return fmt.Errorf("missing %v", flags.L1EthRpcFlag.Name)
}
gameAddr, err := opservice.ParseAddress(ctx.String(GameAddressFlag.Name))
if err != nil {
return err
}

l1Client, err := dial.DialEthClientWithTimeout(ctx.Context, dial.DefaultDialTimeout, logger, rpcUrl)
if err != nil {
return fmt.Errorf("failed to dial L1: %w", err)
}
defer l1Client.Close()

caller := batching.NewMultiCaller(l1Client.Client(), batching.DefaultBatchSize)
contract, err := contracts.NewFaultDisputeGameContract(ctx.Context, metrics.NoopContractMetrics, gameAddr, caller)
if err != nil {
return err
}
return listCredits(ctx.Context, contract)
}

func listCredits(ctx context.Context, game contracts.FaultDisputeGameContract) error {
claims, err := game.GetAllClaims(ctx, rpcblock.Latest)
if err != nil {
return fmt.Errorf("failed to load claims: %w", err)
}
metadata, err := game.GetGameMetadata(ctx, rpcblock.Latest)
if err != nil {
return fmt.Errorf("failed to load metadata: %w", err)
}
recipients := make(map[common.Address]bool)
for _, claim := range claims {
if claim.CounteredBy != (common.Address{}) {
recipients[claim.CounteredBy] = true
}
recipients[claim.Claimant] = true
}
if metadata.L2BlockNumberChallenger != (common.Address{}) {
recipients[metadata.L2BlockNumberChallenger] = true
}

balance, withdrawalDelay, wethAddress, err := game.GetBalanceAndDelay(ctx, rpcblock.Latest)
if err != nil {
return fmt.Errorf("failed to get DelayedWETH info: %w", err)
}
claimants := maps.Keys(recipients)
withdrawals, err := game.GetWithdrawals(ctx, rpcblock.Latest, claimants...)
if err != nil {
return fmt.Errorf("failed to get withdrawals: %w", err)
}
lineFormat := "%-42v %12v %-19v\n"
info := fmt.Sprintf(lineFormat, "Claimant", "ETH", "Unlock Time")
for i, withdrawal := range withdrawals {
var amount string
if withdrawal.Amount.Cmp(big.NewInt(0)) == 0 {
amount = "-"
} else {
amount = fmt.Sprintf("%12.8f", eth.WeiToEther(withdrawal.Amount))
}
var unlockTime string
if withdrawal.Timestamp.Cmp(big.NewInt(0)) == 0 {
unlockTime = "-"
} else {
unlockTime = time.Unix(withdrawal.Timestamp.Int64(), 0).Add(withdrawalDelay).Format(time.DateTime)
}
info += fmt.Sprintf(lineFormat, claimants[i], amount, unlockTime)
}
fmt.Printf("DelayedWETH Contract: %v • Total Balance (ETH): %12.8f • Delay: %v\n%v\n",
wethAddress, eth.WeiToEther(balance), withdrawalDelay, info)
return nil
}

func listCreditsFlags() []cli.Flag {
cliFlags := []cli.Flag{
flags.L1EthRpcFlag,
GameAddressFlag,
}
cliFlags = append(cliFlags, oplog.CLIFlags(flags.EnvVarPrefix)...)
return cliFlags
}

var ListCreditsCommand = &cli.Command{
Name: "list-credits",
Usage: "List the credits in a dispute game",
Description: "Lists the credits in a dispute game",
Action: ListCredits,
Flags: listCreditsFlags(),
}
1 change: 1 addition & 0 deletions op-challenger/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func run(ctx context.Context, args []string, action ConfiguredLifecycle) error {
app.Commands = []*cli.Command{
ListGamesCommand,
ListClaimsCommand,
ListCreditsCommand,
CreateGameCommand,
MoveCommand,
ResolveCommand,
Expand Down
6 changes: 3 additions & 3 deletions op-challenger/game/fault/contracts/faultdisputegame.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,13 +346,13 @@ func (f *FaultDisputeGameContractLatest) addGlobalDataTx(ctx context.Context, da
return oracle.AddGlobalDataTx(data)
}

func (f *FaultDisputeGameContractLatest) GetWithdrawals(ctx context.Context, block rpcblock.Block, gameAddr common.Address, recipients ...common.Address) ([]*WithdrawalRequest, error) {
func (f *FaultDisputeGameContractLatest) GetWithdrawals(ctx context.Context, block rpcblock.Block, recipients ...common.Address) ([]*WithdrawalRequest, error) {
defer f.metrics.StartContractRequest("GetWithdrawals")()
delayedWETH, err := f.getDelayedWETH(ctx, block)
if err != nil {
return nil, err
}
return delayedWETH.GetWithdrawals(ctx, block, gameAddr, recipients...)
return delayedWETH.GetWithdrawals(ctx, block, f.contract.Addr(), recipients...)
}

func (f *FaultDisputeGameContractLatest) getDelayedWETH(ctx context.Context, block rpcblock.Block) (*DelayedWETHContract, error) {
Expand Down Expand Up @@ -615,7 +615,7 @@ type FaultDisputeGameContract interface {
ClaimCreditTx(ctx context.Context, recipient common.Address) (txmgr.TxCandidate, error)
GetRequiredBond(ctx context.Context, position types.Position) (*big.Int, error)
UpdateOracleTx(ctx context.Context, claimIdx uint64, data *types.PreimageOracleData) (txmgr.TxCandidate, error)
GetWithdrawals(ctx context.Context, block rpcblock.Block, gameAddr common.Address, recipients ...common.Address) ([]*WithdrawalRequest, error)
GetWithdrawals(ctx context.Context, block rpcblock.Block, recipients ...common.Address) ([]*WithdrawalRequest, error)
GetOracle(ctx context.Context) (*PreimageOracleContract, error)
GetMaxClockDuration(ctx context.Context) (time.Duration, error)
GetMaxGameDepth(ctx context.Context) (types.Depth, error)
Expand Down
2 changes: 1 addition & 1 deletion op-dispute-mon/mon/extract/caller.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type GameCallerMetrics interface {
}

type GameCaller interface {
GetWithdrawals(context.Context, rpcblock.Block, common.Address, ...common.Address) ([]*contracts.WithdrawalRequest, error)
GetWithdrawals(context.Context, rpcblock.Block, ...common.Address) ([]*contracts.WithdrawalRequest, error)
GetGameMetadata(context.Context, rpcblock.Block) (contracts.GameMetadata, error)
GetAllClaims(context.Context, rpcblock.Block) ([]faultTypes.Claim, error)
BondCaller
Expand Down
2 changes: 1 addition & 1 deletion op-dispute-mon/mon/extract/extractor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ type mockGameCaller struct {
resolved map[int]bool
}

func (m *mockGameCaller) GetWithdrawals(_ context.Context, _ rpcblock.Block, _ common.Address, _ ...common.Address) ([]*contracts.WithdrawalRequest, error) {
func (m *mockGameCaller) GetWithdrawals(_ context.Context, _ rpcblock.Block, _ ...common.Address) ([]*contracts.WithdrawalRequest, error) {
m.withdrawalsCalls++
if m.withdrawalsErr != nil {
return nil, m.withdrawalsErr
Expand Down
2 changes: 1 addition & 1 deletion op-dispute-mon/mon/extract/withdrawals_enricher.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func NewWithdrawalsEnricher() *WithdrawalsEnricher {

func (w *WithdrawalsEnricher) Enrich(ctx context.Context, block rpcblock.Block, caller GameCaller, game *monTypes.EnrichedGameData) error {
recipients := maps.Keys(game.Recipients)
withdrawals, err := caller.GetWithdrawals(ctx, block, game.Proxy, recipients...)
withdrawals, err := caller.GetWithdrawals(ctx, block, recipients...)
if err != nil {
return fmt.Errorf("failed to fetch withdrawals: %w", err)
}
Expand Down

0 comments on commit 2a01915

Please sign in to comment.