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
87231e92
Unverified
Commit
87231e92
authored
Jun 09, 2023
by
mergify[bot]
Committed by
GitHub
Jun 09, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into willc/go-chi-latest
parents
b8c10f77
efea631c
Changes
25
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
581 additions
and
276 deletions
+581
-276
README.md
README.md
+31
-12
go.mod
go.mod
+1
-1
go.sum
go.sum
+2
-2
channel_manager.go
op-batcher/batcher/channel_manager.go
+3
-0
metrics.go
op-batcher/metrics/metrics.go
+43
-2
noop.go
op-batcher/metrics/noop.go
+3
-0
disputegamefactory.go
op-bindings/bindings/disputegamefactory.go
+1
-1
system_test.go
op-e2e/system_test.go
+3
-6
receipts.go
op-node/sources/receipts.go
+24
-4
receipts_test.go
op-node/sources/receipts_test.go
+14
-1
.storage-layout
packages/contracts-bedrock/.storage-layout
+18
-0
BondManager.sol
packages/contracts-bedrock/contracts/dispute/BondManager.sol
+21
-58
DisputeGameFactory.sol
...ontracts-bedrock/contracts/dispute/DisputeGameFactory.sol
+18
-48
IAttestationDisputeGame.sol
...cts-bedrock/contracts/dispute/IAttestationDisputeGame.sol
+0
-63
IBondManager.sol
...cts-bedrock/contracts/dispute/interfaces/IBondManager.sol
+27
-1
IDisputeGame.sol
...cts-bedrock/contracts/dispute/interfaces/IDisputeGame.sol
+19
-9
IDisputeGameFactory.sol
...rock/contracts/dispute/interfaces/IDisputeGameFactory.sol
+16
-2
IFaultDisputeGame.sol
...edrock/contracts/dispute/interfaces/IFaultDisputeGame.sol
+1
-12
IInitializable.sol
...s-bedrock/contracts/dispute/interfaces/IInitializable.sol
+0
-0
IVersioned.sol
...racts-bedrock/contracts/dispute/interfaces/IVersioned.sol
+0
-0
Clone.sol
packages/contracts-bedrock/contracts/libraries/Clone.sol
+123
-0
BondManager.t.sol
packages/contracts-bedrock/contracts/test/BondManager.t.sol
+57
-53
Clones.t.sol
packages/contracts-bedrock/contracts/test/Clones.t.sol
+153
-0
DisputeGameFactory.t.sol
...contracts-bedrock/contracts/test/DisputeGameFactory.t.sol
+1
-1
storage-snapshot.sh
packages/contracts-bedrock/scripts/storage-snapshot.sh
+2
-0
No files found.
README.md
View file @
87231e92
...
@@ -51,6 +51,36 @@ Refer to the Directory Structure section below to understand which packages are
...
@@ -51,6 +51,36 @@ Refer to the Directory Structure section below to understand which packages are
~~ Production ~~
~~ Production ~~
├──
<a
href=
"./packages"
>
packages
</a>
├──
<a
href=
"./packages"
>
packages
</a>
│ ├──
<a
href=
"./packages/common-ts"
>
common-ts
</a>
: Common tools for building apps in TypeScript
│ ├──
<a
href=
"./packages/common-ts"
>
common-ts
</a>
: Common tools for building apps in TypeScript
│ ├──
<a
href=
"./packages/contracts-bedrock"
>
contracts-bedrock
</a>
: Bedrock smart contracts.
│ ├──
<a
href=
"./packages/contracts-periphery"
>
contracts-periphery
</a>
: Peripheral contracts for Optimism
│ ├──
<a
href=
"./packages/core-utils"
>
core-utils
</a>
: Low-level utilities that make building Optimism easier
│ ├──
<a
href=
"./packages/data-transport-layer"
>
data-transport-layer
</a>
: Service for indexing Optimism-related L1 data
│ ├──
<a
href=
"./packages/chain-mon"
>
chain-mon
</a>
: Chain monitoring services
│ ├──
<a
href=
"./packages/fault-detector"
>
fault-detector
</a>
: Service for detecting Sequencer faults
│ ├──
<a
href=
"./packages/message-relayer"
>
message-relayer
</a>
: Tool for automatically relaying L1
<>
L2 messages in development
│ ├──
<a
href=
"./packages/replica-healthcheck"
>
replica-healthcheck
</a>
: Service for monitoring the health of a replica node
│ └──
<a
href=
"./packages/sdk"
>
sdk
</a>
: provides a set of tools for interacting with Optimism
├──
<a
href=
"./op-bindings"
>
op-bindings
</a>
: Go bindings for Bedrock smart contracts.
├──
<a
href=
"./op-batcher"
>
op-batcher
</a>
: L2-Batch Submitter, submits bundles of batches to L1
├──
<a
href=
"./op-bootnode"
>
op-bootnode
</a>
: Standalone op-node discovery bootnode
├──
<a
href=
"./op-chain-ops"
>
op-chain-ops
</a>
: State surgery utilities
├──
<a
href=
"./op-challenger"
>
op-challenger
</a>
: Dispute game challenge agent
├──
<a
href=
"./op-e2e"
>
op-e2e
</a>
: End-to-End testing of all bedrock components in Go
├──
<a
href=
"./op-exporter"
>
op-exporter
</a>
: Prometheus exporter client
├──
<a
href=
"./op-heartbeat"
>
op-heartbeat
</a>
: Heartbeat monitor service
├──
<a
href=
"./op-node"
>
op-node
</a>
: rollup consensus-layer client
├──
<a
href=
"./op-program"
>
op-program
</a>
: Fault proof program
├──
<a
href=
"./op-proposer"
>
op-proposer
</a>
: L2-Output Submitter, submits proposals to L1
├──
<a
href=
"./op-service"
>
op-service
</a>
: Common codebase utilities
├──
<a
href=
"./op-signer"
>
op-signer
</a>
: Client signer
├──
<a
href=
"./op-wheel"
>
op-wheel
</a>
: Database utilities
├──
<a
href=
"./ops-bedrock"
>
ops-bedrock
</a>
: Bedrock devnet work
├──
<a
href=
"./proxyd"
>
proxyd
</a>
: Configurable RPC request router and proxy
└──
<a
href=
"./specs"
>
specs
</a>
: Specs of the rollup starting at the Bedrock upgrade
~~ Pre-BEDROCK ~~
├──
<a
href=
"./packages"
>
packages
</a>
│ ├──
<a
href=
"./packages/common-ts"
>
common-ts
</a>
: Common tools for building apps in TypeScript
│ ├──
<a
href=
"./packages/contracts"
>
contracts
</a>
: L1 and L2 smart contracts for Optimism
│ ├──
<a
href=
"./packages/contracts"
>
contracts
</a>
: L1 and L2 smart contracts for Optimism
│ ├──
<a
href=
"./packages/contracts-periphery"
>
contracts-periphery
</a>
: Peripheral contracts for Optimism
│ ├──
<a
href=
"./packages/contracts-periphery"
>
contracts-periphery
</a>
: Peripheral contracts for Optimism
│ ├──
<a
href=
"./packages/core-utils"
>
core-utils
</a>
: Low-level utilities that make building Optimism easier
│ ├──
<a
href=
"./packages/core-utils"
>
core-utils
</a>
: Low-level utilities that make building Optimism easier
...
@@ -69,18 +99,7 @@ Refer to the Directory Structure section below to understand which packages are
...
@@ -69,18 +99,7 @@ Refer to the Directory Structure section below to understand which packages are
├──
<a
href=
"./l2geth-exporter"
>
l2geth-exporter
</a>
: A prometheus exporter to collect/serve metrics from an L2 geth node
├──
<a
href=
"./l2geth-exporter"
>
l2geth-exporter
</a>
: A prometheus exporter to collect/serve metrics from an L2 geth node
├──
<a
href=
"./op-exporter"
>
op-exporter
</a>
: A prometheus exporter to collect/serve metrics from an Optimism node
├──
<a
href=
"./op-exporter"
>
op-exporter
</a>
: A prometheus exporter to collect/serve metrics from an Optimism node
├──
<a
href=
"./proxyd"
>
proxyd
</a>
: Configurable RPC request router and proxy
├──
<a
href=
"./proxyd"
>
proxyd
</a>
: Configurable RPC request router and proxy
├──
<a
href=
"./technical-documents"
>
technical-documents
</a>
: audits and post-mortem documents
└──
<a
href=
"./technical-documents"
>
technical-documents
</a>
: audits and post-mortem documents
~~ BEDROCK upgrade - Not production-ready yet, part of next major upgrade ~~
├──
<a
href=
"./packages"
>
packages
</a>
│ └──
<a
href=
"./packages/contracts-bedrock"
>
contracts-bedrock
</a>
: Bedrock smart contracts. To be merged with ./packages/contracts.
├──
<a
href=
"./op-bindings"
>
op-bindings
</a>
: Go bindings for Bedrock smart contracts.
├──
<a
href=
"./op-batcher"
>
op-batcher
</a>
: L2-Batch Submitter, submits bundles of batches to L1
├──
<a
href=
"./op-e2e"
>
op-e2e
</a>
: End-to-End testing of all bedrock components in Go
├──
<a
href=
"./op-node"
>
op-node
</a>
: rollup consensus-layer client.
├──
<a
href=
"./op-proposer"
>
op-proposer
</a>
: L2-Output Submitter, submits proposals to L1
├──
<a
href=
"./ops-bedrock"
>
ops-bedrock
</a>
: Bedrock devnet work
└──
<a
href=
"./specs"
>
specs
</a>
: Specs of the rollup starting at the Bedrock upgrade
</pre>
</pre>
## Branching Model
## Branching Model
...
...
go.mod
View file @
87231e92
...
@@ -190,6 +190,6 @@ require (
...
@@ -190,6 +190,6 @@ require (
nhooyr.io/websocket v1.8.7 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)
)
replace github.com/ethereum/go-ethereum v1.11.6 => github.com/ethereum-optimism/op-geth v1.10110
5.2-0.20230526154603-bdab05ca786f
replace github.com/ethereum/go-ethereum v1.11.6 => github.com/ethereum-optimism/op-geth v1.10110
6.0-rc.2
//replace github.com/ethereum/go-ethereum v1.11.6 => ../go-ethereum
//replace github.com/ethereum/go-ethereum v1.11.6 => ../go-ethereum
go.sum
View file @
87231e92
...
@@ -151,8 +151,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
...
@@ -151,8 +151,8 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z8veEq5ZO3DfIhZ7xgRP9WTc=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v1.10110
5.2-0.20230526154603-bdab05ca786f h1:+yZN8K/4AIN5f+gazMwZAeqzDG2EL2GydMrccjnEK+A
=
github.com/ethereum-optimism/op-geth v1.10110
6.0-rc.2 h1:F3SGS0XIvRQ0MjL3Rzbx3A688hNsqv/DtdlBnZimFTw
=
github.com/ethereum-optimism/op-geth v1.10110
5.2-0.20230526154603-bdab05ca786f
/go.mod h1:X9t7oeerFMU9/zMIjZKT/jbIca+O05QqtBTLjL+XVeA=
github.com/ethereum-optimism/op-geth v1.10110
6.0-rc.2
/go.mod h1:X9t7oeerFMU9/zMIjZKT/jbIca+O05QqtBTLjL+XVeA=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
...
...
op-batcher/batcher/channel_manager.go
View file @
87231e92
...
@@ -228,6 +228,7 @@ func (s *channelManager) processBlocks() error {
...
@@ -228,6 +228,7 @@ func (s *channelManager) processBlocks() error {
}
}
blocksAdded
+=
1
blocksAdded
+=
1
latestL2ref
=
l2BlockRefFromBlockAndL1Info
(
block
,
l1info
)
latestL2ref
=
l2BlockRefFromBlockAndL1Info
(
block
,
l1info
)
s
.
metr
.
RecordL2BlockInChannel
(
block
)
// current block got added but channel is now full
// current block got added but channel is now full
if
s
.
currentChannel
.
IsFull
()
{
if
s
.
currentChannel
.
IsFull
()
{
break
break
...
@@ -298,6 +299,8 @@ func (s *channelManager) AddL2Block(block *types.Block) error {
...
@@ -298,6 +299,8 @@ func (s *channelManager) AddL2Block(block *types.Block) error {
if
s
.
tip
!=
(
common
.
Hash
{})
&&
s
.
tip
!=
block
.
ParentHash
()
{
if
s
.
tip
!=
(
common
.
Hash
{})
&&
s
.
tip
!=
block
.
ParentHash
()
{
return
ErrReorg
return
ErrReorg
}
}
s
.
metr
.
RecordL2BlockInPendingQueue
(
block
)
s
.
blocks
=
append
(
s
.
blocks
,
block
)
s
.
blocks
=
append
(
s
.
blocks
,
block
)
s
.
tip
=
block
.
Hash
()
s
.
tip
=
block
.
Hash
()
...
...
op-batcher/metrics/metrics.go
View file @
87231e92
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"context"
"context"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus"
...
@@ -30,6 +31,8 @@ type Metricer interface {
...
@@ -30,6 +31,8 @@ type Metricer interface {
RecordL2BlocksLoaded
(
l2ref
eth
.
L2BlockRef
)
RecordL2BlocksLoaded
(
l2ref
eth
.
L2BlockRef
)
RecordChannelOpened
(
id
derive
.
ChannelID
,
numPendingBlocks
int
)
RecordChannelOpened
(
id
derive
.
ChannelID
,
numPendingBlocks
int
)
RecordL2BlocksAdded
(
l2ref
eth
.
L2BlockRef
,
numBlocksAdded
,
numPendingBlocks
,
inputBytes
,
outputComprBytes
int
)
RecordL2BlocksAdded
(
l2ref
eth
.
L2BlockRef
,
numBlocksAdded
,
numPendingBlocks
,
inputBytes
,
outputComprBytes
int
)
RecordL2BlockInPendingQueue
(
block
*
types
.
Block
)
RecordL2BlockInChannel
(
block
*
types
.
Block
)
RecordChannelClosed
(
id
derive
.
ChannelID
,
numPendingBlocks
int
,
numFrames
int
,
inputBytes
int
,
outputComprBytes
int
,
reason
error
)
RecordChannelClosed
(
id
derive
.
ChannelID
,
numPendingBlocks
int
,
numFrames
int
,
inputBytes
int
,
outputComprBytes
int
,
reason
error
)
RecordChannelFullySubmitted
(
id
derive
.
ChannelID
)
RecordChannelFullySubmitted
(
id
derive
.
ChannelID
)
RecordChannelTimedOut
(
id
derive
.
ChannelID
)
RecordChannelTimedOut
(
id
derive
.
ChannelID
)
...
@@ -55,8 +58,10 @@ type Metrics struct {
...
@@ -55,8 +58,10 @@ type Metrics struct {
// label by openend, closed, fully_submitted, timed_out
// label by openend, closed, fully_submitted, timed_out
channelEvs
opmetrics
.
EventVec
channelEvs
opmetrics
.
EventVec
pendingBlocksCount
prometheus
.
GaugeVec
pendingBlocksCount
prometheus
.
GaugeVec
blocksAddedCount
prometheus
.
Gauge
pendingBlocksBytesTotal
prometheus
.
Counter
pendingBlocksBytesCurrent
prometheus
.
Gauge
blocksAddedCount
prometheus
.
Gauge
channelInputBytes
prometheus
.
GaugeVec
channelInputBytes
prometheus
.
GaugeVec
channelReadyBytes
prometheus
.
Gauge
channelReadyBytes
prometheus
.
Gauge
...
@@ -109,6 +114,16 @@ func NewMetrics(procName string) *Metrics {
...
@@ -109,6 +114,16 @@ func NewMetrics(procName string) *Metrics {
Name
:
"pending_blocks_count"
,
Name
:
"pending_blocks_count"
,
Help
:
"Number of pending blocks, not added to a channel yet."
,
Help
:
"Number of pending blocks, not added to a channel yet."
,
},
[]
string
{
"stage"
}),
},
[]
string
{
"stage"
}),
pendingBlocksBytesTotal
:
factory
.
NewCounter
(
prometheus
.
CounterOpts
{
Namespace
:
ns
,
Name
:
"pending_blocks_bytes_total"
,
Help
:
"Total size of transactions in pending blocks as they are fetched from L2"
,
}),
pendingBlocksBytesCurrent
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
ns
,
Name
:
"pending_blocks_bytes_current"
,
Help
:
"Current size of transactions in the pending (fetched from L2 but not in a channel) stage."
,
}),
blocksAddedCount
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
blocksAddedCount
:
factory
.
NewGauge
(
prometheus
.
GaugeOpts
{
Namespace
:
ns
,
Namespace
:
ns
,
Name
:
"blocks_added_count"
,
Name
:
"blocks_added_count"
,
...
@@ -243,6 +258,18 @@ func (m *Metrics) RecordChannelClosed(id derive.ChannelID, numPendingBlocks int,
...
@@ -243,6 +258,18 @@ func (m *Metrics) RecordChannelClosed(id derive.ChannelID, numPendingBlocks int,
m
.
channelClosedReason
.
Set
(
float64
(
ClosedReasonToNum
(
reason
)))
m
.
channelClosedReason
.
Set
(
float64
(
ClosedReasonToNum
(
reason
)))
}
}
func
(
m
*
Metrics
)
RecordL2BlockInPendingQueue
(
block
*
types
.
Block
)
{
size
:=
float64
(
estimateBatchSize
(
block
))
m
.
pendingBlocksBytesTotal
.
Add
(
size
)
m
.
pendingBlocksBytesCurrent
.
Add
(
size
)
}
func
(
m
*
Metrics
)
RecordL2BlockInChannel
(
block
*
types
.
Block
)
{
size
:=
float64
(
estimateBatchSize
(
block
))
m
.
pendingBlocksBytesCurrent
.
Add
(
-
1
*
size
)
// Refer to RecordL2BlocksAdded to see the current + count of bytes added to a channel
}
func
ClosedReasonToNum
(
reason
error
)
int
{
func
ClosedReasonToNum
(
reason
error
)
int
{
// CLI-3640
// CLI-3640
return
0
return
0
...
@@ -267,3 +294,17 @@ func (m *Metrics) RecordBatchTxSuccess() {
...
@@ -267,3 +294,17 @@ func (m *Metrics) RecordBatchTxSuccess() {
func
(
m
*
Metrics
)
RecordBatchTxFailed
()
{
func
(
m
*
Metrics
)
RecordBatchTxFailed
()
{
m
.
batcherTxEvs
.
Record
(
TxStageFailed
)
m
.
batcherTxEvs
.
Record
(
TxStageFailed
)
}
}
// estimateBatchSize estimates the size of the batch
func
estimateBatchSize
(
block
*
types
.
Block
)
uint64
{
size
:=
uint64
(
70
)
// estimated overhead of batch metadata
for
_
,
tx
:=
range
block
.
Transactions
()
{
// Don't include deposit transactions in the batch.
if
tx
.
IsDepositTx
()
{
continue
}
// Add 2 for the overhead of encoding the tx bytes in a RLP list
size
+=
tx
.
Size
()
+
2
}
return
size
}
op-batcher/metrics/noop.go
View file @
87231e92
...
@@ -5,6 +5,7 @@ import (
...
@@ -5,6 +5,7 @@ import (
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
opmetrics
"github.com/ethereum-optimism/optimism/op-service/metrics"
opmetrics
"github.com/ethereum-optimism/optimism/op-service/metrics"
txmetrics
"github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
txmetrics
"github.com/ethereum-optimism/optimism/op-service/txmgr/metrics"
"github.com/ethereum/go-ethereum/core/types"
)
)
type
noopMetrics
struct
{
type
noopMetrics
struct
{
...
@@ -23,6 +24,8 @@ func (*noopMetrics) RecordLatestL1Block(l1ref eth.L1BlockRef) {}
...
@@ -23,6 +24,8 @@ func (*noopMetrics) RecordLatestL1Block(l1ref eth.L1BlockRef) {}
func
(
*
noopMetrics
)
RecordL2BlocksLoaded
(
eth
.
L2BlockRef
)
{}
func
(
*
noopMetrics
)
RecordL2BlocksLoaded
(
eth
.
L2BlockRef
)
{}
func
(
*
noopMetrics
)
RecordChannelOpened
(
derive
.
ChannelID
,
int
)
{}
func
(
*
noopMetrics
)
RecordChannelOpened
(
derive
.
ChannelID
,
int
)
{}
func
(
*
noopMetrics
)
RecordL2BlocksAdded
(
eth
.
L2BlockRef
,
int
,
int
,
int
,
int
)
{}
func
(
*
noopMetrics
)
RecordL2BlocksAdded
(
eth
.
L2BlockRef
,
int
,
int
,
int
,
int
)
{}
func
(
*
noopMetrics
)
RecordL2BlockInPendingQueue
(
*
types
.
Block
)
{}
func
(
*
noopMetrics
)
RecordL2BlockInChannel
(
*
types
.
Block
)
{}
func
(
*
noopMetrics
)
RecordChannelClosed
(
derive
.
ChannelID
,
int
,
int
,
int
,
int
,
error
)
{}
func
(
*
noopMetrics
)
RecordChannelClosed
(
derive
.
ChannelID
,
int
,
int
,
int
,
int
,
error
)
{}
...
...
op-bindings/bindings/disputegamefactory.go
View file @
87231e92
This diff is collapsed.
Click to expand it.
op-e2e/system_test.go
View file @
87231e92
...
@@ -1084,11 +1084,6 @@ func TestWithdrawals(t *testing.T) {
...
@@ -1084,11 +1084,6 @@ func TestWithdrawals(t *testing.T) {
proveReceipt
,
finalizeReceipt
:=
ProveAndFinalizeWithdrawal
(
t
,
cfg
,
l1Client
,
sys
.
Nodes
[
"verifier"
],
ethPrivKey
,
receipt
)
proveReceipt
,
finalizeReceipt
:=
ProveAndFinalizeWithdrawal
(
t
,
cfg
,
l1Client
,
sys
.
Nodes
[
"verifier"
],
ethPrivKey
,
receipt
)
// Verify balance after withdrawal
// Verify balance after withdrawal
ctx
,
cancel
=
context
.
WithTimeout
(
context
.
Background
(),
1
*
time
.
Second
)
defer
cancel
()
header
,
err
=
l1Client
.
HeaderByNumber
(
ctx
,
finalizeReceipt
.
BlockNumber
)
require
.
Nil
(
t
,
err
)
ctx
,
cancel
=
context
.
WithTimeout
(
context
.
Background
(),
1
*
time
.
Second
)
ctx
,
cancel
=
context
.
WithTimeout
(
context
.
Background
(),
1
*
time
.
Second
)
defer
cancel
()
defer
cancel
()
endBalance
,
err
=
l1Client
.
BalanceAt
(
ctx
,
fromAddr
,
nil
)
endBalance
,
err
=
l1Client
.
BalanceAt
(
ctx
,
fromAddr
,
nil
)
...
@@ -1098,7 +1093,9 @@ func TestWithdrawals(t *testing.T) {
...
@@ -1098,7 +1093,9 @@ func TestWithdrawals(t *testing.T) {
// Fun fact, the fee is greater than the withdrawal amount
// Fun fact, the fee is greater than the withdrawal amount
// NOTE: The gas fees include *both* the ProveWithdrawalTransaction and FinalizeWithdrawalTransaction transactions.
// NOTE: The gas fees include *both* the ProveWithdrawalTransaction and FinalizeWithdrawalTransaction transactions.
diff
=
new
(
big
.
Int
)
.
Sub
(
endBalance
,
startBalance
)
diff
=
new
(
big
.
Int
)
.
Sub
(
endBalance
,
startBalance
)
fees
=
calcGasFees
(
proveReceipt
.
GasUsed
+
finalizeReceipt
.
GasUsed
,
tx
.
GasTipCap
(),
tx
.
GasFeeCap
(),
header
.
BaseFee
)
proveFee
:=
new
(
big
.
Int
)
.
Mul
(
new
(
big
.
Int
)
.
SetUint64
(
proveReceipt
.
GasUsed
),
proveReceipt
.
EffectiveGasPrice
)
finalizeFee
:=
new
(
big
.
Int
)
.
Mul
(
new
(
big
.
Int
)
.
SetUint64
(
finalizeReceipt
.
GasUsed
),
finalizeReceipt
.
EffectiveGasPrice
)
fees
=
new
(
big
.
Int
)
.
Add
(
proveFee
,
finalizeFee
)
withdrawAmount
=
withdrawAmount
.
Sub
(
withdrawAmount
,
fees
)
withdrawAmount
=
withdrawAmount
.
Sub
(
withdrawAmount
,
fees
)
require
.
Equal
(
t
,
withdrawAmount
,
diff
)
require
.
Equal
(
t
,
withdrawAmount
,
diff
)
}
}
...
...
op-node/sources/receipts.go
View file @
87231e92
...
@@ -179,6 +179,7 @@ func (r ReceiptsFetchingMethod) String() string {
...
@@ -179,6 +179,7 @@ func (r ReceiptsFetchingMethod) String() string {
addMaybe
(
DebugGetRawReceipts
,
"debug_getRawReceipts"
)
addMaybe
(
DebugGetRawReceipts
,
"debug_getRawReceipts"
)
addMaybe
(
ParityGetBlockReceipts
,
"parity_getBlockReceipts"
)
addMaybe
(
ParityGetBlockReceipts
,
"parity_getBlockReceipts"
)
addMaybe
(
EthGetBlockReceipts
,
"eth_getBlockReceipts"
)
addMaybe
(
EthGetBlockReceipts
,
"eth_getBlockReceipts"
)
addMaybe
(
ErigonGetBlockReceiptsByBlockHash
,
"erigon_getBlockReceiptsByBlockHash"
)
addMaybe
(
^
ReceiptsFetchingMethod
(
0
),
"unknown"
)
// if anything is left, describe it as unknown
addMaybe
(
^
ReceiptsFetchingMethod
(
0
),
"unknown"
)
// if anything is left, describe it as unknown
return
out
return
out
}
}
...
@@ -230,10 +231,9 @@ const (
...
@@ -230,10 +231,9 @@ const (
// - Nethermind: https://docs.nethermind.io/nethermind/ethereum-client/json-rpc/parity#parity_getblockreceipts
// - Nethermind: https://docs.nethermind.io/nethermind/ethereum-client/json-rpc/parity#parity_getblockreceipts
ParityGetBlockReceipts
ParityGetBlockReceipts
// EthGetBlockReceipts is a non-standard receipt fetching method in the eth namespace,
// EthGetBlockReceipts is a non-standard receipt fetching method in the eth namespace,
// supported by some RPC platforms
and Erigon
.
// supported by some RPC platforms.
// Available in:
// Available in:
// - Alchemy: 500 CU total (and deprecated)
// - Alchemy: 500 CU total (and deprecated)
// - Erigon: free
// - QuickNode: 59 credits total (does not seem to work with block hash arg, inaccurate docs)
// - QuickNode: 59 credits total (does not seem to work with block hash arg, inaccurate docs)
// Method: eth_getBlockReceipts
// Method: eth_getBlockReceipts
// Params:
// Params:
...
@@ -243,7 +243,21 @@ const (
...
@@ -243,7 +243,21 @@ const (
// See:
// See:
// - QuickNode: https://www.quicknode.com/docs/ethereum/eth_getBlockReceipts
// - QuickNode: https://www.quicknode.com/docs/ethereum/eth_getBlockReceipts
// - Alchemy: https://docs.alchemy.com/reference/eth-getblockreceipts
// - Alchemy: https://docs.alchemy.com/reference/eth-getblockreceipts
// Erigon has this available, but does not support block-hash argument to the method:
// https://github.com/ledgerwatch/erigon/blob/287a3d1d6c90fc6a7a088b5ae320f93600d5a167/cmd/rpcdaemon/commands/eth_receipts.go#L571
EthGetBlockReceipts
EthGetBlockReceipts
// ErigonGetBlockReceiptsByBlockHash is an Erigon-specific receipt fetching method,
// the same as EthGetBlockReceipts but supporting a block-hash argument.
// Available in:
// - Erigon
// Method: erigon_getBlockReceiptsByBlockHash
// Params:
// - Erigon: string, hex-encoded block hash
// Returns:
// - Erigon: array of json-ified receipts
// See:
// https://github.com/ledgerwatch/erigon/blob/287a3d1d6c90fc6a7a088b5ae320f93600d5a167/cmd/rpcdaemon/commands/erigon_receipts.go#LL391C24-L391C51
ErigonGetBlockReceiptsByBlockHash
// Other:
// Other:
// - 250 credits, not supported, strictly worse than other options. In quicknode price-table.
// - 250 credits, not supported, strictly worse than other options. In quicknode price-table.
...
@@ -269,13 +283,14 @@ func AvailableReceiptsFetchingMethods(kind RPCProviderKind) ReceiptsFetchingMeth
...
@@ -269,13 +283,14 @@ func AvailableReceiptsFetchingMethods(kind RPCProviderKind) ReceiptsFetchingMeth
case
RPCKindDebugGeth
:
case
RPCKindDebugGeth
:
return
DebugGetRawReceipts
|
EthGetTransactionReceiptBatch
return
DebugGetRawReceipts
|
EthGetTransactionReceiptBatch
case
RPCKindErigon
:
case
RPCKindErigon
:
return
E
thGetBlockReceipts
|
EthGetTransactionReceiptBatch
return
E
rigonGetBlockReceiptsByBlockHash
|
EthGetTransactionReceiptBatch
case
RPCKindBasic
:
case
RPCKindBasic
:
return
EthGetTransactionReceiptBatch
return
EthGetTransactionReceiptBatch
case
RPCKindAny
:
case
RPCKindAny
:
// if it's any kind of RPC provider, then try all methods
// if it's any kind of RPC provider, then try all methods
return
AlchemyGetTransactionReceipts
|
EthGetBlockReceipts
|
return
AlchemyGetTransactionReceipts
|
EthGetBlockReceipts
|
DebugGetRawReceipts
|
ParityGetBlockReceipts
|
EthGetTransactionReceiptBatch
DebugGetRawReceipts
|
ErigonGetBlockReceiptsByBlockHash
|
ParityGetBlockReceipts
|
EthGetTransactionReceiptBatch
default
:
default
:
return
EthGetTransactionReceiptBatch
return
EthGetTransactionReceiptBatch
}
}
...
@@ -310,6 +325,9 @@ func PickBestReceiptsFetchingMethod(kind RPCProviderKind, available ReceiptsFetc
...
@@ -310,6 +325,9 @@ func PickBestReceiptsFetchingMethod(kind RPCProviderKind, available ReceiptsFetc
if
available
&
DebugGetRawReceipts
!=
0
{
if
available
&
DebugGetRawReceipts
!=
0
{
return
DebugGetRawReceipts
return
DebugGetRawReceipts
}
}
if
available
&
ErigonGetBlockReceiptsByBlockHash
!=
0
{
return
ErigonGetBlockReceiptsByBlockHash
}
if
available
&
EthGetBlockReceipts
!=
0
{
if
available
&
EthGetBlockReceipts
!=
0
{
return
EthGetBlockReceipts
return
EthGetBlockReceipts
}
}
...
@@ -428,6 +446,8 @@ func (job *receiptsFetchingJob) runAltMethod(ctx context.Context, m ReceiptsFetc
...
@@ -428,6 +446,8 @@ func (job *receiptsFetchingJob) runAltMethod(ctx context.Context, m ReceiptsFetc
err
=
job
.
client
.
CallContext
(
ctx
,
&
result
,
"parity_getBlockReceipts"
,
job
.
block
.
Hash
)
err
=
job
.
client
.
CallContext
(
ctx
,
&
result
,
"parity_getBlockReceipts"
,
job
.
block
.
Hash
)
case
EthGetBlockReceipts
:
case
EthGetBlockReceipts
:
err
=
job
.
client
.
CallContext
(
ctx
,
&
result
,
"eth_getBlockReceipts"
,
job
.
block
.
Hash
)
err
=
job
.
client
.
CallContext
(
ctx
,
&
result
,
"eth_getBlockReceipts"
,
job
.
block
.
Hash
)
case
ErigonGetBlockReceiptsByBlockHash
:
err
=
job
.
client
.
CallContext
(
ctx
,
&
result
,
"erigon_getBlockReceiptsByBlockHash"
,
job
.
block
.
Hash
)
default
:
default
:
err
=
fmt
.
Errorf
(
"unknown receipt fetching method: %d"
,
uint64
(
m
))
err
=
fmt
.
Errorf
(
"unknown receipt fetching method: %d"
,
uint64
(
m
))
}
}
...
...
op-node/sources/receipts_test.go
View file @
87231e92
...
@@ -40,6 +40,15 @@ func (b *ethBackend) GetBlockReceipts(id string) ([]*types.Receipt, error) {
...
@@ -40,6 +40,15 @@ func (b *ethBackend) GetBlockReceipts(id string) ([]*types.Receipt, error) {
return
out
[
0
]
.
([]
*
types
.
Receipt
),
*
out
[
1
]
.
(
*
error
)
return
out
[
0
]
.
([]
*
types
.
Receipt
),
*
out
[
1
]
.
(
*
error
)
}
}
type
erigonBackend
struct
{
*
mock
.
Mock
}
func
(
b
*
erigonBackend
)
GetBlockReceiptsByBlockHash
(
id
string
)
([]
*
types
.
Receipt
,
error
)
{
out
:=
b
.
Mock
.
MethodCalled
(
"erigon_getBlockReceiptsByBlockHash"
,
id
)
return
out
[
0
]
.
([]
*
types
.
Receipt
),
*
out
[
1
]
.
(
*
error
)
}
type
alchemyBackend
struct
{
type
alchemyBackend
struct
{
*
mock
.
Mock
*
mock
.
Mock
}
}
...
@@ -99,6 +108,7 @@ func (tc *ReceiptsTestCase) Run(t *testing.T) {
...
@@ -99,6 +108,7 @@ func (tc *ReceiptsTestCase) Run(t *testing.T) {
require
.
NoError
(
t
,
srv
.
RegisterName
(
"alchemy"
,
&
alchemyBackend
{
Mock
:
m
}))
require
.
NoError
(
t
,
srv
.
RegisterName
(
"alchemy"
,
&
alchemyBackend
{
Mock
:
m
}))
require
.
NoError
(
t
,
srv
.
RegisterName
(
"debug"
,
&
debugBackend
{
Mock
:
m
}))
require
.
NoError
(
t
,
srv
.
RegisterName
(
"debug"
,
&
debugBackend
{
Mock
:
m
}))
require
.
NoError
(
t
,
srv
.
RegisterName
(
"parity"
,
&
parityBackend
{
Mock
:
m
}))
require
.
NoError
(
t
,
srv
.
RegisterName
(
"parity"
,
&
parityBackend
{
Mock
:
m
}))
require
.
NoError
(
t
,
srv
.
RegisterName
(
"erigon"
,
&
erigonBackend
{
Mock
:
m
}))
block
,
requests
:=
tc
.
setup
(
t
)
block
,
requests
:=
tc
.
setup
(
t
)
...
@@ -127,6 +137,8 @@ func (tc *ReceiptsTestCase) Run(t *testing.T) {
...
@@ -127,6 +137,8 @@ func (tc *ReceiptsTestCase) Run(t *testing.T) {
m
.
On
(
"parity_getBlockReceipts"
,
block
.
Hash
.
String
())
.
Once
()
.
Return
(
req
.
result
,
&
req
.
err
)
m
.
On
(
"parity_getBlockReceipts"
,
block
.
Hash
.
String
())
.
Once
()
.
Return
(
req
.
result
,
&
req
.
err
)
case
EthGetBlockReceipts
:
case
EthGetBlockReceipts
:
m
.
On
(
"eth_getBlockReceipts"
,
block
.
Hash
.
String
())
.
Once
()
.
Return
(
req
.
result
,
&
req
.
err
)
m
.
On
(
"eth_getBlockReceipts"
,
block
.
Hash
.
String
())
.
Once
()
.
Return
(
req
.
result
,
&
req
.
err
)
case
ErigonGetBlockReceiptsByBlockHash
:
m
.
On
(
"erigon_getBlockReceiptsByBlockHash"
,
block
.
Hash
.
String
())
.
Once
()
.
Return
(
req
.
result
,
&
req
.
err
)
default
:
default
:
t
.
Fatalf
(
"unrecognized request method: %d"
,
uint64
(
req
.
method
))
t
.
Fatalf
(
"unrecognized request method: %d"
,
uint64
(
req
.
method
))
}
}
...
@@ -286,7 +298,7 @@ func TestEthClient_FetchReceipts(t *testing.T) {
...
@@ -286,7 +298,7 @@ func TestEthClient_FetchReceipts(t *testing.T) {
{
{
name
:
"erigon"
,
name
:
"erigon"
,
providerKind
:
RPCKindErigon
,
providerKind
:
RPCKindErigon
,
setup
:
fallbackCase
(
4
,
E
thGetBlockReceipts
),
setup
:
fallbackCase
(
4
,
E
rigonGetBlockReceiptsByBlockHash
),
},
},
{
{
name
:
"basic"
,
name
:
"basic"
,
...
@@ -305,6 +317,7 @@ func TestEthClient_FetchReceipts(t *testing.T) {
...
@@ -305,6 +317,7 @@ func TestEthClient_FetchReceipts(t *testing.T) {
setup
:
fallbackCase
(
4
,
setup
:
fallbackCase
(
4
,
AlchemyGetTransactionReceipts
,
AlchemyGetTransactionReceipts
,
DebugGetRawReceipts
,
DebugGetRawReceipts
,
ErigonGetBlockReceiptsByBlockHash
,
EthGetBlockReceipts
,
EthGetBlockReceipts
,
ParityGetBlockReceipts
,
ParityGetBlockReceipts
,
),
),
...
...
packages/contracts-bedrock/.storage-layout
View file @
87231e92
...
@@ -248,3 +248,21 @@
...
@@ -248,3 +248,21 @@
| Name | Type | Slot | Offset | Bytes | Contract |
| Name | Type | Slot | Offset | Bytes | Contract |
|------|------|------|--------|-------|----------|
|------|------|------|--------|-------|----------|
=======================
➡ contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
=======================
| Name | Type | Slot | Offset | Bytes | Contract |
|--------------|-------------------------------------------------|------|--------|-------|-------------------------------------------------------------|
| _owner | address | 0 | 0 | 20 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| gameImpls | mapping(enum GameType => contract IDisputeGame) | 1 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
| disputeGames | mapping(Hash => contract IDisputeGame) | 2 | 0 | 32 | contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory |
=======================
➡ contracts/dispute/BondManager.sol:BondManager
=======================
| Name | Type | Slot | Offset | Bytes | Contract |
|-------|---------------------------------------------|------|--------|-------|-----------------------------------------------|
| bonds | mapping(bytes32 => struct BondManager.Bond) | 0 | 0 | 32 | contracts/dispute/BondManager.sol:BondManager |
packages/contracts-bedrock/contracts/dispute/BondManager.sol
View file @
87231e92
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity ^0.8.15;
import
{ GameType } from
"../libraries/DisputeTypes.sol";
import "../libraries/DisputeTypes.sol";
import { GameStatus } from "../libraries/DisputeTypes.sol";
import { SafeCall } from "../libraries/SafeCall.sol";
import { SafeCall } from "../libraries/SafeCall.sol";
import { IDisputeGame } from "./IDisputeGame.sol";
import { IDisputeGame } from "./interfaces/IDisputeGame.sol";
import { IDisputeGameFactory } from "./IDisputeGameFactory.sol";
import { IDisputeGameFactory } from "./interfaces/IDisputeGameFactory.sol";
import { IBondManager } from "./interfaces/IBondManager.sol";
/**
/**
* @title BondManager
* @title BondManager
* @notice The Bond Manager serves as an escrow for permissionless output proposal bonds.
* @notice The Bond Manager serves as an escrow for permissionless output proposal bonds.
*/
*/
contract BondManager {
contract BondManager
is IBondManager
{
/**
/**
* @notice The Bond Type
* @notice The Bond Type
*/
*/
struct Bond {
struct Bond {
address owner;
address owner;
uint256 expiration;
bytes32 id;
bytes32 id;
uint256 amount;
uint128 expiration;
uint128 amount;
}
}
/**
* @notice Mapping from bondId to bond.
*/
mapping(bytes32 => Bond) public bonds;
/**
* @notice BondPosted is emitted when a bond is posted.
* @param bondId is the id of the bond.
* @param owner is the address that owns the bond.
* @param expiration is the time at which the bond expires.
* @param amount is the amount of the bond.
*/
event BondPosted(bytes32 bondId, address owner, uint256 expiration, uint256 amount);
/**
* @notice BondSeized is emitted when a bond is seized.
* @param bondId is the id of the bond.
* @param owner is the address that owns the bond.
* @param seizer is the address that seized the bond.
* @param amount is the amount of the bond.
*/
event BondSeized(bytes32 bondId, address owner, address seizer, uint256 amount);
/**
* @notice BondReclaimed is emitted when a bond is reclaimed by the owner.
* @param bondId is the id of the bond.
* @param claiment is the address that reclaimed the bond.
* @param amount is the amount of the bond.
*/
event BondReclaimed(bytes32 bondId, address claiment, uint256 amount);
/**
/**
* @notice The permissioned dispute game factory.
* @notice The permissioned dispute game factory.
* @dev Used to verify the status of bonds.
* @dev Used to verify the status of bonds.
...
@@ -67,6 +37,11 @@ contract BondManager {
...
@@ -67,6 +37,11 @@ contract BondManager {
*/
*/
uint256 private constant TRANSFER_GAS = 30_000;
uint256 private constant TRANSFER_GAS = 30_000;
/**
* @notice Mapping from bondId to bond.
*/
mapping(bytes32 => Bond) public bonds;
/**
/**
* @notice Instantiates the bond maanger with the registered dispute game factory.
* @notice Instantiates the bond maanger with the registered dispute game factory.
* @param _disputeGameFactory is the dispute game factory.
* @param _disputeGameFactory is the dispute game factory.
...
@@ -76,37 +51,30 @@ contract BondManager {
...
@@ -76,37 +51,30 @@ contract BondManager {
}
}
/**
/**
* @notice Post a bond with a given id and owner.
* @inheritdoc IBondManager
* @dev This function will revert if the provided bondId is already in use.
* @param _bondId is the id of the bond.
* @param _bondOwner is the address that owns the bond.
* @param _minClaimHold is the minimum amount of time the owner
* must wait before reclaiming their bond.
*/
*/
function post(
function post(
bytes32 _bondId,
bytes32 _bondId,
address _bondOwner,
address _bondOwner,
uint
256
_minClaimHold
uint
128
_minClaimHold
) external payable {
) external payable {
require(bonds[_bondId].owner == address(0), "BondManager: BondId already posted.");
require(bonds[_bondId].owner == address(0), "BondManager: BondId already posted.");
require(_bondOwner != address(0), "BondManager: Owner cannot be the zero address.");
require(_bondOwner != address(0), "BondManager: Owner cannot be the zero address.");
require(msg.value > 0, "BondManager: Value must be non-zero.");
require(msg.value > 0, "BondManager: Value must be non-zero.");
uint
256 expiration = _minClaimHold + block.timestamp
;
uint
128 expiration = uint128(_minClaimHold + block.timestamp)
;
bonds[_bondId] = Bond({
bonds[_bondId] = Bond({
owner: _bondOwner,
owner: _bondOwner,
expiration: expiration,
id: _bondId,
id: _bondId,
amount: msg.value
expiration: expiration,
amount: uint128(msg.value)
});
});
emit BondPosted(_bondId, _bondOwner, expiration, msg.value);
emit BondPosted(_bondId, _bondOwner, expiration, msg.value);
}
}
/**
/**
* @notice Seizes the bond with the given id.
* @inheritdoc IBondManager
* @dev This function will revert if there is no bond at the given id.
* @param _bondId is the id of the bond.
*/
*/
function seize(bytes32 _bondId) external {
function seize(bytes32 _bondId) external {
Bond memory b = bonds[_bondId];
Bond memory b = bonds[_bondId];
...
@@ -131,10 +99,7 @@ contract BondManager {
...
@@ -131,10 +99,7 @@ contract BondManager {
}
}
/**
/**
* @notice Seizes the bond with the given id and distributes it to recipients.
* @inheritdoc IBondManager
* @dev This function will revert if there is no bond at the given id.
* @param _bondId is the id of the bond.
* @param _claimRecipients is a set of addresses to split the bond amongst.
*/
*/
function seizeAndSplit(bytes32 _bondId, address[] calldata _claimRecipients) external {
function seizeAndSplit(bytes32 _bondId, address[] calldata _claimRecipients) external {
Bond memory b = bonds[_bondId];
Bond memory b = bonds[_bondId];
...
@@ -168,9 +133,7 @@ contract BondManager {
...
@@ -168,9 +133,7 @@ contract BondManager {
}
}
/**
/**
* @notice Reclaims the bond of the bond owner.
* @inheritdoc IBondManager
* @dev This function will revert if there is no bond at the given id.
* @param _bondId is the id of the bond.
*/
*/
function reclaim(bytes32 _bondId) external {
function reclaim(bytes32 _bondId) external {
Bond memory b = bonds[_bondId];
Bond memory b = bonds[_bondId];
...
...
packages/contracts-bedrock/contracts/dispute/DisputeGameFactory.sol
View file @
87231e92
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity ^0.8.15;
import "../libraries/DisputeTypes.sol";
import "../libraries/DisputeErrors.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol";
import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol";
import { Claim } from "../libraries/DisputeTypes.sol";
import { IDisputeGame } from "./interfaces/IDisputeGame.sol";
import { Hash } from "../libraries/DisputeTypes.sol";
import { IDisputeGameFactory } from "./interfaces/IDisputeGameFactory.sol";
import { GameType } from "../libraries/DisputeTypes.sol";
import { NoImplementation } from "../libraries/DisputeErrors.sol";
import { GameAlreadyExists } from "../libraries/DisputeErrors.sol";
import { IDisputeGame } from "./IDisputeGame.sol";
import { IDisputeGameFactory } from "./IDisputeGameFactory.sol";
/**
/**
* @title DisputeGameFactory
* @title DisputeGameFactory
...
@@ -25,7 +21,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
...
@@ -25,7 +21,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
using ClonesWithImmutableArgs for address;
using ClonesWithImmutableArgs for address;
/**
/**
* @
notice Mapping of `GameType`s to their respective `IDisputeGame` implementations.
* @
inheritdoc IDisputeGameFactory
*/
*/
mapping(GameType => IDisputeGame) public gameImpls;
mapping(GameType => IDisputeGame) public gameImpls;
...
@@ -45,16 +41,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
...
@@ -45,16 +41,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
}
}
/**
/**
* @notice Retrieves the hash of `gameType . rootClaim . extraData`
* @inheritdoc IDisputeGameFactory
* to the deployed `DisputeGame` clone.
* @dev Note: `.` denotes concatenation.
* @param gameType The type of the DisputeGame.
* Used to decide the implementation to clone.
* @param rootClaim The root claim of the DisputeGame.
* @param extraData Any extra data that should be provided to the
* created dispute game.
* @return _proxy The clone of the `DisputeGame` created with the
* given parameters. `address(0)` if nonexistent.
*/
*/
function games(
function games(
GameType gameType,
GameType gameType,
...
@@ -65,15 +52,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
...
@@ -65,15 +52,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
}
}
/**
/**
* @notice Creates a new DisputeGame proxy contract.
* @inheritdoc IDisputeGameFactory
* @notice If a dispute game with the given parameters already exists,
* it will be returned.
* @param gameType The type of the DisputeGame.
* Used to decide the proxy implementation.
* @param rootClaim The root claim of the DisputeGame.
* @param extraData Any extra data that should be provided
* to the created dispute game.
* @return proxy The clone of the `DisputeGame`.
*/
*/
function create(
function create(
GameType gameType,
GameType gameType,
...
@@ -89,8 +68,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
...
@@ -89,8 +68,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
}
}
// Clone the implementation contract and initialize it with the given parameters.
// Clone the implementation contract and initialize it with the given parameters.
bytes memory data = abi.encodePacked(rootClaim, extraData);
proxy = IDisputeGame(address(impl).clone(abi.encodePacked(rootClaim, extraData)));
proxy = IDisputeGame(address(impl).clone(data));
proxy.initialize();
proxy.initialize();
// Compute the unique identifier for the dispute game.
// Compute the unique identifier for the dispute game.
...
@@ -107,23 +85,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
...
@@ -107,23 +85,7 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
}
}
/**
/**
* @notice Sets the implementation contract for a specific `GameType`.
* @inheritdoc IDisputeGameFactory
* @param gameType The type of the DisputeGame.
* @param impl The implementation contract for the given `GameType`.
*/
function setImplementation(GameType gameType, IDisputeGame impl) external onlyOwner {
gameImpls[gameType] = impl;
emit ImplementationSet(address(impl), gameType);
}
/**
* @notice Returns a unique identifier for the given dispute game parameters.
* @dev Hashes the concatenation of `gameType . rootClaim . extraData`
* without expanding memory.
* @param gameType The type of the DisputeGame.
* @param rootClaim The root claim of the DisputeGame.
* @param extraData Any extra data that should be provided to the created dispute game.
* @return _uuid The unique identifier for the given dispute game parameters.
*/
*/
function getGameUUID(
function getGameUUID(
GameType gameType,
GameType gameType,
...
@@ -160,4 +122,12 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
...
@@ -160,4 +122,12 @@ contract DisputeGameFactory is Ownable, IDisputeGameFactory {
mstore(pointerOffset, tempC)
mstore(pointerOffset, tempC)
}
}
}
}
/**
* @inheritdoc IDisputeGameFactory
*/
function setImplementation(GameType gameType, IDisputeGame impl) external onlyOwner {
gameImpls[gameType] = impl;
emit ImplementationSet(address(impl), gameType);
}
}
}
packages/contracts-bedrock/contracts/dispute/IAttestationDisputeGame.sol
deleted
100644 → 0
View file @
b8c10f77
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import { IDisputeGame } from "./IDisputeGame.sol";
/**
* @title IAttestationDisputeGame
* @notice The interface for an attestation-based DisputeGame meant to contest output
* proposals in Optimism's `L2OutputOracle` contract.
*/
interface IAttestationDisputeGame is IDisputeGame {
/**
* @notice A mapping of addresses from the `signerSet` to booleans signifying whether
* or not they have authorized the `rootClaim` to be invalidated.
* @param challenger The address to check for authorization.
* @return _challenged Whether or not the `challenger` has challenged the `rootClaim`.
*/
function challenges(address challenger) external view returns (bool _challenged);
/**
* @notice The signer set consists of authorized public keys that may challenge
* the `rootClaim`.
* @param addr The address to check for authorization.
* @return _isAuthorized Whether or not the `addr` is part of the signer set.
*/
function signerSet(address addr) external view returns (bool _isAuthorized);
/**
* @notice The amount of signatures required to successfully challenge the `rootClaim`
* output proposal. Once this threshold is met by members of the `signerSet`
* calling `challenge`, the game will be resolved to `CHALLENGER_WINS`.
* @custom:invariant The `signatureThreshold` may never be greater than the length
* of the `signerSet`.
* @return _signatureThreshold The amount of signatures required to successfully
* challenge the `rootClaim` output proposal.
*/
function frozenSignatureThreshold() external view returns (uint256 _signatureThreshold);
/**
* @notice Returns the L2 Block Number that the `rootClaim` commits to.
* Exists within the `extraData`.
* @return _l2BlockNumber The L2 Block Number that the `rootClaim` commits to.
*/
function l2BlockNumber() external view returns (uint256 _l2BlockNumber);
/**
* @notice Challenge the `rootClaim`.
* @dev - If the `ecrecover`ed address that created the signature is not a part of
* the signer set returned by `signerSet`, this function should revert.
* - If the `ecrecover`ed address that created the signature is not the
* msg.sender, this function should revert.
* - If the signature provided is the signature that breaches the signature
* threshold, the function should call the `resolve` function to resolve
* the game as `CHALLENGER_WINS`.
* - When the game resolves, the bond attached to the root claim should be
* distributed among the signers who participated in challenging the
* invalid claim.
* @param signature An EIP-712 signature committing to the `rootClaim` and
* `l2BlockNumber` (within the `extraData`) from a key that exists
* within the `signerSet`.
*/
function challenge(bytes calldata signature) external;
}
packages/contracts-bedrock/contracts/dispute/IBondManager.sol
→
packages/contracts-bedrock/contracts/dispute/
interfaces/
IBondManager.sol
View file @
87231e92
...
@@ -6,6 +6,32 @@ pragma solidity ^0.8.15;
...
@@ -6,6 +6,32 @@ pragma solidity ^0.8.15;
* @notice The Bond Manager holds ether posted as a bond for a bond id.
* @notice The Bond Manager holds ether posted as a bond for a bond id.
*/
*/
interface IBondManager {
interface IBondManager {
/**
* @notice BondPosted is emitted when a bond is posted.
* @param bondId is the id of the bond.
* @param owner is the address that owns the bond.
* @param expiration is the time at which the bond expires.
* @param amount is the amount of the bond.
*/
event BondPosted(bytes32 bondId, address owner, uint256 expiration, uint256 amount);
/**
* @notice BondSeized is emitted when a bond is seized.
* @param bondId is the id of the bond.
* @param owner is the address that owns the bond.
* @param seizer is the address that seized the bond.
* @param amount is the amount of the bond.
*/
event BondSeized(bytes32 bondId, address owner, address seizer, uint256 amount);
/**
* @notice BondReclaimed is emitted when a bond is reclaimed by the owner.
* @param bondId is the id of the bond.
* @param claiment is the address that reclaimed the bond.
* @param amount is the amount of the bond.
*/
event BondReclaimed(bytes32 bondId, address claiment, uint256 amount);
/**
/**
* @notice Post a bond with a given id and owner.
* @notice Post a bond with a given id and owner.
* @dev This function will revert if the provided bondId is already in use.
* @dev This function will revert if the provided bondId is already in use.
...
@@ -17,7 +43,7 @@ interface IBondManager {
...
@@ -17,7 +43,7 @@ interface IBondManager {
function post(
function post(
bytes32 _bondId,
bytes32 _bondId,
address _bondOwner,
address _bondOwner,
uint
256
_minClaimHold
uint
128
_minClaimHold
) external payable;
) external payable;
/**
/**
...
...
packages/contracts-bedrock/contracts/dispute/IDisputeGame.sol
→
packages/contracts-bedrock/contracts/dispute/
interfaces/
IDisputeGame.sol
View file @
87231e92
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity ^0.8.15;
import { Claim } from "../libraries/DisputeTypes.sol";
import "../../libraries/DisputeTypes.sol";
import { GameType } from "../libraries/DisputeTypes.sol";
import { GameStatus } from "../libraries/DisputeTypes.sol";
import { Timestamp } from "../libraries/DisputeTypes.sol";
import { IVersioned } from "./IVersioned.sol";
import { IVersioned } from "./IVersioned.sol";
import { IBondManager } from "./IBondManager.sol";
import { IBondManager } from "./IBondManager.sol";
...
@@ -21,8 +18,6 @@ interface IDisputeGame is IInitializable, IVersioned {
...
@@ -21,8 +18,6 @@ interface IDisputeGame is IInitializable, IVersioned {
*/
*/
event Resolved(GameStatus indexed status);
event Resolved(GameStatus indexed status);
/// @notice Returns the timestamp that the DisputeGame contract was created at.
/**
/**
* @notice Returns the timestamp that the DisputeGame contract was created at.
* @notice Returns the timestamp that the DisputeGame contract was created at.
* @return _createdAt The timestamp that the DisputeGame contract was created at.
* @return _createdAt The timestamp that the DisputeGame contract was created at.
...
@@ -42,21 +37,21 @@ interface IDisputeGame is IInitializable, IVersioned {
...
@@ -42,21 +37,21 @@ interface IDisputeGame is IInitializable, IVersioned {
* i.e. The game type should indicate the security model.
* i.e. The game type should indicate the security model.
* @return _gameType The type of proof system being used.
* @return _gameType The type of proof system being used.
*/
*/
function gameType() external
view
returns (GameType _gameType);
function gameType() external
pure
returns (GameType _gameType);
/**
/**
* @notice Getter for the root claim.
* @notice Getter for the root claim.
* @dev `clones-with-immutable-args` argument #2
* @dev `clones-with-immutable-args` argument #2
* @return _rootClaim The root claim of the DisputeGame.
* @return _rootClaim The root claim of the DisputeGame.
*/
*/
function rootClaim() external
view
returns (Claim _rootClaim);
function rootClaim() external
pure
returns (Claim _rootClaim);
/**
/**
* @notice Getter for the extra data.
* @notice Getter for the extra data.
* @dev `clones-with-immutable-args` argument #3
* @dev `clones-with-immutable-args` argument #3
* @return _extraData Any extra data supplied to the dispute game contract by the creator.
* @return _extraData Any extra data supplied to the dispute game contract by the creator.
*/
*/
function extraData() external
view
returns (bytes memory _extraData);
function extraData() external
pure
returns (bytes memory _extraData);
/**
/**
* @notice Returns the address of the `BondManager` used.
* @notice Returns the address of the `BondManager` used.
...
@@ -73,4 +68,19 @@ interface IDisputeGame is IInitializable, IVersioned {
...
@@ -73,4 +68,19 @@ interface IDisputeGame is IInitializable, IVersioned {
* @return _status The status of the game after resolution.
* @return _status The status of the game after resolution.
*/
*/
function resolve() external returns (GameStatus _status);
function resolve() external returns (GameStatus _status);
/**
* @notice A compliant implementation of this interface should return the components of the
* game UUID's preimage provided in the cwia payload. The preimage of the UUID is
* constructed as `keccak256(gameType . rootClaim . extraData)` where `.` denotes
* concatenation.
*/
function gameData()
external
pure
returns (
GameType _gameType,
Claim _rootClaim,
bytes memory _extraData
);
}
}
packages/contracts-bedrock/contracts/dispute/IDisputeGameFactory.sol
→
packages/contracts-bedrock/contracts/dispute/
interfaces/
IDisputeGameFactory.sol
View file @
87231e92
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity ^0.8.15;
import { Claim } from "../libraries/DisputeTypes.sol";
import "../../libraries/DisputeTypes.sol";
import { GameType } from "../libraries/DisputeTypes.sol";
import { IDisputeGame } from "./IDisputeGame.sol";
import { IDisputeGame } from "./IDisputeGame.sol";
...
@@ -75,4 +74,19 @@ interface IDisputeGameFactory {
...
@@ -75,4 +74,19 @@ interface IDisputeGameFactory {
* @param impl The implementation contract for the given `GameType`.
* @param impl The implementation contract for the given `GameType`.
*/
*/
function setImplementation(GameType gameType, IDisputeGame impl) external;
function setImplementation(GameType gameType, IDisputeGame impl) external;
/**
* @notice Returns a unique identifier for the given dispute game parameters.
* @dev Hashes the concatenation of `gameType . rootClaim . extraData`
* without expanding memory.
* @param gameType The type of the DisputeGame.
* @param rootClaim The root claim of the DisputeGame.
* @param extraData Any extra data that should be provided to the created dispute game.
* @return _uuid The unique identifier for the given dispute game parameters.
*/
function getGameUUID(
GameType gameType,
Claim rootClaim,
bytes memory extraData
) external pure returns (Hash _uuid);
}
}
packages/contracts-bedrock/contracts/dispute/IFaultDisputeGame.sol
→
packages/contracts-bedrock/contracts/dispute/
interfaces/
IFaultDisputeGame.sol
View file @
87231e92
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
pragma solidity ^0.8.15;
import { Clock } from "../libraries/DisputeTypes.sol";
import "../../libraries/DisputeTypes.sol";
import { Claim } from "../libraries/DisputeTypes.sol";
import { Position } from "../libraries/DisputeTypes.sol";
import { Timestamp } from "../libraries/DisputeTypes.sol";
import { ClaimHash } from "../libraries/DisputeTypes.sol";
import { BondAmount } from "../libraries/DisputeTypes.sol";
import { IDisputeGame } from "./IDisputeGame.sol";
import { IDisputeGame } from "./IDisputeGame.sol";
...
@@ -33,12 +28,6 @@ interface IFaultDisputeGame is IDisputeGame {
...
@@ -33,12 +28,6 @@ interface IFaultDisputeGame is IDisputeGame {
*/
*/
event Defend(ClaimHash indexed claimHash, Claim indexed pivot, address indexed claimant);
event Defend(ClaimHash indexed claimHash, Claim indexed pivot, address indexed claimant);
/**
* @notice State variable of the starting timestamp of the game, set on deployment.
* @return The starting timestamp of the game
*/
function gameStart() external view returns (Timestamp);
/**
/**
* @notice Maps a unique ClaimHash to a Claim.
* @notice Maps a unique ClaimHash to a Claim.
* @param claimHash The unique ClaimHash
* @param claimHash The unique ClaimHash
...
...
packages/contracts-bedrock/contracts/dispute/IInitializable.sol
→
packages/contracts-bedrock/contracts/dispute/
interfaces/
IInitializable.sol
View file @
87231e92
File moved
packages/contracts-bedrock/contracts/dispute/IVersioned.sol
→
packages/contracts-bedrock/contracts/dispute/
interfaces/
IVersioned.sol
View file @
87231e92
File moved
packages/contracts-bedrock/contracts/libraries/Clone.sol
0 → 100644
View file @
87231e92
// SPDX-License-Identifier: BSD
pragma solidity ^0.8.15;
// solhint-disable
/**
* @title Clone
* @author zefram.eth, Saw-mon & Natalie, clabby
* @notice Provides helper functions for reading immutable args from calldata
* @dev Original: https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args/blob/105efee1b9127ed7f6fedf139e1fc796ce8791f2/src/Clone.sol
* @dev MODIFICATIONS:
* - Added `_getArgDynBytes` function.
*/
// solhint-enable
contract Clone {
uint256 private constant ONE_WORD = 0x20;
/**
* @notice Reads an immutable arg with type address
* @param argOffset The offset of the arg in the packed data
* @return arg The arg value
*/
function _getArgAddress(uint256 argOffset) internal pure returns (address arg) {
uint256 offset = _getImmutableArgsOffset();
assembly {
arg := shr(0x60, calldataload(add(offset, argOffset)))
}
}
/**
* @notice Reads an immutable arg with type uint256
* @param argOffset The offset of the arg in the packed data
* @return arg The arg value
*/
function _getArgUint256(uint256 argOffset) internal pure returns (uint256 arg) {
uint256 offset = _getImmutableArgsOffset();
assembly {
arg := calldataload(add(offset, argOffset))
}
}
/**
* @notice Reads an immutable arg with type bytes32
* @param argOffset The offset of the arg in the packed data
* @return arg The arg value
*/
function _getArgFixedBytes(uint256 argOffset) internal pure returns (bytes32 arg) {
uint256 offset = _getImmutableArgsOffset();
assembly {
arg := calldataload(add(offset, argOffset))
}
}
/**
* @notice Reads a uint256 array stored in the immutable args.
* @param argOffset The offset of the arg in the packed data
* @param arrLen Number of elements in the array
* @return arr The array
*/
function _getArgUint256Array(uint256 argOffset, uint64 arrLen)
internal
pure
returns (uint256[] memory arr)
{
uint256 offset = _getImmutableArgsOffset() + argOffset;
arr = new uint256[](arrLen);
assembly {
calldatacopy(add(arr, ONE_WORD), offset, shl(5, arrLen))
}
}
/**
* @notice Reads a dynamic bytes array stored in the immutable args.
* @param argOffset The offset of the arg in the packed data
* @param arrLen Number of elements in the array
* @return arr The array
*/
function _getArgDynBytes(uint256 argOffset, uint64 arrLen)
internal
pure
returns (bytes memory arr)
{
uint256 offset = _getImmutableArgsOffset() + argOffset;
arr = new bytes(arrLen);
assembly {
calldatacopy(add(arr, ONE_WORD), offset, arrLen)
}
}
/**
* @notice Reads an immutable arg with type uint64
* @param argOffset The offset of the arg in the packed data
* @return arg The arg value
*/
function _getArgUint64(uint256 argOffset) internal pure returns (uint64 arg) {
uint256 offset = _getImmutableArgsOffset();
assembly {
arg := shr(0xc0, calldataload(add(offset, argOffset)))
}
}
/**
* @notice Reads an immutable arg with type uint8
* @param argOffset The offset of the arg in the packed data
* @return arg The arg value
*/
function _getArgUint8(uint256 argOffset) internal pure returns (uint8 arg) {
uint256 offset = _getImmutableArgsOffset();
assembly {
arg := shr(0xf8, calldataload(add(offset, argOffset)))
}
}
/**
* @return offset The offset of the packed immutable args in calldata
*/
function _getImmutableArgsOffset() internal pure returns (uint256 offset) {
assembly {
offset := sub(calldatasize(), shr(0xf0, calldataload(sub(calldatasize(), 2))))
}
}
}
packages/contracts-bedrock/contracts/test/BondManager.t.sol
View file @
87231e92
...
@@ -5,8 +5,8 @@ import "forge-std/Test.sol";
...
@@ -5,8 +5,8 @@ import "forge-std/Test.sol";
import "../libraries/DisputeTypes.sol";
import "../libraries/DisputeTypes.sol";
import { IDisputeGame } from "../dispute/IDisputeGame.sol";
import { IDisputeGame } from "../dispute/
interfaces/
IDisputeGame.sol";
import { IBondManager } from "../dispute/IBondManager.sol";
import { IBondManager } from "../dispute/
interfaces/
IBondManager.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
...
@@ -45,23 +45,21 @@ contract BondManager_Test is Test {
...
@@ -45,23 +45,21 @@ contract BondManager_Test is Test {
function testFuzz_post_succeeds(
function testFuzz_post_succeeds(
bytes32 bondId,
bytes32 bondId,
address owner,
address owner,
uint
256
minClaimHold,
uint
128
minClaimHold,
uint
256
amount
uint
128
amount
) public {
) public {
vm.assume(owner != address(0));
vm.assume(owner != address(0));
vm.assume(owner != address(bm));
vm.assume(owner != address(bm));
vm.assume(owner != address(this));
vm.assume(owner != address(this));
// Create2Deployer
// Create2Deployer
vm.assume(owner != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));
vm.assume(owner != address(0x4e59b44847b379578588920cA78FbF26c0B4956C));
vm.assume(amount != 0);
amount = uint128(bound(amount, 1, type(uint128).max));
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold > minClaimHold);
}
vm.deal(address(this), amount);
vm.deal(address(this), amount);
vm.expectEmit(true, true, true, true);
vm.expectEmit(true, true, true, true);
uint
256 expiration = block.timestamp + minClaimHold
;
uint
128 expiration = uint128(block.timestamp + minClaimHold)
;
emit BondPosted(bondId, owner, expiration, amount);
emit BondPosted(bondId, owner, expiration, amount);
bm.post{ value: amount }(bondId, owner, minClaimHold);
bm.post{ value: amount }(bondId, owner, minClaimHold);
...
@@ -69,9 +67,9 @@ contract BondManager_Test is Test {
...
@@ -69,9 +67,9 @@ contract BondManager_Test is Test {
// Validate the bond
// Validate the bond
(
(
address newFetchedOwner,
address newFetchedOwner,
uint256 fetchedExpiration,
bytes32 fetchedBondId,
bytes32 fetchedBondId,
uint256 bondAmount
uint128 fetchedExpiration,
uint128 bondAmount
) = bm.bonds(bondId);
) = bm.bonds(bondId);
assertEq(newFetchedOwner, owner);
assertEq(newFetchedOwner, owner);
assertEq(fetchedExpiration, block.timestamp + minClaimHold);
assertEq(fetchedExpiration, block.timestamp + minClaimHold);
...
@@ -85,15 +83,13 @@ contract BondManager_Test is Test {
...
@@ -85,15 +83,13 @@ contract BondManager_Test is Test {
function testFuzz_post_duplicates_reverts(
function testFuzz_post_duplicates_reverts(
bytes32 bondId,
bytes32 bondId,
address owner,
address owner,
uint
256
minClaimHold,
uint
128
minClaimHold,
uint
256
amount
uint
128
amount
) public {
) public {
vm.assume(owner != address(0));
vm.assume(owner != address(0));
amount = amount / 2;
amount = amount / 2;
vm.assume(amount != 0);
amount = uint128(bound(amount, 1, type(uint128).max));
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold > minClaimHold);
}
vm.deal(address(this), amount);
vm.deal(address(this), amount);
bm.post{ value: amount }(bondId, owner, minClaimHold);
bm.post{ value: amount }(bondId, owner, minClaimHold);
...
@@ -108,8 +104,8 @@ contract BondManager_Test is Test {
...
@@ -108,8 +104,8 @@ contract BondManager_Test is Test {
*/
*/
function testFuzz_post_zeroAddress_reverts(
function testFuzz_post_zeroAddress_reverts(
bytes32 bondId,
bytes32 bondId,
uint
256
minClaimHold,
uint
128
minClaimHold,
uint
256
amount
uint
128
amount
) public {
) public {
address owner = address(0);
address owner = address(0);
vm.deal(address(this), amount);
vm.deal(address(this), amount);
...
@@ -123,10 +119,10 @@ contract BondManager_Test is Test {
...
@@ -123,10 +119,10 @@ contract BondManager_Test is Test {
function testFuzz_post_zeroAddress_reverts(
function testFuzz_post_zeroAddress_reverts(
bytes32 bondId,
bytes32 bondId,
address owner,
address owner,
uint
256
minClaimHold
uint
128
minClaimHold
) public {
) public {
vm.assume(owner != address(0));
vm.assume(owner != address(0));
uint
256
amount = 0;
uint
128
amount = 0;
vm.deal(address(this), amount);
vm.deal(address(this), amount);
vm.expectRevert("BondManager: Value must be non-zero.");
vm.expectRevert("BondManager: Value must be non-zero.");
bm.post{ value: amount }(bondId, owner, minClaimHold);
bm.post{ value: amount }(bondId, owner, minClaimHold);
...
@@ -152,16 +148,14 @@ contract BondManager_Test is Test {
...
@@ -152,16 +148,14 @@ contract BondManager_Test is Test {
function testFuzz_seize_expired_reverts(
function testFuzz_seize_expired_reverts(
bytes32 bondId,
bytes32 bondId,
address owner,
address owner,
uint
256
minClaimHold,
uint
128
minClaimHold,
uint
256
amount
uint
128
amount
) public {
) public {
vm.assume(owner != address(0));
vm.assume(owner != address(0));
vm.assume(owner != address(bm));
vm.assume(owner != address(bm));
vm.assume(owner != address(this));
vm.assume(owner != address(this));
vm.assume(amount != 0);
amount = uint128(bound(amount, 1, type(uint128).max));
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold + 1 > minClaimHold);
}
vm.deal(address(this), amount);
vm.deal(address(this), amount);
bm.post{ value: amount }(bondId, owner, minClaimHold);
bm.post{ value: amount }(bondId, owner, minClaimHold);
...
@@ -176,16 +170,15 @@ contract BondManager_Test is Test {
...
@@ -176,16 +170,15 @@ contract BondManager_Test is Test {
function testFuzz_seize_unauthorized_reverts(
function testFuzz_seize_unauthorized_reverts(
bytes32 bondId,
bytes32 bondId,
address owner,
address owner,
uint
256
minClaimHold,
uint
128
minClaimHold,
uint
256
amount
uint
128
amount
) public {
) public {
vm.assume(owner != address(0));
vm.assume(owner != address(0));
vm.assume(owner != address(bm));
vm.assume(owner != address(bm));
vm.assume(owner != address(this));
vm.assume(owner != address(this));
vm.assume(amount != 0);
amount = uint128(bound(amount, 1, type(uint128).max));
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold > minClaimHold);
}
vm.deal(address(this), amount);
vm.deal(address(this), amount);
bm.post{ value: amount }(bondId, owner, minClaimHold);
bm.post{ value: amount }(bondId, owner, minClaimHold);
...
@@ -200,12 +193,10 @@ contract BondManager_Test is Test {
...
@@ -200,12 +193,10 @@ contract BondManager_Test is Test {
*/
*/
function testFuzz_seize_succeeds(
function testFuzz_seize_succeeds(
bytes32 bondId,
bytes32 bondId,
uint
256
minClaimHold,
uint
128
minClaimHold,
bytes calldata extraData
bytes calldata extraData
) public {
) public {
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold > minClaimHold);
}
vm.deal(address(this), 1 ether);
vm.deal(address(this), 1 ether);
bm.post{ value: 1 ether }(bondId, address(0xba5ed), minClaimHold);
bm.post{ value: 1 ether }(bondId, address(0xba5ed), minClaimHold);
...
@@ -255,12 +246,10 @@ contract BondManager_Test is Test {
...
@@ -255,12 +246,10 @@ contract BondManager_Test is Test {
*/
*/
function testFuzz_seizeAndSplit_succeeds(
function testFuzz_seizeAndSplit_succeeds(
bytes32 bondId,
bytes32 bondId,
uint
256
minClaimHold,
uint
128
minClaimHold,
bytes calldata extraData
bytes calldata extraData
) public {
) public {
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold > minClaimHold);
}
vm.deal(address(this), 1 ether);
vm.deal(address(this), 1 ether);
bm.post{ value: 1 ether }(bondId, address(0xba5ed), minClaimHold);
bm.post{ value: 1 ether }(bondId, address(0xba5ed), minClaimHold);
...
@@ -316,15 +305,16 @@ contract BondManager_Test is Test {
...
@@ -316,15 +305,16 @@ contract BondManager_Test is Test {
function testFuzz_reclaim_succeeds(
function testFuzz_reclaim_succeeds(
bytes32 bondId,
bytes32 bondId,
address owner,
address owner,
uint
256
minClaimHold,
uint
128
minClaimHold,
uint
256
amount
uint
128
amount
) public {
) public {
vm.assume(owner != address(factory));
vm.assume(owner != address(bm));
vm.assume(owner != address(this));
vm.assume(owner != address(0));
vm.assume(owner != address(0));
vm.assume(owner.code.length == 0);
vm.assume(owner.code.length == 0);
vm.assume(amount != 0);
amount = uint128(bound(amount, 1, type(uint128).max));
unchecked {
minClaimHold = uint128(bound(minClaimHold, 0, type(uint128).max - block.timestamp));
vm.assume(block.timestamp + minClaimHold > minClaimHold);
}
assumeNoPrecompiles(owner);
assumeNoPrecompiles(owner);
// Post the bond
// Post the bond
...
@@ -332,7 +322,7 @@ contract BondManager_Test is Test {
...
@@ -332,7 +322,7 @@ contract BondManager_Test is Test {
bm.post{ value: amount }(bondId, owner, minClaimHold);
bm.post{ value: amount }(bondId, owner, minClaimHold);
// We can't claim if the block.timestamp is less than the bond expiration.
// We can't claim if the block.timestamp is less than the bond expiration.
(,
uint256 expiration,
, ) = bm.bonds(bondId);
(,
, uint256 expiration
, ) = bm.bonds(bondId);
if (expiration > block.timestamp) {
if (expiration > block.timestamp) {
vm.prank(owner);
vm.prank(owner);
vm.expectRevert("BondManager: Bond isn't claimable yet.");
vm.expectRevert("BondManager: Bond isn't claimable yet.");
...
@@ -351,7 +341,7 @@ contract BondManager_Test is Test {
...
@@ -351,7 +341,7 @@ contract BondManager_Test is Test {
* @title MockAttestationDisputeGame
* @title MockAttestationDisputeGame
* @dev A mock dispute game for testing bond seizures.
* @dev A mock dispute game for testing bond seizures.
*/
*/
contract MockAttestationDisputeGame
is IDisputeGame
{
contract MockAttestationDisputeGame {
GameStatus internal gameStatus;
GameStatus internal gameStatus;
BondManager bm;
BondManager bm;
Claim internal rc;
Claim internal rc;
...
@@ -419,11 +409,11 @@ contract MockAttestationDisputeGame is IDisputeGame {
...
@@ -419,11 +409,11 @@ contract MockAttestationDisputeGame is IDisputeGame {
* -------------------------------------------
* -------------------------------------------
*/
*/
function createdAt() external pure
override
returns (Timestamp _createdAt) {
function createdAt() external pure returns (Timestamp _createdAt) {
return Timestamp.wrap(uint64(0));
return Timestamp.wrap(uint64(0));
}
}
function status() external view
override
returns (GameStatus _status) {
function status() external view returns (GameStatus _status) {
return gameStatus;
return gameStatus;
}
}
...
@@ -431,7 +421,7 @@ contract MockAttestationDisputeGame is IDisputeGame {
...
@@ -431,7 +421,7 @@ contract MockAttestationDisputeGame is IDisputeGame {
return GameType.ATTESTATION;
return GameType.ATTESTATION;
}
}
function rootClaim() external view
override
returns (Claim _rootClaim) {
function rootClaim() external view returns (Claim _rootClaim) {
return rc;
return rc;
}
}
...
@@ -439,7 +429,21 @@ contract MockAttestationDisputeGame is IDisputeGame {
...
@@ -439,7 +429,21 @@ contract MockAttestationDisputeGame is IDisputeGame {
return ed;
return ed;
}
}
function bondManager() external view override returns (IBondManager _bondManager) {
function gameData()
external
pure
returns (
GameType,
Claim,
bytes memory
)
{
assembly {
revert(0, 0)
}
}
function bondManager() external view returns (IBondManager _bondManager) {
return IBondManager(address(bm));
return IBondManager(address(bm));
}
}
...
...
packages/contracts-bedrock/contracts/test/Clones.t.sol
0 → 100644
View file @
87231e92
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "forge-std/Test.sol";
import { ClonesWithImmutableArgs } from "@cwia/ClonesWithImmutableArgs.sol";
import { Clone } from "../libraries/Clone.sol";
contract ExampleClone is Clone {
uint256 argOffset;
constructor(uint256 _argOffset) {
argOffset = _argOffset;
}
function addressArg() public view returns (address) {
return _getArgAddress(argOffset);
}
function uintArg() public view returns (uint256) {
return _getArgUint256(argOffset);
}
function fixedBytesArg() public view returns (bytes32) {
return _getArgFixedBytes(argOffset);
}
function uintArrayArg(uint64 arrLen) public view returns (uint256[] memory) {
return _getArgUint256Array(argOffset, arrLen);
}
function dynBytesArg(uint64 arrLen) public view returns (bytes memory) {
return _getArgDynBytes(argOffset, arrLen);
}
function uint64Arg() public view returns (uint64) {
return _getArgUint64(argOffset);
}
function uint8Arg() public view returns (uint8) {
return _getArgUint8(argOffset);
}
}
contract ExampleCloneFactory {
using ClonesWithImmutableArgs for address;
ExampleClone public implementation;
constructor(ExampleClone implementation_) {
implementation = implementation_;
}
function createAddressClone(address arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createUintClone(uint256 arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createFixedBytesClone(bytes32 arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createUintArrayClone(uint256[] memory arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createDynBytesClone(bytes memory arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createUint64Clone(uint64 arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createUint8Clone(uint8 arg) external returns (ExampleClone clone) {
bytes memory data = abi.encodePacked(arg);
clone = ExampleClone(address(implementation).clone(data));
}
function createClone(bytes memory randomCalldata) external returns (ExampleClone clone) {
clone = ExampleClone(address(implementation).clone(randomCalldata));
}
}
contract Clones_Test is Test {
function testFuzz_clone_addressArg_succeeds(uint256 argOffset, address param) public {
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createAddressClone(param);
address fetched = clone.addressArg();
assertEq(fetched, param);
}
function testFuzz_clone_uintArg_succeeds(uint256 argOffset, uint256 param) public {
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createUintClone(param);
uint256 fetched = clone.uintArg();
assertEq(fetched, param);
}
function testFuzz_clone_fixedBytesArg_succeeds(uint256 argOffset, bytes32 param) public {
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createFixedBytesClone(param);
bytes32 fetched = clone.fixedBytesArg();
assertEq(fetched, param);
}
function testFuzz_clone_uintArrayArg_succeeds(uint256 argOffset, uint256[] memory param)
public
{
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createUintArrayClone(param);
uint256[] memory fetched = clone.uintArrayArg(uint64(param.length));
assertEq(fetched, param);
}
function testFuzz_clone_dynBytesArg_succeeds(uint256 argOffset, bytes memory param) public {
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createDynBytesClone(param);
bytes memory fetched = clone.dynBytesArg(uint64(param.length));
assertEq(fetched, param);
}
function testFuzz_clone_uint64Arg_succeeds(uint256 argOffset, uint64 param) public {
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createUint64Clone(param);
uint64 fetched = clone.uint64Arg();
assertEq(fetched, param);
}
function testFuzz_clone_uint8Arg_succeeds(uint256 argOffset, uint8 param) public {
ExampleClone implementation = new ExampleClone(argOffset);
ExampleCloneFactory factory = new ExampleCloneFactory(implementation);
ExampleClone clone = factory.createUint8Clone(param);
uint8 fetched = clone.uint8Arg();
assertEq(fetched, param);
}
}
packages/contracts-bedrock/contracts/test/DisputeGameFactory.t.sol
View file @
87231e92
...
@@ -6,7 +6,7 @@ import "../libraries/DisputeErrors.sol";
...
@@ -6,7 +6,7 @@ import "../libraries/DisputeErrors.sol";
import { Test } from "forge-std/Test.sol";
import { Test } from "forge-std/Test.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { DisputeGameFactory } from "../dispute/DisputeGameFactory.sol";
import { IDisputeGame } from "../dispute/IDisputeGame.sol";
import { IDisputeGame } from "../dispute/
interfaces/
IDisputeGame.sol";
contract DisputeGameFactory_Test is Test {
contract DisputeGameFactory_Test is Test {
DisputeGameFactory factory;
DisputeGameFactory factory;
...
...
packages/contracts-bedrock/scripts/storage-snapshot.sh
View file @
87231e92
...
@@ -31,6 +31,8 @@ contracts=(
...
@@ -31,6 +31,8 @@ contracts=(
contracts/legacy/L1ChugSplashProxy.sol:L1ChugSplashProxy
contracts/legacy/L1ChugSplashProxy.sol:L1ChugSplashProxy
contracts/universal/OptimismMintableERC20.sol:OptimismMintableERC20
contracts/universal/OptimismMintableERC20.sol:OptimismMintableERC20
contracts/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory
contracts/universal/OptimismMintableERC20Factory.sol:OptimismMintableERC20Factory
contracts/dispute/DisputeGameFactory.sol:DisputeGameFactory
contracts/dispute/BondManager.sol:BondManager
)
)
dir
=
$(
dirname
"
$0
"
)
dir
=
$(
dirname
"
$0
"
)
...
...
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