Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
3fcb8b2c
Unverified
Commit
3fcb8b2c
authored
Oct 16, 2023
by
Adrian Sutton
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
op-challenger: Introduce fault dispute game contract wrapper that uses batch calls.
parent
2f523fbb
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
273 additions
and
0 deletions
+273
-0
faultdisputegame.go
op-challenger/game/fault/contracts/faultdisputegame.go
+105
-0
multicall.go
op-challenger/game/fault/contracts/multicall.go
+168
-0
No files found.
op-challenger/game/fault/contracts/faultdisputegame.go
0 → 100644
View file @
3fcb8b2c
package
contracts
import
(
"context"
"fmt"
"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"
"github.com/ethereum/go-ethereum/common"
)
type
FaultDisputeGameContract
struct
{
multiCaller
*
MultiCaller
addr
common
.
Address
abi
*
abi
.
ABI
}
func
NewFaultDisputeGameContract
(
addr
common
.
Address
,
caller
*
MultiCaller
)
(
*
FaultDisputeGameContract
,
error
)
{
fdgAbi
,
err
:=
bindings
.
FaultDisputeGameMetaData
.
GetAbi
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load fault dispute game ABI: %w"
,
err
)
}
return
&
FaultDisputeGameContract
{
multiCaller
:
caller
,
abi
:
fdgAbi
,
addr
:
addr
,
},
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetMaxGameDepth
(
ctx
context
.
Context
)
(
*
big
.
Int
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCallLatest
(
ctx
,
NewContractCall
(
f
.
abi
,
f
.
addr
,
"MAX_GAME_DEPTH"
))
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch max game depth: %w"
,
err
)
}
return
result
.
GetBigInt
(
0
),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetStatus
(
ctx
context
.
Context
)
(
gameTypes
.
GameStatus
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCallLatest
(
ctx
,
NewContractCall
(
f
.
abi
,
f
.
addr
,
"status"
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch claim count: %w"
,
err
)
}
return
gameTypes
.
GameStatusFromUint8
(
result
.
GetUint8
(
0
))
}
func
(
f
*
FaultDisputeGameContract
)
GetClaimCount
(
ctx
context
.
Context
)
(
uint64
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCallLatest
(
ctx
,
NewContractCall
(
f
.
abi
,
f
.
addr
,
"claimDataLen"
))
if
err
!=
nil
{
return
0
,
fmt
.
Errorf
(
"failed to fetch claim count: %w"
,
err
)
}
return
result
.
GetBigInt
(
0
)
.
Uint64
(),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetClaim
(
ctx
context
.
Context
,
idx
uint64
)
(
types
.
Claim
,
error
)
{
result
,
err
:=
f
.
multiCaller
.
SingleCallLatest
(
ctx
,
NewContractCall
(
f
.
abi
,
f
.
addr
,
"claimData"
,
new
(
big
.
Int
)
.
SetUint64
(
idx
)))
if
err
!=
nil
{
return
types
.
Claim
{},
fmt
.
Errorf
(
"failed to fetch claim %v: %w"
,
idx
,
err
)
}
return
f
.
decodeClaim
(
result
,
int
(
idx
)),
nil
}
func
(
f
*
FaultDisputeGameContract
)
GetAllClaims
(
ctx
context
.
Context
)
([]
types
.
Claim
,
error
)
{
count
,
err
:=
f
.
GetClaimCount
(
ctx
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to load claim count: %w"
,
err
)
}
calls
:=
make
([]
*
ContractCall
,
count
)
for
i
:=
uint64
(
0
);
i
<
count
;
i
++
{
calls
[
i
]
=
NewContractCall
(
f
.
abi
,
f
.
addr
,
"claimData"
,
new
(
big
.
Int
)
.
SetUint64
(
i
))
}
results
,
err
:=
f
.
multiCaller
.
CallLatest
(
ctx
,
calls
...
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch claim data: %w"
,
err
)
}
var
claims
[]
types
.
Claim
for
idx
,
result
:=
range
results
{
claims
=
append
(
claims
,
f
.
decodeClaim
(
result
,
idx
))
}
return
claims
,
nil
}
func
(
f
*
FaultDisputeGameContract
)
decodeClaim
(
result
*
CallResult
,
contractIndex
int
)
types
.
Claim
{
parentIndex
:=
result
.
GetUint32
(
0
)
countered
:=
result
.
GetBool
(
1
)
claim
:=
result
.
GetHash
(
2
)
position
:=
result
.
GetBigInt
(
3
)
clock
:=
result
.
GetBigInt
(
4
)
return
types
.
Claim
{
ClaimData
:
types
.
ClaimData
{
Value
:
claim
,
Position
:
types
.
NewPositionFromGIndex
(
position
),
},
Countered
:
countered
,
Clock
:
clock
.
Uint64
(),
ContractIndex
:
contractIndex
,
ParentContractIndex
:
int
(
parentIndex
),
}
}
op-challenger/game/fault/contracts/multicall.go
0 → 100644
View file @
3fcb8b2c
package
contracts
import
(
"context"
"fmt"
"io"
"math/big"
"github.com/ethereum-optimism/optimism/op-service/sources"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rpc"
)
type
EthRpc
interface
{
CallContext
(
ctx
context
.
Context
,
out
interface
{},
method
string
,
args
...
interface
{})
error
BatchCallContext
(
ctx
context
.
Context
,
b
[]
rpc
.
BatchElem
)
error
}
type
ContractCall
struct
{
Abi
*
abi
.
ABI
Addr
common
.
Address
Method
string
Args
[]
interface
{}
}
func
NewContractCall
(
abi
*
abi
.
ABI
,
addr
common
.
Address
,
method
string
,
args
...
interface
{})
*
ContractCall
{
return
&
ContractCall
{
Abi
:
abi
,
Addr
:
addr
,
Method
:
method
,
Args
:
args
,
}
}
func
(
c
*
ContractCall
)
ToCallArgs
()
(
interface
{},
error
)
{
data
,
err
:=
c
.
Abi
.
Pack
(
c
.
Method
,
c
.
Args
...
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to pack arguments: %w"
,
err
)
}
msg
:=
ethereum
.
CallMsg
{
To
:
&
c
.
Addr
,
Data
:
data
,
}
return
toCallArg
(
msg
),
nil
}
func
(
c
*
ContractCall
)
Unpack
(
hex
hexutil
.
Bytes
)
([]
interface
{},
error
)
{
out
,
err
:=
c
.
Abi
.
Unpack
(
c
.
Method
,
hex
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to unpack claim data: %w"
,
err
)
}
return
out
,
nil
}
type
CallResult
struct
{
out
[]
interface
{}
}
func
(
c
*
CallResult
)
GetUint8
(
i
int
)
uint8
{
return
*
abi
.
ConvertType
(
c
.
out
[
i
],
new
(
uint8
))
.
(
*
uint8
)
}
func
(
c
*
CallResult
)
GetUint32
(
i
int
)
uint32
{
return
*
abi
.
ConvertType
(
c
.
out
[
i
],
new
(
uint32
))
.
(
*
uint32
)
}
func
(
c
*
CallResult
)
GetBool
(
i
int
)
bool
{
return
*
abi
.
ConvertType
(
c
.
out
[
i
],
new
(
bool
))
.
(
*
bool
)
}
func
(
c
*
CallResult
)
GetHash
(
i
int
)
common
.
Hash
{
return
*
abi
.
ConvertType
(
c
.
out
[
i
],
new
([
32
]
byte
))
.
(
*
[
32
]
byte
)
}
func
(
c
*
CallResult
)
GetBigInt
(
i
int
)
*
big
.
Int
{
return
*
abi
.
ConvertType
(
c
.
out
[
i
],
new
(
*
big
.
Int
))
.
(
**
big
.
Int
)
}
type
MultiCaller
struct
{
rpc
EthRpc
batchSize
int
}
func
NewMultiCaller
(
rpc
EthRpc
,
batchSize
int
)
*
MultiCaller
{
return
&
MultiCaller
{
rpc
:
rpc
,
batchSize
:
batchSize
,
}
}
func
(
m
*
MultiCaller
)
SingleCallLatest
(
ctx
context
.
Context
,
call
*
ContractCall
)
(
*
CallResult
,
error
)
{
results
,
err
:=
m
.
CallLatest
(
ctx
,
call
)
if
err
!=
nil
{
return
nil
,
err
}
return
results
[
0
],
nil
}
func
(
m
*
MultiCaller
)
CallLatest
(
ctx
context
.
Context
,
calls
...*
ContractCall
)
([]
*
CallResult
,
error
)
{
keys
:=
make
([]
interface
{},
len
(
calls
))
for
i
:=
0
;
i
<
len
(
calls
);
i
++
{
args
,
err
:=
calls
[
i
]
.
ToCallArgs
()
if
err
!=
nil
{
return
nil
,
err
}
keys
[
i
]
=
args
}
fetcher
:=
sources
.
NewIterativeBatchCall
[
interface
{},
*
hexutil
.
Bytes
](
keys
,
func
(
args
interface
{})
(
*
hexutil
.
Bytes
,
rpc
.
BatchElem
)
{
out
:=
new
(
hexutil
.
Bytes
)
return
out
,
rpc
.
BatchElem
{
Method
:
"eth_call"
,
Args
:
[]
interface
{}{
args
,
"latest"
},
Result
:
&
out
,
}
},
m
.
rpc
.
BatchCallContext
,
m
.
rpc
.
CallContext
,
m
.
batchSize
)
for
{
if
err
:=
fetcher
.
Fetch
(
ctx
);
err
==
io
.
EOF
{
break
}
else
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to fetch claims: %w"
,
err
)
}
}
results
,
err
:=
fetcher
.
Result
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get batch call results: %w"
,
err
)
}
callResults
:=
make
([]
*
CallResult
,
len
(
results
))
for
i
,
result
:=
range
results
{
call
:=
calls
[
i
]
out
,
err
:=
call
.
Unpack
(
*
result
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to unpack result: %w"
,
err
)
}
callResults
[
i
]
=
&
CallResult
{
out
:
out
,
}
}
return
callResults
,
nil
}
func
toCallArg
(
msg
ethereum
.
CallMsg
)
interface
{}
{
arg
:=
map
[
string
]
interface
{}{
"from"
:
msg
.
From
,
"to"
:
msg
.
To
,
}
if
len
(
msg
.
Data
)
>
0
{
arg
[
"data"
]
=
hexutil
.
Bytes
(
msg
.
Data
)
}
if
msg
.
Value
!=
nil
{
arg
[
"value"
]
=
(
*
hexutil
.
Big
)(
msg
.
Value
)
}
if
msg
.
Gas
!=
0
{
arg
[
"gas"
]
=
hexutil
.
Uint64
(
msg
.
Gas
)
}
if
msg
.
GasPrice
!=
nil
{
arg
[
"gasPrice"
]
=
(
*
hexutil
.
Big
)(
msg
.
GasPrice
)
}
return
arg
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment