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
d19ebe01
Unverified
Commit
d19ebe01
authored
Jun 11, 2023
by
Roberto Bayardo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make governance token predeploy optional
add non-legacy L2 superchain mainnet deploy utility
parent
2959bbb2
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
238 additions
and
25 deletions
+238
-25
addresses.go
op-bindings/predeploys/addresses.go
+23
-0
config.go
op-chain-ops/genesis/config.go
+15
-12
layer_two.go
op-chain-ops/genesis/layer_two.go
+81
-2
layer_two_test.go
op-chain-ops/genesis/layer_two_test.go
+114
-8
test-deploy-config-devnet-l1.json
...in-ops/genesis/testdata/test-deploy-config-devnet-l1.json
+5
-1
deploy-config.ts
packages/contracts-bedrock/src/deploy-config.ts
+0
-2
No files found.
op-bindings/predeploys/addresses.go
View file @
d19ebe01
...
@@ -46,6 +46,29 @@ var (
...
@@ -46,6 +46,29 @@ var (
Predeploys
=
make
(
map
[
string
]
*
common
.
Address
)
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
:
return
false
case
WETH9Addr
:
return
false
case
GovernanceTokenAddr
:
return
false
case
ProxyAdminAddr
:
return
false
default
:
return
true
}
}
// 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
()
{
func
init
()
{
Predeploys
[
"L2ToL1MessagePasser"
]
=
&
L2ToL1MessagePasserAddr
Predeploys
[
"L2ToL1MessagePasser"
]
=
&
L2ToL1MessagePasserAddr
Predeploys
[
"DeployerWhitelist"
]
=
&
DeployerWhitelistAddr
Predeploys
[
"DeployerWhitelist"
]
=
&
DeployerWhitelistAddr
...
...
op-chain-ops/genesis/config.go
View file @
d19ebe01
...
@@ -240,15 +240,16 @@ func (d *DeployConfig) Check() error {
...
@@ -240,15 +240,16 @@ func (d *DeployConfig) Check() error {
if
d
.
L2GenesisBlockBaseFeePerGas
==
nil
{
if
d
.
L2GenesisBlockBaseFeePerGas
==
nil
{
return
fmt
.
Errorf
(
"%w: L2 genesis block base fee per gas cannot be nil"
,
ErrInvalidDeployConfig
)
return
fmt
.
Errorf
(
"%w: L2 genesis block base fee per gas cannot be nil"
,
ErrInvalidDeployConfig
)
}
}
if
d
.
GovernanceTokenName
==
""
{
if
d
.
GovernanceTokenName
!=
""
{
return
fmt
.
Errorf
(
"%w: GovernanceToken.name cannot be empty"
,
ErrInvalidDeployConfig
)
}
if
d
.
GovernanceTokenSymbol
==
""
{
if
d
.
GovernanceTokenSymbol
==
""
{
return
fmt
.
Errorf
(
"%w: GovernanceToken.symbol cannot be empty"
,
ErrInvalidDeployConfig
)
return
fmt
.
Errorf
(
"%w: GovernanceToken.symbol cannot be empty"
,
ErrInvalidDeployConfig
)
}
}
if
d
.
GovernanceTokenOwner
==
(
common
.
Address
{})
{
if
d
.
GovernanceTokenOwner
==
(
common
.
Address
{})
{
return
fmt
.
Errorf
(
"%w: GovernanceToken owner cannot be address(0)"
,
ErrInvalidDeployConfig
)
return
fmt
.
Errorf
(
"%w: GovernanceToken owner cannot be address(0)"
,
ErrInvalidDeployConfig
)
}
}
}
else
if
d
.
GovernanceTokenSymbol
!=
""
||
d
.
GovernanceTokenOwner
!=
(
common
.
Address
{})
{
return
fmt
.
Errorf
(
"%w: Governance token fields must be either all specified or all empty"
,
ErrInvalidDeployConfig
)
}
return
nil
return
nil
}
}
...
@@ -492,11 +493,13 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
...
@@ -492,11 +493,13 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"symbol"
:
"WETH"
,
"symbol"
:
"WETH"
,
"decimals"
:
18
,
"decimals"
:
18
,
}
}
if
len
(
config
.
GovernanceTokenName
)
!=
0
{
storage
[
"GovernanceToken"
]
=
state
.
StorageValues
{
storage
[
"GovernanceToken"
]
=
state
.
StorageValues
{
"_name"
:
config
.
GovernanceTokenName
,
"_name"
:
config
.
GovernanceTokenName
,
"_symbol"
:
config
.
GovernanceTokenSymbol
,
"_symbol"
:
config
.
GovernanceTokenSymbol
,
"_owner"
:
config
.
GovernanceTokenOwner
,
"_owner"
:
config
.
GovernanceTokenOwner
,
}
}
}
storage
[
"ProxyAdmin"
]
=
state
.
StorageValues
{
storage
[
"ProxyAdmin"
]
=
state
.
StorageValues
{
"_owner"
:
config
.
ProxyAdminOwner
,
"_owner"
:
config
.
ProxyAdminOwner
,
}
}
...
...
op-chain-ops/genesis/layer_two.go
View file @
d19ebe01
package
genesis
package
genesis
import
(
import
(
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"errors"
"github.com/ethereum/go-ethereum/core/types"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"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
// BuildL2DeveloperGenesis will build the developer Optimism Genesis
...
@@ -46,3 +54,74 @@ func BuildL2DeveloperGenesis(config *DeployConfig, l1StartBlock *types.Block) (*
...
@@ -46,3 +54,74 @@ func BuildL2DeveloperGenesis(config *DeployConfig, l1StartBlock *types.Block) (*
return
db
.
Genesis
(),
nil
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.
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
&&
storage
[
"GovernanceToken"
]
==
nil
{
// there is no governance token configured, so skip the 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
())
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 @
d19ebe01
...
@@ -8,17 +8,16 @@ import (
...
@@ -8,17 +8,16 @@ import (
"os"
"os"
"testing"
"testing"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/stretchr/testify/require"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"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/core"
"github.com/ethereum/go-ethereum/crypto"
"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-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
"github.com/stretchr/testify/require"
)
)
var
writeFile
bool
var
writeFile
bool
...
@@ -53,7 +52,7 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
...
@@ -53,7 +52,7 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
addr
:=
*
address
addr
:=
*
address
account
,
ok
:=
gen
.
Alloc
[
addr
]
account
,
ok
:=
gen
.
Alloc
[
addr
]
require
.
Equal
(
t
,
ok
,
true
)
require
.
Equal
(
t
,
true
,
ok
)
require
.
Greater
(
t
,
len
(
account
.
Code
),
0
)
require
.
Greater
(
t
,
len
(
account
.
Code
),
0
)
if
name
==
"GovernanceToken"
||
name
==
"LegacyERC20ETH"
||
name
==
"ProxyAdmin"
||
name
==
"WETH9"
{
if
name
==
"GovernanceToken"
||
name
==
"LegacyERC20ETH"
||
name
==
"ProxyAdmin"
||
name
==
"WETH9"
{
...
@@ -61,9 +60,9 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
...
@@ -61,9 +60,9 @@ func TestBuildL2DeveloperGenesis(t *testing.T) {
}
}
adminSlot
,
ok
:=
account
.
Storage
[
genesis
.
AdminSlot
]
adminSlot
,
ok
:=
account
.
Storage
[
genesis
.
AdminSlot
]
require
.
Equal
(
t
,
ok
,
true
)
require
.
Equal
(
t
,
true
,
ok
)
require
.
Equal
(
t
,
adminSlot
,
predeploys
.
ProxyAdminAddr
.
Hash
()
)
require
.
Equal
(
t
,
predeploys
.
ProxyAdminAddr
.
Hash
(),
adminSlot
)
require
.
Equal
(
t
,
account
.
Code
,
depB
)
require
.
Equal
(
t
,
depB
,
account
.
Code
)
}
}
require
.
Equal
(
t
,
2343
,
len
(
gen
.
Alloc
))
require
.
Equal
(
t
,
2343
,
len
(
gen
.
Alloc
))
...
@@ -94,3 +93,110 @@ func TestBuildL2DeveloperGenesisDevAccountsFunding(t *testing.T) {
...
@@ -94,3 +93,110 @@ func TestBuildL2DeveloperGenesisDevAccountsFunding(t *testing.T) {
require
.
NoError
(
t
,
err
)
require
.
NoError
(
t
,
err
)
require
.
Equal
(
t
,
2321
,
len
(
gen
.
Alloc
))
require
.
Equal
(
t
,
2321
,
len
(
gen
.
Alloc
))
}
}
func
TestBuildL2MainnetGenesis
(
t
*
testing
.
T
)
{
config
,
err
:=
genesis
.
NewDeployConfig
(
"./testdata/test-deploy-config-devnet-l1.json"
)
require
.
Nil
(
t
,
err
)
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
)
depB
,
err
:=
bindings
.
GetDeployedBytecode
(
"Proxy"
)
require
.
NoError
(
t
,
err
)
for
name
,
predeploy
:=
range
predeploys
.
Predeploys
{
addr
:=
*
predeploy
if
predeploys
.
IsDeprecated
(
addr
)
{
continue
}
account
,
ok
:=
gen
.
Alloc
[
addr
]
if
predeploys
.
IsDeprecated
(
addr
)
&&
!
predeploys
.
IsProxied
(
addr
)
{
require
.
Equal
(
t
,
false
,
ok
,
name
)
continue
}
require
.
Equal
(
t
,
true
,
ok
,
name
)
require
.
Greater
(
t
,
len
(
account
.
Code
),
0
)
if
!
predeploys
.
IsProxied
(
addr
)
{
continue
}
adminSlot
,
ok
:=
account
.
Storage
[
genesis
.
AdminSlot
]
require
.
Equal
(
t
,
true
,
ok
)
require
.
Equal
(
t
,
predeploys
.
ProxyAdminAddr
.
Hash
(),
adminSlot
)
require
.
Equal
(
t
,
depB
,
account
.
Code
)
}
require
.
Equal
(
t
,
2063
,
len
(
gen
.
Alloc
))
// TODO: confirm 2063 is correct!
if
writeFile
{
file
,
_
:=
json
.
MarshalIndent
(
gen
,
""
,
" "
)
_
=
os
.
WriteFile
(
"genesis.json"
,
file
,
0644
)
}
}
// Same test as TestBuildL2MainnetGenesis, only we blow away the governance token config and
// confirm the governance predeploy doesn't exist (or more precisely, there's an unused proxy
// contract at its address instead).
func
TestBuildL2MainnetNoGovernanceGenesis
(
t
*
testing
.
T
)
{
config
,
err
:=
genesis
.
NewDeployConfig
(
"./testdata/test-deploy-config-devnet-l1.json"
)
require
.
Nil
(
t
,
err
)
config
.
GovernanceTokenSymbol
=
""
config
.
GovernanceTokenName
=
""
config
.
GovernanceTokenOwner
=
common
.
Address
{}
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
)
depB
,
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
)
{
require
.
Equal
(
t
,
false
,
ok
,
name
)
continue
}
require
.
Equal
(
t
,
true
,
ok
,
name
)
require
.
Greater
(
t
,
len
(
account
.
Code
),
0
)
if
!
predeploys
.
IsProxied
(
addr
)
&&
addr
!=
predeploys
.
GovernanceTokenAddr
{
continue
}
adminSlot
,
ok
:=
account
.
Storage
[
genesis
.
AdminSlot
]
require
.
Equal
(
t
,
true
,
ok
)
require
.
Equal
(
t
,
predeploys
.
ProxyAdminAddr
.
Hash
(),
adminSlot
)
require
.
Equal
(
t
,
depB
,
account
.
Code
)
}
require
.
Equal
(
t
,
2063
,
len
(
gen
.
Alloc
))
// TODO: confirm 2063 is correct!
if
writeFile
{
file
,
_
:=
json
.
MarshalIndent
(
gen
,
""
,
" "
)
_
=
os
.
WriteFile
(
"genesis.json"
,
file
,
0644
)
}
}
op-chain-ops/genesis/testdata/test-deploy-config-devnet-l1.json
View file @
d19ebe01
...
@@ -35,5 +35,9 @@
...
@@ -35,5 +35,9 @@
"l1CrossDomainMessengerProxy"
:
"0xff000000000000000000000000000000000000dd"
,
"l1CrossDomainMessengerProxy"
:
"0xff000000000000000000000000000000000000dd"
,
"deploymentWaitConfirmations"
:
1
,
"deploymentWaitConfirmations"
:
1
,
"fundDevAccounts"
:
true
"fundDevAccounts"
:
true
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenOwner"
:
"0x0000000000000000000000000000000000000333"
}
}
packages/contracts-bedrock/src/deploy-config.ts
View file @
d19ebe01
...
@@ -416,11 +416,9 @@ export const deployConfigSpec: {
...
@@ -416,11 +416,9 @@ export const deployConfigSpec: {
},
},
governanceTokenSymbol
:
{
governanceTokenSymbol
:
{
type
:
'
string
'
,
type
:
'
string
'
,
default
:
'
OP
'
,
},
},
governanceTokenName
:
{
governanceTokenName
:
{
type
:
'
string
'
,
type
:
'
string
'
,
default
:
'
Optimism
'
,
},
},
governanceTokenOwner
:
{
governanceTokenOwner
:
{
type
:
'
string
'
,
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