Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nebula
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
exchain
nebula
Commits
1e475ace
Unverified
Commit
1e475ace
authored
Jun 14, 2023
by
mergify[bot]
Committed by
GitHub
Jun 14, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into cleanup/migration-rehearsal-script
parents
02f74b99
e33d0005
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
344 additions
and
172 deletions
+344
-172
Makefile
Makefile
+2
-2
__init__.py
bedrock-devnet/devnet/__init__.py
+101
-33
addresses.go
op-bindings/predeploys/addresses.go
+20
-0
config.go
op-chain-ops/genesis/config.go
+18
-12
layer_two.go
op-chain-ops/genesis/layer_two.go
+98
-2
layer_two_test.go
op-chain-ops/genesis/layer_two_test.go
+72
-9
test-deploy-config-devnet-l1.json
...in-ops/genesis/testdata/test-deploy-config-devnet-l1.json
+6
-1
test-deploy-config-full.json
op-chain-ops/genesis/testdata/test-deploy-config-full.json
+1
-0
memory_db.go
op-chain-ops/state/memory_db.go
+9
-0
devnet-up.sh
ops-bedrock/devnet-up.sh
+0
-111
devnetL1.json
packages/contracts-bedrock/deploy-config/devnetL1.json
+1
-0
getting-started.json
...ages/contracts-bedrock/deploy-config/getting-started.json
+1
-0
goerli-forked.json
packages/contracts-bedrock/deploy-config/goerli-forked.json
+1
-0
goerli.json
packages/contracts-bedrock/deploy-config/goerli.json
+1
-0
hardhat.json
packages/contracts-bedrock/deploy-config/hardhat.json
+1
-0
internal-devnet.json
...ages/contracts-bedrock/deploy-config/internal-devnet.json
+1
-0
local.ts
packages/contracts-bedrock/deploy-config/local.ts
+1
-0
mainnet.json
packages/contracts-bedrock/deploy-config/mainnet.json
+1
-0
deploy-config.ts
packages/contracts-bedrock/src/deploy-config.ts
+9
-2
No files found.
Makefile
View file @
1e475ace
...
...
@@ -74,11 +74,11 @@ nuke: clean devnet-clean
.PHONY
:
nuke
devnet-up
:
@
bash ./ops-bedrock/devnet-up.sh
PYTHONPATH
=
./bedrock-devnet python3 ./bedrock-devnet/main.py
--monorepo-dir
=
.
.PHONY
:
devnet-up
devnet-up-deploy
:
PYTHONPATH
=
./bedrock-devnet python3 ./bedrock-devnet/main.py
--monorepo-dir
=
.
PYTHONPATH
=
./bedrock-devnet python3 ./bedrock-devnet/main.py
--monorepo-dir
=
.
--deploy
.PHONY
:
devnet-up-deploy
devnet-down
:
...
...
bedrock-devnet/devnet/__init__.py
View file @
1e475ace
...
...
@@ -4,74 +4,142 @@ import os
import
subprocess
import
json
import
socket
import
calendar
import
datetime
import
time
import
shutil
import
devnet.log_setup
from
devnet.genesis
import
GENESIS_TMPL
pjoin
=
os
.
path
.
join
parser
=
argparse
.
ArgumentParser
(
description
=
'Bedrock devnet launcher'
)
parser
.
add_argument
(
'--monorepo-dir'
,
help
=
'Directory of the monorepo'
,
default
=
os
.
getcwd
())
parser
.
add_argument
(
'--deploy'
,
help
=
'Whether the contracts should be predeployed or deployed'
,
type
=
bool
,
action
=
argparse
.
BooleanOptionalAction
)
log
=
logging
.
getLogger
()
class
Bunch
:
def
__init__
(
self
,
**
kwds
):
self
.
__dict__
.
update
(
kwds
)
def
main
():
args
=
parser
.
parse_args
()
pjoin
=
os
.
path
.
join
monorepo_dir
=
os
.
path
.
abspath
(
args
.
monorepo_dir
)
devnet_dir
=
pjoin
(
monorepo_dir
,
'.devnet'
)
ops_bedrock_dir
=
pjoin
(
monorepo_dir
,
'ops-bedrock'
)
contracts_bedrock_dir
=
pjoin
(
monorepo_dir
,
'packages'
,
'contracts-bedrock'
)
deployment_dir
=
pjoin
(
contracts_bedrock_dir
,
'deployments'
,
'devnetL1'
)
op_node_dir
=
pjoin
(
args
.
monorepo_dir
,
'op-node'
)
genesis_l1_path
=
pjoin
(
devnet_dir
,
'genesis-l1.json'
)
genesis_l2_path
=
pjoin
(
devnet_dir
,
'genesis-l2.json'
)
addresses_json_path
=
pjoin
(
devnet_dir
,
'addresses.json'
)
sdk_addresses_json_path
=
pjoin
(
devnet_dir
,
'sdk-addresses.json'
)
rollup_config_path
=
pjoin
(
devnet_dir
,
'rollup.json'
)
ops_bedrock_dir
=
pjoin
(
monorepo_dir
,
'ops-bedrock'
)
paths
=
Bunch
(
mono_repo_dir
=
monorepo_dir
,
devnet_dir
=
devnet_dir
,
contracts_bedrock_dir
=
contracts_bedrock_dir
,
deployment_dir
=
deployment_dir
,
deploy_config_dir
=
pjoin
(
contracts_bedrock_dir
,
'deploy-config'
),
op_node_dir
=
op_node_dir
,
ops_bedrock_dir
=
ops_bedrock_dir
,
genesis_l1_path
=
pjoin
(
devnet_dir
,
'genesis-l1.json'
),
genesis_l2_path
=
pjoin
(
devnet_dir
,
'genesis-l2.json'
),
addresses_json_path
=
pjoin
(
devnet_dir
,
'addresses.json'
),
sdk_addresses_json_path
=
pjoin
(
devnet_dir
,
'sdk-addresses.json'
),
rollup_config_path
=
pjoin
(
devnet_dir
,
'rollup.json'
)
)
os
.
makedirs
(
devnet_dir
,
exist_ok
=
True
)
if
os
.
path
.
exists
(
genesis_l1_path
):
log
.
info
(
'L2 genesis already generated.'
)
if
args
.
deploy
:
log
.
info
(
'Devnet with upcoming smart contract deployments'
)
devnet_deploy
(
paths
)
else
:
log
.
info
(
'Devnet with smart contracts pre-deployed'
)
devnet_prestate
(
paths
)
# Bring up the devnet where the L1 contracts are in the genesis state
def
devnet_prestate
(
paths
):
date
=
datetime
.
datetime
.
utcnow
()
utc_time
=
hex
(
calendar
.
timegm
(
date
.
utctimetuple
()))
done_file
=
pjoin
(
paths
.
devnet_dir
,
'done'
)
if
os
.
path
.
exists
(
done_file
):
log
.
info
(
'Genesis files already exist'
)
else
:
log
.
info
(
'Creating genesis files'
)
deploy_config_path
=
pjoin
(
paths
.
deploy_config_dir
,
'devnetL1.json'
)
# read the json file
deploy_config
=
read_json
(
deploy_config_path
)
deploy_config
[
'l1GenesisBlockTimestamp'
]
=
utc_time
temp_deploy_config
=
pjoin
(
paths
.
devnet_dir
,
'deploy-config.json'
)
write_json
(
temp_deploy_config
,
deploy_config
)
outfile_l1
=
paths
.
genesis_l1_path
outfile_l2
=
paths
.
genesis_l2_path
outfile_rollup
=
paths
.
rollup_config_path
run_command
([
'go'
,
'run'
,
'cmd/main.go'
,
'genesis'
,
'devnet'
,
'--deploy-config'
,
temp_deploy_config
,
'--outfile.l1'
,
outfile_l1
,
'--outfile.l2'
,
outfile_l2
,
'--outfile.rollup'
,
outfile_rollup
],
cwd
=
paths
.
op_node_dir
)
write_json
(
done_file
,
{})
log
.
info
(
'Bringing up L1.'
)
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'l1'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
})
wait_up
(
8545
)
log
.
info
(
'Bringing up L2.'
)
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'l2'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
})
wait_up
(
9545
)
log
.
info
(
'Bringing up the services.'
)
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'op-proposer'
,
'op-batcher'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
,
'L2OO_ADDRESS'
:
'0x6900000000000000000000000000000000000000'
})
# Bring up the devnet where the contracts are deployed to L1
def
devnet_deploy
(
paths
):
if
os
.
path
.
exists
(
paths
.
genesis_l1_path
):
log
.
info
(
'L1 genesis already generated.'
)
else
:
log
.
info
(
'Generating L1 genesis.'
)
write_json
(
genesis_l1_path
,
GENESIS_TMPL
)
write_json
(
paths
.
genesis_l1_path
,
GENESIS_TMPL
)
log
.
info
(
'Starting L1.'
)
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'l1'
],
cwd
=
ops_bedrock_dir
,
env
=
{
'PWD'
:
ops_bedrock_dir
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'l1'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
})
wait_up
(
8545
)
log
.
info
(
'Generating network config.'
)
devnet_cfg_orig
=
pjoin
(
contracts_bedrock_dir
,
'deploy-config'
,
'devnetL1.json'
)
devnet_cfg_backup
=
pjoin
(
devnet_dir
,
'devnetL1.json.bak'
)
devnet_cfg_orig
=
pjoin
(
paths
.
contracts_bedrock_dir
,
'deploy-config'
,
'devnetL1.json'
)
devnet_cfg_backup
=
pjoin
(
paths
.
devnet_dir
,
'devnetL1.json.bak'
)
shutil
.
copy
(
devnet_cfg_orig
,
devnet_cfg_backup
)
deploy_config
=
read_json
(
devnet_cfg_orig
)
deploy_config
[
'l1GenesisBlockTimestamp'
]
=
GENESIS_TMPL
[
'timestamp'
]
deploy_config
[
'l1StartingBlockTag'
]
=
'earliest'
write_json
(
devnet_cfg_orig
,
deploy_config
)
if
os
.
path
.
exists
(
addresses_json_path
):
if
os
.
path
.
exists
(
paths
.
addresses_json_path
):
log
.
info
(
'Contracts already deployed.'
)
addresses
=
read_json
(
addresses_json_path
)
addresses
=
read_json
(
paths
.
addresses_json_path
)
else
:
log
.
info
(
'Deploying contracts.'
)
run_command
([
'yarn'
,
'hardhat'
,
'--network'
,
'devnetL1'
,
'deploy'
,
'--tags'
,
'l1'
],
env
=
{
'CHAIN_ID'
:
'900'
,
'L1_RPC'
:
'http://localhost:8545'
,
'PRIVATE_KEY_DEPLOYER'
:
'ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80'
},
cwd
=
contracts_bedrock_dir
)
contracts
=
os
.
listdir
(
deployment_dir
)
},
cwd
=
paths
.
contracts_bedrock_dir
)
contracts
=
os
.
listdir
(
paths
.
deployment_dir
)
addresses
=
{}
for
c
in
contracts
:
if
not
c
.
endswith
(
'.json'
):
continue
data
=
read_json
(
pjoin
(
deployment_dir
,
c
))
data
=
read_json
(
pjoin
(
paths
.
deployment_dir
,
c
))
addresses
[
c
.
replace
(
'.json'
,
''
)]
=
data
[
'address'
]
sdk_addresses
=
{}
sdk_addresses
.
update
({
...
...
@@ -84,10 +152,10 @@ def main():
sdk_addresses
[
'L1StandardBridge'
]
=
addresses
[
'Proxy__OVM_L1StandardBridge'
]
sdk_addresses
[
'OptimismPortal'
]
=
addresses
[
'OptimismPortalProxy'
]
sdk_addresses
[
'L2OutputOracle'
]
=
addresses
[
'L2OutputOracleProxy'
]
write_json
(
addresses_json_path
,
addresses
)
write_json
(
sdk_addresses_json_path
,
sdk_addresses
)
write_json
(
paths
.
addresses_json_path
,
addresses
)
write_json
(
paths
.
sdk_addresses_json_path
,
sdk_addresses
)
if
os
.
path
.
exists
(
genesis_l2_path
):
if
os
.
path
.
exists
(
paths
.
genesis_l2_path
):
log
.
info
(
'L2 genesis and rollup configs already generated.'
)
else
:
log
.
info
(
'Generating L2 genesis and rollup configs.'
)
...
...
@@ -95,25 +163,25 @@ def main():
'go'
,
'run'
,
'cmd/main.go'
,
'genesis'
,
'l2'
,
'--l1-rpc'
,
'http://localhost:8545'
,
'--deploy-config'
,
devnet_cfg_orig
,
'--deployment-dir'
,
deployment_dir
,
'--outfile.l2'
,
pjoin
(
devnet_dir
,
'genesis-l2.json'
),
'--outfile.rollup'
,
pjoin
(
devnet_dir
,
'rollup.json'
)
],
cwd
=
op_node_dir
)
'--deployment-dir'
,
paths
.
deployment_dir
,
'--outfile.l2'
,
pjoin
(
paths
.
devnet_dir
,
'genesis-l2.json'
),
'--outfile.rollup'
,
pjoin
(
paths
.
devnet_dir
,
'rollup.json'
)
],
cwd
=
paths
.
op_node_dir
)
rollup_config
=
read_json
(
rollup_config_path
)
rollup_config
=
read_json
(
paths
.
rollup_config_path
)
if
os
.
path
.
exists
(
devnet_cfg_backup
):
shutil
.
move
(
devnet_cfg_backup
,
devnet_cfg_orig
)
log
.
info
(
'Bringing up L2.'
)
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'l2'
],
cwd
=
ops_bedrock_dir
,
env
=
{
'PWD'
:
ops_bedrock_dir
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'l2'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
})
wait_up
(
9545
)
log
.
info
(
'Bringing up everything else.'
)
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'op-node'
,
'op-proposer'
,
'op-batcher'
],
cwd
=
ops_bedrock_dir
,
env
=
{
'PWD'
:
ops_bedrock_dir
,
run_command
([
'docker-compose'
,
'up'
,
'-d'
,
'op-node'
,
'op-proposer'
,
'op-batcher'
],
cwd
=
paths
.
ops_bedrock_dir
,
env
=
{
'PWD'
:
paths
.
ops_bedrock_dir
,
'L2OO_ADDRESS'
:
addresses
[
'L2OutputOracleProxy'
],
'SEQUENCER_BATCH_INBOX_ADDRESS'
:
rollup_config
[
'batch_inbox_address'
]
})
...
...
op-bindings/predeploys/addresses.go
View file @
1e475ace
...
...
@@ -46,6 +46,26 @@ var (
Predeploys
=
make
(
map
[
string
]
*
common
.
Address
)
)
// IsProxied returns true for predeploys that will sit behind a proxy contract
func
IsProxied
(
predeployAddr
common
.
Address
)
bool
{
switch
predeployAddr
{
case
LegacyERC20ETHAddr
:
case
WETH9Addr
:
case
GovernanceTokenAddr
:
case
ProxyAdminAddr
:
default
:
return
true
}
return
false
}
// IsDeprecated returns true for predeploys we should skip in post-bedrock genesis generation
func
IsDeprecated
(
predeployAddr
common
.
Address
)
bool
{
// TODO: confirm if we can safely add the remaining deprecated predeploys here
// (see https://github.com/ethereum-optimism/optimism/blob/develop/specs/predeploys.md#overview)
return
predeployAddr
==
LegacyERC20ETHAddr
}
func
init
()
{
Predeploys
[
"L2ToL1MessagePasser"
]
=
&
L2ToL1MessagePasserAddr
Predeploys
[
"DeployerWhitelist"
]
=
&
DeployerWhitelistAddr
...
...
op-chain-ops/genesis/config.go
View file @
1e475ace
...
...
@@ -113,6 +113,8 @@ type DeployConfig struct {
GasPriceOracleOverhead
uint64
`json:"gasPriceOracleOverhead"`
// The initial value of the gas scalar
GasPriceOracleScalar
uint64
`json:"gasPriceOracleScalar"`
// Whether or not include governance token predeploy
EnableGovernance
bool
`json:"enableGovernance"`
// The ERC20 symbol of the GovernanceToken
GovernanceTokenSymbol
string
`json:"governanceTokenSymbol"`
// The ERC20 name of the GovernanceToken
...
...
@@ -240,14 +242,16 @@ func (d *DeployConfig) Check() error {
if
d
.
L2GenesisBlockBaseFeePerGas
==
nil
{
return
fmt
.
Errorf
(
"%w: L2 genesis block base fee per gas cannot be nil"
,
ErrInvalidDeployConfig
)
}
if
d
.
GovernanceTokenName
==
""
{
return
fmt
.
Errorf
(
"%w: GovernanceToken.name cannot be empty"
,
ErrInvalidDeployConfig
)
}
if
d
.
GovernanceTokenSymbol
==
""
{
return
fmt
.
Errorf
(
"%w: GovernanceToken.symbol cannot be empty"
,
ErrInvalidDeployConfig
)
}
if
d
.
GovernanceTokenOwner
==
(
common
.
Address
{})
{
return
fmt
.
Errorf
(
"%w: GovernanceToken owner cannot be address(0)"
,
ErrInvalidDeployConfig
)
if
d
.
EnableGovernance
{
if
d
.
GovernanceTokenName
==
""
{
return
fmt
.
Errorf
(
"%w: GovernanceToken.name cannot be empty"
,
ErrInvalidDeployConfig
)
}
if
d
.
GovernanceTokenSymbol
==
""
{
return
fmt
.
Errorf
(
"%w: GovernanceToken.symbol cannot be empty"
,
ErrInvalidDeployConfig
)
}
if
d
.
GovernanceTokenOwner
==
(
common
.
Address
{})
{
return
fmt
.
Errorf
(
"%w: GovernanceToken owner cannot be address(0)"
,
ErrInvalidDeployConfig
)
}
}
return
nil
}
...
...
@@ -492,10 +496,12 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"symbol"
:
"WETH"
,
"decimals"
:
18
,
}
storage
[
"GovernanceToken"
]
=
state
.
StorageValues
{
"_name"
:
config
.
GovernanceTokenName
,
"_symbol"
:
config
.
GovernanceTokenSymbol
,
"_owner"
:
config
.
GovernanceTokenOwner
,
if
config
.
EnableGovernance
{
storage
[
"GovernanceToken"
]
=
state
.
StorageValues
{
"_name"
:
config
.
GovernanceTokenName
,
"_symbol"
:
config
.
GovernanceTokenSymbol
,
"_owner"
:
config
.
GovernanceTokenOwner
,
}
}
storage
[
"ProxyAdmin"
]
=
state
.
StorageValues
{
"_owner"
:
config
.
ProxyAdminOwner
,
...
...
op-chain-ops/genesis/layer_two.go
View file @
1e475ace
package
genesis
import
(
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum/core/types"
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/immutables"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
)
// BuildL2DeveloperGenesis will build the developer Optimism Genesis
...
...
@@ -46,3 +55,90 @@ func BuildL2DeveloperGenesis(config *DeployConfig, l1StartBlock *types.Block) (*
return
db
.
Genesis
(),
nil
}
// BuildL2MainnetGenesis will build an L2 Genesis suitable for a Superchain mainnet that does not
// require a pre-bedrock migration & supports optional governance token predeploy. Details:
//
// - Creates proxies for predeploys in the address space:
// [0x4200000000000000000000000000000000000000, 0x4200000000000000000000000000000000000800)
//
// - All predeploy proxies owned by the ProxyAdmin
//
// - Predeploys as per the spec except for no LegacyERC20ETH predeploy at
// 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000
//
// - optional governance token at 0x4200000000000000000000000000000000000042 if
// config.EnableGovernance is true (& otherwise a no-impl proxy remains at this address)
//
// - no accounts are pre-funded
func
BuildL2MainnetGenesis
(
config
*
DeployConfig
,
l1StartBlock
*
types
.
Block
)
(
*
core
.
Genesis
,
error
)
{
genspec
,
err
:=
NewL2Genesis
(
config
,
l1StartBlock
)
if
err
!=
nil
{
return
nil
,
err
}
db
:=
state
.
NewMemoryStateDB
(
genspec
)
storage
,
err
:=
NewL2StorageConfig
(
config
,
l1StartBlock
)
if
err
!=
nil
{
return
nil
,
err
}
immutable
,
err
:=
NewL2ImmutableConfig
(
config
,
l1StartBlock
)
if
err
!=
nil
{
return
nil
,
err
}
// Set up the proxies
depBytecode
,
err
:=
bindings
.
GetDeployedBytecode
(
"Proxy"
)
if
err
!=
nil
{
return
nil
,
err
}
if
len
(
depBytecode
)
==
0
{
return
nil
,
errors
.
New
(
"Proxy has empty bytecode"
)
}
for
i
:=
uint64
(
0
);
i
<=
2048
;
i
++
{
bigAddr
:=
new
(
big
.
Int
)
.
Or
(
bigL2PredeployNamespace
,
new
(
big
.
Int
)
.
SetUint64
(
i
))
addr
:=
common
.
BigToAddress
(
bigAddr
)
db
.
CreateAccount
(
addr
)
db
.
SetCode
(
addr
,
depBytecode
)
db
.
SetState
(
addr
,
AdminSlot
,
predeploys
.
ProxyAdminAddr
.
Hash
())
}
// Set up the implementations
deployResults
,
err
:=
immutables
.
BuildOptimism
(
immutable
)
if
err
!=
nil
{
return
nil
,
err
}
for
name
,
predeploy
:=
range
predeploys
.
Predeploys
{
addr
:=
*
predeploy
if
predeploys
.
IsDeprecated
(
addr
)
{
continue
}
if
addr
==
predeploys
.
GovernanceTokenAddr
&&
!
config
.
EnableGovernance
{
// there is no governance token configured, so skip the governance token predeploy
log
.
Warn
(
"Governance is not enabled, skipping governance token predeploy."
)
continue
}
codeAddr
:=
addr
if
predeploys
.
IsProxied
(
addr
)
{
codeAddr
,
err
=
AddressToCodeNamespace
(
addr
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"error converting to code namespace: %w"
,
err
)
}
db
.
CreateAccount
(
codeAddr
)
db
.
SetState
(
addr
,
ImplementationSlot
,
codeAddr
.
Hash
())
}
else
{
db
.
DeleteState
(
addr
,
AdminSlot
)
}
if
err
:=
setupPredeploy
(
db
,
deployResults
,
storage
,
name
,
addr
,
codeAddr
);
err
!=
nil
{
return
nil
,
err
}
code
:=
db
.
GetCode
(
codeAddr
)
if
len
(
code
)
==
0
{
return
nil
,
fmt
.
Errorf
(
"code not set for %s"
,
name
)
}
}
return
db
.
Genesis
(),
nil
}
op-chain-ops/genesis/layer_two_test.go
View file @
1e475ace
...
...
@@ -8,17 +8,16 @@ import (
"os"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/stretchr/testify/require"
)
var
writeFile
bool
...
...
@@ -46,14 +45,14 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
require
.
Nil
(
t
,
err
)
require
.
NotNil
(
t
,
gen
)
depB
,
err
:=
bindings
.
GetDeployedBytecode
(
"Proxy"
)
proxyBytecode
,
err
:=
bindings
.
GetDeployedBytecode
(
"Proxy"
)
require
.
NoError
(
t
,
err
)
for
name
,
address
:=
range
predeploys
.
Predeploys
{
addr
:=
*
address
account
,
ok
:=
gen
.
Alloc
[
addr
]
require
.
Equal
(
t
,
ok
,
true
)
require
.
Equal
(
t
,
true
,
ok
)
require
.
Greater
(
t
,
len
(
account
.
Code
),
0
)
if
name
==
"GovernanceToken"
||
name
==
"LegacyERC20ETH"
||
name
==
"ProxyAdmin"
||
name
==
"WETH9"
{
...
...
@@ -61,9 +60,9 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
}
adminSlot
,
ok
:=
account
.
Storage
[
genesis
.
AdminSlot
]
require
.
Equal
(
t
,
ok
,
tru
e
)
require
.
Equal
(
t
,
adminSlot
,
predeploys
.
ProxyAdminAddr
.
Hash
()
)
require
.
Equal
(
t
,
account
.
Code
,
depB
)
require
.
Equal
(
t
,
true
,
ok
,
nam
e
)
require
.
Equal
(
t
,
predeploys
.
ProxyAdminAddr
.
Hash
(),
adminSlot
)
require
.
Equal
(
t
,
proxyBytecode
,
account
.
Code
)
}
require
.
Equal
(
t
,
2343
,
len
(
gen
.
Alloc
))
...
...
@@ -94,3 +93,67 @@ func TestBuildL2DeveloperGenesisDevAccountsFunding(t *testing.T) {
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
2321
,
len
(
gen
.
Alloc
))
}
// Tests the BuildL2MainnetGenesis factory. enableGovernance is used to override enableGovernance
// config option. When false, the test confirms the governance token predeploy address instead
// holds a proxy contract.
func
testBuildL2Genesis
(
t
*
testing
.
T
,
enableGovernance
bool
)
{
config
,
err
:=
genesis
.
NewDeployConfig
(
"./testdata/test-deploy-config-devnet-l1.json"
)
require
.
Nil
(
t
,
err
)
config
.
EnableGovernance
=
enableGovernance
backend
:=
backends
.
NewSimulatedBackend
(
core
.
GenesisAlloc
{
crypto
.
PubkeyToAddress
(
testKey
.
PublicKey
)
:
{
Balance
:
big
.
NewInt
(
10000000000000000
)},
},
15000000
,
)
block
,
err
:=
backend
.
BlockByNumber
(
context
.
Background
(),
common
.
Big0
)
require
.
NoError
(
t
,
err
)
gen
,
err
:=
genesis
.
BuildL2MainnetGenesis
(
config
,
block
)
require
.
Nil
(
t
,
err
)
require
.
NotNil
(
t
,
gen
)
proxyBytecode
,
err
:=
bindings
.
GetDeployedBytecode
(
"Proxy"
)
require
.
NoError
(
t
,
err
)
for
name
,
predeploy
:=
range
predeploys
.
Predeploys
{
addr
:=
*
predeploy
account
,
ok
:=
gen
.
Alloc
[
addr
]
if
predeploys
.
IsDeprecated
(
addr
)
&&
!
predeploys
.
IsProxied
(
addr
)
{
// deprecated, non-proxied predeploys should have no account
require
.
Equal
(
t
,
false
,
ok
,
name
)
continue
}
require
.
Equal
(
t
,
true
,
ok
,
name
)
require
.
Greater
(
t
,
len
(
account
.
Code
),
0
)
adminSlot
,
ok
:=
account
.
Storage
[
genesis
.
AdminSlot
]
isProxy
:=
predeploys
.
IsProxied
(
addr
)
||
(
!
enableGovernance
&&
addr
==
predeploys
.
GovernanceTokenAddr
)
if
isProxy
{
require
.
Equal
(
t
,
true
,
ok
,
name
)
require
.
Equal
(
t
,
predeploys
.
ProxyAdminAddr
.
Hash
(),
adminSlot
)
require
.
Equal
(
t
,
proxyBytecode
,
account
.
Code
)
}
else
{
require
.
Equal
(
t
,
false
,
ok
,
name
)
require
.
NotEqual
(
t
,
proxyBytecode
,
account
.
Code
,
name
)
}
}
require
.
Equal
(
t
,
2063
,
len
(
gen
.
Alloc
))
if
writeFile
{
file
,
_
:=
json
.
MarshalIndent
(
gen
,
""
,
" "
)
_
=
os
.
WriteFile
(
"genesis.json"
,
file
,
0644
)
}
}
func
TestBuildL2MainnetGenesis
(
t
*
testing
.
T
)
{
testBuildL2Genesis
(
t
,
true
)
}
func
TestBuildL2MainnetNoGovernanceGenesis
(
t
*
testing
.
T
)
{
testBuildL2Genesis
(
t
,
false
)
}
op-chain-ops/genesis/testdata/test-deploy-config-devnet-l1.json
View file @
1e475ace
...
...
@@ -35,5 +35,10 @@
"l1CrossDomainMessengerProxy"
:
"0xff000000000000000000000000000000000000dd"
,
"deploymentWaitConfirmations"
:
1
,
"fundDevAccounts"
:
true
"fundDevAccounts"
:
true
,
"enableGovernance"
:
true
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenOwner"
:
"0x0000000000000000000000000000000000000333"
}
op-chain-ops/genesis/testdata/test-deploy-config-full.json
View file @
1e475ace
...
...
@@ -54,6 +54,7 @@
"proxyAdminOwner"
:
"0x0000000000000000000000000000000000000222"
,
"gasPriceOracleOverhead"
:
2100
,
"gasPriceOracleScalar"
:
1000000
,
"enableGovernance"
:
true
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenOwner"
:
"0x0000000000000000000000000000000000000333"
,
...
...
op-chain-ops/state/memory_db.go
View file @
1e475ace
...
...
@@ -226,6 +226,15 @@ func (db *MemoryStateDB) SetState(addr common.Address, key, value common.Hash) {
db
.
genesis
.
Alloc
[
addr
]
=
account
}
func
(
db
*
MemoryStateDB
)
DeleteState
(
addr
common
.
Address
,
key
common
.
Hash
)
{
account
,
ok
:=
db
.
genesis
.
Alloc
[
addr
]
if
!
ok
{
panic
(
fmt
.
Sprintf
(
"%s not in state"
,
addr
))
}
delete
(
account
.
Storage
,
key
)
db
.
genesis
.
Alloc
[
addr
]
=
account
}
func
(
db
*
MemoryStateDB
)
Suicide
(
common
.
Address
)
bool
{
panic
(
"Suicide unimplemented"
)
}
...
...
ops-bedrock/devnet-up.sh
deleted
100755 → 0
View file @
02f74b99
#!/usr/bin/env bash
# This script starts a local devnet using Docker Compose. We have to use
# this more complicated Bash script rather than Compose's native orchestration
# tooling because we need to start each service in a specific order, and specify
# their configuration along the way. The order is:
#
# 1. Start L1.
# 2. Compile contracts.
# 3. Deploy the contracts to L1 if necessary.
# 4. Start L2, inserting the compiled contract artifacts into the genesis.
# 5. Get the genesis hashes and timestamps from L1/L2.
# 6. Generate the rollup driver's config using the genesis hashes and the
# timestamps recovered in step 4 as well as the address of the OptimismPortal
# contract deployed in step 3.
# 7. Start the rollup driver.
# 8. Start the L2 output submitter.
#
# The timestamps are critically important here, since the rollup driver will fill in
# empty blocks if the tip of L1 lags behind the current timestamp. This can lead to
# a perceived infinite loop. To get around this, we set the timestamp to the current
# time in this script.
#
# This script is safe to run multiple times. It stores state in `.devnet`, and
# contracts-bedrock/deployments/devnetL1.
#
# Don't run this script directly. Run it using the makefile, e.g. `make devnet-up`.
# To clean up your devnet, run `make devnet-clean`.
set
-eu
L1_URL
=
"http://localhost:8545"
L2_URL
=
"http://localhost:9545"
OP_NODE
=
"
$PWD
/op-node"
CONTRACTS_BEDROCK
=
"
$PWD
/packages/contracts-bedrock"
NETWORK
=
devnetL1
DEVNET
=
"
$PWD
/.devnet"
# Helper method that waits for a given URL to be up. Can't use
# cURL's built-in retry logic because connection reset errors
# are ignored unless you're using a very recent version of cURL
function
wait_up
{
echo
-n
"Waiting for
$1
to come up..."
i
=
0
until
curl
-s
-f
-o
/dev/null
"
$1
"
do
echo
-n
.
sleep
0.25
((
i
=
i+1
))
if
[
"
$i
"
-eq
300
]
;
then
echo
" Timeout!"
>
&2
exit
1
fi
done
echo
"Done!"
}
mkdir
-p
./.devnet
# Regenerate the L1 genesis file if necessary. The existence of the genesis
# file is used to determine if we need to recreate the devnet's state folder.
if
[
!
-f
"
$DEVNET
/done"
]
;
then
echo
"Regenerating genesis files"
TIMESTAMP
=
$(
date
+%s | xargs
printf
'0x%x'
)
cat
"
$CONTRACTS_BEDROCK
/deploy-config/devnetL1.json"
| jq
-r
".l1GenesisBlockTimestamp =
\"
$TIMESTAMP
\"
"
>
/tmp/bedrock-devnet-deploy-config.json
(
cd
"
$OP_NODE
"
go run cmd/main.go genesis devnet
\
--deploy-config
/tmp/bedrock-devnet-deploy-config.json
\
--outfile
.l1
$DEVNET
/genesis-l1.json
\
--outfile
.l2
$DEVNET
/genesis-l2.json
\
--outfile
.rollup
$DEVNET
/rollup.json
touch
"
$DEVNET
/done"
)
fi
# Bring up L1.
(
cd
ops-bedrock
echo
"Bringing up L1..."
DOCKER_BUILDKIT
=
1 docker-compose build
--progress
plain
docker-compose up
-d
l1
wait_up
$L1_URL
)
# Bring up L2.
(
cd
ops-bedrock
echo
"Bringing up L2..."
docker-compose up
-d
l2
wait_up
$L2_URL
)
L2OO_ADDRESS
=
"0x6900000000000000000000000000000000000000"
# Bring up everything else.
(
cd
ops-bedrock
echo
"Bringing up devnet..."
L2OO_ADDRESS
=
"
$L2OO_ADDRESS
"
\
docker-compose up
-d
op-proposer op-batcher
echo
"Bringing up stateviz webserver..."
docker-compose up
-d
stateviz
)
echo
"Devnet ready."
packages/contracts-bedrock/deploy-config/devnetL1.json
View file @
1e475ace
...
...
@@ -34,6 +34,7 @@
"l2GenesisBlockBaseFeePerGas"
:
"0x3B9ACA00"
,
"gasPriceOracleOverhead"
:
2100
,
"gasPriceOracleScalar"
:
1000000
,
"enableGovernance"
:
true
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenOwner"
:
"0xBcd4042DE499D14e55001CcbB24a551F3b954096"
,
...
...
packages/contracts-bedrock/deploy-config/getting-started.json
View file @
1e475ace
...
...
@@ -43,6 +43,7 @@
"gasPriceOracleOverhead"
:
2100
,
"gasPriceOracleScalar"
:
1000000
,
"enableGovernance"
:
true
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenOwner"
:
"ADMIN"
,
...
...
packages/contracts-bedrock/deploy-config/goerli-forked.json
View file @
1e475ace
...
...
@@ -24,6 +24,7 @@
"proxyAdminOwner"
:
"0x62790eFcB3a5f3A5D398F95B47930A9Addd83807"
,
"enableGovernance"
:
true
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76"
,
...
...
packages/contracts-bedrock/deploy-config/goerli.json
View file @
1e475ace
...
...
@@ -43,6 +43,7 @@
"gasPriceOracleOverhead"
:
2100
,
"gasPriceOracleScalar"
:
1000000
,
"enableGovernance"
:
true
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenOwner"
:
"0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76"
,
...
...
packages/contracts-bedrock/deploy-config/hardhat.json
View file @
1e475ace
...
...
@@ -29,6 +29,7 @@
"baseFeeVaultWithdrawalNetwork"
:
0
,
"l1FeeVaultWithdrawalNetwork"
:
0
,
"sequencerFeeVaultWithdrawalNetwork"
:
0
,
"enableGovernance"
:
true
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"
,
...
...
packages/contracts-bedrock/deploy-config/internal-devnet.json
View file @
1e475ace
...
...
@@ -34,6 +34,7 @@
"l1FeeVaultWithdrawalNetwork"
:
0
,
"sequencerFeeVaultWithdrawalNetwork"
:
0
,
"enableGovernance"
:
true
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x858F0751ef8B4067f0d2668C076BDB50a8549fbF"
,
...
...
packages/contracts-bedrock/deploy-config/local.ts
View file @
1e475ace
...
...
@@ -37,6 +37,7 @@ const config: DeployConfig = {
l1FeeVaultWithdrawalNetwork
:
0
,
sequencerFeeVaultWithdrawalNetwork
:
0
,
enableGovernance
:
true
,
governanceTokenName
:
'
Optimism
'
,
governanceTokenSymbol
:
'
OP
'
,
governanceTokenOwner
:
'
0x90F79bf6EB2c4f870365E785982E1f101E93b906
'
,
...
...
packages/contracts-bedrock/deploy-config/mainnet.json
View file @
1e475ace
...
...
@@ -28,6 +28,7 @@
"baseFeeVaultWithdrawalNetwork"
:
0
,
"l1FeeVaultWithdrawalNetwork"
:
0
,
"sequencerFeeVaultWithdrawalNetwork"
:
0
,
"enableGovernance"
:
true
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x5C4e7Ba1E219E47948e6e3F55019A647bA501005"
,
...
...
packages/contracts-bedrock/src/deploy-config.ts
View file @
1e475ace
...
...
@@ -110,6 +110,11 @@ interface RequiredDeployConfig {
*/
l2OutputOracleChallenger
:
string
/**
* Whether to enable governance token predeploy.
*/
enableGovernance
:
boolean
/**
* ERC20 symbol used for the L2 GovernanceToken.
*/
...
...
@@ -414,13 +419,15 @@ export const deployConfigSpec: {
type
:
'
number
'
,
default
:
1
_000_000
,
},
enableGovernance
:
{
type
:
'
boolean
'
,
default
:
false
,
},
governanceTokenSymbol
:
{
type
:
'
string
'
,
default
:
'
OP
'
,
},
governanceTokenName
:
{
type
:
'
string
'
,
default
:
'
Optimism
'
,
},
governanceTokenOwner
:
{
type
:
'
string
'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment