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
48a146d7
Unverified
Commit
48a146d7
authored
Sep 19, 2023
by
mergify[bot]
Committed by
GitHub
Sep 19, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into inphi/fdg-rez
parents
7fefff6e
8d8b6703
Changes
19
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1512 additions
and
97 deletions
+1512
-97
db.go
indexer/database/db.go
+17
-5
artifacts.json
op-bindings/artifacts.json
+2
-1
delayedvetoable.go
op-bindings/bindings/delayedvetoable.go
+928
-0
delayedvetoable_more.go
op-bindings/bindings/delayedvetoable_more.go
+25
-0
mips_more.go
op-bindings/bindings/mips_more.go
+1
-1
preimageoracle_more.go
op-bindings/bindings/preimageoracle_more.go
+1
-1
main_test.go
op-challenger/cmd/main_test.go
+23
-0
config.go
op-challenger/config/config.go
+9
-0
config_test.go
op-challenger/config/config_test.go
+10
-0
flags.go
op-challenger/flags/flags.go
+15
-2
config.go
op-program/host/config/config.go
+31
-22
config_test.go
op-program/host/config/config_test.go
+16
-1
local.go
op-program/host/kvstore/local.go
+9
-1
local_test.go
op-program/host/kvstore/local_test.go
+1
-2
.gas-snapshot
packages/contracts-bedrock/.gas-snapshot
+3
-0
semver-lock.json
packages/contracts-bedrock/semver-lock.json
+1
-0
DelayedVetoable.sol
packages/contracts-bedrock/src/L1/DelayedVetoable.sol
+198
-0
DelayedVetoable.t.sol
packages/contracts-bedrock/test/DelayedVetoable.t.sol
+201
-0
pnpm-lock.yaml
pnpm-lock.yaml
+21
-61
No files found.
indexer/database/db.go
View file @
48a146d7
...
@@ -2,10 +2,13 @@
...
@@ -2,10 +2,13 @@
package
database
package
database
import
(
import
(
"context"
"fmt"
"fmt"
"github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/indexer/config"
_
"github.com/ethereum-optimism/optimism/indexer/database/serializers"
_
"github.com/ethereum-optimism/optimism/indexer/database/serializers"
"github.com/ethereum-optimism/optimism/op-service/retry"
"github.com/pkg/errors"
"gorm.io/driver/postgres"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm"
...
@@ -31,6 +34,8 @@ type DB struct {
...
@@ -31,6 +34,8 @@ type DB struct {
}
}
func
NewDB
(
dbConfig
config
.
DBConfig
)
(
*
DB
,
error
)
{
func
NewDB
(
dbConfig
config
.
DBConfig
)
(
*
DB
,
error
)
{
retryStrategy
:=
&
retry
.
ExponentialStrategy
{
Min
:
1000
,
Max
:
20
_000
,
MaxJitter
:
250
}
dsn
:=
fmt
.
Sprintf
(
"host=%s port=%d dbname=%s sslmode=disable"
,
dbConfig
.
Host
,
dbConfig
.
Port
,
dbConfig
.
Name
)
dsn
:=
fmt
.
Sprintf
(
"host=%s port=%d dbname=%s sslmode=disable"
,
dbConfig
.
Host
,
dbConfig
.
Port
,
dbConfig
.
Name
)
if
dbConfig
.
User
!=
""
{
if
dbConfig
.
User
!=
""
{
dsn
+=
fmt
.
Sprintf
(
" user=%s"
,
dbConfig
.
User
)
dsn
+=
fmt
.
Sprintf
(
" user=%s"
,
dbConfig
.
User
)
...
@@ -38,17 +43,24 @@ func NewDB(dbConfig config.DBConfig) (*DB, error) {
...
@@ -38,17 +43,24 @@ func NewDB(dbConfig config.DBConfig) (*DB, error) {
if
dbConfig
.
Password
!=
""
{
if
dbConfig
.
Password
!=
""
{
dsn
+=
fmt
.
Sprintf
(
" password=%s"
,
dbConfig
.
Password
)
dsn
+=
fmt
.
Sprintf
(
" password=%s"
,
dbConfig
.
Password
)
}
}
gorm
,
err
:=
gorm
.
Open
(
postgres
.
Open
(
dsn
),
&
gorm
.
Config
{
gormConfig
:=
gorm
.
Config
{
// The indexer will explicitly manage the transactions
// The indexer will explicitly manage the transactions
SkipDefaultTransaction
:
true
,
SkipDefaultTransaction
:
true
,
// We may choose to create an adapter such that the
// logger emits to the geth logger when on DEBUG mode
Logger
:
logger
.
Default
.
LogMode
(
logger
.
Silent
),
Logger
:
logger
.
Default
.
LogMode
(
logger
.
Silent
),
}
gorm
,
err
:=
retry
.
Do
[
*
gorm
.
DB
](
context
.
Background
(),
10
,
retryStrategy
,
func
()
(
*
gorm
.
DB
,
error
)
{
gorm
,
err
:=
gorm
.
Open
(
postgres
.
Open
(
dsn
),
&
gormConfig
)
if
err
!=
nil
{
return
nil
,
errors
.
Wrap
(
err
,
"failed to connect to database"
)
}
return
gorm
,
nil
})
})
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
ors
.
Wrap
(
err
,
"failed to connect to database after multiple retries"
)
}
}
db
:=
&
DB
{
db
:=
&
DB
{
...
...
op-bindings/artifacts.json
View file @
48a146d7
...
@@ -38,5 +38,6 @@
...
@@ -38,5 +38,6 @@
"SchemaRegistry"
,
"SchemaRegistry"
,
"ProtocolVersions"
,
"ProtocolVersions"
,
"Safe"
,
"Safe"
,
"SafeProxyFactory"
"SafeProxyFactory"
,
"DelayedVetoable"
]
]
op-bindings/bindings/delayedvetoable.go
0 → 100644
View file @
48a146d7
This diff is collapsed.
Click to expand it.
op-bindings/bindings/delayedvetoable_more.go
0 → 100644
View file @
48a146d7
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package
bindings
import
(
"encoding/json"
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const
DelayedVetoableStorageLayoutJSON
=
"{
\"
storage
\"
:[{
\"
astId
\"
:1000,
\"
contract
\"
:
\"
src/L1/DelayedVetoable.sol:DelayedVetoable
\"
,
\"
label
\"
:
\"
_delay
\"
,
\"
offset
\"
:0,
\"
slot
\"
:
\"
0
\"
,
\"
type
\"
:
\"
t_uint256
\"
},{
\"
astId
\"
:1001,
\"
contract
\"
:
\"
src/L1/DelayedVetoable.sol:DelayedVetoable
\"
,
\"
label
\"
:
\"
_queuedAt
\"
,
\"
offset
\"
:0,
\"
slot
\"
:
\"
1
\"
,
\"
type
\"
:
\"
t_mapping(t_bytes32,t_uint256)
\"
}],
\"
types
\"
:{
\"
t_bytes32
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
bytes32
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
},
\"
t_mapping(t_bytes32,t_uint256)
\"
:{
\"
encoding
\"
:
\"
mapping
\"
,
\"
label
\"
:
\"
mapping(bytes32 =
\u003e
uint256)
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
,
\"
key
\"
:
\"
t_bytes32
\"
,
\"
value
\"
:
\"
t_uint256
\"
},
\"
t_uint256
\"
:{
\"
encoding
\"
:
\"
inplace
\"
,
\"
label
\"
:
\"
uint256
\"
,
\"
numberOfBytes
\"
:
\"
32
\"
}}}"
var
DelayedVetoableStorageLayout
=
new
(
solc
.
StorageLayout
)
var
DelayedVetoableDeployedBin
=
"0x608060405234801561001057600080fd5b50600436106100725760003560e01c8063b912de5d11610050578063b912de5d14610111578063d4b8399214610124578063d8bff4401461012c57610072565b806354fd4d501461007c5780635c39fcc1146100ce5780636a42b8f8146100fb575b61007a610134565b005b6100b86040518060400160405280600581526020017f312e302e3000000000000000000000000000000000000000000000000000000081525081565b6040516100c591906106a7565b60405180910390f35b6100d66104fb565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c5565b610103610532565b6040519081526020016100c5565b61010361011f36600461071a565b610540565b6100d6610567565b6100d6610593565b361580156101425750600054155b15610298573373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016148015906101c357503373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614155b1561023d576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660048201523360248201526044015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000060008190556040519081527febf28bfb587e28dfffd9173cf71c32ba5d3f0544a0117b5539c9b274a5bba2a89060200160405180910390a1565b600080366040516102aa929190610733565b60405190819003902090503373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103065750600081815260016020526040902054155b1561036c5760005460000361031e5761031e816105bf565b6000818152600160205260408082204290555182917f87a332a414acbc7da074543639ce7ae02ff1ea72e88379da9f261b080beb5a139161036191903690610743565b60405180910390a250565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161480156103be575060008181526001602052604090205415155b15610406576000818152600160205260408082208290555182917fbede6852c1d97d93ff557f676de76670cd0dec861e7fe8beb13aa0ba2b0ab0409161036191903690610743565b600081815260016020526040812054900361048b576040517f295a81c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166004820152336024820152604401610234565b60008054828252600160205260409091205442916104a891610790565b10156104e0576040517f43dc986d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600160205260408120556104f8816105bf565b50565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b61052f610134565b90565b600033610527575060005490565b60003361055a575060009081526001602052604090205490565b610562610134565b919050565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b60003361052757507f000000000000000000000000000000000000000000000000000000000000000090565b807f4c109d85bcd0bb5c735b4be850953d652afe4cd9aa2e0b1426a65a4dcb2e12296000366040516105f2929190610743565b60405180910390a26000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16600036604051610645929190610733565b6000604051808303816000865af19150503d8060008114610682576040519150601f19603f3d011682016040523d82523d6000602084013e610687565b606091505b50909250905081151560010361069f57805160208201f35b805160208201fd5b600060208083528351808285015260005b818110156106d4578581018301518582016040015282016106b8565b818111156106e6576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b60006020828403121561072c57600080fd5b5035919050565b8183823760009101908152919050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600082198211156107ca577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fea164736f6c634300080f000a"
func
init
()
{
if
err
:=
json
.
Unmarshal
([]
byte
(
DelayedVetoableStorageLayoutJSON
),
DelayedVetoableStorageLayout
);
err
!=
nil
{
panic
(
err
)
}
layouts
[
"DelayedVetoable"
]
=
DelayedVetoableStorageLayout
deployedBytecodes
[
"DelayedVetoable"
]
=
DelayedVetoableDeployedBin
}
op-bindings/bindings/mips_more.go
View file @
48a146d7
This diff is collapsed.
Click to expand it.
op-bindings/bindings/preimageoracle_more.go
View file @
48a146d7
This diff is collapsed.
Click to expand it.
op-challenger/cmd/main_test.go
View file @
48a146d7
...
@@ -24,6 +24,7 @@ var (
...
@@ -24,6 +24,7 @@ var (
cannonPreState
=
"./pre.json"
cannonPreState
=
"./pre.json"
datadir
=
"./test_data"
datadir
=
"./test_data"
cannonL2
=
"http://example.com:9545"
cannonL2
=
"http://example.com:9545"
rollupRpc
=
"http://example.com:8555"
alphabetTrace
=
"abcdefghijz"
alphabetTrace
=
"abcdefghijz"
agreeWithProposedOutput
=
"true"
agreeWithProposedOutput
=
"true"
)
)
...
@@ -249,6 +250,25 @@ func TestDataDir(t *testing.T) {
...
@@ -249,6 +250,25 @@ func TestDataDir(t *testing.T) {
})
})
}
}
func
TestRollupRpc
(
t
*
testing
.
T
)
{
t
.
Run
(
"NotRequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"--rollup-rpc"
))
})
t
.
Run
(
"NotRequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeCannon
,
"--rollup-rpc"
))
})
t
.
Run
(
"RequiredForOutputCannonTrace"
,
func
(
t
*
testing
.
T
)
{
verifyArgsInvalid
(
t
,
"flag rollup-rpc is required"
,
addRequiredArgsExcept
(
config
.
TraceTypeOutputCannon
,
"--rollup-rpc"
))
})
t
.
Run
(
"Valid"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
configForArgs
(
t
,
addRequiredArgs
(
config
.
TraceTypeOutputCannon
))
require
.
Equal
(
t
,
rollupRpc
,
cfg
.
RollupRpc
)
})
}
func
TestCannonL2
(
t
*
testing
.
T
)
{
func
TestCannonL2
(
t
*
testing
.
T
)
{
t
.
Run
(
"NotRequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
"NotRequiredForAlphabetTrace"
,
func
(
t
*
testing
.
T
)
{
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"--cannon-l2"
))
configForArgs
(
t
,
addRequiredArgsExcept
(
config
.
TraceTypeAlphabet
,
"--cannon-l2"
))
...
@@ -429,6 +449,9 @@ func requiredArgs(traceType config.TraceType) map[string]string {
...
@@ -429,6 +449,9 @@ func requiredArgs(traceType config.TraceType) map[string]string {
args
[
"--cannon-prestate"
]
=
cannonPreState
args
[
"--cannon-prestate"
]
=
cannonPreState
args
[
"--cannon-l2"
]
=
cannonL2
args
[
"--cannon-l2"
]
=
cannonL2
}
}
if
traceType
==
config
.
TraceTypeOutputCannon
{
args
[
"--rollup-rpc"
]
=
rollupRpc
}
return
args
return
args
}
}
...
...
op-challenger/config/config.go
View file @
48a146d7
...
@@ -32,6 +32,7 @@ var (
...
@@ -32,6 +32,7 @@ var (
ErrCannonNetworkAndRollupConfig
=
errors
.
New
(
"only specify one of network or rollup config path"
)
ErrCannonNetworkAndRollupConfig
=
errors
.
New
(
"only specify one of network or rollup config path"
)
ErrCannonNetworkAndL2Genesis
=
errors
.
New
(
"only specify one of network or l2 genesis path"
)
ErrCannonNetworkAndL2Genesis
=
errors
.
New
(
"only specify one of network or l2 genesis path"
)
ErrCannonNetworkUnknown
=
errors
.
New
(
"unknown cannon network"
)
ErrCannonNetworkUnknown
=
errors
.
New
(
"unknown cannon network"
)
ErrMissingRollupRpc
=
errors
.
New
(
"missing rollup rpc url"
)
)
)
type
TraceType
string
type
TraceType
string
...
@@ -107,6 +108,9 @@ type Config struct {
...
@@ -107,6 +108,9 @@ type Config struct {
// Specific to the alphabet trace provider
// Specific to the alphabet trace provider
AlphabetTrace
string
// String for the AlphabetTraceProvider
AlphabetTrace
string
// String for the AlphabetTraceProvider
// Specific to the output cannon trace type
RollupRpc
string
// Specific to the cannon trace provider
// Specific to the cannon trace provider
CannonBin
string
// Path to the cannon executable to run when generating trace data
CannonBin
string
// Path to the cannon executable to run when generating trace data
CannonServer
string
// Path to the op-program executable that provides the pre-image oracle server
CannonServer
string
// Path to the op-program executable that provides the pre-image oracle server
...
@@ -168,6 +172,11 @@ func (c Config) Check() error {
...
@@ -168,6 +172,11 @@ func (c Config) Check() error {
if
c
.
MaxConcurrency
==
0
{
if
c
.
MaxConcurrency
==
0
{
return
ErrMaxConcurrencyZero
return
ErrMaxConcurrencyZero
}
}
if
c
.
TraceType
==
TraceTypeOutputCannon
{
if
c
.
RollupRpc
==
""
{
return
ErrMissingRollupRpc
}
}
if
c
.
TraceType
==
TraceTypeCannon
||
c
.
TraceType
==
TraceTypeOutputCannon
{
if
c
.
TraceType
==
TraceTypeCannon
||
c
.
TraceType
==
TraceTypeOutputCannon
{
if
c
.
CannonBin
==
""
{
if
c
.
CannonBin
==
""
{
return
ErrMissingCannonBin
return
ErrMissingCannonBin
...
...
op-challenger/config/config_test.go
View file @
48a146d7
...
@@ -20,6 +20,7 @@ var (
...
@@ -20,6 +20,7 @@ var (
validCannonAbsolutPreState
=
"pre.json"
validCannonAbsolutPreState
=
"pre.json"
validDatadir
=
"/tmp/data"
validDatadir
=
"/tmp/data"
validCannonL2
=
"http://localhost:9545"
validCannonL2
=
"http://localhost:9545"
validRollupRpc
=
"http://localhost:8555"
agreeWithProposedOutput
=
true
agreeWithProposedOutput
=
true
)
)
...
@@ -35,6 +36,9 @@ func validConfig(traceType TraceType) Config {
...
@@ -35,6 +36,9 @@ func validConfig(traceType TraceType) Config {
cfg
.
CannonL2
=
validCannonL2
cfg
.
CannonL2
=
validCannonL2
cfg
.
CannonNetwork
=
validCannonNetwork
cfg
.
CannonNetwork
=
validCannonNetwork
}
}
if
traceType
==
TraceTypeOutputCannon
{
cfg
.
RollupRpc
=
validRollupRpc
}
return
cfg
return
cfg
}
}
...
@@ -125,6 +129,12 @@ func TestHttpPollInterval(t *testing.T) {
...
@@ -125,6 +129,12 @@ func TestHttpPollInterval(t *testing.T) {
})
})
}
}
func
TestRollupRpcRequired
(
t
*
testing
.
T
)
{
config
:=
validConfig
(
TraceTypeOutputCannon
)
config
.
RollupRpc
=
""
require
.
ErrorIs
(
t
,
config
.
Check
(),
ErrMissingRollupRpc
)
}
func
TestCannonL2Required
(
t
*
testing
.
T
)
{
func
TestCannonL2Required
(
t
*
testing
.
T
)
{
config
:=
validConfig
(
TraceTypeCannon
)
config
:=
validConfig
(
TraceTypeCannon
)
config
.
CannonL2
=
""
config
.
CannonL2
=
""
...
...
op-challenger/flags/flags.go
View file @
48a146d7
...
@@ -76,6 +76,11 @@ var (
...
@@ -76,6 +76,11 @@ var (
EnvVars
:
prefixEnvVars
(
"HTTP_POLL_INTERVAL"
),
EnvVars
:
prefixEnvVars
(
"HTTP_POLL_INTERVAL"
),
Value
:
config
.
DefaultPollInterval
,
Value
:
config
.
DefaultPollInterval
,
}
}
RollupRpcFlag
=
&
cli
.
StringFlag
{
Name
:
"rollup-rpc"
,
Usage
:
"HTTP provider URL for the rollup node"
,
EnvVars
:
prefixEnvVars
(
"ROLLUP_RPC"
),
}
AlphabetFlag
=
&
cli
.
StringFlag
{
AlphabetFlag
=
&
cli
.
StringFlag
{
Name
:
"alphabet"
,
Name
:
"alphabet"
,
Usage
:
"Correct Alphabet Trace (alphabet trace type only)"
,
Usage
:
"Correct Alphabet Trace (alphabet trace type only)"
,
...
@@ -83,7 +88,10 @@ var (
...
@@ -83,7 +88,10 @@ var (
}
}
CannonNetworkFlag
=
&
cli
.
StringFlag
{
CannonNetworkFlag
=
&
cli
.
StringFlag
{
Name
:
"cannon-network"
,
Name
:
"cannon-network"
,
Usage
:
fmt
.
Sprintf
(
"Predefined network selection. Available networks: %s (cannon trace type only)"
,
strings
.
Join
(
chaincfg
.
AvailableNetworks
(),
", "
)),
Usage
:
fmt
.
Sprintf
(
"Predefined network selection. Available networks: %s (cannon trace type only)"
,
strings
.
Join
(
chaincfg
.
AvailableNetworks
(),
", "
),
),
EnvVars
:
prefixEnvVars
(
"CANNON_NETWORK"
),
EnvVars
:
prefixEnvVars
(
"CANNON_NETWORK"
),
}
}
CannonRollupConfigFlag
=
&
cli
.
StringFlag
{
CannonRollupConfigFlag
=
&
cli
.
StringFlag
{
...
@@ -149,6 +157,7 @@ var requiredFlags = []cli.Flag{
...
@@ -149,6 +157,7 @@ var requiredFlags = []cli.Flag{
var
optionalFlags
=
[]
cli
.
Flag
{
var
optionalFlags
=
[]
cli
.
Flag
{
MaxConcurrencyFlag
,
MaxConcurrencyFlag
,
HTTPPollInterval
,
HTTPPollInterval
,
RollupRpcFlag
,
AlphabetFlag
,
AlphabetFlag
,
GameAllowlistFlag
,
GameAllowlistFlag
,
CannonNetworkFlag
,
CannonNetworkFlag
,
...
@@ -221,6 +230,9 @@ func CheckRequired(ctx *cli.Context) error {
...
@@ -221,6 +230,9 @@ func CheckRequired(ctx *cli.Context) error {
if
err
:=
CheckCannonFlags
(
ctx
);
err
!=
nil
{
if
err
:=
CheckCannonFlags
(
ctx
);
err
!=
nil
{
return
err
return
err
}
}
if
!
ctx
.
IsSet
(
RollupRpcFlag
.
Name
)
{
return
fmt
.
Errorf
(
"flag %s is required"
,
RollupRpcFlag
.
Name
)
}
default
:
default
:
return
fmt
.
Errorf
(
"invalid trace type. must be one of %v"
,
config
.
TraceTypes
)
return
fmt
.
Errorf
(
"invalid trace type. must be one of %v"
,
config
.
TraceTypes
)
}
}
...
@@ -266,6 +278,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
...
@@ -266,6 +278,7 @@ func NewConfigFromCLI(ctx *cli.Context) (*config.Config, error) {
GameWindow
:
ctx
.
Duration
(
GameWindowFlag
.
Name
),
GameWindow
:
ctx
.
Duration
(
GameWindowFlag
.
Name
),
MaxConcurrency
:
maxConcurrency
,
MaxConcurrency
:
maxConcurrency
,
PollInterval
:
ctx
.
Duration
(
HTTPPollInterval
.
Name
),
PollInterval
:
ctx
.
Duration
(
HTTPPollInterval
.
Name
),
RollupRpc
:
ctx
.
String
(
RollupRpcFlag
.
Name
),
AlphabetTrace
:
ctx
.
String
(
AlphabetFlag
.
Name
),
AlphabetTrace
:
ctx
.
String
(
AlphabetFlag
.
Name
),
CannonNetwork
:
ctx
.
String
(
CannonNetworkFlag
.
Name
),
CannonNetwork
:
ctx
.
String
(
CannonNetworkFlag
.
Name
),
CannonRollupConfigPath
:
ctx
.
String
(
CannonRollupConfigFlag
.
Name
),
CannonRollupConfigPath
:
ctx
.
String
(
CannonRollupConfigFlag
.
Name
),
...
...
op-program/host/config/config.go
View file @
48a146d7
...
@@ -64,6 +64,9 @@ type Config struct {
...
@@ -64,6 +64,9 @@ type Config struct {
// ServerMode indicates that the program should run in pre-image server mode and wait for requests.
// ServerMode indicates that the program should run in pre-image server mode and wait for requests.
// No client program is run.
// No client program is run.
ServerMode
bool
ServerMode
bool
// IsCustomChainConfig indicates that the program uses a custom chain configuration
IsCustomChainConfig
bool
}
}
func
(
c
*
Config
)
Check
()
error
{
func
(
c
*
Config
)
Check
()
error
{
...
@@ -117,6 +120,8 @@ func NewConfig(
...
@@ -117,6 +120,8 @@ func NewConfig(
l2Claim
common
.
Hash
,
l2Claim
common
.
Hash
,
l2ClaimBlockNum
uint64
,
l2ClaimBlockNum
uint64
,
)
*
Config
{
)
*
Config
{
_
,
err
:=
params
.
LoadOPStackChainConfig
(
l2Genesis
.
ChainID
.
Uint64
())
isCustomConfig
:=
err
!=
nil
return
&
Config
{
return
&
Config
{
Rollup
:
rollupCfg
,
Rollup
:
rollupCfg
,
L2ChainConfig
:
l2Genesis
,
L2ChainConfig
:
l2Genesis
,
...
@@ -126,6 +131,7 @@ func NewConfig(
...
@@ -126,6 +131,7 @@ func NewConfig(
L2Claim
:
l2Claim
,
L2Claim
:
l2Claim
,
L2ClaimBlockNumber
:
l2ClaimBlockNum
,
L2ClaimBlockNumber
:
l2ClaimBlockNum
,
L1RPCKind
:
sources
.
RPCKindBasic
,
L1RPCKind
:
sources
.
RPCKindBasic
,
IsCustomChainConfig
:
isCustomConfig
,
}
}
}
}
...
@@ -156,6 +162,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
...
@@ -156,6 +162,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
}
}
l2GenesisPath
:=
ctx
.
String
(
flags
.
L2GenesisPath
.
Name
)
l2GenesisPath
:=
ctx
.
String
(
flags
.
L2GenesisPath
.
Name
)
var
l2ChainConfig
*
params
.
ChainConfig
var
l2ChainConfig
*
params
.
ChainConfig
var
isCustomConfig
bool
if
l2GenesisPath
==
""
{
if
l2GenesisPath
==
""
{
networkName
:=
ctx
.
String
(
flags
.
Network
.
Name
)
networkName
:=
ctx
.
String
(
flags
.
Network
.
Name
)
ch
:=
chaincfg
.
ChainByName
(
networkName
)
ch
:=
chaincfg
.
ChainByName
(
networkName
)
...
@@ -169,6 +176,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
...
@@ -169,6 +176,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
l2ChainConfig
=
cfg
l2ChainConfig
=
cfg
}
else
{
}
else
{
l2ChainConfig
,
err
=
loadChainConfigFromGenesis
(
l2GenesisPath
)
l2ChainConfig
,
err
=
loadChainConfigFromGenesis
(
l2GenesisPath
)
isCustomConfig
=
true
}
}
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"invalid genesis: %w"
,
err
)
return
nil
,
fmt
.
Errorf
(
"invalid genesis: %w"
,
err
)
...
@@ -188,6 +196,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
...
@@ -188,6 +196,7 @@ func NewConfigFromCLI(log log.Logger, ctx *cli.Context) (*Config, error) {
L1RPCKind
:
sources
.
RPCProviderKind
(
ctx
.
String
(
flags
.
L1RPCProviderKind
.
Name
)),
L1RPCKind
:
sources
.
RPCProviderKind
(
ctx
.
String
(
flags
.
L1RPCProviderKind
.
Name
)),
ExecCmd
:
ctx
.
String
(
flags
.
Exec
.
Name
),
ExecCmd
:
ctx
.
String
(
flags
.
Exec
.
Name
),
ServerMode
:
ctx
.
Bool
(
flags
.
Server
.
Name
),
ServerMode
:
ctx
.
Bool
(
flags
.
Server
.
Name
),
IsCustomChainConfig
:
isCustomConfig
,
},
nil
},
nil
}
}
...
...
op-program/host/config/config_test.go
View file @
48a146d7
package
config
package
config
import
(
import
(
"math/big"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-program/chainconfig"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/require"
...
@@ -12,7 +14,7 @@ import (
...
@@ -12,7 +14,7 @@ import (
var
(
var
(
validRollupConfig
=
chaincfg
.
Goerli
validRollupConfig
=
chaincfg
.
Goerli
validL2Genesis
=
params
.
GoerliChainConfig
validL2Genesis
=
chainconfig
.
OP
GoerliChainConfig
validL1Head
=
common
.
Hash
{
0xaa
}
validL1Head
=
common
.
Hash
{
0xaa
}
validL2Head
=
common
.
Hash
{
0xbb
}
validL2Head
=
common
.
Hash
{
0xbb
}
validL2Claim
=
common
.
Hash
{
0xcc
}
validL2Claim
=
common
.
Hash
{
0xcc
}
...
@@ -158,6 +160,19 @@ func TestRejectExecAndServerMode(t *testing.T) {
...
@@ -158,6 +160,19 @@ func TestRejectExecAndServerMode(t *testing.T) {
require
.
ErrorIs
(
t
,
err
,
ErrNoExecInServerMode
)
require
.
ErrorIs
(
t
,
err
,
ErrNoExecInServerMode
)
}
}
func
TestIsCustomChainConfig
(
t
*
testing
.
T
)
{
t
.
Run
(
"nonCustom"
,
func
(
t
*
testing
.
T
)
{
cfg
:=
validConfig
()
require
.
Equal
(
t
,
cfg
.
IsCustomChainConfig
,
false
)
})
t
.
Run
(
"custom"
,
func
(
t
*
testing
.
T
)
{
customChainConfig
:=
&
params
.
ChainConfig
{
ChainID
:
big
.
NewInt
(
0x1212121212
)}
cfg
:=
NewConfig
(
validRollupConfig
,
customChainConfig
,
validL1Head
,
validL2Head
,
validL2OutputRoot
,
validL2Claim
,
validL2ClaimBlockNum
)
require
.
Equal
(
t
,
cfg
.
IsCustomChainConfig
,
true
)
})
}
func
validConfig
()
*
Config
{
func
validConfig
()
*
Config
{
cfg
:=
NewConfig
(
validRollupConfig
,
validL2Genesis
,
validL1Head
,
validL2Head
,
validL2OutputRoot
,
validL2Claim
,
validL2ClaimBlockNum
)
cfg
:=
NewConfig
(
validRollupConfig
,
validL2Genesis
,
validL1Head
,
validL2Head
,
validL2OutputRoot
,
validL2Claim
,
validL2ClaimBlockNum
)
cfg
.
DataDir
=
"/tmp/configTest"
cfg
.
DataDir
=
"/tmp/configTest"
...
...
op-program/host/kvstore/local.go
View file @
48a146d7
...
@@ -38,7 +38,15 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
...
@@ -38,7 +38,15 @@ func (s *LocalPreimageSource) Get(key common.Hash) ([]byte, error) {
case
l2ClaimBlockNumberKey
:
case
l2ClaimBlockNumberKey
:
return
binary
.
BigEndian
.
AppendUint64
(
nil
,
s
.
config
.
L2ClaimBlockNumber
),
nil
return
binary
.
BigEndian
.
AppendUint64
(
nil
,
s
.
config
.
L2ClaimBlockNumber
),
nil
case
l2ChainIDKey
:
case
l2ChainIDKey
:
return
binary
.
BigEndian
.
AppendUint64
(
nil
,
client
.
CustomChainIDIndicator
),
nil
// The CustomChainIDIndicator informs the client to rely on the L2ChainConfigKey to
// read the chain config. Otherwise, it'll attempt to read a non-existent hardcoded chain config
var
chainID
uint64
if
s
.
config
.
IsCustomChainConfig
{
chainID
=
client
.
CustomChainIDIndicator
}
else
{
chainID
=
s
.
config
.
L2ChainConfig
.
ChainID
.
Uint64
()
}
return
binary
.
BigEndian
.
AppendUint64
(
nil
,
chainID
),
nil
case
l2ChainConfigKey
:
case
l2ChainConfigKey
:
return
json
.
Marshal
(
s
.
config
.
L2ChainConfig
)
return
json
.
Marshal
(
s
.
config
.
L2ChainConfig
)
case
rollupKey
:
case
rollupKey
:
...
...
op-program/host/kvstore/local_test.go
View file @
48a146d7
...
@@ -7,7 +7,6 @@ import (
...
@@ -7,7 +7,6 @@ import (
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
"github.com/ethereum-optimism/optimism/op-node/chaincfg"
preimage
"github.com/ethereum-optimism/optimism/op-preimage"
preimage
"github.com/ethereum-optimism/optimism/op-preimage"
"github.com/ethereum-optimism/optimism/op-program/client"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum-optimism/optimism/op-program/host/config"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/params"
...
@@ -33,7 +32,7 @@ func TestLocalPreimageSource(t *testing.T) {
...
@@ -33,7 +32,7 @@ func TestLocalPreimageSource(t *testing.T) {
{
"L2OutputRoot"
,
l2OutputRootKey
,
cfg
.
L2OutputRoot
.
Bytes
()},
{
"L2OutputRoot"
,
l2OutputRootKey
,
cfg
.
L2OutputRoot
.
Bytes
()},
{
"L2Claim"
,
l2ClaimKey
,
cfg
.
L2Claim
.
Bytes
()},
{
"L2Claim"
,
l2ClaimKey
,
cfg
.
L2Claim
.
Bytes
()},
{
"L2ClaimBlockNumber"
,
l2ClaimBlockNumberKey
,
binary
.
BigEndian
.
AppendUint64
(
nil
,
cfg
.
L2ClaimBlockNumber
)},
{
"L2ClaimBlockNumber"
,
l2ClaimBlockNumberKey
,
binary
.
BigEndian
.
AppendUint64
(
nil
,
cfg
.
L2ClaimBlockNumber
)},
{
"L2ChainID"
,
l2ChainIDKey
,
binary
.
BigEndian
.
AppendUint64
(
nil
,
c
lient
.
CustomChainIDIndicator
)},
{
"L2ChainID"
,
l2ChainIDKey
,
binary
.
BigEndian
.
AppendUint64
(
nil
,
c
fg
.
L2ChainConfig
.
ChainID
.
Uint64
()
)},
{
"Rollup"
,
rollupKey
,
asJson
(
t
,
cfg
.
Rollup
)},
{
"Rollup"
,
rollupKey
,
asJson
(
t
,
cfg
.
Rollup
)},
{
"ChainConfig"
,
l2ChainConfigKey
,
asJson
(
t
,
cfg
.
L2ChainConfig
)},
{
"ChainConfig"
,
l2ChainConfigKey
,
asJson
(
t
,
cfg
.
L2ChainConfig
)},
{
"Unknown"
,
preimage
.
LocalIndexKey
(
1000
)
.
PreimageKey
(),
nil
},
{
"Unknown"
,
preimage
.
LocalIndexKey
(
1000
)
.
PreimageKey
(),
nil
},
...
...
packages/contracts-bedrock/.gas-snapshot
View file @
48a146d7
...
@@ -46,6 +46,9 @@ CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 1208
...
@@ -46,6 +46,9 @@ CrossDomainOwnable3_Test:test_transferOwnership_zeroAddress_reverts() (gas: 1208
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81417)
CrossDomainOwnableThroughPortal_Test:test_depositTransaction_crossDomainOwner_succeeds() (gas: 81417)
CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_notOwner_reverts() (gas: 10597)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
CrossDomainOwnable_Test:test_onlyOwner_succeeds() (gas: 34883)
DelayedVetoable_Getters_Test:test_getters() (gas: 21342)
DelayedVetoable_Getters_TestFail:test_getters_notZeroAddress_reverts() (gas: 26649)
DelayedVetoable_HandleCall_TestFail:test_handleCall_unauthorizedInitiation_reverts() (gas: 20234)
DeleteOutput:test_script_succeeds() (gas: 3100)
DeleteOutput:test_script_succeeds() (gas: 3100)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_owner_succeeds() (gas: 7582)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
DeployerWhitelist_Test:test_storageSlots_succeeds() (gas: 33395)
...
...
packages/contracts-bedrock/semver-lock.json
View file @
48a146d7
{
{
"src/EAS/EAS.sol"
:
"0x1acb25751a1206eb859cc5fcf934da2f84cfb907b8e8951d86fc4e43c53a7303"
,
"src/EAS/EAS.sol"
:
"0x1acb25751a1206eb859cc5fcf934da2f84cfb907b8e8951d86fc4e43c53a7303"
,
"src/EAS/SchemaRegistry.sol"
:
"0x305f3afed2e337cd70aac70fc202e6503b947b0a31e0d4e18c49486eeb635bb5"
,
"src/EAS/SchemaRegistry.sol"
:
"0x305f3afed2e337cd70aac70fc202e6503b947b0a31e0d4e18c49486eeb635bb5"
,
"src/L1/DelayedVetoable.sol"
:
"0x276c6276292095e6aa37a70008cf4e0d1cbcc020dbc9107459bbc72ab5ed744f"
,
"src/L1/L1CrossDomainMessenger.sol"
:
"0x14f5991022705b8bd3bf931e138a528cc9c9e90d0f1ec398efd5079224d61b3b"
,
"src/L1/L1CrossDomainMessenger.sol"
:
"0x14f5991022705b8bd3bf931e138a528cc9c9e90d0f1ec398efd5079224d61b3b"
,
"src/L1/L1ERC721Bridge.sol"
:
"0x3e0e3d2f4c151e41585850f06e6452cdda86348debfe6ff16e364a839266450b"
,
"src/L1/L1ERC721Bridge.sol"
:
"0x3e0e3d2f4c151e41585850f06e6452cdda86348debfe6ff16e364a839266450b"
,
"src/L1/L1StandardBridge.sol"
:
"0x12e227c6054660a83b92d823a7447db96a7d476b7a94e0f1807772d400329880"
,
"src/L1/L1StandardBridge.sol"
:
"0x12e227c6054660a83b92d823a7447db96a7d476b7a94e0f1807772d400329880"
,
...
...
packages/contracts-bedrock/src/L1/DelayedVetoable.sol
0 → 100644
View file @
48a146d7
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ISemver } from "src/universal/ISemver.sol";
/// @title DelayedVetoable
/// @notice This contract enables a delay before a call is forwarded to a target contract, and during the delay period
/// the call can be vetoed by the authorized vetoer.
/// This contract does not support value transfers, only data is forwarded.
/// Additionally, this contract cannot be used to forward calls with data beginning with the function selector
/// of the queuedAt(bytes32) function. This is because of input validation checks which solidity performs at
/// runtime on functions which take an argument.
contract DelayedVetoable is ISemver {
/// @notice Error for when the delay has already been set.
error AlreadyDelayed();
/// @notice Error for when attempting to forward too early.
error ForwardingEarly();
/// @notice Error for the target is not set.
error TargetUnitialized();
/// @notice Error for unauthorized calls.
error Unauthorized(address expected, address actual);
/// @notice An event that is emitted when the delay is activated.
/// @param delay The delay that was activated.
event DelayActivated(uint256 delay);
/// @notice An event that is emitted when a call is initiated.
/// @param callHash The hash of the call data.
/// @param data The data of the initiated call.
event Initiated(bytes32 indexed callHash, bytes data);
/// @notice An event that is emitted each time a call is forwarded.
/// @param callHash The hash of the call data.
/// @param data The data forwarded to the target.
event Forwarded(bytes32 indexed callHash, bytes data);
/// @notice An event that is emitted each time a call is vetoed.
/// @param callHash The hash of the call data.
/// @param data The data forwarded to the target.
event Vetoed(bytes32 indexed callHash, bytes data);
/// @notice The address that all calls are forwarded to after the delay.
address internal immutable TARGET;
/// @notice The address that can veto a call.
address internal immutable VETOER;
/// @notice The address that can initiate a call.
address internal immutable INITIATOR;
/// @notice The delay which will be set after the initial system deployment is completed.
uint256 internal immutable OPERATING_DELAY;
/// @notice The current amount of time to wait before forwarding a call.
uint256 internal _delay;
/// @notice The time that a call was initiated.
mapping(bytes32 => uint256) internal _queuedAt;
/// @notice A modifier that reverts if not called by the vetoer or by address(0) to allow
/// eth_call to interact with this proxy without needing to use low-level storage
/// inspection. We assume that nobody is able to trigger calls from address(0) during
/// normal EVM execution.
modifier readOrHandle() {
if (msg.sender == address(0)) {
_;
} else {
// This WILL halt the call frame on completion.
_handleCall();
}
}
/// @notice Semantic version.
/// @custom:semver 1.0.0
string public constant version = "1.0.0";
/// @notice Sets the target admin during contract deployment.
/// @param vetoer_ Address of the vetoer.
/// @param initiator_ Address of the initiator.
/// @param target_ Address of the target.
/// @param operatingDelay_ Time to delay when the system is operational.
constructor(address vetoer_, address initiator_, address target_, uint256 operatingDelay_) {
// Note that the _delay value is not set here. Having an initial delay of 0 is helpful
// during the deployment of a new system.
VETOER = vetoer_;
INITIATOR = initiator_;
TARGET = target_;
OPERATING_DELAY = operatingDelay_;
}
/// @notice Gets the initiator
/// @return initiator_ Initiator address.
function initiator() external virtual readOrHandle returns (address initiator_) {
initiator_ = INITIATOR;
}
//// @notice Queries the vetoer address.
/// @return vetoer_ Vetoer address.
function vetoer() external virtual readOrHandle returns (address vetoer_) {
vetoer_ = VETOER;
}
//// @notice Queries the target address.
/// @return target_ Target address.
function target() external readOrHandle returns (address target_) {
target_ = TARGET;
}
/// @notice Gets the delay
/// @return delay_ Delay address.
function delay() external readOrHandle returns (uint256 delay_) {
delay_ = _delay;
}
/// @notice Gets entries in the _queuedAt mapping.
/// @param callHash The hash of the call data.
/// @return queuedAt_ The time the callHash was recorded.
function queuedAt(bytes32 callHash) external readOrHandle returns (uint256 queuedAt_) {
queuedAt_ = _queuedAt[callHash];
}
/// @notice Used for all calls that pass data to the contract.
fallback() external {
_handleCall();
}
/// @notice Receives all calls other than those made by the vetoer.
/// This enables transparent initiation and forwarding of calls to the target and avoids
/// the need for additional layers of abi encoding.
function _handleCall() internal {
// The initiator and vetoer activate the delay by passing in null data.
if (msg.data.length == 0 && _delay == 0) {
if (msg.sender != INITIATOR && msg.sender != VETOER) {
revert Unauthorized(INITIATOR, msg.sender);
}
_delay = OPERATING_DELAY;
emit DelayActivated(_delay);
return;
}
bytes32 callHash = keccak256(msg.data);
// Case 1: The initiator is calling the contract to initiate a call.
if (msg.sender == INITIATOR && _queuedAt[callHash] == 0) {
if (_delay == 0) {
// This forward function will halt the call frame on completion.
_forwardAndHalt(callHash);
}
_queuedAt[callHash] = block.timestamp;
emit Initiated(callHash, msg.data);
return;
}
// Case 2: The vetoer is calling the contract to veto a call.
// Note: The vetoer retains the ability to veto even after the delay has passed. This makes censoring the vetoer
// more costly, as there is no time limit after which their transaction can be included.
if (msg.sender == VETOER && _queuedAt[callHash] != 0) {
delete _queuedAt[callHash];
emit Vetoed(callHash, msg.data);
return;
}
// Case 3: The call is from an unpermissioned actor. We'll forward the call if the delay has
// passed.
if (_queuedAt[callHash] == 0) {
// The call has not been initiated, so we'll treat this is an unauthorized initiation attempt.
revert Unauthorized(INITIATOR, msg.sender);
}
if (_queuedAt[callHash] + _delay < block.timestamp) {
// Not enough time has passed, so we'll revert.
revert ForwardingEarly();
}
// Delete the call to prevent replays
delete _queuedAt[callHash];
_forwardAndHalt(callHash);
}
/// @notice Forwards the call to the target and halts the call frame.
function _forwardAndHalt(bytes32 callHash) internal {
// Forward the call
emit Forwarded(callHash, msg.data);
(bool success, bytes memory returndata) = TARGET.call(msg.data);
if (success == true) {
assembly {
return(add(returndata, 0x20), mload(returndata))
}
} else {
assembly {
revert(add(returndata, 0x20), mload(returndata))
}
}
}
}
packages/contracts-bedrock/test/DelayedVetoable.t.sol
0 → 100644
View file @
48a146d7
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { CommonTest } from "./CommonTest.t.sol";
import { DelayedVetoable } from "src/L1/DelayedVetoable.sol";
contract DelayedVetoable_Init is CommonTest {
error Unauthorized(address expected, address actual);
error ForwardingEarly();
event Initiated(bytes32 indexed callHash, bytes data);
event Forwarded(bytes32 indexed callHash, bytes data);
event Vetoed(bytes32 indexed callHash, bytes data);
address target = address(0xabba);
address initiator = alice;
address vetoer = bob;
uint256 operatingDelay = 14 days;
DelayedVetoable delayedVetoable;
function setUp() public override {
super.setUp();
delayedVetoable = new DelayedVetoable({
initiator_: alice,
vetoer_: bob,
target_: address(target),
operatingDelay_: operatingDelay
});
// Most tests will use the operating delay, so we call as the initiator with null data
// to set the delay. For tests that need to use the initial zero delay, we'll modify the
// value in storage.
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(hex"");
}
/// @dev This function is used to prevent initiating the delay unintentionally..
/// @param data The data to be used in the call.
function assumeNonzeroData(bytes memory data) internal pure {
vm.assume(data.length > 0);
}
}
contract DelayedVetoable_Getters_Test is DelayedVetoable_Init {
/// @dev The getters return the expected values when called by the zero address.
function test_getters() external {
vm.startPrank(address(0));
assertEq(delayedVetoable.initiator(), initiator);
assertEq(delayedVetoable.vetoer(), vetoer);
assertEq(delayedVetoable.target(), target);
assertEq(delayedVetoable.delay(), operatingDelay);
}
}
contract DelayedVetoable_Getters_TestFail is DelayedVetoable_Init {
/// @dev Check that getter calls from unauthorized entities will revert.
function test_getters_notZeroAddress_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.initiator();
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.vetoer();
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.target();
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
delayedVetoable.delay();
}
}
contract DelayedVetoable_HandleCall_Test is DelayedVetoable_Init {
/// @dev A call can be initiated by the initiator.
function testFuzz_handleCall_initiation_succeeds(bytes memory data) external {
assumeNonzeroData(data);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Initiated(keccak256(data), data);
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
assertTrue(success);
}
/// @dev The delay is inititially set to zero and the call is immediately forwarded.
function testFuzz_handleCall_initialForwardingImmediately_succeeds(
bytes calldata inData,
bytes calldata outData
)
external
{
assumeNonzeroData(inData);
if (inData.length >= 4) {
vm.assume(bytes4(inData[0:4]) != bytes4(keccak256("queuedAt(bytes32)")));
}
// Reset the delay to zero
vm.store(address(delayedVetoable), bytes32(uint256(0)), bytes32(uint256(0)));
vm.mockCall(target, inData, outData);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
vm.expectCall({ callee: target, data: inData });
emit Forwarded(keccak256(inData), inData);
vm.prank(initiator);
(bool success, bytes memory returnData) = address(delayedVetoable).call(inData);
assertTrue(success);
assertEq(returnData, outData);
}
/// @dev The delay can be activated by the vetoer or initiator, and are not forwarded until the delay has passed
/// once activated.
function testFuzz_handleCall_forwardingWithDelay_succeeds(bytes memory data) external {
assumeNonzeroData(data);
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
// Check that the call is in the _queuedAt mapping
bytes32 callHash = keccak256(data);
vm.prank(address(0));
assertEq(delayedVetoable.queuedAt(callHash), block.timestamp);
vm.warp(block.timestamp + operatingDelay);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Forwarded(keccak256(data), data);
vm.expectCall({ callee: target, data: data });
(success,) = address(delayedVetoable).call(data);
assertTrue(success);
}
}
contract DelayedVetoable_HandleCall_TestFail is DelayedVetoable_Init {
/// @dev The delay is inititially set to zero and the call is immediately forwarded.
function test_handleCall_unauthorizedInitiation_reverts() external {
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(bool success,) = address(delayedVetoable).call(NON_ZERO_DATA);
}
/// @dev The call cannot be forewarded until the delay has passed.
function testFuzz_handleCall_forwardingTooSoon_reverts(bytes memory data) external {
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
vm.expectRevert(abi.encodeWithSelector(ForwardingEarly.selector));
(success,) = address(delayedVetoable).call(data);
}
/// @dev The call cannot be forwarded a second time.
function testFuzz_handleCall_forwardingTwice_reverts(bytes memory data) external {
assumeNonzeroData(data);
// Initiate the call
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(data);
vm.warp(block.timestamp + operatingDelay);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Forwarded(keccak256(data), data);
// Forward the call
vm.expectCall({ callee: target, data: data });
(success,) = address(delayedVetoable).call(data);
assertTrue(success);
// Attempt to foward the same call again.
vm.expectRevert(abi.encodeWithSelector(Unauthorized.selector, initiator, address(this)));
(success,) = address(delayedVetoable).call(data);
assertTrue(success);
}
/// @dev If the target reverts, it is bubbled up.
function testFuzz_handleCall_forwardingTargetReverts_reverts(bytes memory inData, bytes memory outData) external {
assumeNonzeroData(inData);
// Initiate the call
vm.prank(initiator);
(bool success,) = address(delayedVetoable).call(inData);
vm.warp(block.timestamp + operatingDelay);
vm.expectEmit(true, false, false, true, address(delayedVetoable));
emit Forwarded(keccak256(inData), inData);
vm.mockCallRevert(target, inData, outData);
// Forward the call
vm.expectRevert(outData);
(bool success2,) = address(delayedVetoable).call(inData);
}
/// @dev A test documenting the single instance in which the contract is not 'transparent' to the initiator.
function testFuzz_handleCall_queuedAtClash_reverts(bytes memory outData) external {
// This will get us calldata with the same function selector as the queuedAt function, but
// with the incorrect input data length.
bytes memory inData = abi.encodePacked(keccak256("queuedAt(bytes32)"));
// Reset the delay to zero
vm.store(address(delayedVetoable), bytes32(uint256(0)), bytes32(uint256(0)));
vm.prank(initiator);
vm.expectRevert(outData);
(bool success,) = address(delayedVetoable).call(inData);
}
}
pnpm-lock.yaml
View file @
48a146d7
...
@@ -35,7 +35,7 @@ importers:
...
@@ -35,7 +35,7 @@ importers:
version
:
10.0.1
version
:
10.0.1
'
@types/node'
:
'
@types/node'
:
specifier
:
^20.5.3
specifier
:
^20.5.3
version
:
20.6.
1
version
:
20.6.
2
'
@typescript-eslint/eslint-plugin'
:
'
@typescript-eslint/eslint-plugin'
:
specifier
:
^6.7.0
specifier
:
^6.7.0
version
:
6.7.0(@typescript-eslint/parser@6.7.0)(eslint@8.49.0)(typescript@5.1.6)
version
:
6.7.0(@typescript-eslint/parser@6.7.0)(eslint@8.49.0)(typescript@5.1.6)
...
@@ -92,7 +92,7 @@ importers:
...
@@ -92,7 +92,7 @@ importers:
version
:
14.0.1
version
:
14.0.1
markdownlint
:
markdownlint
:
specifier
:
^0.31.0
specifier
:
^0.31.0
version
:
0.31.
0
version
:
0.31.
1
markdownlint-cli2
:
markdownlint-cli2
:
specifier
:
0.4.0
specifier
:
0.4.0
version
:
0.4.0
version
:
0.4.0
...
@@ -342,7 +342,7 @@ importers:
...
@@ -342,7 +342,7 @@ importers:
version
:
5.1.6
version
:
5.1.6
vite
:
vite
:
specifier
:
^4.4.6
specifier
:
^4.4.6
version
:
4.4.6(@types/node@20.6.
1
)
version
:
4.4.6(@types/node@20.6.
2
)
vitest
:
vitest
:
specifier
:
^0.34.2
specifier
:
^0.34.2
version
:
0.34.2(jsdom@22.1.0)
version
:
0.34.2(jsdom@22.1.0)
...
@@ -436,7 +436,7 @@ importers:
...
@@ -436,7 +436,7 @@ importers:
version
:
1.3.1(typescript@5.1.6)
version
:
1.3.1(typescript@5.1.6)
vite
:
vite
:
specifier
:
^4.4.6
specifier
:
^4.4.6
version
:
4.4.6(@types/node@20.6.
1
)
version
:
4.4.6(@types/node@20.6.
2
)
vitest
:
vitest
:
specifier
:
^0.34.2
specifier
:
^0.34.2
version
:
0.34.2(jsdom@22.1.0)
version
:
0.34.2(jsdom@22.1.0)
...
@@ -567,7 +567,7 @@ importers:
...
@@ -567,7 +567,7 @@ importers:
version
:
1.6.0(typescript@5.1.6)(zod@3.22.0)
version
:
1.6.0(typescript@5.1.6)(zod@3.22.0)
vite
:
vite
:
specifier
:
^4.4.9
specifier
:
^4.4.9
version
:
4.4.9(@types/node@20.6.
1
)
version
:
4.4.9(@types/node@20.6.
2
)
vitest
:
vitest
:
specifier
:
^0.34.1
specifier
:
^0.34.1
version
:
0.34.1
version
:
0.34.1
...
@@ -3783,7 +3783,7 @@ packages:
...
@@ -3783,7 +3783,7 @@ packages:
resolution
:
{
integrity
:
sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==
}
resolution
:
{
integrity
:
sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==
}
dependencies
:
dependencies
:
'
@types/minimatch'
:
5.1.2
'
@types/minimatch'
:
5.1.2
'
@types/node'
:
20.6.
1
'
@types/node'
:
20.6.
2
dev
:
true
dev
:
true
/@types/is-ci@3.0.0
:
/@types/is-ci@3.0.0
:
...
@@ -3852,7 +3852,7 @@ packages:
...
@@ -3852,7 +3852,7 @@ packages:
/@types/morgan@1.9.4
:
/@types/morgan@1.9.4
:
resolution
:
{
integrity
:
sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==
}
resolution
:
{
integrity
:
sha512-cXoc4k+6+YAllH3ZHmx4hf7La1dzUk6keTR4bF4b4Sc0mZxU/zK4wO7l+ZzezXm/jkYj/qC+uYGZrarZdIVvyQ==
}
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
1
'
@types/node'
:
20.6.
2
dev
:
true
dev
:
true
/@types/ms@0.7.31
:
/@types/ms@0.7.31
:
...
@@ -3876,10 +3876,6 @@ packages:
...
@@ -3876,10 +3876,6 @@ packages:
resolution
:
{
integrity
:
sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==
}
resolution
:
{
integrity
:
sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==
}
dev
:
true
dev
:
true
/@types/node@20.6.1
:
resolution
:
{
integrity
:
sha512-4LcJvuXQlv4lTHnxwyHQZ3uR9Zw2j7m1C9DfuwoTFQQP4Pmu04O6IfLYgMmHoOCt0nosItLLZAH+sOrRE0Bo8g==
}
dev
:
true
/@types/node@20.6.2
:
/@types/node@20.6.2
:
resolution
:
{
integrity
:
sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
}
resolution
:
{
integrity
:
sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
}
...
@@ -10707,8 +10703,8 @@ packages:
...
@@ -10707,8 +10703,8 @@ packages:
markdown-it
:
12.3.2
markdown-it
:
12.3.2
dev
:
true
dev
:
true
/markdownlint@0.31.
0
:
/markdownlint@0.31.
1
:
resolution
:
{
integrity
:
sha512-
e+jZGRGZrz1s0T4wiPDFtyQafq7sKgdbf2sdL46gRT8zLEvDDihQmGeSCV6VXp9BsfkuZ0dPTAg9hf4j6NFgjg
==
}
resolution
:
{
integrity
:
sha512-
CKMR2hgcIBrYlIUccDCOvi966PZ0kJExDrUi1R+oF9PvqQmCrTqjOsgIvf2403OmJ+CWomuzDoylr6KbuMyvHA
==
}
engines
:
{
node
:
'
>=16'
}
engines
:
{
node
:
'
>=16'
}
dependencies
:
dependencies
:
markdown-it
:
13.0.1
markdown-it
:
13.0.1
...
@@ -14649,7 +14645,7 @@ packages:
...
@@ -14649,7 +14645,7 @@ packages:
-
zod
-
zod
dev
:
true
dev
:
true
/vite-node@0.34.1(@types/node@20.6.
1
)
:
/vite-node@0.34.1(@types/node@20.6.
2
)
:
resolution
:
{
integrity
:
sha512-odAZAL9xFMuAg8aWd7nSPT+hU8u2r9gU3LRm9QKjxBEF2rRdWpMuqkrkjvyVQEdNFiBctqr2Gg4uJYizm5Le6w==
}
resolution
:
{
integrity
:
sha512-odAZAL9xFMuAg8aWd7nSPT+hU8u2r9gU3LRm9QKjxBEF2rRdWpMuqkrkjvyVQEdNFiBctqr2Gg4uJYizm5Le6w==
}
engines
:
{
node
:
'
>=v14.18.0'
}
engines
:
{
node
:
'
>=v14.18.0'
}
hasBin
:
true
hasBin
:
true
...
@@ -14659,7 +14655,7 @@ packages:
...
@@ -14659,7 +14655,7 @@ packages:
mlly
:
1.4.0
mlly
:
1.4.0
pathe
:
1.1.1
pathe
:
1.1.1
picocolors
:
1.0.0
picocolors
:
1.0.0
vite
:
4.4.9(@types/node@20.6.
1
)
vite
:
4.4.9(@types/node@20.6.
2
)
transitivePeerDependencies
:
transitivePeerDependencies
:
-
'
@types/node'
-
'
@types/node'
-
less
-
less
...
@@ -14671,7 +14667,7 @@ packages:
...
@@ -14671,7 +14667,7 @@ packages:
-
terser
-
terser
dev
:
true
dev
:
true
/vite-node@0.34.2(@types/node@20.6.
1
)
:
/vite-node@0.34.2(@types/node@20.6.
2
)
:
resolution
:
{
integrity
:
sha512-JtW249Zm3FB+F7pQfH56uWSdlltCo1IOkZW5oHBzeQo0iX4jtC7o1t9aILMGd9kVekXBP2lfJBEQt9rBh07ebA==
}
resolution
:
{
integrity
:
sha512-JtW249Zm3FB+F7pQfH56uWSdlltCo1IOkZW5oHBzeQo0iX4jtC7o1t9aILMGd9kVekXBP2lfJBEQt9rBh07ebA==
}
engines
:
{
node
:
'
>=v14.18.0'
}
engines
:
{
node
:
'
>=v14.18.0'
}
hasBin
:
true
hasBin
:
true
...
@@ -14681,7 +14677,7 @@ packages:
...
@@ -14681,7 +14677,7 @@ packages:
mlly
:
1.4.0
mlly
:
1.4.0
pathe
:
1.1.1
pathe
:
1.1.1
picocolors
:
1.0.0
picocolors
:
1.0.0
vite
:
4.4.9(@types/node@20.6.
1
)
vite
:
4.4.9(@types/node@20.6.
2
)
transitivePeerDependencies
:
transitivePeerDependencies
:
-
'
@types/node'
-
'
@types/node'
-
less
-
less
...
@@ -14715,7 +14711,7 @@ packages:
...
@@ -14715,7 +14711,7 @@ packages:
-
terser
-
terser
dev
:
true
dev
:
true
/vite@4.4.6(@types/node@20.6.
1
)
:
/vite@4.4.6(@types/node@20.6.
2
)
:
resolution
:
{
integrity
:
sha512-EY6Mm8vJ++S3D4tNAckaZfw3JwG3wa794Vt70M6cNJ6NxT87yhq7EC8Rcap3ahyHdo8AhCmV9PTk+vG1HiYn1A==
}
resolution
:
{
integrity
:
sha512-EY6Mm8vJ++S3D4tNAckaZfw3JwG3wa794Vt70M6cNJ6NxT87yhq7EC8Rcap3ahyHdo8AhCmV9PTk+vG1HiYn1A==
}
engines
:
{
node
:
^14.18.0 || >=16.0.0
}
engines
:
{
node
:
^14.18.0 || >=16.0.0
}
hasBin
:
true
hasBin
:
true
...
@@ -14743,7 +14739,7 @@ packages:
...
@@ -14743,7 +14739,7 @@ packages:
terser
:
terser
:
optional
:
true
optional
:
true
dependencies
:
dependencies
:
'
@types/node'
:
20.6.
1
'
@types/node'
:
20.6.
2
esbuild
:
0.18.15
esbuild
:
0.18.15
postcss
:
8.4.27
postcss
:
8.4.27
rollup
:
3.26.3
rollup
:
3.26.3
...
@@ -14751,42 +14747,6 @@ packages:
...
@@ -14751,42 +14747,6 @@ packages:
fsevents
:
2.3.2
fsevents
:
2.3.2
dev
:
true
dev
:
true
/vite@4.4.9(@types/node@20.6.1)
:
resolution
:
{
integrity
:
sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==
}
engines
:
{
node
:
^14.18.0 || >=16.0.0
}
hasBin
:
true
peerDependencies
:
'
@types/node'
:
'
>=
14'
less
:
'
*'
lightningcss
:
^1.21.0
sass
:
'
*'
stylus
:
'
*'
sugarss
:
'
*'
terser
:
^5.4.0
peerDependenciesMeta
:
'
@types/node'
:
optional
:
true
less
:
optional
:
true
lightningcss
:
optional
:
true
sass
:
optional
:
true
stylus
:
optional
:
true
sugarss
:
optional
:
true
terser
:
optional
:
true
dependencies
:
'
@types/node'
:
20.6.1
esbuild
:
0.18.15
postcss
:
8.4.27
rollup
:
3.28.0
optionalDependencies
:
fsevents
:
2.3.2
dev
:
true
/vite@4.4.9(@types/node@20.6.2)
:
/vite@4.4.9(@types/node@20.6.2)
:
resolution
:
{
integrity
:
sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==
}
resolution
:
{
integrity
:
sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==
}
engines
:
{
node
:
^14.18.0 || >=16.0.0
}
engines
:
{
node
:
^14.18.0 || >=16.0.0
}
...
@@ -14856,7 +14816,7 @@ packages:
...
@@ -14856,7 +14816,7 @@ packages:
dependencies
:
dependencies
:
'
@types/chai'
:
4.3.6
'
@types/chai'
:
4.3.6
'
@types/chai-subset'
:
1.3.3
'
@types/chai-subset'
:
1.3.3
'
@types/node'
:
20.6.
1
'
@types/node'
:
20.6.
2
'
@vitest/expect'
:
0.34.1
'
@vitest/expect'
:
0.34.1
'
@vitest/runner'
:
0.34.1
'
@vitest/runner'
:
0.34.1
'
@vitest/snapshot'
:
0.34.1
'
@vitest/snapshot'
:
0.34.1
...
@@ -14875,8 +14835,8 @@ packages:
...
@@ -14875,8 +14835,8 @@ packages:
strip-literal
:
1.0.1
strip-literal
:
1.0.1
tinybench
:
2.5.0
tinybench
:
2.5.0
tinypool
:
0.7.0
tinypool
:
0.7.0
vite
:
4.4.9(@types/node@20.6.
1
)
vite
:
4.4.9(@types/node@20.6.
2
)
vite-node
:
0.34.1(@types/node@20.6.
1
)
vite-node
:
0.34.1(@types/node@20.6.
2
)
why-is-node-running
:
2.2.2
why-is-node-running
:
2.2.2
transitivePeerDependencies
:
transitivePeerDependencies
:
-
less
-
less
...
@@ -14921,7 +14881,7 @@ packages:
...
@@ -14921,7 +14881,7 @@ packages:
dependencies
:
dependencies
:
'
@types/chai'
:
4.3.6
'
@types/chai'
:
4.3.6
'
@types/chai-subset'
:
1.3.3
'
@types/chai-subset'
:
1.3.3
'
@types/node'
:
20.6.
1
'
@types/node'
:
20.6.
2
'
@vitest/expect'
:
0.34.2
'
@vitest/expect'
:
0.34.2
'
@vitest/runner'
:
0.34.2
'
@vitest/runner'
:
0.34.2
'
@vitest/snapshot'
:
0.34.2
'
@vitest/snapshot'
:
0.34.2
...
@@ -14941,8 +14901,8 @@ packages:
...
@@ -14941,8 +14901,8 @@ packages:
strip-literal
:
1.0.1
strip-literal
:
1.0.1
tinybench
:
2.5.0
tinybench
:
2.5.0
tinypool
:
0.7.0
tinypool
:
0.7.0
vite
:
4.4.9(@types/node@20.6.
1
)
vite
:
4.4.9(@types/node@20.6.
2
)
vite-node
:
0.34.2(@types/node@20.6.
1
)
vite-node
:
0.34.2(@types/node@20.6.
2
)
why-is-node-running
:
2.2.2
why-is-node-running
:
2.2.2
transitivePeerDependencies
:
transitivePeerDependencies
:
-
less
-
less
...
...
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