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
b36be32b
Commit
b36be32b
authored
Aug 02, 2023
by
clabby
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Only allow checkpointing 1 block back in the `BlockOracle`
parent
e0c0f867
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
77 additions
and
80 deletions
+77
-80
blockoracle.go
op-bindings/bindings/blockoracle.go
+14
-14
blockoracle_more.go
op-bindings/bindings/blockoracle_more.go
+2
-2
deploy.go
op-e2e/e2eutils/disputegame/deploy.go
+30
-18
helper.go
op-e2e/e2eutils/disputegame/helper.go
+2
-2
.gas-snapshot
packages/contracts-bedrock/.gas-snapshot
+3
-2
BlockOracle.sol
packages/contracts-bedrock/src/dispute/BlockOracle.sol
+9
-11
FaultDisputeGame.sol
packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol
+3
-1
BlockOracle.t.sol
packages/contracts-bedrock/test/BlockOracle.t.sol
+10
-27
FaultDisputeGame.t.sol
packages/contracts-bedrock/test/FaultDisputeGame.t.sol
+4
-3
No files found.
op-bindings/bindings/blockoracle.go
View file @
b36be32b
...
...
@@ -36,8 +36,8 @@ type BlockOracleBlockInfo struct {
// BlockOracleMetaData contains all meta data concerning the BlockOracle contract.
var
BlockOracleMetaData
=
&
bind
.
MetaData
{
ABI
:
"[{
\"
inputs
\"
:[],
\"
name
\"
:
\"
BlockHashNotPresent
\"
,
\"
type
\"
:
\"
error
\"
},{
\"
inputs
\"
:[],
\"
name
\"
:
\"
BlockNumberOOB
\"
,
\"
type
\"
:
\"
error
\"
},{
\"
inputs
\"
:[{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_blockNumber
\"
,
\"
type
\"
:
\"
uint256
\"
}],
\"
name
\"
:
\"
load
\"
,
\"
outputs
\"
:[{
\"
components
\"
:[{
\"
internalType
\"
:
\"
Hash
\"
,
\"
name
\"
:
\"
hash
\"
,
\"
type
\"
:
\"
bytes32
\"
},{
\"
internalType
\"
:
\"
Timestamp
\"
,
\"
name
\"
:
\"
timestamp
\"
,
\"
type
\"
:
\"
uint64
\"
}],
\"
internalType
\"
:
\"
structBlockOracle.BlockInfo
\"
,
\"
name
\"
:
\"
blockInfo_
\"
,
\"
type
\"
:
\"
tuple
\"
}],
\"
stateMutability
\"
:
\"
view
\"
,
\"
type
\"
:
\"
function
\"
},{
\"
inputs
\"
:[{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_blockNumber
\"
,
\"
type
\"
:
\"
uint256
\"
}],
\"
name
\"
:
\"
store
\"
,
\"
outputs
\"
:[],
\"
stateMutability
\"
:
\"
nonpayable
\"
,
\"
type
\"
:
\"
function
\"
}]"
,
Bin
:
"0x608060405234801561001057600080fd5b50610
279806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80636057361d1461003b57806399d548aa14610050575b600080fd5b61004e6100493660046101d0565b61008c565b005b61006361005e3660046101d0565b610151565b604080518251815260209283015167ffffffffffffffff16928101929092520160405180910390f35b804060008190036100c9576040517fd82756d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006100d58343610218565b6100e090600d61022f565b6100ea9042610218565b60408051808201825293845267ffffffffffffffff918216602080860191825260009687528690529420925183559251600190920180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016929093169190911790915550565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff1692840192909252036101cb576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000602082840312156101e257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561022a5761022a6101e9565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610267576102676101e9565b5002
9056fea164736f6c634300080f000a"
,
ABI
:
"[{
\"
inputs
\"
:[],
\"
name
\"
:
\"
BlockHashNotPresent
\"
,
\"
type
\"
:
\"
error
\"
},{
\"
inputs
\"
:[],
\"
name
\"
:
\"
checkpoint
\"
,
\"
outputs
\"
:[{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
blockNumber_
\"
,
\"
type
\"
:
\"
uint256
\"
}],
\"
stateMutability
\"
:
\"
nonpayable
\"
,
\"
type
\"
:
\"
function
\"
},{
\"
inputs
\"
:[{
\"
internalType
\"
:
\"
uint256
\"
,
\"
name
\"
:
\"
_blockNumber
\"
,
\"
type
\"
:
\"
uint256
\"
}],
\"
name
\"
:
\"
load
\"
,
\"
outputs
\"
:[{
\"
components
\"
:[{
\"
internalType
\"
:
\"
Hash
\"
,
\"
name
\"
:
\"
hash
\"
,
\"
type
\"
:
\"
bytes32
\"
},{
\"
internalType
\"
:
\"
Timestamp
\"
,
\"
name
\"
:
\"
timestamp
\"
,
\"
type
\"
:
\"
uint64
\"
}],
\"
internalType
\"
:
\"
structBlockOracle.BlockInfo
\"
,
\"
name
\"
:
\"
blockInfo_
\"
,
\"
type
\"
:
\"
tuple
\"
}],
\"
stateMutability
\"
:
\"
view
\"
,
\"
type
\"
:
\"
function
\"
}]"
,
Bin
:
"0x608060405234801561001057600080fd5b50610
1fb806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806399d548aa1461003b578063c2c4c5c114610078575b600080fd5b61004e610049366004610197565b61008e565b604080518251815260209283015167ffffffffffffffff1692810192909252015b60405180910390f35b61008061010d565b60405190815260200161006f565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff169284019290925203610108576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008061011b6001436101b0565b9150508040600061012d600d426101b0565b60408051808201825293845267ffffffffffffffff9182166020808601918252600087815290819052919091209351845551600190930180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001693909116929092179091555090565b6000602082840312156101a957600080fd5b5035919050565b6000828210156101e9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5003
9056fea164736f6c634300080f000a"
,
}
// BlockOracleABI is the input ABI used to generate the binding from.
...
...
@@ -238,23 +238,23 @@ func (_BlockOracle *BlockOracleCallerSession) Load(_blockNumber *big.Int) (Block
return
_BlockOracle
.
Contract
.
Load
(
&
_BlockOracle
.
CallOpts
,
_blockNumber
)
}
//
Store is a paid mutator transaction binding the contract method 0x6057361d
.
//
Checkpoint is a paid mutator transaction binding the contract method 0xc2c4c5c1
.
//
// Solidity: function
store(uint256 _blockNumber) returns(
)
func
(
_BlockOracle
*
BlockOracleTransactor
)
Store
(
opts
*
bind
.
TransactOpts
,
_blockNumber
*
big
.
Int
)
(
*
types
.
Transaction
,
error
)
{
return
_BlockOracle
.
contract
.
Transact
(
opts
,
"
store"
,
_blockNumber
)
// Solidity: function
checkpoint() returns(uint256 blockNumber_
)
func
(
_BlockOracle
*
BlockOracleTransactor
)
Checkpoint
(
opts
*
bind
.
TransactOpts
)
(
*
types
.
Transaction
,
error
)
{
return
_BlockOracle
.
contract
.
Transact
(
opts
,
"
checkpoint"
)
}
//
Store is a paid mutator transaction binding the contract method 0x6057361d
.
//
Checkpoint is a paid mutator transaction binding the contract method 0xc2c4c5c1
.
//
// Solidity: function
store(uint256 _blockNumber) returns(
)
func
(
_BlockOracle
*
BlockOracleSession
)
Store
(
_blockNumber
*
big
.
Int
)
(
*
types
.
Transaction
,
error
)
{
return
_BlockOracle
.
Contract
.
Store
(
&
_BlockOracle
.
TransactOpts
,
_blockNumber
)
// Solidity: function
checkpoint() returns(uint256 blockNumber_
)
func
(
_BlockOracle
*
BlockOracleSession
)
Checkpoint
(
)
(
*
types
.
Transaction
,
error
)
{
return
_BlockOracle
.
Contract
.
Checkpoint
(
&
_BlockOracle
.
TransactOpts
)
}
//
Store is a paid mutator transaction binding the contract method 0x6057361d
.
//
Checkpoint is a paid mutator transaction binding the contract method 0xc2c4c5c1
.
//
// Solidity: function
store(uint256 _blockNumber) returns(
)
func
(
_BlockOracle
*
BlockOracleTransactorSession
)
Store
(
_blockNumber
*
big
.
Int
)
(
*
types
.
Transaction
,
error
)
{
return
_BlockOracle
.
Contract
.
Store
(
&
_BlockOracle
.
TransactOpts
,
_blockNumber
)
// Solidity: function
checkpoint() returns(uint256 blockNumber_
)
func
(
_BlockOracle
*
BlockOracleTransactorSession
)
Checkpoint
(
)
(
*
types
.
Transaction
,
error
)
{
return
_BlockOracle
.
Contract
.
Checkpoint
(
&
_BlockOracle
.
TransactOpts
)
}
op-bindings/bindings/blockoracle_more.go
View file @
b36be32b
...
...
@@ -9,11 +9,11 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const
BlockOracleStorageLayoutJSON
=
"{
\"
storage
\"
:[{
\"
astId
\"
:1000,
\"
contract
\"
:
\"
src/dispute/BlockOracle.sol:BlockOracle
\"
,
\"
label
\"
:
\"
block
Hashe
s
\"
,
\"
offset
\"
:0,
\"
slot
\"
:
\"
0
\"
,
\"
type
\"
:
\"
t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)
\"
}],
\"
types
\"
:{
\"
t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)
\"
:{
\"
encoding
\"
:
\"
mapping
\"
,
\"
label
\"
:
\"
mapping(uint256 =
\u003e
struct BlockOracle.BlockInfo)
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
,
\"
key
\"
:
\"
t_uint256
\"
,
\"
value
\"
:
\"
t_struct(BlockInfo)1001_storage
\"
},
\"
t_struct(BlockInfo)1001_storage
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
struct BlockOracle.BlockInfo
\"
,
\"
numberOfBytes
\"
:
\"
64
\"
},
\"
t_uint256
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
uint256
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
},
\"
t_userDefinedValueType(Hash)1002
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
Hash
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
},
\"
t_userDefinedValueType(Timestamp)1003
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
Timestamp
\"
,
\"
numberOfBytes
\"
:
\"
8
\"
}}}"
const
BlockOracleStorageLayoutJSON
=
"{
\"
storage
\"
:[{
\"
astId
\"
:1000,
\"
contract
\"
:
\"
src/dispute/BlockOracle.sol:BlockOracle
\"
,
\"
label
\"
:
\"
blocks
\"
,
\"
offset
\"
:0,
\"
slot
\"
:
\"
0
\"
,
\"
type
\"
:
\"
t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)
\"
}],
\"
types
\"
:{
\"
t_mapping(t_uint256,t_struct(BlockInfo)1001_storage)
\"
:{
\"
encoding
\"
:
\"
mapping
\"
,
\"
label
\"
:
\"
mapping(uint256 =
\u003e
struct BlockOracle.BlockInfo)
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
,
\"
key
\"
:
\"
t_uint256
\"
,
\"
value
\"
:
\"
t_struct(BlockInfo)1001_storage
\"
},
\"
t_struct(BlockInfo)1001_storage
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
struct BlockOracle.BlockInfo
\"
,
\"
numberOfBytes
\"
:
\"
64
\"
},
\"
t_uint256
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
uint256
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
},
\"
t_userDefinedValueType(Hash)1002
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
Hash
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
},
\"
t_userDefinedValueType(Timestamp)1003
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
Timestamp
\"
,
\"
numberOfBytes
\"
:
\"
8
\"
}}}"
var
BlockOracleStorageLayout
=
new
(
solc
.
StorageLayout
)
var
BlockOracleDeployedBin
=
"0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063
6057361d1461003b57806399d548aa14610050575b600080fd5b61004e6100493660046101d0565b61008c565b005b61006361005e3660046101d0565b610151565b604080518251815260209283015167ffffffffffffffff16928101929092520160405180910390f35b804060008190036100c9576040517fd82756d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006100d58343610218565b6100e090600d61022f565b6100ea9042610218565b60408051808201825293845267ffffffffffffffff918216602080860191825260009687528690529420925183559251600190920180547fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000016929093169190911790915550565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff1692840192909252036101cb576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b6000602082840312156101e257600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561022a5761022a6101e9565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610267576102676101e9565b5002
9056fea164736f6c634300080f000a"
var
BlockOracleDeployedBin
=
"0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063
99d548aa1461003b578063c2c4c5c114610078575b600080fd5b61004e610049366004610197565b61008e565b604080518251815260209283015167ffffffffffffffff1692810192909252015b60405180910390f35b61008061010d565b60405190815260200161006f565b604080518082018252600080825260209182018190528381528082528281208351808501909452805480855260019091015467ffffffffffffffff169284019290925203610108576040517f37cf270500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b919050565b60008061011b6001436101b0565b9150508040600061012d600d426101b0565b60408051808201825293845267ffffffffffffffff9182166020808601918252600087815290819052919091209351845551600190930180547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001693909116929092179091555090565b6000602082840312156101a957600080fd5b5035919050565b6000828210156101e9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5003
9056fea164736f6c634300080f000a"
func
init
()
{
if
err
:=
json
.
Unmarshal
([]
byte
(
BlockOracleStorageLayoutJSON
),
BlockOracleStorageLayout
);
err
!=
nil
{
...
...
op-e2e/e2eutils/disputegame/deploy.go
View file @
b36be32b
...
...
@@ -17,7 +17,7 @@ import (
// It configures the alphabet fault game as game type 0 (faultGameType)
// If/when the dispute game factory becomes a predeployed contract this can be removed and just use the
// predeployed version
func
deployDisputeGameContracts
(
require
*
require
.
Assertions
,
ctx
context
.
Context
,
client
*
ethclient
.
Client
,
opts
*
bind
.
TransactOpts
,
gameDuration
uint64
)
(
*
bindings
.
DisputeGameFactory
,
uint64
)
{
func
deployDisputeGameContracts
(
require
*
require
.
Assertions
,
ctx
context
.
Context
,
client
*
ethclient
.
Client
,
opts
*
bind
.
TransactOpts
,
gameDuration
uint64
)
(
*
bindings
.
DisputeGameFactory
,
*
big
.
Int
)
{
ctx
,
cancel
:=
context
.
WithTimeout
(
ctx
,
5
*
time
.
Minute
)
defer
cancel
()
// Deploy the proxy
...
...
@@ -51,14 +51,6 @@ func deployDisputeGameContracts(require *require.Assertions, ctx context.Context
alphaVMAddr
,
err
:=
bind
.
WaitDeployed
(
ctx
,
client
,
tx
)
require
.
NoError
(
err
)
// Deploy the block hash oracle
_
,
tx
,
_
,
err
=
bindings
.
DeployBlockOracle
(
opts
,
client
)
require
.
NoError
(
err
)
blockHashOracleAddr
,
err
:=
bind
.
WaitDeployed
(
ctx
,
client
,
tx
)
require
.
NoError
(
err
)
blockHashOracle
,
err
:=
bindings
.
NewBlockOracle
(
blockHashOracleAddr
,
client
)
require
.
NoError
(
err
)
// Deploy the L2 output oracle
_
,
tx
,
_
,
err
=
bindings
.
DeployL2OutputOracle
(
opts
,
...
...
@@ -77,15 +69,17 @@ func deployDisputeGameContracts(require *require.Assertions, ctx context.Context
l2OutputOracle
,
err
:=
bindings
.
NewL2OutputOracle
(
l2OutputOracleAddr
,
client
)
require
.
NoError
(
err
)
// Deploy the
fault dispute game implementation
_
,
tx
,
_
,
err
=
bindings
.
Deploy
FaultDisputeGame
(
opts
,
client
,
alphabetVMAbsolutePrestateClaim
,
big
.
NewInt
(
alphabetGameDepth
),
gameDuration
,
alphaVMAddr
,
l2OutputOracleAddr
,
blockHashOracleAddr
)
// Deploy the
block hash oracle
_
,
tx
,
_
,
err
=
bindings
.
Deploy
BlockOracle
(
opts
,
client
)
require
.
NoError
(
err
)
faultDisputeGameAddr
,
err
:=
bind
.
WaitDeployed
(
ctx
,
client
,
tx
)
blockHashOracleAddr
,
err
:=
bind
.
WaitDeployed
(
ctx
,
client
,
tx
)
require
.
NoError
(
err
)
blockHashOracle
,
err
:=
bindings
.
NewBlockOracle
(
blockHashOracleAddr
,
client
)
require
.
NoError
(
err
)
// Propose 2 outputs
for
i
:=
uint8
(
0
);
i
<
2
;
i
++
{
nextBlockNumber
,
err
:=
l2OutputOracle
.
NextBlockNumber
(
nil
)
nextBlockNumber
,
err
:=
l2OutputOracle
.
NextBlockNumber
(
&
bind
.
CallOpts
{
Pending
:
true
,
Context
:
ctx
}
)
require
.
NoError
(
err
)
block
,
err
:=
client
.
BlockByNumber
(
ctx
,
big
.
NewInt
(
int64
(
i
)))
require
.
NoError
(
err
)
...
...
@@ -97,18 +91,36 @@ func deployDisputeGameContracts(require *require.Assertions, ctx context.Context
}
// Store the current block in the oracle
blockNo
,
err
:=
client
.
BlockNumber
(
ctx
)
require
.
NoError
(
err
)
tx
,
err
=
blockHashOracle
.
Store
(
opts
,
big
.
NewInt
(
int64
(
blockNo
)))
tx
,
err
=
blockHashOracle
.
Checkpoint
(
opts
)
require
.
NoError
(
err
)
_
,
err
=
utils
.
WaitReceiptOK
(
ctx
,
client
,
tx
.
Hash
())
r
,
err
:
=
utils
.
WaitReceiptOK
(
ctx
,
client
,
tx
.
Hash
())
require
.
NoError
(
err
,
"failed to store block in blockoracle"
)
_
,
tx
,
_
,
err
=
bindings
.
DeployMIPS
(
opts
,
client
)
require
.
NoError
(
err
)
_
,
err
=
bind
.
WaitDeployed
(
ctx
,
client
,
tx
)
require
.
NoError
(
err
)
// Deploy the fault dispute game implementation
_
,
tx
,
_
,
err
=
bindings
.
DeployFaultDisputeGame
(
opts
,
client
,
alphabetVMAbsolutePrestateClaim
,
big
.
NewInt
(
alphabetGameDepth
),
gameDuration
,
alphaVMAddr
,
l2OutputOracleAddr
,
blockHashOracleAddr
,
)
require
.
NoError
(
err
)
faultDisputeGameAddr
,
err
:=
bind
.
WaitDeployed
(
ctx
,
client
,
tx
)
require
.
NoError
(
err
)
// Set the fault game type implementation
tx
,
err
=
factory
.
SetImplementation
(
opts
,
faultGameType
,
faultDisputeGameAddr
)
require
.
NoError
(
err
)
_
,
err
=
utils
.
WaitReceiptOK
(
ctx
,
client
,
tx
.
Hash
())
require
.
NoError
(
err
,
"wait for final transaction to be included and OK"
)
return
factory
,
blockNo
return
factory
,
new
(
big
.
Int
)
.
Sub
(
r
.
BlockNumber
,
big
.
NewInt
(
1
))
}
op-e2e/e2eutils/disputegame/helper.go
View file @
b36be32b
...
...
@@ -44,7 +44,7 @@ type FactoryHelper struct {
client
*
ethclient
.
Client
opts
*
bind
.
TransactOpts
factory
*
bindings
.
DisputeGameFactory
l1Head
uint64
l1Head
*
big
.
Int
}
func
NewFactoryHelper
(
t
*
testing
.
T
,
ctx
context
.
Context
,
client
*
ethclient
.
Client
,
gameDuration
uint64
)
*
FactoryHelper
{
...
...
@@ -74,7 +74,7 @@ func (h *FactoryHelper) StartAlphabetGame(ctx context.Context, claimedAlphabet s
h
.
require
.
NoError
(
err
,
"get root claim"
)
extraData
:=
make
([]
byte
,
64
)
binary
.
BigEndian
.
PutUint64
(
extraData
[
24
:
],
uint64
(
3600
))
binary
.
BigEndian
.
PutUint64
(
extraData
[
56
:
],
h
.
l1Head
)
binary
.
BigEndian
.
PutUint64
(
extraData
[
56
:
],
h
.
l1Head
.
Uint64
()
)
tx
,
err
:=
h
.
factory
.
Create
(
h
.
opts
,
faultGameType
,
rootClaim
,
extraData
)
h
.
require
.
NoError
(
err
,
"create fault dispute game"
)
rcpt
,
err
:=
utils
.
WaitReceiptOK
(
ctx
,
h
.
client
,
tx
.
Hash
())
...
...
packages/contracts-bedrock/.gas-snapshot
View file @
b36be32b
...
...
@@ -16,7 +16,8 @@ AssetReceiverTest:test_withdrawETHwithAmount_unauthorized_reverts() (gas: 10738)
AttestationStationTest:test_attest_bulk_succeeds() (gas: 703740)
AttestationStationTest:test_attest_individual_succeeds() (gas: 632078)
AttestationStationTest:test_attest_single_succeeds() (gas: 651316)
BlockOracle_Test:test_load_noBlockHash_reverts() (gas: 12849)
BlockOracle_Test:test_checkpointAndLoad_succeeds() (gas: 51618)
BlockOracle_Test:test_load_noBlockHash_reverts() (gas: 12805)
Bytes_slice_Test:test_slice_acrossMultipleWords_works() (gas: 9413)
Bytes_slice_Test:test_slice_acrossWords_works() (gas: 1430)
Bytes_slice_Test:test_slice_fromNonZeroIdx_works() (gas: 17240)
...
...
@@ -102,7 +103,7 @@ FaultDisputeGame_Test:test_gameStart_succeeds() (gas: 10410)
FaultDisputeGame_Test:test_gameType_succeeds() (gas: 8266)
FaultDisputeGame_Test:test_initialize_correctData_succeeds() (gas: 58226)
FaultDisputeGame_Test:test_initialize_firstOutput_reverts() (gas: 210532)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 2
76399
)
FaultDisputeGame_Test:test_initialize_l1HeadTooOld_reverts() (gas: 2
28360
)
FaultDisputeGame_Test:test_move_clockCorrectness_succeeds() (gas: 415921)
FaultDisputeGame_Test:test_move_clockTimeExceeded_reverts() (gas: 26428)
FaultDisputeGame_Test:test_move_defendRoot_reverts() (gas: 13322)
...
...
packages/contracts-bedrock/src/dispute/BlockOracle.sol
View file @
b36be32b
...
...
@@ -14,33 +14,31 @@ contract BlockOracle {
}
/// @notice Maps block numbers to block hashes and timestamps
mapping(uint256 => BlockInfo) internal block
Hashe
s;
mapping(uint256 => BlockInfo) internal blocks;
/// @notice Loads a block hash for a given block number, assuming that the block number
/// has been stored in the oracle.
/// @param _blockNumber The block number to load the block hash and timestamp for.
/// @return blockInfo_ The block hash and timestamp for the given block number.
function load(uint256 _blockNumber) external view returns (BlockInfo memory blockInfo_) {
blockInfo_ = block
Hashe
s[_blockNumber];
blockInfo_ = blocks[_blockNumber];
if (Hash.unwrap(blockInfo_.hash) == 0) revert BlockHashNotPresent();
}
/// @notice Stores a block hash for
a given
block number, assuming that the block number
/// @notice Stores a block hash for
the previous
block number, assuming that the block number
/// is within the acceptable range of [tip - 256, tip].
/// @param _blockNumber The block number to persist the block hash for.
function store(uint256 _blockNumber) external {
function checkpoint() external returns (uint256 blockNumber_) {
// Fetch the block hash for the given block number and revert if it is out of
// the `BLOCKHASH` opcode's range.
bytes32 blockHash = blockhash(_blockNumber);
if (blockHash == 0) revert BlockNumberOOB();
// SAFETY: This block hash will always be accessible by the `BLOCKHASH` opcode,
// and in the case of `block.number = 0`, we'll underflow.
bytes32 blockHash = blockhash(blockNumber_ = block.number - 1);
// Estimate the timestamp of the block assuming an average block time of 13 seconds.
Timestamp estimatedTimestamp = Timestamp.wrap(
uint64(block.timestamp - ((block.number - _blockNumber) * 13))
);
Timestamp estimatedTimestamp = Timestamp.wrap(uint64(block.timestamp - 13));
// Persist the block information.
block
Hashes[_blockNumber
] = BlockInfo({
block
s[blockNumber_
] = BlockInfo({
hash: Hash.wrap(blockHash),
timestamp: estimatedTimestamp
});
...
...
packages/contracts-bedrock/src/dispute/FaultDisputeGame.sol
View file @
b36be32b
...
...
@@ -478,7 +478,9 @@ contract FaultDisputeGame is IFaultDisputeGame, Clone, Semver {
// the game cannot be played.
// TODO(clabby): The block timestamp in the oracle is an estimate that assumes a 13
// second block time. Should we add a buffer here to ensure that the
// estimation has room for error? This invariant cannot break.
// estimation has room for error? This invariant cannot break. We could
// add the L1 block number to the `Types.OutputProposal` type as well,
// which would remove the need for estimation.
if (Timestamp.unwrap(blockInfo.timestamp) < disputed.timestamp) revert L1HeadTooOld();
// Persist the output proposals fetched from the oracle. These outputs will be referenced
...
...
packages/contracts-bedrock/test/BlockOracle.t.sol
View file @
b36be32b
...
...
@@ -11,36 +11,19 @@ contract BlockOracle_Test is Test {
function setUp() public {
oracle = new BlockOracle();
// Roll the chain forward 255 blocks.
vm.roll(block.number + 255);
// Set the time to a realistic date.
vm.warp(1690906994);
// Roll the chain forward 1 block.
vm.roll(block.number + 1);
vm.warp(block.timestamp + 13);
}
/// @notice Tests that
loading a block hash for a block number within the range of the
/// `BLOCKHASH` opcode succeeds.
function testFuzz_store_succeeds(uint256 _blockNumber) public {
_blockNumber = bound(_blockNumber, 0, 255)
;
oracle.store(_
blockNumber);
/// @notice Tests that
checkpointing a block and loading its information succeeds.
function test_checkpointAndLoad_succeeds() public {
oracle.checkpoint();
uint256 blockNumber = block.number - 1
;
BlockOracle.BlockInfo memory res = oracle.load(
blockNumber);
BlockOracle.BlockInfo memory res = oracle.load(_blockNumber);
assertEq(Hash.unwrap(res.hash), blockhash(_blockNumber));
assertEq(Timestamp.unwrap(res.timestamp), block.timestamp - ((block.number - _blockNumber) * 13));
}
/// @notice Tests that loading a block hash for a block number outside the range of the
/// `BLOCKHASH` opcode fails.
function testFuzz_store_oob_reverts(uint256 _blockNumber) public {
// Fast forward another 256 blocks.
vm.roll(block.number + 256);
// Bound the block number to the set { 0, ..., 255 } ∪ { 512, ..., type(uint256).max }
_blockNumber = _blockNumber % 2 == 0
? bound(_blockNumber, 0, 255)
: bound(_blockNumber, 512, type(uint256).max);
// Attempt to load the block hash, which should fail.
vm.expectRevert(BlockNumberOOB.selector);
oracle.store(_blockNumber);
assertEq(Hash.unwrap(res.hash), blockhash(blockNumber));
assertEq(Timestamp.unwrap(res.timestamp), block.timestamp - 13);
}
/// @notice Tests that the `load` function reverts if the block hash for the given block
...
...
packages/contracts-bedrock/test/FaultDisputeGame.t.sol
View file @
b36be32b
...
...
@@ -53,7 +53,7 @@ contract FaultDisputeGame_Init is DisputeGameFactory_Init {
// Deploy a new block hash oracle and store the block hash for the genesis block.
BlockOracle blockOracle = new BlockOracle();
blockOracle.
store(block.number - 1
);
blockOracle.
checkpoint(
);
// Set the extra data for the game creation
extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 1);
...
...
@@ -127,8 +127,9 @@ contract FaultDisputeGame_Test is FaultDisputeGame_Init {
/// @dev Tests that a game cannot be created by the factory if the L1 head hash does not
/// contain the disputed L2 output root.
function test_initialize_l1HeadTooOld_reverts() public {
gameProxy.BLOCK_ORACLE().store(block.number - 128);
bytes memory _extraData = abi.encode(oracle.SUBMISSION_INTERVAL() * 2, block.number - 128);
// 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);
vm.expectRevert(L1HeadTooOld.selector);
factory.create(GAME_TYPE, ROOT_CLAIM, _extraData);
...
...
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