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
c3cff501
Unverified
Commit
c3cff501
authored
Jun 13, 2023
by
OptimismBot
Committed by
GitHub
Jun 13, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5986 from roberto-bayardo/optional-governance
Support non-legacy L2 deployments with optional governance
parents
34fae45a
c47fe5d9
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
241 additions
and
26 deletions
+241
-26
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
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.
op-bindings/predeploys/addresses.go
View file @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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"
)
}
...
...
packages/contracts-bedrock/deploy-config/devnetL1.json
View file @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -24,6 +24,7 @@
"proxyAdminOwner"
:
"0x62790eFcB3a5f3A5D398F95B47930A9Addd83807"
,
"enableGovernance"
:
true
,
"governanceTokenName"
:
"Optimism"
,
"governanceTokenSymbol"
:
"OP"
,
"governanceTokenOwner"
:
"0x038a8825A3C3B0c08d52Cc76E5E361953Cf6Dc76"
,
...
...
packages/contracts-bedrock/deploy-config/goerli.json
View file @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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 @
c3cff501
...
...
@@ -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