Skip to content

Commit 4480f86

Browse files
authored
print-staging-report: Update to support fetching permissioned dispute game parameters from game args (#1150)
1 parent 59e22d2 commit 4480f86

File tree

6 files changed

+265
-11
lines changed

6 files changed

+265
-11
lines changed

ops/internal/gameargs/gameargs.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package gameargs
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
7+
"github.com/ethereum/go-ethereum/common"
8+
)
9+
10+
const (
11+
PermissionlessArgsLength = 124
12+
PermissionedArgsLength = 164
13+
)
14+
15+
var ErrInvalidGameArgs = errors.New("invalid game args")
16+
17+
func ParseAbsoluteState(args []byte) (common.Hash, error) {
18+
if len(args) != PermissionlessArgsLength && len(args) != PermissionedArgsLength {
19+
return common.Hash{}, fmt.Errorf("%w: invalid length (%v)", ErrInvalidGameArgs, len(args))
20+
}
21+
// In both permissioned and permissionless game args, the absolute prestate is the first 32 bytes.
22+
return common.BytesToHash(args[0:32]), nil
23+
}

ops/internal/report/bindings.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ var (
2121

2222
ownerFnABI = w3.MustNewFunc("owner()", "address")
2323

24+
gameArgsABI = w3.MustNewFunc("gameArgs(uint32)", "bytes")
25+
2426
gameTypeABI = w3.MustNewFunc("gameType()", "uint32")
2527

2628
absolutePrestateFnABI = w3.MustNewFunc("absolutePrestate()", "bytes32")

ops/internal/report/l1.go

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"math/big"
88

99
"github.com/ethereum-optimism/optimism/op-deployer/pkg/deployer/standard"
10+
"github.com/ethereum-optimism/superchain-registry/ops/internal/gameargs"
1011
"github.com/ethereum-optimism/superchain-registry/validation"
1112
"github.com/ethereum/go-ethereum/common"
1213
"github.com/ethereum/go-ethereum/core/types"
@@ -146,7 +147,13 @@ func ScanL1(
146147
return nil, fmt.Errorf("failed to validate ownership: %w", err)
147148
}
148149

149-
permissionedGameReport, err := ScanFDG(ctx, rpcClient, deployedEvent.DeployOutput.PermissionedDisputeGame)
150+
permissionedGameReport, err := ScanFDG(
151+
ctx,
152+
rpcClient,
153+
1, // PERMISSIONED
154+
deployedEvent.DeployOutput.DisputeGameFactoryProxy,
155+
deployedEvent.DeployOutput.PermissionedDisputeGame,
156+
)
150157
if err != nil {
151158
return nil, fmt.Errorf("failed to validate permissioned dispute game: %w", err)
152159
}
@@ -194,10 +201,12 @@ func ScanOwnership(
194201
func ScanFDG(
195202
ctx context.Context,
196203
rpc *rpc.Client,
197-
addr common.Address,
204+
gameType uint32,
205+
factoryAddr common.Address,
206+
gameAddr common.Address,
198207
) (L1FDGReport, error) {
199208
w3Client := w3.NewClient(rpc)
200-
makeBatchCall := bindBatchCallTo(addr)
209+
makeBatchCall := bindBatchCallTo(gameAddr)
201210

202211
var maxGameDepth big.Int
203212
var splitDepth big.Int
@@ -216,6 +225,29 @@ func ScanFDG(
216225
return report, fmt.Errorf("failed to get FDG data: %w", err)
217226
}
218227

228+
if report.AbsolutePrestate == (common.Hash{}) {
229+
// Absolute prestate wasn't available from the implementation contract.
230+
// Try to fetch it from the game args instead.
231+
// Note that gameArgs isn't available in older DisputeGameFactory implementations so this isn't requested
232+
// as part of the above batch.
233+
var gameArgs []byte
234+
if err := CallBatch(
235+
ctx,
236+
w3Client,
237+
batchCallMethod(factoryAddr, gameArgsABI, &gameArgs, gameType),
238+
); err != nil {
239+
return report, fmt.Errorf("failed to get FDG game args: %w", err)
240+
}
241+
prestate, err := gameargs.ParseAbsoluteState(gameArgs)
242+
if err != nil {
243+
return report, fmt.Errorf("failed to parse FDG game args: %w", err)
244+
}
245+
report.AbsolutePrestate = prestate
246+
// When using game args, the game type is passed in by the DisputeGameFactory so always matches the game type
247+
// the implementation is set as.
248+
report.GameType = gameType
249+
}
250+
219251
maxU64Big := new(big.Int).SetUint64(math.MaxUint64)
220252
if maxGameDepth.Cmp(maxU64Big) > 0 {
221253
return report, fmt.Errorf("unexpectedly large max game depth: %s", maxGameDepth.String())
@@ -318,23 +350,23 @@ func ScanSemvers(
318350
return report, nil
319351
}
320352

321-
func bindBatchCallTo(to common.Address) func(fn *w3.Func, out any) BatchCall {
322-
return func(fn *w3.Func, out any) BatchCall {
323-
return batchCallMethod(to, fn, out)
353+
func bindBatchCallTo(to common.Address) func(fn *w3.Func, out any, args ...any) BatchCall {
354+
return func(fn *w3.Func, out any, args ...any) BatchCall {
355+
return batchCallMethod(to, fn, out, args...)
324356
}
325357
}
326358

327-
func bindBatchCallMethod(method *w3.Func) func(to common.Address, out any) BatchCall {
328-
return func(to common.Address, out any) BatchCall {
329-
return batchCallMethod(to, method, out)
359+
func bindBatchCallMethod(method *w3.Func) func(to common.Address, out any, args ...any) BatchCall {
360+
return func(to common.Address, out any, args ...any) BatchCall {
361+
return batchCallMethod(to, method, out, args...)
330362
}
331363
}
332364

333-
func batchCallMethod(to common.Address, fn *w3.Func, out any) BatchCall {
365+
func batchCallMethod(to common.Address, fn *w3.Func, out any, args ...any) BatchCall {
334366
return BatchCall{
335367
To: to,
336368
Encoder: func() ([]byte, error) {
337-
return fn.EncodeArgs()
369+
return fn.EncodeArgs(args...)
338370
},
339371
Decoder: func(rawOutput []byte) error {
340372
return fn.DecodeReturns(rawOutput, out)

ops/internal/report/l1_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,56 @@ func TestScanSystemConfig(t *testing.T) {
194194
}
195195
}
196196

197+
func TestScanFDG(t *testing.T) {
198+
factoryAddr := common.HexToAddress("0x05F9613aDB30026FFd634f38e5C4dFd30a197Fa1")
199+
gameAddr := common.HexToAddress("0x034edD2A225f7f429A63E0f1D2084B9E0A93b538")
200+
201+
tests := []struct {
202+
name string
203+
filename string
204+
report L1FDGReport
205+
}{
206+
{
207+
"pre-game-args",
208+
"test-scan-fdg-pre-game-args.json",
209+
L1FDGReport{
210+
GameType: 2,
211+
AbsolutePrestate: common.HexToHash("0x03caa1871bb9fe7f9b11217c245c16e4ded33367df5b3ccb2c6d0a847a217d1b"),
212+
MaxGameDepth: 78,
213+
SplitDepth: 33,
214+
MaxClockDuration: 987654,
215+
ClockExtension: 4333,
216+
},
217+
},
218+
{
219+
"post-game-args",
220+
"test-scan-fdg-post-game-args.json",
221+
L1FDGReport{
222+
GameType: 1,
223+
AbsolutePrestate: common.HexToHash("0x03caa1871bb9fe7f9b11217c245c16e4ded33367df5b3ccb2c6d0a847a217d1b"),
224+
MaxGameDepth: 78,
225+
SplitDepth: 33,
226+
MaxClockDuration: 987654,
227+
ClockExtension: 4333,
228+
},
229+
},
230+
}
231+
for _, tt := range tests {
232+
t.Run(tt.name, func(t *testing.T) {
233+
t.Parallel()
234+
235+
l1Client, mockRPC := mockRPCClient(t, tt.filename)
236+
ctx, cancel := context.WithCancel(context.Background())
237+
defer cancel()
238+
239+
report, err := ScanFDG(ctx, l1Client, tt.report.GameType, factoryAddr, gameAddr)
240+
require.NoError(t, err)
241+
require.EqualValues(t, tt.report, report)
242+
mockRPC.AssertExpectations(t)
243+
})
244+
}
245+
}
246+
197247
func mockRPCClient(t *testing.T, p string) (*rpc.Client, *mockrpc.MockRPC) {
198248
mockRPC := mockrpc.NewMockRPC(
199249
t,
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
[
2+
{
3+
"method": "eth_call",
4+
"params": [
5+
{
6+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
7+
"data": "0xbbdc02db"
8+
},
9+
"latest"
10+
],
11+
"result": "0x0000000000000000000000000000000000000000000000000000000000000000"
12+
},
13+
{
14+
"method": "eth_call",
15+
"params": [
16+
{
17+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
18+
"data": "0x8d450a95"
19+
},
20+
"latest"
21+
],
22+
"result": "0x0000000000000000000000000000000000000000000000000000000000000000"
23+
},
24+
{
25+
"method": "eth_call",
26+
"params": [
27+
{
28+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
29+
"data": "0xfa315aa9"
30+
},
31+
"latest"
32+
],
33+
"result": "0x000000000000000000000000000000000000000000000000000000000000004e"
34+
},
35+
{
36+
"method": "eth_call",
37+
"params": [
38+
{
39+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
40+
"data": "0xec5e6308"
41+
},
42+
"latest"
43+
],
44+
"result": "0x0000000000000000000000000000000000000000000000000000000000000021"
45+
},
46+
{
47+
"method": "eth_call",
48+
"params": [
49+
{
50+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
51+
"data": "0xdabd396d"
52+
},
53+
"latest"
54+
],
55+
"result": "0x00000000000000000000000000000000000000000000000000000000000f1206"
56+
},
57+
{
58+
"method": "eth_call",
59+
"params": [
60+
{
61+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
62+
"data": "0x6b6716c0"
63+
},
64+
"latest"
65+
],
66+
"result": "0x00000000000000000000000000000000000000000000000000000000000010ed"
67+
},
68+
{
69+
"method": "eth_call",
70+
"params": [
71+
{
72+
"to": "0x05f9613adb30026ffd634f38e5c4dfd30a197fa1",
73+
"data": "0x74cc86ac0000000000000000000000000000000000000000000000000000000000000001"
74+
},
75+
"latest"
76+
],
77+
"result": "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a403caa1871bb9fe7f9b11217c245c16e4ded33367df5b3ccb2c6d0a847a217d1bfb180daf48a79ee0b10d394651850fd4a178892ee285ece1511455780875d64ee2d3d0d0de6bf8f9b44ce85ff044c6b1f83b8e883bbf857aab99c5b252c7429c32f3a8aeb79ef856f659c18f0dcecc77c75e7a81bfde275f67cfe242cf3cc354f3ede2d6becc4ea3ae5e88526a9f4a578bcb9ef2d4a65314768d6d299761ea9e4f5aa6ae00000000000000000000000000000000000000000000000000000000"
78+
}
79+
]
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
[
2+
{
3+
"method": "eth_call",
4+
"params": [
5+
{
6+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
7+
"data": "0xbbdc02db"
8+
},
9+
"latest"
10+
],
11+
"result": "0x0000000000000000000000000000000000000000000000000000000000000002"
12+
},
13+
{
14+
"method": "eth_call",
15+
"params": [
16+
{
17+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
18+
"data": "0x8d450a95"
19+
},
20+
"latest"
21+
],
22+
"result": "0x03caa1871bb9fe7f9b11217c245c16e4ded33367df5b3ccb2c6d0a847a217d1b"
23+
},
24+
{
25+
"method": "eth_call",
26+
"params": [
27+
{
28+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
29+
"data": "0xfa315aa9"
30+
},
31+
"latest"
32+
],
33+
"result": "0x000000000000000000000000000000000000000000000000000000000000004e"
34+
},
35+
{
36+
"method": "eth_call",
37+
"params": [
38+
{
39+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
40+
"data": "0xec5e6308"
41+
},
42+
"latest"
43+
],
44+
"result": "0x0000000000000000000000000000000000000000000000000000000000000021"
45+
},
46+
{
47+
"method": "eth_call",
48+
"params": [
49+
{
50+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
51+
"data": "0xdabd396d"
52+
},
53+
"latest"
54+
],
55+
"result": "0x00000000000000000000000000000000000000000000000000000000000f1206"
56+
},
57+
{
58+
"method": "eth_call",
59+
"params": [
60+
{
61+
"to": "0x034edd2a225f7f429a63e0f1d2084b9e0a93b538",
62+
"data": "0x6b6716c0"
63+
},
64+
"latest"
65+
],
66+
"result": "0x00000000000000000000000000000000000000000000000000000000000010ed"
67+
}
68+
]

0 commit comments

Comments
 (0)