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
0bc630b7
Unverified
Commit
0bc630b7
authored
Mar 31, 2023
by
mergify[bot]
Committed by
GitHub
Mar 31, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into inphi/eq-log
parents
10d72a0a
b7f161c4
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1580 additions
and
199 deletions
+1580
-199
migration_test.go
op-e2e/migration_test.go
+2
-0
setup.go
op-e2e/setup.go
+2
-0
cli.go
op-service/txmgr/cli.go
+24
-4
send_state.go
op-service/txmgr/send_state.go
+39
-27
send_state_test.go
op-service/txmgr/send_state_test.go
+32
-3
txmgr.go
op-service/txmgr/txmgr.go
+151
-153
txmgr_test.go
op-service/txmgr/txmgr_test.go
+35
-9
docker-compose.yml
ops-bedrock/docker-compose.yml
+0
-1
README.md
packages/contracts-bedrock/README.md
+3
-1
mainnet.json
packages/contracts-bedrock/deploy-config/mainnet.json
+36
-0
mainnet.ts
packages/contracts-bedrock/deploy-config/mainnet.ts
+52
-0
hardhat.config.ts
packages/contracts-bedrock/hardhat.config.ts
+3
-1
deploy-config.ts
packages/contracts-bedrock/src/deploy-config.ts
+36
-0
generate-deploy-config.ts
packages/contracts-bedrock/tasks/generate-deploy-config.ts
+25
-0
index.ts
packages/contracts-bedrock/tasks/index.ts
+1
-0
OptimistInviter.t.sol
...s-periphery/contracts/foundry-tests/OptimistInviter.t.sol
+650
-0
OptimistInviterHelper.sol
...phery/contracts/testing/helpers/OptimistInviterHelper.sol
+146
-0
TestERC1271Wallet.sol
...periphery/contracts/testing/helpers/TestERC1271Wallet.sol
+27
-0
OptimistInviter.sol
...-periphery/contracts/universal/op-nft/OptimistInviter.sol
+301
-0
OptimistConstants.sol
...ontracts/universal/op-nft/libraries/OptimistConstants.sol
+15
-0
No files found.
op-e2e/migration_test.go
View file @
0bc630b7
...
...
@@ -346,6 +346,7 @@ func TestMigration(t *testing.T) {
NumConfirmations
:
1
,
ResubmissionTimeout
:
5
*
time
.
Second
,
SafeAbortNonceTooLowCount
:
3
,
TxNotInMempoolTimeout
:
2
*
time
.
Minute
,
},
LogConfig
:
oplog
.
CLIConfig
{
Level
:
"info"
,
...
...
@@ -371,6 +372,7 @@ func TestMigration(t *testing.T) {
NumConfirmations
:
1
,
ResubmissionTimeout
:
3
*
time
.
Second
,
SafeAbortNonceTooLowCount
:
3
,
TxNotInMempoolTimeout
:
2
*
time
.
Minute
,
},
LogConfig
:
oplog
.
CLIConfig
{
Level
:
"info"
,
...
...
op-e2e/setup.go
View file @
0bc630b7
...
...
@@ -580,6 +580,7 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
ResubmissionTimeout
:
3
*
time
.
Second
,
ReceiptQueryInterval
:
50
*
time
.
Millisecond
,
NetworkTimeout
:
2
*
time
.
Second
,
TxNotInMempoolTimeout
:
2
*
time
.
Minute
,
},
AllowNonFinalized
:
cfg
.
NonFinalizedProposals
,
LogConfig
:
oplog
.
CLIConfig
{
...
...
@@ -615,6 +616,7 @@ func (cfg SystemConfig) Start(_opts ...SystemConfigOption) (*System, error) {
ResubmissionTimeout
:
3
*
time
.
Second
,
ReceiptQueryInterval
:
50
*
time
.
Millisecond
,
NetworkTimeout
:
2
*
time
.
Second
,
TxNotInMempoolTimeout
:
2
*
time
.
Minute
,
},
LogConfig
:
oplog
.
CLIConfig
{
Level
:
"info"
,
...
...
op-service/txmgr/cli.go
View file @
0bc630b7
...
...
@@ -28,6 +28,7 @@ const (
ResubmissionTimeoutFlagName
=
"resubmission-timeout"
NetworkTimeoutFlagName
=
"network-timeout"
TxSendTimeoutFlagName
=
"txmgr.send-timeout"
TxNotInMempoolTimeoutFlagName
=
"txmgr.not-in-mempool-timeout"
ReceiptQueryIntervalFlagName
=
"txmgr.receipt-query-interval"
)
...
...
@@ -95,6 +96,12 @@ func CLIFlags(envPrefix string) []cli.Flag {
Value
:
0
,
EnvVar
:
opservice
.
PrefixEnvVar
(
envPrefix
,
"TXMGR_TX_SEND_TIMEOUT"
),
},
cli
.
DurationFlag
{
Name
:
TxNotInMempoolTimeoutFlagName
,
Usage
:
"Timeout for aborting a tx send if the tx does not make it to the mempool."
,
Value
:
2
*
time
.
Minute
,
EnvVar
:
opservice
.
PrefixEnvVar
(
envPrefix
,
"TXMGR_TX_NOT_IN_MEMPOOL_TIMEOUT"
),
},
cli
.
DurationFlag
{
Name
:
ReceiptQueryIntervalFlagName
,
Usage
:
"Frequency to poll for receipts"
,
...
...
@@ -118,6 +125,7 @@ type CLIConfig struct {
ReceiptQueryInterval
time
.
Duration
NetworkTimeout
time
.
Duration
TxSendTimeout
time
.
Duration
TxNotInMempoolTimeout
time
.
Duration
}
func
(
m
CLIConfig
)
Check
()
error
{
...
...
@@ -125,16 +133,22 @@ func (m CLIConfig) Check() error {
return
errors
.
New
(
"must provide a L1 RPC url"
)
}
if
m
.
NumConfirmations
==
0
{
return
errors
.
New
(
"
num c
onfirmations must not be 0"
)
return
errors
.
New
(
"
NumC
onfirmations must not be 0"
)
}
if
m
.
NetworkTimeout
==
0
{
return
errors
.
New
(
"must provide
a network t
imeout"
)
return
errors
.
New
(
"must provide
NetworkT
imeout"
)
}
if
m
.
ResubmissionTimeout
==
0
{
return
errors
.
New
(
"must provide
a resumbission interval
"
)
return
errors
.
New
(
"must provide
ResubmissionTimeout
"
)
}
if
m
.
ReceiptQueryInterval
==
0
{
return
errors
.
New
(
"must provide a receipt query interval"
)
return
errors
.
New
(
"must provide ReceiptQueryInterval"
)
}
if
m
.
TxNotInMempoolTimeout
==
0
{
return
errors
.
New
(
"must provide TxNotInMempoolTimeout"
)
}
if
m
.
SafeAbortNonceTooLowCount
==
0
{
return
errors
.
New
(
"SafeAbortNonceTooLowCount must not be 0"
)
}
if
err
:=
m
.
SignerCLIConfig
.
Check
();
err
!=
nil
{
return
err
...
...
@@ -157,6 +171,7 @@ func ReadCLIConfig(ctx *cli.Context) CLIConfig {
ReceiptQueryInterval
:
ctx
.
GlobalDuration
(
ReceiptQueryIntervalFlagName
),
NetworkTimeout
:
ctx
.
GlobalDuration
(
NetworkTimeoutFlagName
),
TxSendTimeout
:
ctx
.
GlobalDuration
(
TxSendTimeoutFlagName
),
TxNotInMempoolTimeout
:
ctx
.
GlobalDuration
(
TxNotInMempoolTimeoutFlagName
),
}
}
...
...
@@ -197,6 +212,7 @@ func NewConfig(cfg CLIConfig, l log.Logger) (Config, error) {
ResubmissionTimeout
:
cfg
.
ResubmissionTimeout
,
ChainID
:
chainID
,
TxSendTimeout
:
cfg
.
TxSendTimeout
,
TxNotInMempoolTimeout
:
cfg
.
TxNotInMempoolTimeout
,
NetworkTimeout
:
cfg
.
NetworkTimeout
,
ReceiptQueryInterval
:
cfg
.
ReceiptQueryInterval
,
NumConfirmations
:
cfg
.
NumConfirmations
,
...
...
@@ -222,6 +238,10 @@ type Config struct {
// By default it is unbounded. If set, this is recommended to be at least 20 minutes.
TxSendTimeout
time
.
Duration
// TxNotInMempoolTimeout is how long to wait before aborting a transaction send if the transaction does not
// make it to the mempool. If the tx is in the mempool, TxSendTimeout is used instead.
TxNotInMempoolTimeout
time
.
Duration
// NetworkTimeout is the allowed duration for a single network request.
// This is intended to be used for network requests that can be replayed.
NetworkTimeout
time
.
Duration
...
...
op-service/txmgr/send_state.go
View file @
0bc630b7
...
...
@@ -3,6 +3,7 @@ package txmgr
import
(
"strings"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
...
...
@@ -12,48 +13,53 @@ import (
// this context, a txn may correspond to multiple different txn hashes due to
// varying gas prices, though we treat them all as the same logical txn. This
// struct is primarily used to determine whether or not the txmgr should abort a
// given txn
and retry with a higher nonce
.
// given txn.
type
SendState
struct
{
minedTxs
map
[
common
.
Hash
]
struct
{}
nonceTooLowCount
uint64
mu
sync
.
RWMutex
minedTxs
map
[
common
.
Hash
]
struct
{}
mu
sync
.
RWMutex
now
func
()
time
.
Time
safeAbortNonceTooLowCount
uint64
// Config
nonceTooLowCount
uint64
txInMempoolDeadline
time
.
Time
// deadline to abort at if no transactions are in the mempool
// Counts of the different types of errors
successFullPublishCount
uint64
// nil error => tx made it to the mempool
safeAbortNonceTooLowCount
uint64
// nonce too low error
}
// NewSendState parameterizes a new SendState from the passed
// safeAbortNonceTooLowCount.
func
NewSendState
(
safeAbortNonceTooLowCount
uint64
)
*
SendState
{
// NewSendStateWithNow creates a new send state with the provided clock.
func
NewSendStateWithNow
(
safeAbortNonceTooLowCount
uint64
,
unableToSendTimeout
time
.
Duration
,
now
func
()
time
.
Time
)
*
SendState
{
if
safeAbortNonceTooLowCount
==
0
{
panic
(
"txmgr: safeAbortNonceTooLowCount cannot be zero"
)
}
return
&
SendState
{
minedTxs
:
make
(
map
[
common
.
Hash
]
struct
{}),
nonceTooLowCount
:
0
,
safeAbortNonceTooLowCount
:
safeAbortNonceTooLowCount
,
txInMempoolDeadline
:
now
()
.
Add
(
unableToSendTimeout
),
now
:
now
,
}
}
// NewSendState creates a new send state
func
NewSendState
(
safeAbortNonceTooLowCount
uint64
,
unableToSendTimeout
time
.
Duration
)
*
SendState
{
return
NewSendStateWithNow
(
safeAbortNonceTooLowCount
,
unableToSendTimeout
,
time
.
Now
)
}
// ProcessSendError should be invoked with the error returned for each
// publication. It is safe to call this method with nil or arbitrary errors.
// Currently it only acts on errors containing the ErrNonceTooLow message.
func
(
s
*
SendState
)
ProcessSendError
(
err
error
)
{
// Nothing to do.
if
err
==
nil
{
return
}
// Only concerned with ErrNonceTooLow.
if
!
strings
.
Contains
(
err
.
Error
(),
core
.
ErrNonceTooLow
.
Error
())
{
return
}
s
.
mu
.
Lock
()
defer
s
.
mu
.
Unlock
()
// Record this nonce too low observation.
s
.
nonceTooLowCount
++
// Record the type of error
switch
{
case
err
==
nil
:
s
.
successFullPublishCount
++
case
strings
.
Contains
(
err
.
Error
(),
core
.
ErrNonceTooLow
.
Error
())
:
s
.
nonceTooLowCount
++
}
}
// TxMined records that the txn with txnHash has been mined and is await
...
...
@@ -85,8 +91,9 @@ func (s *SendState) TxNotMined(txHash common.Hash) {
}
// ShouldAbortImmediately returns true if the txmgr should give up on trying a
// given txn with the target nonce. For now, this only happens if we see an
// extended period of getting ErrNonceTooLow without having a txn mined.
// given txn with the target nonce.
// This occurs when the set of errors recorded indicates that no further progress can be made
// on this transaction.
func
(
s
*
SendState
)
ShouldAbortImmediately
()
bool
{
s
.
mu
.
RLock
()
defer
s
.
mu
.
RUnlock
()
...
...
@@ -96,9 +103,14 @@ func (s *SendState) ShouldAbortImmediately() bool {
return
false
}
// Only abort if we've observed enough ErrNonceTooLow to meet our safe abort
// threshold.
return
s
.
nonceTooLowCount
>=
s
.
safeAbortNonceTooLowCount
// If we have exceeded the nonce too low count, abort
if
s
.
nonceTooLowCount
>=
s
.
safeAbortNonceTooLowCount
||
// If we have not published a transaction in the allotted time, abort
(
s
.
successFullPublishCount
==
0
&&
s
.
now
()
.
After
(
s
.
txInMempoolDeadline
))
{
return
true
}
return
false
}
// IsWaitingForConfirmation returns true if we have at least one confirmation on
...
...
op-service/txmgr/send_state_test.go
View file @
0bc630b7
...
...
@@ -3,6 +3,7 @@ package txmgr_test
import
(
"errors"
"testing"
"time"
"github.com/stretchr/testify/require"
...
...
@@ -11,14 +12,18 @@ import (
"github.com/ethereum/go-ethereum/core"
)
const
testSafeAbortNonceTooLowCount
=
3
var
(
testHash
=
common
.
HexToHash
(
"0x01"
)
)
const
testSafeAbortNonceTooLowCount
=
3
func
newSendState
()
*
txmgr
.
SendState
{
return
txmgr
.
NewSendState
(
testSafeAbortNonceTooLowCount
)
return
newSendStateWithTimeout
(
time
.
Hour
,
time
.
Now
)
}
func
newSendStateWithTimeout
(
t
time
.
Duration
,
now
func
()
time
.
Time
)
*
txmgr
.
SendState
{
return
txmgr
.
NewSendStateWithNow
(
testSafeAbortNonceTooLowCount
,
t
,
now
)
}
func
processNSendErrors
(
sendState
*
txmgr
.
SendState
,
err
error
,
n
int
)
{
...
...
@@ -160,3 +165,27 @@ func TestSendStateIsNotWaitingForConfirmationAfterTxUnmined(t *testing.T) {
sendState
.
TxNotMined
(
testHash
)
require
.
False
(
t
,
sendState
.
IsWaitingForConfirmation
())
}
func
stepClock
(
step
time
.
Duration
)
func
()
time
.
Time
{
i
:=
0
return
func
()
time
.
Time
{
var
start
time
.
Time
i
+=
1
return
start
.
Add
(
time
.
Duration
(
i
)
*
step
)
}
}
// TestSendStateTimeoutAbort ensure that this will abort if it passes the tx pool timeout
// when no successful transactions have been recorded
func
TestSendStateTimeoutAbort
(
t
*
testing
.
T
)
{
sendState
:=
newSendStateWithTimeout
(
10
*
time
.
Millisecond
,
stepClock
(
20
*
time
.
Millisecond
))
require
.
True
(
t
,
sendState
.
ShouldAbortImmediately
(),
"Should abort after timing out"
)
}
// TestSendStateNoTimeoutAbortIfPublishedTx ensure that this will not abort if there is
// a successful transaction send.
func
TestSendStateNoTimeoutAbortIfPublishedTx
(
t
*
testing
.
T
)
{
sendState
:=
newSendStateWithTimeout
(
10
*
time
.
Millisecond
,
stepClock
(
20
*
time
.
Millisecond
))
sendState
.
ProcessSendError
(
nil
)
require
.
False
(
t
,
sendState
.
ShouldAbortImmediately
(),
"Should not abort if published transcation successfully"
)
}
op-service/txmgr/txmgr.go
View file @
0bc630b7
This diff is collapsed.
Click to expand it.
op-service/txmgr/txmgr_test.go
View file @
0bc630b7
...
...
@@ -3,6 +3,7 @@ package txmgr
import
(
"context"
"errors"
"fmt"
"math/big"
"sync"
"testing"
...
...
@@ -20,6 +21,10 @@ import (
type
sendTransactionFunc
func
(
ctx
context
.
Context
,
tx
*
types
.
Transaction
)
error
func
testSendState
()
*
SendState
{
return
NewSendState
(
100
,
time
.
Hour
)
}
// testHarness houses the necessary resources to test the SimpleTxManager.
type
testHarness
struct
{
cfg
Config
...
...
@@ -68,6 +73,7 @@ func configWithNumConfs(numConfirmations uint64) Config {
ReceiptQueryInterval
:
50
*
time
.
Millisecond
,
NumConfirmations
:
numConfirmations
,
SafeAbortNonceTooLowCount
:
3
,
TxNotInMempoolTimeout
:
1
*
time
.
Hour
,
Signer
:
func
(
ctx
context
.
Context
,
from
common
.
Address
,
tx
*
types
.
Transaction
)
(
*
types
.
Transaction
,
error
)
{
return
tx
,
nil
},
...
...
@@ -530,7 +536,7 @@ func TestWaitMinedReturnsReceiptOnFirstSuccess(t *testing.T) {
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
5
*
time
.
Second
)
defer
cancel
()
receipt
,
err
:=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
nil
)
receipt
,
err
:=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
testSendState
()
)
require
.
Nil
(
t
,
err
)
require
.
NotNil
(
t
,
receipt
)
require
.
Equal
(
t
,
receipt
.
TxHash
,
txHash
)
...
...
@@ -549,7 +555,7 @@ func TestWaitMinedCanBeCanceled(t *testing.T) {
// Create an unimined tx.
tx
:=
types
.
NewTx
(
&
types
.
LegacyTx
{})
receipt
,
err
:=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
nil
)
receipt
,
err
:=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
NewSendState
(
10
,
time
.
Hour
)
)
require
.
Equal
(
t
,
err
,
context
.
DeadlineExceeded
)
require
.
Nil
(
t
,
receipt
)
}
...
...
@@ -570,7 +576,7 @@ func TestWaitMinedMultipleConfs(t *testing.T) {
txHash
:=
tx
.
Hash
()
h
.
backend
.
mine
(
&
txHash
,
new
(
big
.
Int
))
receipt
,
err
:=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
nil
)
receipt
,
err
:=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
NewSendState
(
10
,
time
.
Hour
)
)
require
.
Equal
(
t
,
err
,
context
.
DeadlineExceeded
)
require
.
Nil
(
t
,
receipt
)
...
...
@@ -579,7 +585,7 @@ func TestWaitMinedMultipleConfs(t *testing.T) {
// Mine an empty block, tx should now be confirmed.
h
.
backend
.
mine
(
nil
,
nil
)
receipt
,
err
=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
nil
)
receipt
,
err
=
h
.
mgr
.
waitMined
(
ctx
,
tx
,
NewSendState
(
10
,
time
.
Hour
)
)
require
.
Nil
(
t
,
err
)
require
.
NotNil
(
t
,
receipt
)
require
.
Equal
(
t
,
txHash
,
receipt
.
TxHash
)
...
...
@@ -692,7 +698,7 @@ func TestWaitMinedReturnsReceiptAfterFailure(t *testing.T) {
ctx
,
cancel
:=
context
.
WithTimeout
(
context
.
Background
(),
10
*
time
.
Second
)
defer
cancel
()
receipt
,
err
:=
mgr
.
waitMined
(
ctx
,
tx
,
nil
)
receipt
,
err
:=
mgr
.
waitMined
(
ctx
,
tx
,
testSendState
()
)
require
.
Nil
(
t
,
err
)
require
.
NotNil
(
t
,
receipt
)
require
.
Equal
(
t
,
receipt
.
TxHash
,
txHash
)
...
...
@@ -724,8 +730,7 @@ func doGasPriceIncrease(t *testing.T, txTipCap, txFeeCap, newTip, newBaseFee int
GasTipCap
:
big
.
NewInt
(
txTipCap
),
GasFeeCap
:
big
.
NewInt
(
txFeeCap
),
})
newTx
,
err
:=
mgr
.
increaseGasPrice
(
context
.
Background
(),
tx
)
require
.
NoError
(
t
,
err
)
newTx
:=
mgr
.
increaseGasPrice
(
context
.
Background
(),
tx
)
return
tx
,
newTx
}
...
...
@@ -831,11 +836,32 @@ func TestIncreaseGasPriceNotExponential(t *testing.T) {
// Run IncreaseGasPrice a bunch of times in a row to simulate a very fast resubmit loop.
for
i
:=
0
;
i
<
20
;
i
++
{
ctx
:=
context
.
Background
()
newTx
,
err
:=
mgr
.
increaseGasPrice
(
ctx
,
tx
)
require
.
NoError
(
t
,
err
)
newTx
:=
mgr
.
increaseGasPrice
(
ctx
,
tx
)
require
.
True
(
t
,
newTx
.
GasFeeCap
()
.
Cmp
(
feeCap
)
==
0
,
"new tx fee cap must be equal L1"
)
require
.
True
(
t
,
newTx
.
GasTipCap
()
.
Cmp
(
borkedBackend
.
gasTip
)
==
0
,
"new tx tip must be equal L1"
)
tx
=
newTx
}
}
func
TestErrStringMatch
(
t
*
testing
.
T
)
{
tests
:=
[]
struct
{
err
error
target
error
match
bool
}{
{
err
:
nil
,
target
:
nil
,
match
:
true
},
{
err
:
errors
.
New
(
"exists"
),
target
:
nil
,
match
:
false
},
{
err
:
nil
,
target
:
errors
.
New
(
"exists"
),
match
:
false
},
{
err
:
errors
.
New
(
"exact match"
),
target
:
errors
.
New
(
"exact match"
),
match
:
true
},
{
err
:
errors
.
New
(
"partial: match"
),
target
:
errors
.
New
(
"match"
),
match
:
true
},
}
for
i
,
test
:=
range
tests
{
i
:=
i
test
:=
test
t
.
Run
(
fmt
.
Sprint
(
i
),
func
(
t
*
testing
.
T
)
{
require
.
Equal
(
t
,
test
.
match
,
errStringMatch
(
test
.
err
,
test
.
target
))
})
}
}
ops-bedrock/docker-compose.yml
View file @
0bc630b7
...
...
@@ -123,7 +123,6 @@ services:
OP_BATCHER_L1_ETH_RPC
:
http://l1:8545
OP_BATCHER_L2_ETH_RPC
:
http://l2:8545
OP_BATCHER_ROLLUP_RPC
:
http://op-node:8545
TX_MANAGER_TIMEOUT
:
10m
OFFLINE_GAS_ESTIMATION
:
false
OP_BATCHER_MAX_CHANNEL_DURATION
:
1
OP_BATCHER_MAX_L1_TX_SIZE_BYTES
:
120000
...
...
packages/contracts-bedrock/README.md
View file @
0bc630b7
...
...
@@ -92,8 +92,10 @@ yarn echidna:aliasing
#### Configuration
1.
Create or modify a file
`<network-name>.
json
`
inside of the
[
`deploy-config`
](
./deploy-config/
)
folder.
1.
Create or modify a file
`<network-name>.
ts
`
inside of the
[
`deploy-config`
](
./deploy-config/
)
folder.
2.
Fill out this file according to the
`deployConfigSpec`
located inside of the
[
`hardhat.config.ts
](
./hardhat.config.ts
)
3.
Optionally: Run
`npx hardhat generate-deploy-config --network <network-name>`
to generate the associated JSON
file. This is required if using
`op-chain-ops`
.
#### Execution
...
...
packages/contracts-bedrock/deploy-config/mainnet.json
0 → 100644
View file @
0bc630b7
{
"finalSystemOwner"
:
"0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A"
,
"controller"
:
"0x78339d822c23d943e4a2d4c3dd5408f66e6d662d"
,
"portalGuardian"
:
"0x78339d822c23d943e4a2d4c3dd5408f66e6d662d"
,
"l1StartingBlockTag"
:
"0x126e52a0cc0ae18948f567ee9443f4a8f0db67c437706e35baee424eb314a0d0"
,
"l1ChainID"
:
1
,
"l2ChainID"
:
10
,
"l2BlockTime"
:
2
,
"maxSequencerDrift"
:
600
,
"sequencerWindowSize"
:
3600
,
"channelTimeout"
:
300
,
"p2pSequencerAddress"
:
"0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65"
,
"batchInboxAddress"
:
"0xff00000000000000000000000000000000000010"
,
"batchSenderAddress"
:
"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
,
"l2OutputOracleSubmissionInterval"
:
20
,
"l2OutputOracleStartingTimestamp"
:
1679069195
,
"l2OutputOracleStartingBlockNumber"
:
79149704
,
"l2OutputOracleProposer"
:
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"
,
"l2OutputOracleChallenger"
:
"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC"
,
"finalizationPeriodSeconds"
:
2
,
"proxyAdminOwner"
:
"0x90F79bf6EB2c4f870365E785982E1f101E93b906"
,
"baseFeeVaultRecipient"
:
"0x90F79bf6EB2c4f870365E785982E1f101E93b906"
,
"l1FeeVaultRecipient"
:
"0x90F79bf6EB2c4f870365E785982E1f101E93b906"
,
"sequencerFeeVaultRecipient"
:
"0x90F79bf6EB2c4f870365E785982E1f101E93b906"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x90F79bf6EB2c4f870365E785982E1f101E93b906"
,
"l2GenesisBlockGasLimit"
:
"0x17D7840"
,
"l2GenesisBlockCoinbase"
:
"0x4200000000000000000000000000000000000011"
,
"l2GenesisBlockBaseFeePerGas"
:
"0x3b9aca00"
,
"gasPriceOracleOverhead"
:
2100
,
"gasPriceOracleScalar"
:
1000000
,
"eip1559Denominator"
:
50
,
"eip1559Elasticity"
:
10
,
"l2GenesisRegolithTimeOffset"
:
"0x0"
}
\ No newline at end of file
packages/contracts-bedrock/deploy-config/mainnet.ts
0 → 100644
View file @
0bc630b7
import
{
DeployConfig
}
from
'
../src/deploy-config
'
// NOTE: The 'mainnet' network is currently being used for bedrock migration rehearsals.
// The system configured below is not yet live on mainnet, and many of the addresses used are
// unsafe for a production system.
const
config
:
DeployConfig
=
{
finalSystemOwner
:
'
0x9BA6e03D8B90dE867373Db8cF1A58d2F7F006b3A
'
,
controller
:
'
0x78339d822c23d943e4a2d4c3dd5408f66e6d662d
'
,
portalGuardian
:
'
0x78339d822c23d943e4a2d4c3dd5408f66e6d662d
'
,
l1StartingBlockTag
:
'
0x126e52a0cc0ae18948f567ee9443f4a8f0db67c437706e35baee424eb314a0d0
'
,
l1ChainID
:
1
,
l2ChainID
:
10
,
l2BlockTime
:
2
,
maxSequencerDrift
:
600
,
sequencerWindowSize
:
3600
,
channelTimeout
:
300
,
p2pSequencerAddress
:
'
0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65
'
,
batchInboxAddress
:
'
0xff00000000000000000000000000000000000010
'
,
batchSenderAddress
:
'
0x70997970C51812dc3A010C7d01b50e0d17dc79C8
'
,
l2OutputOracleSubmissionInterval
:
20
,
l2OutputOracleStartingTimestamp
:
1679069195
,
l2OutputOracleStartingBlockNumber
:
79149704
,
l2OutputOracleProposer
:
'
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
'
,
l2OutputOracleChallenger
:
'
0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC
'
,
finalizationPeriodSeconds
:
2
,
proxyAdminOwner
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
baseFeeVaultRecipient
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
l1FeeVaultRecipient
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
sequencerFeeVaultRecipient
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
governanceTokenName
:
'
Optimism
'
,
governanceTokenSymbol
:
'
OP
'
,
governanceTokenOwner
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
l2GenesisBlockGasLimit
:
'
0x17D7840
'
,
l2GenesisBlockCoinbase
:
'
0x4200000000000000000000000000000000000011
'
,
l2GenesisBlockBaseFeePerGas
:
'
0x3b9aca00
'
,
gasPriceOracleOverhead
:
2100
,
gasPriceOracleScalar
:
1000000
,
eip1559Denominator
:
50
,
eip1559Elasticity
:
10
,
l2GenesisRegolithTimeOffset
:
'
0x0
'
,
}
export
default
config
packages/contracts-bedrock/hardhat.config.ts
View file @
0bc630b7
...
...
@@ -22,8 +22,10 @@ const config: HardhatUserConfig = {
hardhat
:
{
live
:
false
,
},
// NOTE: The 'mainnet' network is currently being used for mainnet rehearsals.
mainnet
:
{
url
:
process
.
env
.
L1_RPC
||
'
http://localhost:8545
'
,
url
:
process
.
env
.
L1_RPC
||
'
https://mainnet-l1-rehearsal.optimism.io
'
,
accounts
:
[
process
.
env
.
PRIVATE_KEY_DEPLOYER
||
ethers
.
constants
.
HashZero
],
},
devnetL1
:
{
live
:
false
,
...
...
packages/contracts-bedrock/src/deploy-config.ts
View file @
0bc630b7
...
...
@@ -129,6 +129,26 @@ interface RequiredDeployConfig {
* Output finalization period in seconds.
*/
finalizationPeriodSeconds
:
number
/**
* Owner of the ProxyAdmin contract.
*/
proxyAdminOwner
:
string
/**
* L1 address which receives the base fee for the L2 network.
*/
baseFeeVaultRecipient
:
string
/**
* L1 address which receives data fees for the L2 network.
*/
l1FeeVaultRecipient
:
string
/**
* L1 address which receives tip fees for the L2 network.
*/
sequencerFeeVaultRecipient
:
string
}
/**
...
...
@@ -160,6 +180,10 @@ interface OptionalL2DeployConfig {
l2GenesisBlockGasUsed
:
string
l2GenesisBlockParentHash
:
string
l2GenesisBlockBaseFeePerGas
:
string
l2GenesisBlockCoinbase
:
string
l2GenesisRegolithTimeOffset
:
string
eip1559Denominator
:
number
eip1559Elasticity
:
number
gasPriceOracleOverhead
:
number
gasPriceOracleScalar
:
number
}
...
...
@@ -243,6 +267,18 @@ export const deployConfigSpec: {
type
:
'
number
'
,
default
:
2
,
},
proxyAdminOwner
:
{
type
:
'
address
'
,
},
baseFeeVaultRecipient
:
{
type
:
'
address
'
,
},
l1FeeVaultRecipient
:
{
type
:
'
address
'
,
},
sequencerFeeVaultRecipient
:
{
type
:
'
address
'
,
},
cliqueSignerAddress
:
{
type
:
'
address
'
,
default
:
ethers
.
constants
.
AddressZero
,
...
...
packages/contracts-bedrock/tasks/generate-deploy-config.ts
0 → 100644
View file @
0bc630b7
import
fs
from
'
fs
'
import
path
from
'
path
'
import
{
task
}
from
'
hardhat/config
'
import
{
HardhatRuntimeEnvironment
}
from
'
hardhat/types
'
task
(
'
generate-deploy-config
'
,
'
generates a json config file for the current network
'
).
setAction
(
async
({},
hre
:
HardhatRuntimeEnvironment
)
=>
{
try
{
const
base
=
path
.
join
(
hre
.
config
.
paths
.
deployConfig
,
hre
.
network
.
name
)
if
(
fs
.
existsSync
(
`
${
base
}
.ts`
))
{
// eslint-disable-next-line @typescript-eslint/no-var-requires
const
config
=
require
(
`
${
base
}
.ts`
).
default
fs
.
writeFileSync
(
`
${
base
}
.json`
,
JSON
.
stringify
(
config
,
null
,
2
),
'
utf8
'
)
}
else
{
throw
new
Error
(
'
not found
'
)
}
}
catch
(
err
)
{
throw
new
Error
(
`error while loading deploy config for network:
${
hre
.
network
.
name
}
,
${
err
}
`
)
}
})
packages/contracts-bedrock/tasks/index.ts
View file @
0bc630b7
...
...
@@ -10,3 +10,4 @@ import './check-l2'
import
'
./update-dynamic-oracle-config
'
import
'
./wait-for-final-batch
'
import
'
./wait-for-final-deposit
'
import
'
./generate-deploy-config
'
packages/contracts-periphery/contracts/foundry-tests/OptimistInviter.t.sol
0 → 100644
View file @
0bc630b7
This diff is collapsed.
Click to expand it.
packages/contracts-periphery/contracts/testing/helpers/OptimistInviterHelper.sol
0 → 100644
View file @
0bc630b7
//SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { OptimistInviter } from "../../universal/op-nft/OptimistInviter.sol";
/**
* Simple helper contract that helps with testing flow and signature for OptimistInviter contract.
* Made this a separate contract instead of including in OptimistInviter.t.sol for reusability.
*/
contract OptimistInviterHelper {
/**
* @notice EIP712 typehash for the ClaimableInvite type.
*/
bytes32 public constant CLAIMABLE_INVITE_TYPEHASH =
keccak256("ClaimableInvite(address issuer,bytes32 nonce)");
/**
* @notice EIP712 typehash for the EIP712Domain type that is included as part of the signature.
*/
bytes32 public constant EIP712_DOMAIN_TYPEHASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
/**
* @notice Address of OptimistInviter contract we are testing.
*/
OptimistInviter public optimistInviter;
/**
* @notice OptimistInviter contract name. Used to construct the EIP-712 domain.
*/
string public name;
/**
* @notice Keeps track of current nonce to generate new nonces for each invite.
*/
uint256 public currentNonce;
constructor(OptimistInviter _optimistInviter, string memory _name) {
optimistInviter = _optimistInviter;
name = _name;
}
/**
* @notice Returns the hash of the struct ClaimableInvite.
*
* @param _claimableInvite ClaimableInvite struct to hash.
*
* @return EIP-712 typed struct hash.
*/
function getClaimableInviteStructHash(OptimistInviter.ClaimableInvite memory _claimableInvite)
public
pure
returns (bytes32)
{
return
keccak256(
abi.encode(
CLAIMABLE_INVITE_TYPEHASH,
_claimableInvite.issuer,
_claimableInvite.nonce
)
);
}
/**
* @notice Returns a bytes32 nonce that should change everytime. In practice, people should use
* pseudorandom nonces.
*
* @return Nonce that should be used as part of ClaimableInvite.
*/
function consumeNonce() public returns (bytes32) {
return bytes32(keccak256(abi.encode(currentNonce++)));
}
/**
* @notice Returns a ClaimableInvite with the issuer and current nonce.
*
* @param _issuer Issuer to include in the ClaimableInvite.
*
* @return ClaimableInvite that can be hashed & signed.
*/
function getClaimableInviteWithNewNonce(address _issuer)
public
returns (OptimistInviter.ClaimableInvite memory)
{
return OptimistInviter.ClaimableInvite(_issuer, consumeNonce());
}
/**
* @notice Computes the EIP712 digest with default correct parameters.
*
* @param _claimableInvite ClaimableInvite struct to hash.
*
* @return EIP-712 compatible digest.
*/
function getDigest(OptimistInviter.ClaimableInvite calldata _claimableInvite)
public
view
returns (bytes32)
{
return
getDigestWithEIP712Domain(
_claimableInvite,
bytes(name),
bytes(optimistInviter.EIP712_VERSION()),
block.chainid,
address(optimistInviter)
);
}
/**
* @notice Computes the EIP712 digest with the given domain parameters.
* Used for testing that different domain parameters fail.
*
* @param _claimableInvite ClaimableInvite struct to hash.
* @param _name Contract name to use in the EIP712 domain.
* @param _version Contract version to use in the EIP712 domain.
* @param _chainid Chain ID to use in the EIP712 domain.
* @param _verifyingContract Address to use in the EIP712 domain.
*
* @return EIP-712 compatible digest.
*/
function getDigestWithEIP712Domain(
OptimistInviter.ClaimableInvite calldata _claimableInvite,
bytes memory _name,
bytes memory _version,
uint256 _chainid,
address _verifyingContract
) public pure returns (bytes32) {
bytes32 domainSeparator = keccak256(
abi.encode(
EIP712_DOMAIN_TYPEHASH,
keccak256(_name),
keccak256(_version),
_chainid,
_verifyingContract
)
);
return
ECDSA.toTypedDataHash(domainSeparator, getClaimableInviteStructHash(_claimableInvite));
}
}
packages/contracts-periphery/contracts/testing/helpers/TestERC1271Wallet.sol
0 → 100644
View file @
0bc630b7
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
// solhint-disable max-line-length
/**
* Simple ERC1271 wallet that can be used to test the ERC1271 signature checker.
* https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/mocks/ERC1271WalletMock.sol
*/
contract TestERC1271Wallet is Ownable, IERC1271 {
constructor(address originalOwner) {
transferOwnership(originalOwner);
}
function isValidSignature(bytes32 hash, bytes memory signature)
public
view
override
returns (bytes4 magicValue)
{
return
ECDSA.recover(hash, signature) == owner() ? this.isValidSignature.selector : bytes4(0);
}
}
packages/contracts-periphery/contracts/universal/op-nft/OptimistInviter.sol
0 → 100644
View file @
0bc630b7
This diff is collapsed.
Click to expand it.
packages/contracts-periphery/contracts/universal/op-nft/libraries/OptimistConstants.sol
0 → 100644
View file @
0bc630b7
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
/**
* @title OptimistConstants
* @notice Library for storing Optimist related constants that are shared in multiple contracts.
*/
library OptimistConstants {
/**
* @notice Attestation key issued by OptimistInviter allowing the attested account to mint.
*/
bytes32 internal constant OPTIMIST_CAN_MINT_FROM_INVITE_ATTESTATION_KEY =
bytes32("optimist.can-mint-from-invite");
}
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