Commit f5c6160a authored by Joshua Gutow's avatar Joshua Gutow

Merge branch 'develop' into jg/l1_state_uninit_v2

parents 9eaae63d 956bc072
......@@ -2,4 +2,4 @@
'@eth-optimism/contracts-bedrock': patch
---
Removes historicalTotalBlocks from the L2OutputOracle
Add echidna test commands
---
'@eth-optimism/contracts-bedrock': minor
---
Deleted Unused Variables fundAccount , impersonatedTx
---
'@eth-optimism/indexer': patch
'@eth-optimism/contracts-bedrock': patch
'@eth-optimism/contracts-periphery': patch
---
Updated forge-std version
---
'@eth-optimism/data-transport-layer': patch
---
Updates the DTL in preparation for shutoff during the Bedrock migration. So long, DTL!
---
"@eth-optimism/l2geth-exporter": patch
---
Fix: Adding proper debug output for L1 CTC Address env var in l2geth-exporter
---
'@eth-optimism/indexer': minor
'@eth-optimism/contracts-bedrock': minor
'@eth-optimism/integration-tests-bedrock': minor
'@eth-optimism/sdk': minor
---
Adds an implementation of the Two Step Withdrawals V2 proposal
This diff is collapsed.
......@@ -114,7 +114,6 @@ pull_request_rules:
request_reviews:
users:
- roninjin10
- nickbalestra
- name: Add sdk tag and ecopod reviewers
conditions:
- 'files~=^packages/sdk/'
......@@ -125,7 +124,6 @@ pull_request_rules:
request_reviews:
users:
- roninjin10
- nickbalestra
- name: Add common-ts tag and ecopod reviewers
conditions:
- 'files~=^packages/common-ts/'
......@@ -135,5 +133,4 @@ pull_request_rules:
- common-ts
request_reviews:
users:
- imranjami
- roninjin10
......@@ -31,7 +31,6 @@ jobs:
l2geth-exporter: ${{ steps.packages.outputs.l2geth-exporter }}
batch-submitter-service: ${{ steps.packages.outputs.batch-submitter-service }}
indexer: ${{ steps.packages.outputs.indexer }}
teleportr: ${{ steps.packages.outputs.teleportr }}
endpoint-monitor: ${{ steps.packages.outputs.l2geth-exporter }}
steps:
......@@ -568,43 +567,6 @@ jobs:
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
teleportr:
name: Publish Teleportr Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish
if: needs.canary-publish.outputs.teleportr != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set build args
id: build_args
run: |
echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)"
echo ::set-output name=GITVERSION::$(jq -r .version ./teleportr/package.json)
echo ::set-output name=GITCOMMIT::"$GITHUB_SHA"
- name: Build and push
uses: docker/build-push-action@v2
with:
context: .
file: ./teleportr/Dockerfile
push: true
tags: ethereumoptimism/teleportr:${{ needs.canary-publish.outputs.teleportr }}
build-args: |
GITDATE=${{ steps.build_args.outputs.GITDATE }}
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
endpoint-monitor:
name: Publish endpoint-monitor Version ${{ needs.canary-publish.outputs.canary-docker-tag }}
needs: canary-publish
......
......@@ -26,7 +26,6 @@ jobs:
l2geth-exporter: ${{ steps.packages.outputs.l2geth-exporter }}
batch-submitter-service: ${{ steps.packages.outputs.batch-submitter-service }}
indexer: ${{ steps.packages.outputs.indexer }}
teleportr: ${{ steps.packages.outputs.teleportr }}
ci-builder: ${{ steps.packages.outputs.ci-builder }}
foundry: ${{ steps.packages.outputs.foundry }}
endpoint-monitor: ${{ steps.packages.outputs.endpoint-monitor }}
......@@ -600,43 +599,6 @@ jobs:
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
teleportr:
name: Publish Teleportr Version ${{ needs.release.outputs.teleportr }}
needs: release
if: needs.release.outputs.teleportr != ''
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Login to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_USERNAME }}
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN_SECRET }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Set build args
id: build_args
run: |
echo ::set-output name=GITDATE::"$(date +%d-%m-%Y)"
echo ::set-output name=GITVERSION::$(jq -r .version ./teleportr/package.json)
echo ::set-output name=GITCOMMIT::"$GITHUB_SHA"
- name: Publish Teleportr
uses: docker/build-push-action@v2
with:
context: .
file: ./teleportr/Dockerfile
push: true
tags: ethereumoptimism/teleportr:${{ needs.release.outputs.teleportr }},ethereumoptimism/teleportr:latest
build-args: |
GITDATE=${{ steps.build_args.outputs.GITDATE }}
GITCOMMIT=${{ steps.build_args.outputs.GITCOMMIT }}
GITVERSION=${{ steps.build_args.outputs.GITVERSION }}
endpoint-monitor:
name: Publish endpoint-monitor Version ${{ needs.release.outputs.endpoint-monitor}}
needs: release
......
......@@ -6,7 +6,7 @@ There are plenty of ways to contribute, in particular we appreciate support in t
- Reporting issues. For security issues see [Security policy](https://github.com/ethereum-optimism/.github/blob/master/SECURITY.md).
- Fixing and responding to existing issues. You can start off with those tagged ["good first issue"](https://github.com/ethereum-optimism/optimism/contribute) which are meant as introductory issues for external contributors.
- Improving the [community site](https://community.optimism.io/)[documentation](https://github.com/ethereum-optimism/community-hub) and [tutorials](https://github.com/ethereum-optimism/optimism-tutorial).
- Improving the [community site](https://community.optimism.io/), [documentation](https://github.com/ethereum-optimism/community-hub) and [tutorials](https://github.com/ethereum-optimism/optimism-tutorial).
- Become an "Optimizer" and answer questions in the [Optimism Discord](https://discord.optimism.io).
- Get involved in the protocol design process by proposing changes or new features or write parts of the spec yourself in the [optimistic-specs repo](https://github.com/ethereum-optimism/optimistic-specs).
......
(The MIT License)
Copyright 2020-2021 Optimism
Copyright 2020-2022 Optimism
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
......
......@@ -73,7 +73,6 @@ Refer to the Directory Structure section below to understand which packages are
├── <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="./technical-documents">technical-documents</a>: audits and post-mortem documents
├── <a href="./teleportr">teleportr</a>: Bridge for teleporting ETH between L1 and L2 at low cost
~~ BEDROCK upgrade - Not production-ready yet, part of next major upgrade ~~
├── <a href="./packages">packages</a>
......
......@@ -61,7 +61,7 @@ def main():
addresses = read_json(addresses_json_path)
else:
log.info('Deploying contracts.')
run_command(['yarn', 'hardhat', '--network', 'devnetL1', 'deploy', '--tags', 'fresh'], env={
run_command(['yarn', 'hardhat', '--network', 'devnetL1', 'deploy'], env={
'CHAIN_ID': '900',
'L1_RPC': 'http://localhost:8545',
'PRIVATE_KEY_DEPLOYER': 'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
......@@ -80,8 +80,8 @@ def main():
'CanonicalTransactionChain': '0x0000000000000000000000000000000000000000',
'BondManager': '0x0000000000000000000000000000000000000000',
})
sdk_addresses['L1CrossDomainMessenger'] = addresses['L1CrossDomainMessengerProxy']
sdk_addresses['L1StandardBridge'] = addresses['L1StandardBridgeProxy']
sdk_addresses['L1CrossDomainMessenger'] = addresses['Proxy__OVM_L1CrossDomainMessenger']
sdk_addresses['L1StandardBridge'] = addresses['Proxy__OVM_L1StandardBridge']
sdk_addresses['OptimismPortal'] = addresses['OptimismPortalProxy']
sdk_addresses['L2OutputOracle'] = addresses['L2OutputOracleProxy']
write_json(addresses_json_path, addresses)
......
......@@ -17,7 +17,6 @@ use (
./op-proposer
./op-service
./proxyd
./teleportr
)
replace github.com/ethereum/go-ethereum v1.10.26 => github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be
......
......@@ -86,6 +86,7 @@ github.com/btcsuite/snappy-go v1.0.0 h1:ZxaA6lo2EpxGddsA8JwWOcxlzRybb444sgmeJQMJ
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23 h1:D21IyuvjDCshj1/qq+pCNd3VZOAEI9jy6Bi131YlXgI=
github.com/c-bata/go-prompt v0.2.2 h1:uyKRz6Z6DUyj49QVijyM339UJV9yhbr70gESwbNU3e0=
github.com/casbin/casbin/v2 v2.1.2 h1:bTwon/ECRx9dwBy2ewRVr5OiqjeXSGiTUY74sDPQi/g=
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
......@@ -424,8 +425,6 @@ github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82 h1:LneqU9PHDsg/
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537 h1:YGaxtkYjb8mnTvtufv2LKLwCQu2/C7qFB7UtrOlTWOY=
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133 h1:JtcyT0rk/9PKOdnKQzuDR+FSjh7SGtJwpgVpfZBRKlQ=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns=
......@@ -606,6 +605,7 @@ google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
......
# @eth-optimism/indexer
## 0.4.0
### Minor Changes
- 1bfe79f20: Adds an implementation of the Two Step Withdrawals V2 proposal
### Patch Changes
- f49b71d50: Updated forge-std version
## 0.3.3
### Patch Changes
......
{
"name": "@eth-optimism/indexer",
"version": "0.3.3",
"version": "0.4.0",
"private": true,
"license": "MIT"
}
......@@ -30,9 +30,9 @@
"devDependencies": {
"@babel/eslint-parser": "^7.5.4",
"@eth-optimism/contracts": "^0.5.38",
"@eth-optimism/contracts-periphery": "^1.0.2",
"@eth-optimism/contracts-periphery": "^1.0.3",
"@eth-optimism/core-utils": "0.11.0",
"@eth-optimism/sdk": "1.6.11",
"@eth-optimism/sdk": "1.7.0",
"@ethersproject/abstract-provider": "^5.7.0",
"@ethersproject/providers": "^5.7.0",
"@ethersproject/transactions": "^5.7.0",
......
# @eth-optimism/l2geth-exporter
## 0.0.7
### Patch Changes
- 896e23387: Fix: Adding proper debug output for L1 CTC Address env var in l2geth-exporter
## 0.0.6
### Patch Changes
......
{
"name": "@eth-optimism/l2geth-exporter",
"version": "0.0.6",
"version": "0.0.7",
"private": true,
"devDependencies": {}
}
......@@ -147,7 +147,7 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
return &BatchSubmitter{
cfg: batcherCfg,
addr: addr,
txMgr: NewTransactionManger(l, txManagerConfig, batchInboxAddress, chainID, sequencerPrivKey, l1Client),
txMgr: NewTransactionManager(l, txManagerConfig, batchInboxAddress, chainID, sequencerPrivKey, l1Client),
done: make(chan struct{}),
log: l,
state: NewChannelManager(l, cfg.ChannelTimeout),
......
......@@ -4,9 +4,9 @@ go 1.18
require (
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/optimism/op-node v0.10.0
github.com/ethereum-optimism/optimism/op-proposer v0.10.0
github.com/ethereum-optimism/optimism/op-service v0.10.0
github.com/ethereum-optimism/optimism/op-node v0.10.1
github.com/ethereum-optimism/optimism/op-proposer v0.10.1
github.com/ethereum-optimism/optimism/op-service v0.10.1
github.com/ethereum/go-ethereum v1.10.26
github.com/urfave/cli v1.22.9
)
......@@ -23,7 +23,7 @@ require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/deckarep/golang-set v1.8.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
github.com/ethereum-optimism/optimism/op-bindings v0.10.0 // indirect
github.com/ethereum-optimism/optimism/op-bindings v0.10.1 // indirect
github.com/fjl/memsize v0.0.1 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-stack/stack v1.8.1 // indirect
......
......@@ -106,14 +106,14 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be h1:8TdM3M7FjZkrYeGGX9nEVtDDlZ5RiuHtc0mbi5bGKyY=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be/go.mod h1:1g9UmZgEINqvYfXmWOUCRJX9fxegeOHudVkLCRAXO5Y=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0 h1:M2nwcOXH9YiRDH6UXnzHI+/eAM5UoFWp7HTlAWrZ4Os=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-node v0.10.0 h1:I6lzMP596P8PfNdPd/z5aO6uWJJABkPKC8jMV3qg9Pc=
github.com/ethereum-optimism/optimism/op-node v0.10.0/go.mod h1:ihuS69UXdeteQENbAZpmEfw4AiVbNrf2ylWRgu1CpEk=
github.com/ethereum-optimism/optimism/op-proposer v0.10.0 h1:G6UpTX20XWGGmPbcMrdjTQqZ6mKj/r3K0u3BaB1jjJU=
github.com/ethereum-optimism/optimism/op-proposer v0.10.0/go.mod h1:6dgDo0DrJnqdMpvi2YFniCCaOa6AzZ1cJfG5jHmYyWQ=
github.com/ethereum-optimism/optimism/op-service v0.10.0 h1:hkWVsVVFf0ybLWwpSqnPasndiFJLk+u++YStaQRRMFY=
github.com/ethereum-optimism/optimism/op-service v0.10.0/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1 h1:OxzYjPmjl5DblgvS0z27M8lZInjdm9Wt6ajozXuMhmw=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-node v0.10.1 h1:kVBaOEOYLV22XEHRhB7dfdmoXepO0kx/RsZQK+Bpk1Y=
github.com/ethereum-optimism/optimism/op-node v0.10.1/go.mod h1:pup7wiiUs9g8cZKwXeB5tEGCqwUUwFVmej9MmSIm6S8=
github.com/ethereum-optimism/optimism/op-proposer v0.10.1 h1:2akYgVF+a7aGRRwXx9x+rdeq1MjRc0+BgZTgS9kGmsE=
github.com/ethereum-optimism/optimism/op-proposer v0.10.1/go.mod h1:dQr8k0SMo48u79Eyt2vn3AuPVtWEgGdz24MavQiz2Cg=
github.com/ethereum-optimism/optimism/op-service v0.10.1 h1:s8CisVat3ia04Z0mW3IiwZ7V1EInyVe3ODq6UXSyJG4=
github.com/ethereum-optimism/optimism/op-service v0.10.1/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
......
......@@ -31,7 +31,7 @@ type TransactionManager struct {
log log.Logger
}
func NewTransactionManger(log log.Logger, txMgrConfg txmgr.Config, batchInboxAddress common.Address, chainID *big.Int, privKey *ecdsa.PrivateKey, l1Client *ethclient.Client) *TransactionManager {
func NewTransactionManager(log log.Logger, txMgrConfg txmgr.Config, batchInboxAddress common.Address, chainID *big.Int, privKey *ecdsa.PrivateKey, l1Client *ethclient.Client) *TransactionManager {
signerFn := func(rawTx types.TxData) (*types.Transaction, error) {
return types.SignNewTx(privKey, types.LatestSignerForChainID(chainID), rawTx)
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -41,7 +41,6 @@ type DeployConfig struct {
L2OutputOracleStartingTimestamp int `json:"l2OutputOracleStartingTimestamp"`
L2OutputOracleProposer common.Address `json:"l2OutputOracleProposer"`
L2OutputOracleOwner common.Address `json:"l2OutputOracleOwner"`
L2OutputOracleGenesisL2Output common.Hash `json:"l2OutputOracleGenesisL2Output"`
SystemConfigOwner common.Address `json:"systemConfigOwner"`
......@@ -145,9 +144,6 @@ func (d *DeployConfig) Check() error {
if d.L2OutputOracleOwner == (common.Address{}) {
return fmt.Errorf("%w: L2OutputOracleOwner cannot be address(0)", ErrInvalidDeployConfig)
}
if d.L2OutputOracleGenesisL2Output == (common.Hash{}) {
log.Warn("L2OutputOracleGenesisL2Output is bytes32(0)")
}
if d.SystemConfigOwner == (common.Address{}) {
return fmt.Errorf("%w: SystemConfigOwner cannot be address(0)", ErrInvalidDeployConfig)
}
......
......@@ -102,7 +102,8 @@ func BuildL1DeveloperGenesis(config *DeployConfig) (*core.Genesis, error) {
}
data, err = l2ooABI.Pack(
"initialize",
config.L2OutputOracleGenesisL2Output,
big.NewInt(0),
uint642Big(uint64(config.L1GenesisBlockTimestamp)),
config.L2OutputOracleProposer,
config.L2OutputOracleOwner,
)
......@@ -275,10 +276,9 @@ func deployL1Contracts(config *DeployConfig, backend *backends.SimulatedBackend)
Name: "L2OutputOracle",
Args: []interface{}{
uint642Big(config.L2OutputOracleSubmissionInterval),
[32]byte(config.L2OutputOracleGenesisL2Output),
uint642Big(config.L2BlockTime),
big.NewInt(0),
uint642Big(uint64(config.L1GenesisBlockTimestamp)),
uint642Big(config.L2BlockTime),
config.L2OutputOracleProposer,
config.L2OutputOracleOwner,
},
......@@ -337,12 +337,11 @@ func l1Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
opts,
backend,
deployment.Args[0].(*big.Int),
deployment.Args[1].([32]byte),
deployment.Args[1].(*big.Int),
deployment.Args[2].(*big.Int),
deployment.Args[3].(*big.Int),
deployment.Args[4].(*big.Int),
deployment.Args[4].(common.Address),
deployment.Args[5].(common.Address),
deployment.Args[6].(common.Address),
)
case "OptimismPortal":
_, tx, _, err = bindings.DeployOptimismPortal(
......
......@@ -55,7 +55,7 @@ func TestBuildL1DeveloperGenesis(t *testing.T) {
require.NoError(t, err)
require.EqualValues(t, config.L2OutputOracleSubmissionInterval, interval.Uint64())
startBlock, err := oracle.STARTINGBLOCKNUMBER(callOpts)
startBlock, err := oracle.StartingBlockNumber(callOpts)
require.NoError(t, err)
require.EqualValues(t, 0, startBlock.Uint64())
......
......@@ -33,7 +33,6 @@
"l2GenesisBlockDifficulty": "0x1",
"l2GenesisBlockMixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l2GenesisBlockCoinbase": "0x42000000000000000000000000000000000000f0",
"l2OutputOracleGenesisL2Output": "0x0000000000000000000000000000000000000000000000000000000000000000",
"l2GenesisBlockNumber": "0x0",
"l2GenesisBlockGasUsed": "0x0",
"l2GenesisBlockParentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
......
......@@ -3,7 +3,7 @@ module github.com/ethereum-optimism/optimism/op-chain-ops
go 1.18
require (
github.com/ethereum-optimism/optimism/op-bindings v0.10.0
github.com/ethereum-optimism/optimism/op-bindings v0.10.1
github.com/ethereum/go-ethereum v1.10.26
github.com/holiman/uint256 v1.2.0
github.com/mattn/go-isatty v0.0.14
......
......@@ -76,8 +76,8 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be h1:8TdM3M7FjZkrYeGGX9nEVtDDlZ5RiuHtc0mbi5bGKyY=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be/go.mod h1:1g9UmZgEINqvYfXmWOUCRJX9fxegeOHudVkLCRAXO5Y=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0 h1:M2nwcOXH9YiRDH6UXnzHI+/eAM5UoFWp7HTlAWrZ4Os=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1 h1:OxzYjPmjl5DblgvS0z27M8lZInjdm9Wt6ajozXuMhmw=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
......
......@@ -8,12 +8,12 @@ require (
github.com/docker/docker v20.10.21+incompatible
github.com/docker/go-connections v0.4.0
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/optimism/op-batcher v0.10.0
github.com/ethereum-optimism/optimism/op-bindings v0.10.0
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.0
github.com/ethereum-optimism/optimism/op-node v0.10.0
github.com/ethereum-optimism/optimism/op-proposer v0.10.0
github.com/ethereum-optimism/optimism/op-service v0.10.0
github.com/ethereum-optimism/optimism/op-batcher v0.10.1
github.com/ethereum-optimism/optimism/op-bindings v0.10.1
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.1
github.com/ethereum-optimism/optimism/op-node v0.10.1
github.com/ethereum-optimism/optimism/op-proposer v0.10.1
github.com/ethereum-optimism/optimism/op-service v0.10.1
github.com/ethereum/go-ethereum v1.10.26
github.com/libp2p/go-libp2p v0.23.3
github.com/stretchr/testify v1.8.0
......
......@@ -159,16 +159,18 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be h1:8TdM3M7FjZkrYeGGX9nEVtDDlZ5RiuHtc0mbi5bGKyY=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be/go.mod h1:1g9UmZgEINqvYfXmWOUCRJX9fxegeOHudVkLCRAXO5Y=
github.com/ethereum-optimism/optimism/op-batcher v0.10.0 h1:mI3udjjhK7FRoYnr7PNRSRPNldm7Vn1X1Kpl2Mixpkg=
github.com/ethereum-optimism/optimism/op-batcher v0.10.0/go.mod h1:u14Dchn2F0sdWxH/V6wtNVFCQJAfrURb/mwvYP/RiMk=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0 h1:M2nwcOXH9YiRDH6UXnzHI+/eAM5UoFWp7HTlAWrZ4Os=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-node v0.10.0 h1:I6lzMP596P8PfNdPd/z5aO6uWJJABkPKC8jMV3qg9Pc=
github.com/ethereum-optimism/optimism/op-node v0.10.0/go.mod h1:ihuS69UXdeteQENbAZpmEfw4AiVbNrf2ylWRgu1CpEk=
github.com/ethereum-optimism/optimism/op-proposer v0.10.0 h1:G6UpTX20XWGGmPbcMrdjTQqZ6mKj/r3K0u3BaB1jjJU=
github.com/ethereum-optimism/optimism/op-proposer v0.10.0/go.mod h1:6dgDo0DrJnqdMpvi2YFniCCaOa6AzZ1cJfG5jHmYyWQ=
github.com/ethereum-optimism/optimism/op-service v0.10.0 h1:hkWVsVVFf0ybLWwpSqnPasndiFJLk+u++YStaQRRMFY=
github.com/ethereum-optimism/optimism/op-service v0.10.0/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/ethereum-optimism/optimism/op-batcher v0.10.1 h1:y/PlBJfmJ74UzbPPLntIfCO/l4yAOeCPPyUsiZd7C9Q=
github.com/ethereum-optimism/optimism/op-batcher v0.10.1/go.mod h1:GUWRM7Bhc05H4gUj8ggTZnegVS4bfltZq0gqXh18Fvk=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1 h1:OxzYjPmjl5DblgvS0z27M8lZInjdm9Wt6ajozXuMhmw=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.1 h1:SJls5Zs8mXooHItwCFsxCyOhssuGIJCnucjGJjo+eQ0=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.1/go.mod h1:b3nDzF9sIqDUVRM58P9d1u7+bWPOEMX3gqyCuL0CMjI=
github.com/ethereum-optimism/optimism/op-node v0.10.1 h1:kVBaOEOYLV22XEHRhB7dfdmoXepO0kx/RsZQK+Bpk1Y=
github.com/ethereum-optimism/optimism/op-node v0.10.1/go.mod h1:pup7wiiUs9g8cZKwXeB5tEGCqwUUwFVmej9MmSIm6S8=
github.com/ethereum-optimism/optimism/op-proposer v0.10.1 h1:2akYgVF+a7aGRRwXx9x+rdeq1MjRc0+BgZTgS9kGmsE=
github.com/ethereum-optimism/optimism/op-proposer v0.10.1/go.mod h1:dQr8k0SMo48u79Eyt2vn3AuPVtWEgGdz24MavQiz2Cg=
github.com/ethereum-optimism/optimism/op-service v0.10.1 h1:s8CisVat3ia04Z0mW3IiwZ7V1EInyVe3ODq6UXSyJG4=
github.com/ethereum-optimism/optimism/op-service v0.10.1/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
......
......@@ -29,6 +29,13 @@ fuzz:
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzUnmarshallLogEvent ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzParseFrames ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzFrameUnmarshalBinary ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzBatchRoundTrip ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDeriveDepositsRoundTrip ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDeriveDepositsBadVersion ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzParseL1InfoDepositTxDataValid ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzParseL1InfoDepositTxDataBadLength ./rollup/derive
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzRejectCreateBlockBadTimestamp ./rollup/driver
go test -run NOTAREALTEST -v -fuzztime 10s -fuzz FuzzDecodeDepositTxDataToL1Info ./rollup/driver
.PHONY: \
......
......@@ -6,12 +6,13 @@ require (
github.com/btcsuite/btcd v0.23.3
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0
github.com/ethereum-optimism/optimism/op-bindings v0.10.0
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.0
github.com/ethereum-optimism/optimism/op-service v0.10.0
github.com/ethereum-optimism/optimism/op-bindings v0.10.1
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.1
github.com/ethereum-optimism/optimism/op-service v0.10.1
github.com/ethereum/go-ethereum v1.10.26
github.com/golang/snappy v0.0.4
github.com/google/go-cmp v0.5.8
github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/holiman/uint256 v1.2.0
......
......@@ -145,12 +145,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be h1:8TdM3M7FjZkrYeGGX9nEVtDDlZ5RiuHtc0mbi5bGKyY=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be/go.mod h1:1g9UmZgEINqvYfXmWOUCRJX9fxegeOHudVkLCRAXO5Y=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0 h1:M2nwcOXH9YiRDH6UXnzHI+/eAM5UoFWp7HTlAWrZ4Os=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.0 h1:WwxEw+w7FF3aqqnZoN4ipFK+O1bVrf3/qN4jcm15ek0=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.0/go.mod h1:TYuGpQKaWofyb3ZotSJjmluGgH0c3gNO40de3C9ueks=
github.com/ethereum-optimism/optimism/op-service v0.10.0 h1:hkWVsVVFf0ybLWwpSqnPasndiFJLk+u++YStaQRRMFY=
github.com/ethereum-optimism/optimism/op-service v0.10.0/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1 h1:OxzYjPmjl5DblgvS0z27M8lZInjdm9Wt6ajozXuMhmw=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.1 h1:SJls5Zs8mXooHItwCFsxCyOhssuGIJCnucjGJjo+eQ0=
github.com/ethereum-optimism/optimism/op-chain-ops v0.10.1/go.mod h1:b3nDzF9sIqDUVRM58P9d1u7+bWPOEMX3gqyCuL0CMjI=
github.com/ethereum-optimism/optimism/op-service v0.10.1 h1:s8CisVat3ia04Z0mW3IiwZ7V1EInyVe3ODq6UXSyJG4=
github.com/ethereum-optimism/optimism/op-service v0.10.1/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
......@@ -250,6 +250,8 @@ github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8 h1:Ep/joEub9YwcjRY6ND3+Y/w0ncE540RtGatVhtZL0/Q=
github.com/google/gofuzz v1.2.1-0.20220503160820-4a35382e8fc8/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
......
package derive
import (
"testing"
"github.com/ethereum-optimism/optimism/op-node/testutils/fuzzerutils"
fuzz "github.com/google/gofuzz"
"github.com/stretchr/testify/require"
)
// FuzzBatchRoundTrip executes a fuzz test similar to TestBatchRoundTrip, which tests that arbitrary BatchData will be
// encoded and decoded without loss of its original values.
func FuzzBatchRoundTrip(f *testing.F) {
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
// Create our fuzzer wrapper to generate complex values
typeProvider := fuzz.NewFromGoFuzz(fuzzedData).NilChance(0).MaxDepth(10000).NumElements(0, 0x100).AllowUnexportedFields(true)
fuzzerutils.AddFuzzerFunctions(typeProvider)
// Create our batch data from fuzzed data
var batchData BatchData
typeProvider.Fuzz(&batchData)
// Encode our batch data
enc, err := batchData.MarshalBinary()
require.NoError(t, err)
// Decode our encoded batch data
var dec BatchData
err = dec.UnmarshalBinary(enc)
require.NoError(t, err)
// Ensure the round trip encoding of batch data did not result in data loss
require.Equal(t, &batchData, &dec, "round trip batch encoding/decoding did not match original values")
})
}
package derive
import (
"math/big"
"testing"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-node/testutils/fuzzerutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
fuzz "github.com/google/gofuzz"
"github.com/stretchr/testify/require"
)
// fuzzReceipts is similar to makeReceipts except it uses the fuzzer to populate DepositTx fields.
func fuzzReceipts(typeProvider *fuzz.Fuzzer, blockHash common.Hash, depositContractAddr common.Address) (receipts []*types.Receipt, expectedDeposits []*types.DepositTx) {
// Determine how many receipts to generate (capped)
var receiptCount uint64
typeProvider.Fuzz(&receiptCount)
// Cap our receipt count otherwise we might generate for too long and our fuzzer will assume we hung
if receiptCount > 0x10 {
receiptCount = 0x10
}
// Create every receipt we intend to
logIndex := uint(0)
for i := uint64(0); i < receiptCount; i++ {
// Obtain our fuzz parameters for generating this receipt
var txReceiptValues struct {
GoodReceipt bool
DepositLogs []bool
}
typeProvider.Fuzz(&txReceiptValues)
// Generate a list of transaction receipts
var logs []*types.Log
status := types.ReceiptStatusSuccessful
if txReceiptValues.GoodReceipt {
status = types.ReceiptStatusFailed
}
// Determine if this log will be a deposit log or not and generate it accordingly
for _, isDeposit := range txReceiptValues.DepositLogs {
var ev *types.Log
var err error
if isDeposit {
// Generate a user deposit source
source := UserDepositSource{L1BlockHash: blockHash, LogIndex: uint64(logIndex)}
// Fuzz parameters to construct our deposit log
var fuzzedDepositInfo struct {
FromAddr *common.Address
ToAddr *common.Address
Value *big.Int
Gas uint64
Data []byte
Mint *big.Int
}
typeProvider.Fuzz(&fuzzedDepositInfo)
// Create our deposit transaction
dep := &types.DepositTx{
SourceHash: source.SourceHash(),
From: *fuzzedDepositInfo.FromAddr,
To: fuzzedDepositInfo.ToAddr,
Value: fuzzedDepositInfo.Value,
Gas: fuzzedDepositInfo.Gas,
Data: fuzzedDepositInfo.Data,
Mint: fuzzedDepositInfo.Mint,
IsSystemTransaction: false,
}
// Marshal our actual log event
ev, err = MarshalDepositLogEvent(depositContractAddr, dep)
if err != nil {
panic(err)
}
// If we have a good version and our tx succeeded, we add this to our list of expected deposits to
// return.
if status == types.ReceiptStatusSuccessful {
expectedDeposits = append(expectedDeposits, dep)
}
} else {
// If we're generated an unrelated log event (not deposit), fuzz some random parameters to use.
var randomUnrelatedLogInfo struct {
Addr *common.Address
Topics []common.Hash
Data []byte
}
typeProvider.Fuzz(&randomUnrelatedLogInfo)
// Generate the random log
ev = testutils.GenerateLog(*randomUnrelatedLogInfo.Addr, randomUnrelatedLogInfo.Topics, randomUnrelatedLogInfo.Data)
}
ev.TxIndex = uint(i)
ev.Index = logIndex
ev.BlockHash = blockHash
logs = append(logs, ev)
logIndex++
}
// Add our receipt to our list
receipts = append(receipts, &types.Receipt{
Type: types.DynamicFeeTxType,
Status: status,
Logs: logs,
BlockHash: blockHash,
TransactionIndex: uint(i),
})
}
return
}
// FuzzDeriveDepositsRoundTrip tests the derivation of deposits from transaction receipt event logs. It mixes
// valid and invalid deposit transactions and ensures all valid deposits are derived as expected.
// This is a fuzz test corresponding to TestDeriveUserDeposits.
func FuzzDeriveDepositsRoundTrip(f *testing.F) {
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
// Create our fuzzer wrapper to generate complex values
typeProvider := fuzz.NewFromGoFuzz(fuzzedData).NilChance(0).MaxDepth(10000).NumElements(0, 0x100).Funcs(
func(e *big.Int, c fuzz.Continue) {
var temp [32]byte
c.Fuzz(&temp)
e.SetBytes(temp[:])
},
func(e *common.Hash, c fuzz.Continue) {
var temp [32]byte
c.Fuzz(&temp)
e.SetBytes(temp[:])
},
func(e *common.Address, c fuzz.Continue) {
var temp [20]byte
c.Fuzz(&temp)
e.SetBytes(temp[:])
})
// Create a dummy block hash for this block
var blockHash common.Hash
typeProvider.Fuzz(&blockHash)
// Fuzz to generate some random deposit events
receipts, expectedDeposits := fuzzReceipts(typeProvider, blockHash, MockDepositContractAddr)
// Derive our user deposits from the transaction receipts
derivedDeposits, err := UserDeposits(receipts, MockDepositContractAddr)
require.NoError(t, err)
// Ensure all deposits we derived matched what we expected to receive.
require.Equal(t, len(derivedDeposits), len(expectedDeposits))
for i, derivedDeposit := range derivedDeposits {
expectedDeposit := expectedDeposits[i]
require.Equal(t, expectedDeposit, derivedDeposit)
}
})
}
// FuzzDeriveDepositsBadVersion ensures that if a deposit transaction receipt event log specifies an invalid deposit
// version, no deposits should be derived.
func FuzzDeriveDepositsBadVersion(f *testing.F) {
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
// Create our fuzzer wrapper to generate complex values
typeProvider := fuzz.NewFromGoFuzz(fuzzedData).NilChance(0).MaxDepth(10000).NumElements(0, 0x100)
fuzzerutils.AddFuzzerFunctions(typeProvider)
// Create a dummy block hash for this block
var blockHash common.Hash
typeProvider.Fuzz(&blockHash)
// Fuzz to generate some random deposit events
receipts, _ := fuzzReceipts(typeProvider, blockHash, MockDepositContractAddr)
// Loop through all receipt logs and let the fuzzer determine which (if any) to patch.
hasBadDepositVersion := false
for _, receipt := range receipts {
// TODO: Using a hardcoded index (Topics[3]) here is not ideal. The MarshalDepositLogEvent method should
// be spliced apart to be more configurable for these tests.
// Loop for each log in this receipt and check if it has a deposit event from our contract
for _, log := range receipt.Logs {
if log.Address == MockDepositContractAddr && len(log.Topics) >= 4 && log.Topics[0] == DepositEventABIHash {
// Determine if we should set a bad deposit version for this log
var patchBadDeposit bool
typeProvider.Fuzz(&patchBadDeposit)
if patchBadDeposit {
// Generate any topic but the deposit event versions we support.
// TODO: As opposed to keeping this hardcoded, a method such as IsValidVersion(v) should be
// used here.
badTopic := DepositEventVersion0
for badTopic == DepositEventVersion0 {
typeProvider.Fuzz(&badTopic)
}
// Set our bad topic and update our state
log.Topics[3] = badTopic
hasBadDepositVersion = true
}
}
}
}
// Derive our user deposits from the transaction receipts
_, err := UserDeposits(receipts, MockDepositContractAddr)
// If we patched a bad deposit version this iteration, we should expect an error and not be able to proceed
// further
if hasBadDepositVersion {
require.Errorf(t, err, "")
return
}
require.NoError(t, err, "")
})
}
package derive
import (
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum-optimism/optimism/op-node/testutils/fuzzerutils"
fuzz "github.com/google/gofuzz"
"github.com/stretchr/testify/require"
)
// FuzzParseL1InfoDepositTxDataValid is a fuzz test built from TestParseL1InfoDepositTxData, which constructs random
// L1 deposit tx info and derives a tx from it, then derives the info back from the tx, to ensure round-trip
// derivation is upheld. This generates "valid" data and ensures it is always derived back to original values.
func FuzzParseL1InfoDepositTxDataValid(f *testing.F) {
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
// Create our fuzzer wrapper to generate complex values
typeProvider := fuzz.NewFromGoFuzz(fuzzedData).NilChance(0).MaxDepth(10000).NumElements(0, 0x100)
fuzzerutils.AddFuzzerFunctions(typeProvider)
var l1Info testutils.MockBlockInfo
typeProvider.Fuzz(&l1Info)
var seqNr uint64
typeProvider.Fuzz(&seqNr)
var sysCfg eth.SystemConfig
typeProvider.Fuzz(&sysCfg)
// Create our deposit tx from our info
depTx, err := L1InfoDeposit(seqNr, &l1Info, sysCfg)
require.NoError(t, err, "error creating deposit tx from L1 info")
// Get our info from out deposit tx
res, err := L1InfoDepositTxData(depTx.Data)
require.NoError(t, err, "expected valid deposit info")
// Verify all parameters match in our round trip deriving operations
require.Equal(t, res.Number, l1Info.NumberU64())
require.Equal(t, res.Time, l1Info.Time())
require.True(t, res.BaseFee.Sign() >= 0)
require.Equal(t, res.BaseFee.Bytes(), l1Info.BaseFee().Bytes())
require.Equal(t, res.BlockHash, l1Info.Hash())
require.Equal(t, res.SequenceNumber, seqNr)
require.Equal(t, res.BatcherAddr, sysCfg.BatcherAddr)
require.Equal(t, res.L1FeeOverhead, sysCfg.Overhead)
require.Equal(t, res.L1FeeScalar, sysCfg.Scalar)
})
}
// Reverse of the above test. Accepts a random byte string and attempts to extract L1Info from it,
// then attempts to convert that info back into the tx data and compare it with the original input.
func FuzzDecodeDepositTxDataToL1Info(f *testing.F) {
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
// Get our info from out deposit tx
res, err := L1InfoDepositTxData(fuzzedData)
if err != nil {
return
}
l1Info := testutils.MockBlockInfo{
InfoHash: res.BlockHash,
InfoNum: res.Number,
InfoTime: res.Time,
InfoBaseFee: res.BaseFee,
}
sysCfg := eth.SystemConfig{
BatcherAddr: res.BatcherAddr,
Overhead: res.L1FeeOverhead,
Scalar: res.L1FeeScalar,
GasLimit: uint64(0),
}
depTx, err := L1InfoDeposit(res.SequenceNumber, &l1Info, sysCfg)
require.NoError(t, err, "error creating deposit tx from L1 info")
require.Equal(t, depTx.Data, fuzzedData)
})
}
// FuzzParseL1InfoDepositTxDataBadLength is a fuzz test built from TestParseL1InfoDepositTxData, which constructs
// random L1 deposit tx info and derives a tx from it, then derives the info back from the tx, to ensure round-trip
// derivation is upheld. This generates "invalid" data and ensures it always throws an error where expected.
func FuzzParseL1InfoDepositTxDataBadLength(f *testing.F) {
const expectedDepositTxDataLength = 4 + 32 + 32 + 32 + 32 + 32
f.Fuzz(func(t *testing.T, fuzzedData []byte) {
// Derive a transaction from random fuzzed data
_, err := L1InfoDepositTxData(fuzzedData)
// If the data is null, or too short or too long, we expect an error
if fuzzedData == nil || len(fuzzedData) != expectedDepositTxDataLength {
require.Error(t, err)
}
})
}
// On develop
package driver
import (
"context"
"errors"
"math/rand"
"testing"
"github.com/ethereum-optimism/optimism/op-node/eth"
"github.com/ethereum-optimism/optimism/op-node/metrics"
"github.com/ethereum-optimism/optimism/op-node/rollup"
"github.com/ethereum-optimism/optimism/op-node/testutils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log"
"github.com/prometheus/client_golang/prometheus"
"github.com/stretchr/testify/require"
)
type TestDummyOutputImpl struct {
willError bool
SequencerIface
}
func (d TestDummyOutputImpl) CreateNewBlock(ctx context.Context, l2Head eth.L2BlockRef, l2SafeHead eth.BlockID, l2Finalized eth.BlockID, l1Origin eth.L1BlockRef) (eth.L2BlockRef, *eth.ExecutionPayload, error) {
// If we're meant to error, return one
if d.willError {
return l2Head, nil, errors.New("the TestDummyOutputImpl.createNewBlock operation failed")
}
payload := eth.ExecutionPayload{
ParentHash: common.Hash{},
FeeRecipient: common.Address{},
StateRoot: eth.Bytes32{},
ReceiptsRoot: eth.Bytes32{},
LogsBloom: eth.Bytes256{},
PrevRandao: eth.Bytes32{},
BlockNumber: 0,
GasLimit: 0,
GasUsed: 0,
Timestamp: 0,
ExtraData: nil,
BaseFeePerGas: eth.Uint256Quantity{},
BlockHash: common.Hash{},
Transactions: []eth.Data{},
}
return l2Head, &payload, nil
}
type TestDummyDerivationPipeline struct {
DerivationPipeline
l2Head eth.L2BlockRef
l2SafeHead eth.L2BlockRef
l2Finalized eth.L2BlockRef
}
func (d TestDummyDerivationPipeline) Reset() {}
func (d TestDummyDerivationPipeline) Step(ctx context.Context) error { return nil }
func (d TestDummyDerivationPipeline) SetUnsafeHead(head eth.L2BlockRef) {}
func (d TestDummyDerivationPipeline) AddUnsafePayload(payload *eth.ExecutionPayload) {}
func (d TestDummyDerivationPipeline) Finalized() eth.L2BlockRef { return d.l2Head }
func (d TestDummyDerivationPipeline) SafeL2Head() eth.L2BlockRef { return d.l2SafeHead }
func (d TestDummyDerivationPipeline) UnsafeL2Head() eth.L2BlockRef { return d.l2Finalized }
type TestDummyL1OriginSelector struct {
retval eth.L1BlockRef
}
func (l TestDummyL1OriginSelector) FindL1Origin(ctx context.Context, l1Head eth.L1BlockRef, l2Head eth.L2BlockRef) (eth.L1BlockRef, error) {
return l.retval, nil
}
// TestRejectCreateBlockBadTimestamp tests that a block creation with invalid timestamps will be caught.
// This does not test:
// - The findL1Origin call (it is hardcoded to be the head)
// - The outputInterface used to create a new block from a given payload.
// - The DerivationPipeline setting unsafe head (a mock provider is used to pretend to set it)
// - Metrics (only mocked enough to let the method proceed)
// - Publishing (network is set to nil so publishing won't occur)
func TestRejectCreateBlockBadTimestamp(t *testing.T) {
// Create our random provider
rng := rand.New(rand.NewSource(rand.Int63()))
// Create our context for methods to execute under
ctx := context.Background()
// Create our fake L1/L2 heads and link them accordingly
l1HeadRef := testutils.RandomBlockRef(rng)
l2HeadRef := testutils.RandomL2BlockRef(rng)
l2l1OriginBlock := l1HeadRef
l2HeadRef.L1Origin = l2l1OriginBlock.ID()
// Create a rollup config
cfg := rollup.Config{
BlockTime: uint64(60),
Genesis: rollup.Genesis{
L1: l1HeadRef.ID(),
L2: l2HeadRef.ID(),
L2Time: 0x7000, // dummy value
},
}
// Patch our timestamp so we fail
l2HeadRef.Time = l2l1OriginBlock.Time - (cfg.BlockTime * 2)
// Create our outputter
outputProvider := TestDummyOutputImpl{willError: false}
// Create our state
s := Driver{
l1State: &L1State{
l1Head: l1HeadRef,
log: log.New(),
metrics: &metrics.Metrics{TransactionsSequencedTotal: prometheus.NewCounter(prometheus.CounterOpts{})},
},
log: log.New(),
l1OriginSelector: TestDummyL1OriginSelector{retval: l1HeadRef},
config: &cfg,
sequencer: outputProvider,
derivation: TestDummyDerivationPipeline{},
metrics: &metrics.Metrics{TransactionsSequencedTotal: prometheus.NewCounter(prometheus.CounterOpts{})},
}
// Create a new block
// - L2Head's L1Origin, its timestamp should be greater than L1 genesis.
// - L2Head timestamp + BlockTime should be greater than or equal to the L1 Time.
err := s.createNewL2Block(ctx)
// Verify the L1Origin's block number is greater than L1 genesis in our config.
if l2l1OriginBlock.Number < s.config.Genesis.L1.Number {
require.NoError(t, err, "L1Origin block number should be greater than the L1 genesis block number")
}
// Verify the new L2 block to create will have a time stamp equal or newer than our L1 origin block we derive from.
if l2HeadRef.Time+cfg.BlockTime < l2l1OriginBlock.Time {
// If not, we expect a specific error.
// TODO: This isn't the cleanest, we should construct + compare the whole error message.
require.NotNil(t, err)
require.Contains(t, err.Error(), "cannot build L2 block on top")
require.Contains(t, err.Error(), "for time")
require.Contains(t, err.Error(), "before L1 origin")
return
}
// If we expected the outputter to error, capture that here
if outputProvider.willError {
require.NotNil(t, err, "outputInterface failed to createNewBlock, so createNewL2Block should also have failed")
return
}
// Otherwise we should have no error.
require.NoError(t, err, "error raised in TestRejectCreateBlockBadTimestamp")
}
// FuzzRejectCreateBlockBadTimestamp is a property test derived from the TestRejectCreateBlockBadTimestamp unit test.
// It fuzzes timestamps and block times to find a configuration to violate error checking.
func FuzzRejectCreateBlockBadTimestamp(f *testing.F) {
f.Fuzz(func(t *testing.T, randSeed int64, l2Time uint64, blockTime uint64, forceOutputFail bool, currentL2HeadTime uint64) {
// Create our random provider
rng := rand.New(rand.NewSource(randSeed))
// Create our context for methods to execute under
ctx := context.Background()
// Create our fake L1/L2 heads and link them accordingly
l1HeadRef := testutils.RandomBlockRef(rng)
l2HeadRef := testutils.RandomL2BlockRef(rng)
l2l1OriginBlock := l1HeadRef
l2HeadRef.L1Origin = l2l1OriginBlock.ID()
// TODO: Cap our block time so it doesn't overflow
if blockTime > 0x100000 {
blockTime = 0x100000
}
// Create a rollup config
cfg := rollup.Config{
BlockTime: blockTime,
Genesis: rollup.Genesis{
L1: l1HeadRef.ID(),
L2: l2HeadRef.ID(),
L2Time: l2Time, // dummy value
},
}
// Patch our timestamp so we fail
l2HeadRef.Time = currentL2HeadTime
// Create our outputter
outputProvider := TestDummyOutputImpl{willError: forceOutputFail}
// Create our state
s := Driver{
l1State: &L1State{
l1Head: l1HeadRef,
log: log.New(),
metrics: &metrics.Metrics{TransactionsSequencedTotal: prometheus.NewCounter(prometheus.CounterOpts{})},
},
log: log.New(),
l1OriginSelector: TestDummyL1OriginSelector{retval: l1HeadRef},
config: &cfg,
sequencer: outputProvider,
derivation: TestDummyDerivationPipeline{},
metrics: &metrics.Metrics{TransactionsSequencedTotal: prometheus.NewCounter(prometheus.CounterOpts{})},
}
// Create a new block
// - L2Head's L1Origin, its timestamp should be greater than L1 genesis.
// - L2Head timestamp + BlockTime should be greater than or equal to the L1 Time.
err := s.createNewL2Block(ctx)
// Verify the L1Origin's timestamp is greater than L1 genesis in our config.
if l2l1OriginBlock.Number < s.config.Genesis.L1.Number {
require.NoError(t, err)
return
}
// Verify the new L2 block to create will have a time stamp equal or newer than our L1 origin block we derive from.
if l2HeadRef.Time+cfg.BlockTime < l2l1OriginBlock.Time {
// If not, we expect a specific error.
// TODO: This isn't the cleanest, we should construct + compare the whole error message.
require.NotNil(t, err)
require.Contains(t, err.Error(), "cannot build L2 block on top")
require.Contains(t, err.Error(), "for time")
require.Contains(t, err.Error(), "before L1 origin")
return
}
// Otherwise we should have no error.
require.Nil(t, err)
// If we expected the outputter to error, capture that here
if outputProvider.willError {
require.NotNil(t, err, "outputInterface failed to createNewBlock, so createNewL2Block should also have failed")
return
}
// Otherwise we should have no error.
require.NoError(t, err, "L1Origin block number should be greater than the L1 genesis block number")
})
}
package fuzzerutils
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
fuzz "github.com/google/gofuzz"
)
// AddFuzzerFunctions takes a fuzz.Fuzzer and adds a list of functions to handle different
// data types in a fuzzing campaign. It adds support for commonly used types throughout the
// application.
func AddFuzzerFunctions(fuzzer *fuzz.Fuzzer) {
fuzzer.Funcs(
func(e *big.Int, c fuzz.Continue) {
var temp [32]byte
c.Fuzz(&temp)
e.SetBytes(temp[:])
},
func(e *common.Hash, c fuzz.Continue) {
var temp [32]byte
c.Fuzz(&temp)
e.SetBytes(temp[:])
},
func(e *common.Address, c fuzz.Continue) {
var temp [20]byte
c.Fuzz(&temp)
e.SetBytes(temp[:])
},
)
}
......@@ -4,9 +4,9 @@ go 1.18
require (
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3
github.com/ethereum-optimism/optimism/op-bindings v0.10.0
github.com/ethereum-optimism/optimism/op-node v0.10.0
github.com/ethereum-optimism/optimism/op-service v0.10.0
github.com/ethereum-optimism/optimism/op-bindings v0.10.1
github.com/ethereum-optimism/optimism/op-node v0.10.1
github.com/ethereum-optimism/optimism/op-service v0.10.1
github.com/ethereum/go-ethereum v1.10.26
github.com/stretchr/testify v1.8.0
github.com/urfave/cli v1.22.9
......
......@@ -107,12 +107,12 @@ github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3 h1:RWHKLhCrQThMfch+QJ1Z
github.com/ethereum-optimism/go-ethereum-hdwallet v0.1.3/go.mod h1:QziizLAiF0KqyLdNJYD7O5cpDlaFMNZzlxYNcWsJUxs=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be h1:8TdM3M7FjZkrYeGGX9nEVtDDlZ5RiuHtc0mbi5bGKyY=
github.com/ethereum-optimism/op-geth v0.0.0-20221104231810-30db39cae2be/go.mod h1:1g9UmZgEINqvYfXmWOUCRJX9fxegeOHudVkLCRAXO5Y=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0 h1:M2nwcOXH9YiRDH6UXnzHI+/eAM5UoFWp7HTlAWrZ4Os=
github.com/ethereum-optimism/optimism/op-bindings v0.10.0/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-node v0.10.0 h1:I6lzMP596P8PfNdPd/z5aO6uWJJABkPKC8jMV3qg9Pc=
github.com/ethereum-optimism/optimism/op-node v0.10.0/go.mod h1:ihuS69UXdeteQENbAZpmEfw4AiVbNrf2ylWRgu1CpEk=
github.com/ethereum-optimism/optimism/op-service v0.10.0 h1:hkWVsVVFf0ybLWwpSqnPasndiFJLk+u++YStaQRRMFY=
github.com/ethereum-optimism/optimism/op-service v0.10.0/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1 h1:OxzYjPmjl5DblgvS0z27M8lZInjdm9Wt6ajozXuMhmw=
github.com/ethereum-optimism/optimism/op-bindings v0.10.1/go.mod h1:UeTZlpZyhOL3y9Sogzvbn8Z3q1tDmZEv1VmGxMiZYCg=
github.com/ethereum-optimism/optimism/op-node v0.10.1 h1:kVBaOEOYLV22XEHRhB7dfdmoXepO0kx/RsZQK+Bpk1Y=
github.com/ethereum-optimism/optimism/op-node v0.10.1/go.mod h1:pup7wiiUs9g8cZKwXeB5tEGCqwUUwFVmej9MmSIm6S8=
github.com/ethereum-optimism/optimism/op-service v0.10.1 h1:s8CisVat3ia04Z0mW3IiwZ7V1EInyVe3ODq6UXSyJG4=
github.com/ethereum-optimism/optimism/op-service v0.10.1/go.mod h1:d7IryyBivUjxhQt91nNBxUainSFmRjwf6H/nCNBowvk=
github.com/fjl/memsize v0.0.1 h1:+zhkb+dhUgx0/e+M8sF0QqiouvMQUiKR+QYvdxIOKcQ=
github.com/fjl/memsize v0.0.1/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
......
# @eth-optimism/ci-builder
## 0.3.6
### Patch Changes
- 011acf411: Add echidna to ci-builder
## 0.3.5
### Patch Changes
......
......@@ -26,6 +26,8 @@ RUN source $HOME/.profile && \
FROM ethereum/client-go:alltools-v1.10.25 as geth
FROM ghcr.io/crytic/echidna/echidna:testing-master as echidna-test
FROM python:3.8.13-slim-bullseye
ENV GOPATH=/go
......@@ -36,6 +38,7 @@ COPY --from=foundry-build /opt/foundry/target/release/forge /usr/local/bin/forge
COPY --from=foundry-build /opt/foundry/target/release/cast /usr/local/bin/cast
COPY --from=foundry-build /opt/foundry/target/release/anvil /usr/local/bin/anvil
COPY --from=geth /usr/local/bin/abigen /usr/local/bin/abigen
COPY --from=echidna-test /usr/local/bin/echidna-test /usr/local/bin/echidna-test
COPY check-changed.sh /usr/local/bin/check-changed
RUN apt-get update && \
......
{
"name": "@eth-optimism/ci-builder",
"version": "0.3.5",
"version": "0.3.6",
"scripts": {},
"license": "MIT",
"dependencies": {}
......
......@@ -20,7 +20,6 @@
"ops/docker/ci-builder",
"ops/docker/foundry",
"proxyd",
"teleportr",
"endpoint-monitor"
],
"nohoist": [
......
# @eth-optimism/actor-tests
## 0.0.14
### Patch Changes
- Updated dependencies [c025a1153]
- Updated dependencies [f8697a607]
- Updated dependencies [59adcaa09]
- Updated dependencies [c71500a7e]
- Updated dependencies [f49b71d50]
- Updated dependencies [1bfe79f20]
- Updated dependencies [ccaf5bc83]
- @eth-optimism/contracts-bedrock@0.10.0
- @eth-optimism/sdk@1.7.0
## 0.0.13
### Patch Changes
......
{
"name": "@eth-optimism/actor-tests",
"version": "0.0.13",
"version": "0.0.14",
"description": "A library and suite of tests to stress test Optimism Bedrock.",
"license": "MIT",
"author": "",
......@@ -18,9 +18,9 @@
"test:coverage": "yarn test"
},
"dependencies": {
"@eth-optimism/contracts-bedrock": "0.9.1",
"@eth-optimism/contracts-bedrock": "0.10.0",
"@eth-optimism/core-utils": "^0.11.0",
"@eth-optimism/sdk": "^1.6.11",
"@eth-optimism/sdk": "^1.7.0",
"@types/chai": "^4.2.18",
"@types/chai-as-promised": "^7.1.4",
"async-mutex": "^0.3.2",
......
......@@ -5,7 +5,7 @@ GasBenchMark_L1StandardBridge_Deposit:test_depositERC20_benchmark_1() (gas: 1122
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_0() (gas: 348176)
GasBenchMark_L1StandardBridge_Deposit:test_depositETH_benchmark_1() (gas: 112253)
GasBenchMark_L1StandardBridge_Finalize:test_finalizeETHWithdrawal_benchmark() (gas: 40502)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 68648)
GasBenchMark_L2OutputOracle:test_proposeL2Output_benchmark() (gas: 72829)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark() (gas: 74956)
GasBenchMark_OptimismPortal:test_depositTransaction_benchmark_1() (gas: 35693)
CrossDomainMessenger_Test:testFuzz_baseGas(uint32) (runs: 256, μ: 20196, ~: 20196)
......@@ -85,29 +85,30 @@ L2CrossDomainMessenger_Test:test_L2MessengerSendMessage() (gas: 122423)
L2CrossDomainMessenger_Test:test_L2MessengerTwiceSendMessage() (gas: 134632)
L2CrossDomainMessenger_Test:test_L2MessengerXDomainSenderReverts() (gas: 10568)
L2CrossDomainMessenger_Test:test_L2MessengerxDomainMessageSenderResets() (gas: 52615)
L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 26850)
L2OutputOracleTest:testCannot_constructWithBadTimestamp() (gas: 50654)
L2OutputOracleTest:testCannot_deleteL2Output_ifNotOwner() (gas: 25090)
L2OutputOracleTest:testCannot_deleteL2Output_withWrongRoot() (gas: 91399)
L2OutputOracleTest:testCannot_deleteL2Output_withWrongTime() (gas: 87382)
L2OutputOracleTest:testCannot_proposeEmptyOutput() (gas: 24126)
L2OutputOracleTest:testCannot_proposeFutureTimetamp() (gas: 26095)
L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 23563)
L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 26368)
L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 26003)
L2OutputOracleTest:test_changeProposer() (gas: 55872)
L2OutputOracleTest:test_computeL2Timestamp() (gas: 30215)
L2OutputOracleTest:test_constructor() (gas: 45612)
L2OutputOracleTest:test_deleteOutput() (gas: 77197)
L2OutputOracleTest:test_getL2Output() (gas: 88478)
L2OutputOracleTest:test_latestBlockNumber() (gas: 76240)
L2OutputOracleTest:testCannot_ProposeWithUnmatchedBlockhash() (gas: 31194)
L2OutputOracleTest:testCannot_constructWithBadTimestamp() (gas: 70886)
L2OutputOracleTest:testCannot_deleteL2Outputs_afterLatest() (gas: 199838)
L2OutputOracleTest:testCannot_deleteL2Outputs_ifNotOwner() (gas: 18871)
L2OutputOracleTest:testCannot_deleteL2Outputs_nonExistent() (gas: 91129)
L2OutputOracleTest:testCannot_proposeEmptyOutput() (gas: 28503)
L2OutputOracleTest:testCannot_proposeFutureTimetamp() (gas: 30461)
L2OutputOracleTest:testCannot_proposeL2OutputIfNotProposer() (gas: 27724)
L2OutputOracleTest:testCannot_proposeOnWrongFork() (gas: 30789)
L2OutputOracleTest:testCannot_proposeUnexpectedBlockNumber() (gas: 30164)
L2OutputOracleTest:test_changeProposer() (gas: 47223)
L2OutputOracleTest:test_computeL2Timestamp() (gas: 37163)
L2OutputOracleTest:test_constructor() (gas: 39324)
L2OutputOracleTest:test_deleteOutputs_multipleOutputs() (gas: 262835)
L2OutputOracleTest:test_deleteOutputs_singleOutput() (gas: 152682)
L2OutputOracleTest:test_getL2Output() (gas: 89261)
L2OutputOracleTest:test_latestBlockNumber() (gas: 80647)
L2OutputOracleTest:test_nextBlockNumber() (gas: 15187)
L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 75044)
L2OutputOracleTest:test_proposingAnotherOutput() (gas: 76869)
L2OutputOracleTest:test_updateOwner() (gas: 46134)
L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 17403)
L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 22398)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 36094)
L2OutputOracleTest:test_proposeWithBlockhashAndHeight() (gas: 79453)
L2OutputOracleTest:test_proposingAnotherOutput() (gas: 81255)
L2OutputOracleTest:test_updateOwner() (gas: 36063)
L2OutputOracleUpgradeable_Test:test_cannotInitImpl() (gas: 19546)
L2OutputOracleUpgradeable_Test:test_cannotInitProxy() (gas: 24523)
L2OutputOracleUpgradeable_Test:test_initValuesOnProxy() (gas: 30297)
L2OutputOracleUpgradeable_Test:test_upgrading() (gas: 180457)
L2StandardBridge_Test:test_cannotWithdrawEthWithoutSendingIt() (gas: 21749)
L2StandardBridge_Test:test_finalizeBridgeETH_incorrectValueReverts() (gas: 23733)
......@@ -149,21 +150,23 @@ OptimismPortalUpgradeable_Test:test_initialize_cannotInitImpl_reverts() (gas: 10
OptimismPortalUpgradeable_Test:test_initialize_cannotInitProxy_reverts() (gas: 15767)
OptimismPortalUpgradeable_Test:test_params_initValuesOnProxy_success() (gas: 16010)
OptimismPortalUpgradeable_Test:test_upgradeToAndCall_upgrading_success() (gas: 180435)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 192796)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 195084)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 39589)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 190538)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 192953)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 173010)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 233210)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 232682)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_success() (gas: 224676)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 327313)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 191294)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 81333)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 50776)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_oninvalidWithdrawalProof_reverts() (gas: 130105)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_success() (gas: 176847)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputRootChanges_reverts() (gas: 199367)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 201567)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 39634)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 197043)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 195266)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 175309)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 235543)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 239675)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_success() (gas: 231454)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_targetFails_fails() (gas: 334069)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_timestampLessThanL2OracleStart_reverts() (gas: 195723)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onInvalidOutputRootProof_reverts() (gas: 85495)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_onSelfCall_reverts() (gas: 50754)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_oninvalidWithdrawalProof_reverts() (gas: 138753)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProveChangedOutputRoot_success() (gas: 279048)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_replayProve_reverts() (gas: 191110)
OptimismPortal_FinalizeWithdrawal_Test:test_proveWithdrawalTransaction_validWithdrawalProof_success() (gas: 181320)
OptimismPortal_Test:test_OptimismPortalConstructor() (gas: 17298)
OptimismPortal_Test:test_OptimismPortalReceiveEth_success() (gas: 127483)
OptimismPortal_Test:test_depositTransaction_NoValueContract_success() (gas: 76706)
......@@ -175,7 +178,7 @@ OptimismPortal_Test:test_depositTransaction_withEthValueAndContractContractCreat
OptimismPortal_Test:test_depositTransaction_withEthValueAndEOAContractCreation_success() (gas: 75852)
OptimismPortal_Test:test_depositTransaction_withEthValueFromContract_success() (gas: 83370)
OptimismPortal_Test:test_depositTransaction_withEthValueFromEOA_success() (gas: 83964)
OptimismPortal_Test:test_isBlockFinalized_success() (gas: 113537)
OptimismPortal_Test:test_isBlockFinalized_success() (gas: 109644)
OptimismPortal_Test:test_simple_isBlockFinalized_success() (gas: 24142)
Proxy_Test:test_clashingFunctionSignatures() (gas: 101347)
Proxy_Test:test_implementationKey() (gas: 20887)
......
......@@ -64,25 +64,29 @@
➡ contracts/L1/L2OutputOracle.sol:L2OutputOracle
=======================
+-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------+
| Name | Type | Slot | Offset | Bytes | Contract |
+==============================================================================================================================================+
| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| _initializing | bool | 0 | 1 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| __gap | uint256[50] | 1 | 0 | 1600 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| _owner | address | 51 | 0 | 20 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| __gap | uint256[49] | 52 | 0 | 1568 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| proposer | address | 101 | 0 | 20 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| latestBlockNumber | uint256 | 102 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| l2Outputs | mapping(uint256 => struct Types.OutputProposal) | 103 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
+-------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------+
+---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------+
| Name | Type | Slot | Offset | Bytes | Contract |
+================================================================================================================================================+
| _initialized | uint8 | 0 | 0 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| _initializing | bool | 0 | 1 | 1 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| __gap | uint256[50] | 1 | 0 | 1600 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| _owner | address | 51 | 0 | 20 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| __gap | uint256[49] | 52 | 0 | 1568 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| startingBlockNumber | uint256 | 101 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| startingTimestamp | uint256 | 102 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| proposer | address | 103 | 0 | 20 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| latestBlockNumber | uint256 | 104 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
|---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------|
| l2Outputs | mapping(uint256 => struct Types.OutputProposal) | 105 | 0 | 32 | contracts/L1/L2OutputOracle.sol:L2OutputOracle |
+---------------------+-------------------------------------------------+------+--------+-------+------------------------------------------------+
=======================
➡ contracts/L1/OptimismPortal.sol:OptimismPortal
......
# @eth-optimism/contracts-bedrock
## 0.10.0
### Minor Changes
- 59adcaa09: Deleted Unused Variables fundAccount , impersonatedTx
- 1bfe79f20: Adds an implementation of the Two Step Withdrawals V2 proposal
### Patch Changes
- c025a1153: Fixes a severe vulnerability found in ToB's November 2022 audit of the Bedrock contracts
- f8697a607: Removes historicalTotalBlocks from the L2OutputOracle
- c71500a7e: Updates L2OutputOracle to easily delete multiple outputs at once
- f49b71d50: Updated forge-std version
- ccaf5bc83: Allows owner and proposer addresses to be the same in L2OutputOracle
## 0.9.1
### Patch Changes
......
......@@ -77,6 +77,17 @@ yarn build
yarn test
```
#### Running Echidna tests
You must have [Echidna](https://github.com/crytic/echidna) installed.
Contracts targetted for Echidna testing are located in `./contracts/echidna`
Each target contract is tested with a separate yarn command, for example:
```shell
yarn echidna:aliasing
```
### Deployment
#### Configuration
......
......@@ -189,8 +189,19 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// and to prevent replay attacks.
bytes32 withdrawalHash = Hashing.hashWithdrawal(_tx);
// Load the ProvenWithdrawal into memory
ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];
// Only allow re-proving a withdrawal transaction if the output root has changed.
require(
provenWithdrawal.timestamp == 0 ||
(_l2BlockNumber == provenWithdrawal.l2BlockNumber &&
outputRoot != provenWithdrawal.outputRoot),
"OptimismPortal: withdrawal hash has already been proven"
);
// Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract on
// L2. If this is true, then we know that this withdrawal was actually triggered on L2
// L2. If this is true, then we know that this withdrawal was actually triggered on L2
// and can therefore be relayed on L1.
require(
_verifyWithdrawalInclusion(
......@@ -202,9 +213,9 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
);
// Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`,
// and `l2BlockNumber` in the `provenWithdrawals` mapping. A certain withdrawal
// can be proved multiple times and thus overwrite a previously stored `ProvenWithdrawal`,
// but this is safe due to the replay check in `finalizeWithdrawalTransaction`.
// and `l2BlockNumber` in the `provenWithdrawals` mapping. A withdrawalHash can only
// be proven once to prevent a censorship attack unless it is submitted again
// with a different outputRoot.
provenWithdrawals[withdrawalHash] = ProvenWithdrawal({
outputRoot: outputRoot,
timestamp: uint128(block.timestamp),
......@@ -240,7 +251,7 @@ contract OptimismPortal is Initializable, ResourceMetering, Semver {
// Ensure that the proven withdrawal's timestamp is greater than the
// L2 Oracle's starting timestamp.
require(
provenWithdrawal.timestamp >= L2_ORACLE.STARTING_TIMESTAMP(),
provenWithdrawal.timestamp >= L2_ORACLE.startingTimestamp(),
"OptimismPortal: withdrawal timestamp less than L2 Oracle starting timestamp"
);
......
......@@ -56,14 +56,21 @@ contract BaseSystemDictator is Ownable {
}
/**
* @notice Set of implementation addresses.
* @notice Fixed L2OutputOracle config.
*/
struct L2OutputOracleConfig {
bytes32 l2OutputOracleGenesisL2Output;
address l2OutputOracleProposer;
address l2OutputOracleOwner;
}
/**
* @notice Dynamic L2OutputOracle config.
*/
struct L2OutputOracleDynamicConfig {
uint256 l2OutputOracleStartingBlockNumber;
uint256 l2OutputOracleStartingTimestamp;
}
/**
* @notice Values for the system config contract.
*/
......@@ -91,11 +98,21 @@ contract BaseSystemDictator is Ownable {
*/
DeployConfig public config;
/**
* @notice Dynamic configuration for the L2OutputOracle.
*/
L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;
/**
* @notice Current step;
*/
uint8 public currentStep = 1;
/**
* @notice Whether or not dynamic config has been set.
*/
bool public dynamicConfigSet;
/**
* @notice Checks that the current step is the expected step, then bumps the current step.
*
......@@ -114,4 +131,16 @@ contract BaseSystemDictator is Ownable {
config = _config;
_transferOwnership(config.globalConfig.controller);
}
/**
* @notice Allows the owner to update dynamic L2OutputOracle config.
*
* @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.
*/
function updateL2OutputOracleDynamicConfig(
L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig
) external onlyOwner {
l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;
dynamicConfigSet = true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
import { BaseSystemDictator } from "./BaseSystemDictator.sol";
/**
* @title FreshSystemDictator
* @notice The FreshSystemDictator is responsible for coordinating initialization of a fresh
* deployment of the Optimism system. We expect that all proxies and implementations
* already be deployed before this contract is used.
*/
contract FreshSystemDictator is BaseSystemDictator {
/**
* @param _config System configuration.
*/
constructor(DeployConfig memory _config) BaseSystemDictator(_config) {}
/**
* @notice Upgrades and initializes proxy contracts.
*/
function step1() external onlyOwner step(1) {
// Upgrade and initialize the L2OutputOracle.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.l2OutputOracleProxy),
address(config.implementationAddressConfig.l2OutputOracleImpl),
abi.encodeCall(
L2OutputOracle.initialize,
(
config.l2OutputOracleConfig.l2OutputOracleGenesisL2Output,
config.l2OutputOracleConfig.l2OutputOracleProposer,
config.l2OutputOracleConfig.l2OutputOracleOwner
)
)
);
// Upgrade and initialize the OptimismPortal.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.optimismPortalProxy),
address(config.implementationAddressConfig.optimismPortalImpl),
abi.encodeCall(OptimismPortal.initialize, ())
);
// Upgrade and initialize the L1CrossDomainMessenger.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),
address(config.implementationAddressConfig.l1CrossDomainMessengerImpl),
abi.encodeCall(L1CrossDomainMessenger.initialize, (config.globalConfig.finalOwner))
);
// Upgrade the L1StandardBridge (no initializer).
config.globalConfig.proxyAdmin.upgrade(
payable(config.proxyAddressConfig.l1StandardBridgeProxy),
address(config.implementationAddressConfig.l1StandardBridgeImpl)
);
// Upgrade the OptimismMintableERC20Factory (no initializer).
config.globalConfig.proxyAdmin.upgrade(
payable(config.proxyAddressConfig.optimismMintableERC20FactoryProxy),
address(config.implementationAddressConfig.optimismMintableERC20FactoryImpl)
);
// Upgrade the L1ERC721Bridge (no initializer).
config.globalConfig.proxyAdmin.upgrade(
payable(config.proxyAddressConfig.l1ERC721BridgeProxy),
address(config.implementationAddressConfig.l1ERC721BridgeImpl)
);
// Upgrade and initialize the SystemConfig.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.systemConfigProxy),
address(config.implementationAddressConfig.systemConfigImpl),
abi.encodeCall(
SystemConfig.initialize,
(
config.systemConfigConfig.owner,
config.systemConfigConfig.overhead,
config.systemConfigConfig.scalar,
config.systemConfigConfig.batcherHash,
config.systemConfigConfig.gasLimit
)
)
);
}
/**
* @notice Transfers ownership to final owner.
*/
function step2() external onlyOwner step(2) {
// Transfer ownership of the ProxyAdmin to the final owner.
config.globalConfig.proxyAdmin.transferOwnership(config.globalConfig.finalOwner);
}
}
......@@ -17,16 +17,26 @@ import { BaseSystemDictator } from "./BaseSystemDictator.sol";
* proxies and implementations already be deployed before this contract is used.
*/
contract MigrationSystemDictator is BaseSystemDictator {
/**
* @notice Step after which exit 1 can no longer be used.
*/
uint8 public constant EXIT_1_NO_RETURN_STEP = 3;
/**
* @notice Step where proxy ownership is transferred.
*/
uint8 constant PROXY_TRANSFER_STEP = 3;
uint8 public constant PROXY_TRANSFER_STEP = 4;
/**
* @notice Whether or not the deployment is finalized.
*/
bool public finalized;
/**
* @notice Address of the old L1CrossDomainMessenger implementation.
*/
address public oldL1CrossDomainMessenger;
/**
* @param _config System configuration.
*/
......@@ -63,18 +73,31 @@ contract MigrationSystemDictator is BaseSystemDictator {
* deposit halt flag to tell the Sequencer's DTL to stop accepting deposits.
*/
function step2() external onlyOwner step(2) {
// Store the address of the old L1CrossDomainMessenger implementation. We will need this
// address in the case that we have to exit early.
oldL1CrossDomainMessenger = config.globalConfig.addressManager.getAddress(
"OVM_L1CrossDomainMessenger"
);
// Temporarily brick the L1CrossDomainMessenger by setting its implementation address to
// address(0) which will cause the ResolvedDelegateProxy to revert. Better than pausing
// the L1CrossDomainMessenger via pause() because it can be easily reverted.
config.globalConfig.addressManager.setAddress("OVM_L1CrossDomainMessenger", address(0));
// TODO: Set the deposit halt flag.
// Set the DTL shutoff block, which will tell the DTL to stop syncing new deposits from the
// CanonicalTransactionChain. We do this by setting an address in the AddressManager
// because the DTL already has a reference to the AddressManager and this way we don't also
// need to give it a reference to the SystemDictator.
config.globalConfig.addressManager.setAddress(
"DTL_SHUTOFF_BLOCK",
address(uint160(block.number))
);
}
/**
* @notice Removes deprecated addresses from the AddressManager.
*/
function step3() external onlyOwner step(3) {
function step3() external onlyOwner step(EXIT_1_NO_RETURN_STEP) {
// Remove all deprecated addresses from the AddressManager
string[17] memory deprecated = [
"OVM_CanonicalTransactionChain",
......@@ -104,7 +127,7 @@ contract MigrationSystemDictator is BaseSystemDictator {
/**
* @notice Transfers system ownership to the ProxyAdmin.
*/
function step4() external onlyOwner step(4) {
function step4() external onlyOwner step(PROXY_TRANSFER_STEP) {
// Transfer ownership of the AddressManager to the ProxyAdmin.
config.globalConfig.addressManager.transferOwnership(
address(config.globalConfig.proxyAdmin)
......@@ -120,9 +143,11 @@ contract MigrationSystemDictator is BaseSystemDictator {
* @notice Upgrades and initializes proxy contracts.
*/
function step5() external onlyOwner step(5) {
// Pause the L1CrossDomainMessenger. Now we use the real pause() function because by the
// time we're done here we'll have access to the unpause() function.
L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy).pause();
// Dynamic config must be set before we can initialize the L2OutputOracle.
require(
dynamicConfigSet,
"MigrationSystemDictator: dynamic oracle config is not yet initialized"
);
// Upgrade and initialize the L2OutputOracle.
config.globalConfig.proxyAdmin.upgradeAndCall(
......@@ -131,7 +156,8 @@ contract MigrationSystemDictator is BaseSystemDictator {
abi.encodeCall(
L2OutputOracle.initialize,
(
config.l2OutputOracleConfig.l2OutputOracleGenesisL2Output,
l2OutputOracleDynamicConfig.l2OutputOracleStartingBlockNumber,
l2OutputOracleDynamicConfig.l2OutputOracleStartingTimestamp,
config.l2OutputOracleConfig.l2OutputOracleProposer,
config.l2OutputOracleConfig.l2OutputOracleOwner
)
......@@ -145,13 +171,34 @@ contract MigrationSystemDictator is BaseSystemDictator {
abi.encodeCall(OptimismPortal.initialize, ())
);
// Upgrade the L1CrossDomainMessenger. No initializer because this is
// already initialized.
// Upgrade the L1CrossDomainMessenger.
config.globalConfig.proxyAdmin.upgrade(
payable(config.proxyAddressConfig.l1CrossDomainMessengerProxy),
address(config.implementationAddressConfig.l1CrossDomainMessengerImpl)
);
// Try to initialize the L1CrossDomainMessenger, only fail if it's already been initialized.
try
L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy)
.initialize(address(this))
{
// L1CrossDomainMessenger is the one annoying edge case difference between existing
// networks and fresh networks because in existing networks it'll already be
// initialized but in fresh networks it won't be. Try/catch is the easiest and most
// consistent way to handle this because initialized() is not exposed publicly.
} catch Error(string memory reason) {
require(
keccak256(abi.encodePacked(reason)) ==
keccak256("Initializable: contract is already initialized"),
string.concat(
"MigrationSystemDictator: unexpected error initializing L1XDM: ",
reason
)
);
} catch {
revert("MigrationSystemDictator: unexpected error initializing L1XDM (no reason)");
}
// Transfer ETH from the L1StandardBridge to the OptimismPortal.
config.globalConfig.proxyAdmin.upgradeAndCall(
payable(config.proxyAddressConfig.l1StandardBridgeProxy),
......@@ -192,6 +239,9 @@ contract MigrationSystemDictator is BaseSystemDictator {
)
)
);
// Pause the L1CrossDomainMessenger, chance to check that everything is OK.
L1CrossDomainMessenger(config.proxyAddressConfig.l1CrossDomainMessengerProxy).pause();
}
/**
......@@ -229,4 +279,23 @@ contract MigrationSystemDictator is BaseSystemDictator {
finalized = true;
}
/**
* @notice First exit point, can only be called before step 3 is executed.
*/
function exit1() external onlyOwner {
require(
currentStep == EXIT_1_NO_RETURN_STEP,
"MigrationSystemDictator: can only exit1 before step 3 is executed"
);
// Reset the L1CrossDomainMessenger to the old implementation.
config.globalConfig.addressManager.setAddress(
"OVM_L1CrossDomainMessenger",
oldL1CrossDomainMessenger
);
// Unset the DTL shutoff block which will allow the DTL to sync again.
config.globalConfig.addressManager.setAddress("DTL_SHUTOFF_BLOCK", address(0));
}
}
......@@ -97,7 +97,6 @@ contract L2OutputOracle_Initializer is CommonTest {
address internal owner = 0x000000000000000000000000000000000000ACDC;
uint256 internal submissionInterval = 1800;
uint256 internal l2BlockTime = 2;
bytes32 internal genesisL2Output = keccak256(abi.encode(0));
uint256 internal startingBlockNumber = 200;
uint256 internal startingTimestamp = 1000;
......@@ -120,10 +119,9 @@ contract L2OutputOracle_Initializer is CommonTest {
// Deploy the L2OutputOracle and transfer owernship to the proposer
oracleImpl = new L2OutputOracle(
submissionInterval,
genesisL2Output,
l2BlockTime,
startingBlockNumber,
startingTimestamp,
l2BlockTime,
proposer,
owner
);
......@@ -131,7 +129,10 @@ contract L2OutputOracle_Initializer is CommonTest {
vm.prank(multisig);
proxy.upgradeToAndCall(
address(oracleImpl),
abi.encodeCall(L2OutputOracle.initialize, (genesisL2Output, proposer, owner))
abi.encodeCall(
L2OutputOracle.initialize,
(startingBlockNumber, startingTimestamp, proposer, owner)
)
);
oracle = L2OutputOracle(address(proxy));
vm.label(address(oracle), "L2OutputOracle");
......
......@@ -242,7 +242,9 @@ contract OptimismPortal_Test is Portal_Initializer {
// The checkpointed block should not be finalized until 1 second from now.
assertEq(op.isBlockFinalized(checkpoint), false);
// Nor should a block after it
vm.expectRevert("L2OutputOracle: No output found for that block number.");
vm.expectRevert(
"L2OutputOracle: block number cannot be greater than the latest block number"
);
assertEq(op.isBlockFinalized(checkpoint + 1), false);
// Nor a block before it, even though the finalization period has passed, there is
// not yet a checkpoint block on top of it for which that is true.
......@@ -255,7 +257,9 @@ contract OptimismPortal_Test is Portal_Initializer {
// So should the block before it.
assertEq(op.isBlockFinalized(checkpoint - 1), true);
// But not the block after it.
vm.expectRevert("L2OutputOracle: No output found for that block number.");
vm.expectRevert(
"L2OutputOracle: block number cannot be greater than the latest block number"
);
assertEq(op.isBlockFinalized(checkpoint + 1), false);
}
}
......@@ -371,6 +375,71 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
);
}
// Test: proveWithdrawalTransaction reverts if the passed transaction's withdrawalHash has
// already been proven.
function test_proveWithdrawalTransaction_replayProve_reverts() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(
_defaultTx,
_proposedBlockNumber,
_outputRootProof,
_withdrawalProof
);
vm.expectRevert("OptimismPortal: withdrawal hash has already been proven");
op.proveWithdrawalTransaction(
_defaultTx,
_proposedBlockNumber,
_outputRootProof,
_withdrawalProof
);
}
// Test: proveWithdrawalTransaction succeeds if the passed transaction's withdrawalHash has
// already been proven AND the output root has changed AND the l2BlockNumber stays the same.
function test_proveWithdrawalTransaction_replayProveChangedOutputRoot_success() external {
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(
_defaultTx,
_proposedBlockNumber,
_outputRootProof,
_withdrawalProof
);
// Compute the storage slot of the outputRoot corresponding to the `withdrawalHash`
// inside of the `provenWithdrawal`s mapping.
bytes32 slot;
assembly {
mstore(0x00, sload(_withdrawalHash.slot))
mstore(0x20, 52) // 52 is the slot of the `provenWithdrawals` mapping in OptimismPortal
slot := keccak256(0x00, 0x40)
}
// Store a different output root within the `provenWithdrawals` mapping without
// touching the l2BlockNumber or timestamp.
vm.store(address(op), slot, bytes32(0));
// Warp ahead 1 second
vm.warp(block.timestamp + 1);
// Even though we have already proven this withdrawalHash, we should be allowed to re-submit
// our proof with a changed outputRoot
vm.expectEmit(true, true, true, true);
emit WithdrawalProven(_withdrawalHash, alice, bob);
op.proveWithdrawalTransaction(
_defaultTx,
_proposedBlockNumber,
_outputRootProof,
_withdrawalProof
);
// Ensure that the withdrawal was updated within the mapping
(, uint128 timestamp, ) = op.provenWithdrawals(_withdrawalHash);
assertEq(timestamp, block.timestamp);
}
// Test: proveWithdrawalTransaction succeeds and emits the WithdrawalProven event.
function test_proveWithdrawalTransaction_validWithdrawalProof_success() external {
vm.expectEmit(true, true, true, true);
......@@ -459,10 +528,10 @@ contract OptimismPortal_FinalizeWithdrawal_Test is Portal_Initializer {
// Warp to after the finalization period
vm.warp(block.timestamp + op.FINALIZATION_PERIOD_SECONDS() + 1);
// Mock a STARTING_TIMESTAMP change on the L2 Oracle
// Mock a startingTimestamp change on the L2 Oracle
vm.mockCall(
address(op.L2_ORACLE()),
abi.encodeWithSignature("STARTING_TIMESTAMP()"),
abi.encodeWithSignature("startingTimestamp()"),
abi.encode(block.timestamp + 1)
);
......
......@@ -19,7 +19,6 @@
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleOwner": "0x6925B8704Ff96DEe942623d6FB5e946EF5884b63",
"l2OutputOracleGenesisL2Output": "0x1111111111111111111111111111111111111111111111111111111111111111",
"baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
......
......@@ -19,6 +19,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['ProxyAdmin', 'fresh', 'migration']
deployFn.tags = ['ProxyAdmin']
export default deployFn
......@@ -3,22 +3,22 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
assertContractVariable,
deployAndVerifyAndThen,
getDeploymentAddress,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const proxyAdmin = await getDeploymentAddress(hre, 'ProxyAdmin')
const { deployer } = await hre.getNamedAccounts()
await deployAndVerifyAndThen({
hre,
name: 'L1StandardBridgeProxy',
contract: 'Proxy',
args: [proxyAdmin],
name: 'Lib_AddressManager',
contract: 'AddressManager',
args: [],
postDeployAction: async (contract) => {
await assertContractVariable(contract, 'admin', proxyAdmin)
// Owner is temporarily set to the deployer.
await assertContractVariable(contract, 'owner', deployer)
},
})
}
deployFn.tags = ['L1StandardBridgeProxy', 'fresh']
deployFn.tags = ['AddressManager']
export default deployFn
import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
assertContractVariable,
deployAndVerifyAndThen,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts()
await deployAndVerifyAndThen({
hre,
name: 'Proxy__OVM_L1StandardBridge',
contract: 'L1ChugSplashProxy',
args: [deployer],
postDeployAction: async (contract) => {
await assertContractVariable(contract, 'getOwner', deployer)
},
})
}
deployFn.tags = ['L1StandardBridgeProxy']
export default deployFn
import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
assertContractVariable,
deployAndVerifyAndThen,
getDeploymentAddress,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const proxyAdmin = await getDeploymentAddress(hre, 'ProxyAdmin')
await deployAndVerifyAndThen({
hre,
name: 'L1CrossDomainMessengerProxy',
contract: 'Proxy',
args: [proxyAdmin],
postDeployAction: async (contract) => {
await assertContractVariable(contract, 'admin', proxyAdmin)
},
})
}
deployFn.tags = ['L1CrossDomainMessengerProxy', 'fresh']
export default deployFn
......@@ -19,6 +19,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L2OutputOracleProxy', 'fresh', 'migration']
deployFn.tags = ['L2OutputOracleProxy']
export default deployFn
import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
deployAndVerifyAndThen,
getDeploymentAddress,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const addressManager = await getDeploymentAddress(hre, 'Lib_AddressManager')
await deployAndVerifyAndThen({
hre,
name: 'Proxy__OVM_L1CrossDomainMessenger',
contract: 'ResolvedDelegateProxy',
args: [addressManager, 'OVM_L1CrossDomainMessenger'],
})
}
deployFn.tags = ['L1CrossDomainMessengerProxy']
export default deployFn
......@@ -19,6 +19,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismPortalProxy', 'fresh', 'migration']
deployFn.tags = ['OptimismPortalProxy']
export default deployFn
......@@ -19,6 +19,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismMintableERC20FactoryProxy', 'fresh', 'migration']
deployFn.tags = ['OptimismMintableERC20FactoryProxy']
export default deployFn
......@@ -19,6 +19,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1ERC721BridgeProxy', 'fresh', 'migration']
deployFn.tags = ['L1ERC721BridgeProxy']
export default deployFn
......@@ -19,6 +19,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['SystemConfigProxy', 'fresh', 'migration']
deployFn.tags = ['SystemConfigProxy']
export default deployFn
......@@ -12,6 +12,7 @@ const deployFn: DeployFunction = async (hre) => {
hre,
'OptimismPortalProxy'
)
await deployAndVerifyAndThen({
hre,
name: 'L1CrossDomainMessenger',
......@@ -31,6 +32,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1CrossDomainMessengerImpl', 'fresh', 'migration']
deployFn.tags = ['L1CrossDomainMessengerImpl']
export default deployFn
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import { predeploys } from '../src'
......@@ -9,18 +8,10 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
let L1CrossDomainMessengerProxy: ethers.Contract
try {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
} catch {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy'
)
}
const L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
await deployAndVerifyAndThen({
hre,
......@@ -41,6 +32,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1StandardBridgeImpl', 'fresh', 'migration']
deployFn.tags = ['L1StandardBridgeImpl']
export default deployFn
import assert from 'assert'
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import '@nomiclabs/hardhat-ethers'
......@@ -11,30 +8,14 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
// Use default starting time if starting time is not provided.
let deployL2StartingTimestamp =
hre.deployConfig.l2OutputOracleStartingTimestamp
if (deployL2StartingTimestamp < 0) {
const l1StartingBlock = await hre.ethers.provider.getBlock(
hre.deployConfig.l1StartingBlockTag
)
if (l1StartingBlock === null) {
throw new Error(
`Cannot fetch block tag ${hre.deployConfig.l1StartingBlockTag}`
)
}
deployL2StartingTimestamp = l1StartingBlock.timestamp
}
await deployAndVerifyAndThen({
hre,
name: 'L2OutputOracle',
args: [
hre.deployConfig.l2OutputOracleSubmissionInterval,
hre.deployConfig.l2OutputOracleGenesisL2Output,
hre.deployConfig.l2OutputOracleStartingBlockNumber,
deployL2StartingTimestamp,
hre.deployConfig.l2BlockTime,
0,
0,
hre.deployConfig.l2OutputOracleProposer,
hre.deployConfig.l2OutputOracleOwner,
],
......@@ -44,16 +25,6 @@ const deployFn: DeployFunction = async (hre) => {
'SUBMISSION_INTERVAL',
hre.deployConfig.l2OutputOracleSubmissionInterval
)
await assertContractVariable(
contract,
'STARTING_BLOCK_NUMBER',
hre.deployConfig.l2OutputOracleStartingBlockNumber
)
await assertContractVariable(
contract,
'STARTING_TIMESTAMP',
deployL2StartingTimestamp
)
await assertContractVariable(
contract,
'L2_BLOCK_TIME',
......@@ -69,28 +40,10 @@ const deployFn: DeployFunction = async (hre) => {
'owner',
hre.deployConfig.l2OutputOracleOwner
)
// Has to be done separately since l2Output is a mapping.
if (
hre.deployConfig.l2OutputOracleGenesisL2Output ===
ethers.constants.HashZero
) {
console.log(
`[WARNING] Genesis L2 output is ZERO and should NOT BE ZERO if you are deploying to prod`
)
} else {
const output = await contract.getL2Output(
hre.deployConfig.l2OutputOracleStartingBlockNumber
)
assert(
output.outputRoot === hre.deployConfig.l2OutputOracleGenesisL2Output,
`[FATAL] L2OutputOracleImpl genesis output is ${output.outputRoot} but should be ${hre.deployConfig.l2OutputOracleGenesisL2Output}`
)
}
},
})
}
deployFn.tags = ['L2OutputOracleImpl', 'fresh', 'migration']
deployFn.tags = ['L2OutputOracleImpl']
export default deployFn
......@@ -12,6 +12,7 @@ const deployFn: DeployFunction = async (hre) => {
hre,
'L2OutputOracleProxy'
)
await deployAndVerifyAndThen({
hre,
name: 'OptimismPortal',
......@@ -34,6 +35,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismPortalImpl', 'fresh', 'migration']
deployFn.tags = ['OptimismPortalImpl']
export default deployFn
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
......@@ -8,18 +7,10 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
let L1StandardBridgeProxy: ethers.Contract
try {
L1StandardBridgeProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1StandardBridge'
)
} catch (e) {
L1StandardBridgeProxy = await getContractFromArtifact(
hre,
'L1StandardBridgeProxy'
)
}
const L1StandardBridgeProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1StandardBridge'
)
await deployAndVerifyAndThen({
hre,
......@@ -35,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['OptimismMintableERC20FactoryImpl', 'fresh', 'migration']
deployFn.tags = ['OptimismMintableERC20FactoryImpl']
export default deployFn
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import { predeploys } from '../src'
......@@ -9,18 +8,10 @@ import {
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
let L1CrossDomainMessengerProxy: ethers.Contract
try {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
} catch {
L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy'
)
}
const L1CrossDomainMessengerProxy = await getContractFromArtifact(
hre,
'Proxy__OVM_L1CrossDomainMessenger'
)
await deployAndVerifyAndThen({
hre,
......@@ -36,6 +27,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['L1ERC721BridgeImpl', 'fresh', 'migration']
deployFn.tags = ['L1ERC721BridgeImpl']
export default deployFn
......@@ -11,6 +11,7 @@ const deployFn: DeployFunction = async (hre) => {
hre,
'OptimismPortalProxy'
)
await deployAndVerifyAndThen({
hre,
name: 'PortalSender',
......@@ -25,6 +26,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['PortalSenderImpl', 'fresh', 'migration']
deployFn.tags = ['PortalSenderImpl']
export default deployFn
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import {
deployAndVerifyAndThen,
assertDictatorConfig,
makeDictatorConfig,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts()
const config = await makeDictatorConfig(
hre,
deployer,
hre.deployConfig.finalSystemOwner,
true
)
await deployAndVerifyAndThen({
hre,
name: 'FreshSystemDictator',
args: [config],
postDeployAction: async (contract) => {
await assertDictatorConfig(contract, config)
},
})
}
deployFn.tags = ['FreshSystemDictator', 'fresh']
export default deployFn
......@@ -11,6 +11,7 @@ const deployFn: DeployFunction = async (hre) => {
hre.deployConfig.batchSenderAddress,
32
)
await deployAndVerifyAndThen({
hre,
name: 'SystemConfig',
......@@ -46,6 +47,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['SystemConfigImpl', 'fresh', 'migration']
deployFn.tags = ['SystemConfigImpl']
export default deployFn
import assert from 'assert'
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import {
assertContractVariable,
getContractFromArtifact,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts()
const ProxyAdmin = await getContractFromArtifact(hre, 'ProxyAdmin', {
signerOrProvider: deployer,
})
const FreshSystemDictator = await getContractFromArtifact(
hre,
'FreshSystemDictator',
{
signerOrProvider: deployer,
}
)
if ((await ProxyAdmin.owner()) !== FreshSystemDictator.address) {
console.log(`Transferring proxy admin ownership to the FreshSystemDictator`)
await ProxyAdmin.transferOwnership(FreshSystemDictator.address)
} else {
console.log(`Proxy admin already owned by the FreshSystemDictator`)
}
if ((await FreshSystemDictator.currentStep()) === 1) {
console.log(`Executing step 1`)
await FreshSystemDictator.step1()
// Check L2OutputOracle was initialized properly.
const L2OutputOracle = await getContractFromArtifact(
hre,
'L2OutputOracleProxy',
{
iface: 'L2OutputOracle',
}
)
await assertContractVariable(
L2OutputOracle,
'latestBlockNumber',
hre.deployConfig.l2OutputOracleStartingBlockNumber
)
await assertContractVariable(
L2OutputOracle,
'proposer',
hre.deployConfig.l2OutputOracleProposer
)
await assertContractVariable(
L2OutputOracle,
'owner',
hre.deployConfig.l2OutputOracleOwner
)
if (
hre.deployConfig.l2OutputOracleGenesisL2Output !==
ethers.constants.HashZero
) {
const genesisOutput = await L2OutputOracle.getL2Output(
hre.deployConfig.l2OutputOracleStartingBlockNumber
)
assert(
genesisOutput.outputRoot ===
hre.deployConfig.l2OutputOracleGenesisL2Output,
`L2OutputOracle was not initialized with the correct genesis output root`
)
}
// Check OptimismPortal was initialized properly.
const OptimismPortal = await getContractFromArtifact(
hre,
'OptimismPortalProxy',
{
iface: 'OptimismPortal',
}
)
await assertContractVariable(
OptimismPortal,
'l2Sender',
'0x000000000000000000000000000000000000dEaD'
)
const resourceParams = await OptimismPortal.params()
assert(
resourceParams.prevBaseFee.eq(await OptimismPortal.INITIAL_BASE_FEE()),
`OptimismPortal was not initialized with the correct initial base fee`
)
assert(
resourceParams.prevBoughtGas.eq(0),
`OptimismPortal was not initialized with the correct initial bought gas`
)
assert(
!resourceParams.prevBlockNum.eq(0),
`OptimismPortal was not initialized with the correct initial block number`
)
// Check L1CrossDomainMessenger was initialized properly.
const L1CrossDomainMessenger = await getContractFromArtifact(
hre,
'L1CrossDomainMessengerProxy',
{
iface: 'L1CrossDomainMessenger',
}
)
try {
await L1CrossDomainMessenger.xDomainMessageSender()
assert(false, `L1CrossDomainMessenger was not initialized properly`)
} catch (err) {
assert(
err.message.includes('xDomainMessageSender is not set'),
`L1CrossDomainMessenger was not initialized properly`
)
}
await assertContractVariable(
L1CrossDomainMessenger,
'owner',
hre.deployConfig.finalSystemOwner
)
// Check L1StandardBridge was initialized properly.
const L1StandardBridge = await getContractFromArtifact(
hre,
'L1StandardBridgeProxy',
{
iface: 'L1StandardBridge',
}
)
await assertContractVariable(
L1StandardBridge,
'messenger',
L1CrossDomainMessenger.address
)
// Check OptimismMintableERC20Factory was initialized properly.
const OptimismMintableERC20Factory = await getContractFromArtifact(
hre,
'OptimismMintableERC20FactoryProxy',
{
iface: 'OptimismMintableERC20Factory',
}
)
await assertContractVariable(
OptimismMintableERC20Factory,
'bridge',
L1StandardBridge.address
)
// Check L1ERC721Bridge was initialized properly.
const L1ERC721Bridge = await getContractFromArtifact(
hre,
'L1ERC721BridgeProxy',
{
iface: 'L1ERC721Bridge',
}
)
await assertContractVariable(
L1ERC721Bridge,
'messenger',
L1CrossDomainMessenger.address
)
} else {
console.log(`Step 1 executed`)
}
if ((await FreshSystemDictator.currentStep()) === 2) {
console.log(`Executing step 2`)
await FreshSystemDictator.step2()
// Check the ProxyAdmin owner was changed properly.
await assertContractVariable(
ProxyAdmin,
'owner',
hre.deployConfig.finalSystemOwner
)
} else {
console.log(`Step 2 executed`)
}
}
deployFn.tags = ['FreshSystemDictatorSteps', 'fresh']
export default deployFn
......@@ -46,22 +46,6 @@ const deployFn: DeployFunction = async (hre) => {
}
}
if (
hre.deployConfig.l2OutputOracleGenesisL2Output === ethers.constants.HashZero
) {
if (hre.network.config.live === false) {
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!! A genesis L2 output was not provided.`)
console.log(
`WARNING!!! Make sure you are ONLY doing this on a test network.`
)
} else {
throw new Error(`must specify the finalSystemOwner on live networks`)
}
}
const config = await makeDictatorConfig(hre, controller, finalOwner, false)
await deployAndVerifyAndThen({
hre,
......@@ -73,6 +57,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['MigrationSystemDictator', 'migration']
deployFn.tags = ['MigrationSystemDictator']
export default deployFn
......@@ -17,9 +17,40 @@ const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts()
let isLiveDeployer = false
if (hre.deployConfig.controller === deployer) {
console.log('using a live deployer')
isLiveDeployer = true
let controller = hre.deployConfig.controller
if (controller === ethers.constants.AddressZero) {
if (hre.network.config.live === false) {
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!! A controller address was not provided.`)
console.log(
`WARNING!!! Make sure you are ONLY doing this on a test network.`
)
console.log('using a live deployer')
isLiveDeployer = true
controller = deployer
} else {
throw new Error(
`controller address MUST NOT be the deployer on live networks`
)
}
}
let finalOwner = hre.deployConfig.finalSystemOwner
if (finalOwner === ethers.constants.AddressZero) {
if (hre.network.config.live === false) {
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!!`)
console.log(`WARNING!!! A proxy admin owner address was not provided.`)
console.log(
`WARNING!!! Make sure you are ONLY doing this on a test network.`
)
finalOwner = deployer
} else {
throw new Error(`must specify the finalSystemOwner on live networks`)
}
}
// Set up required contract references.
......@@ -116,6 +147,8 @@ const deployFn: DeployFunction = async (hre) => {
// Transfer ownership of the L1CrossDomainMessenger to MigrationSystemDictator.
if (
(await AddressManager.getAddress('OVM_L1CrossDomainMessenger')) !==
ethers.constants.AddressZero &&
(await L1CrossDomainMessenger.owner()) !== MigrationSystemDictator.address
) {
if (isLiveDeployer) {
......@@ -245,19 +278,6 @@ const deployFn: DeployFunction = async (hre) => {
'owner',
hre.deployConfig.l2OutputOracleOwner
)
if (
hre.deployConfig.l2OutputOracleGenesisL2Output !==
ethers.constants.HashZero
) {
const genesisOutput = await L2OutputOracle.getL2Output(
hre.deployConfig.l2OutputOracleStartingBlockNumber
)
assert(
genesisOutput.outputRoot ===
hre.deployConfig.l2OutputOracleGenesisL2Output,
`L2OutputOracle was not initialized with the correct genesis output root`
)
}
// Check OptimismPortal was initialized properly.
await assertContractVariable(
......@@ -279,7 +299,7 @@ const deployFn: DeployFunction = async (hre) => {
`OptimismPortal was not initialized with the correct initial block number`
)
assert(
(await hre.ethers.provider.getBalance(OptimismPortal.address)).gt(0)
(await hre.ethers.provider.getBalance(L1StandardBridge.address)).eq(0)
)
// Check L1CrossDomainMessenger was initialized properly.
......@@ -329,7 +349,40 @@ const deployFn: DeployFunction = async (hre) => {
}
for (let i = 1; i <= 6; i++) {
if ((await MigrationSystemDictator.currentStep()) === i) {
const currentStep = await MigrationSystemDictator.currentStep()
if (currentStep === i) {
if (
currentStep > (await MigrationSystemDictator.PROXY_TRANSFER_STEP()) &&
!(await MigrationSystemDictator.dynamicConfigSet())
) {
if (isLiveDeployer) {
console.log(`Updating dynamic oracle config...`)
// Use default starting time if not provided
let deployL2StartingTimestamp =
hre.deployConfig.l2OutputOracleStartingTimestamp
if (deployL2StartingTimestamp < 0) {
const l1StartingBlock = await hre.ethers.provider.getBlock(
hre.deployConfig.l1StartingBlockTag
)
if (l1StartingBlock === null) {
throw new Error(
`Cannot fetch block tag ${hre.deployConfig.l1StartingBlockTag}`
)
}
deployL2StartingTimestamp = l1StartingBlock.timestamp
}
await MigrationSystemDictator.updateL2OutputOracleDynamicConfig({
l2OutputOracleStartingBlockNumber:
hre.deployConfig.l2OutputOracleStartingBlockNumber,
l2OutputOracleStartingTimestamp: deployL2StartingTimestamp,
})
} else {
console.log(`Please update dynamic oracle config...`)
}
}
if (isLiveDeployer) {
console.log(`Executing step ${i}...`)
await MigrationSystemDictator[`step${i}`]()
......@@ -361,20 +414,12 @@ const deployFn: DeployFunction = async (hre) => {
return MigrationSystemDictator.finalized()
})
await assertContractVariable(
L1CrossDomainMessenger,
'owner',
hre.deployConfig.finalSystemOwner
)
await assertContractVariable(L1CrossDomainMessenger, 'owner', finalOwner)
await assertContractVariable(
ProxyAdmin,
'owner',
hre.deployConfig.finalSystemOwner
)
await assertContractVariable(ProxyAdmin, 'owner', finalOwner)
}
}
deployFn.tags = ['MigrationSystemDictatorSteps', 'migration']
deployFn.tags = ['MigrationSystemDictatorSteps']
export default deployFn
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment