Commit f97364ba authored by Kelvin Fichter's avatar Kelvin Fichter Committed by Kelvin Fichter

refactor: simplify the genesis file process

parent d5f012ab
...@@ -155,13 +155,9 @@ var ( ...@@ -155,13 +155,9 @@ var (
optimismFlags = []cli.Flag{ optimismFlags = []cli.Flag{
utils.Eth1SyncServiceEnable, utils.Eth1SyncServiceEnable,
utils.Eth1CanonicalTransactionChainDeployHeightFlag, utils.Eth1CanonicalTransactionChainDeployHeightFlag,
utils.Eth1L1CrossDomainMessengerAddressFlag,
utils.Eth1L1FeeWalletAddressFlag,
utils.Eth1StandardBridgeAddressFlag,
utils.Eth1ChainIdFlag, utils.Eth1ChainIdFlag,
utils.RollupClientHttpFlag, utils.RollupClientHttpFlag,
utils.RollupEnableVerifierFlag, utils.RollupEnableVerifierFlag,
utils.RollupAddressManagerOwnerAddressFlag,
utils.RollupTimstampRefreshFlag, utils.RollupTimstampRefreshFlag,
utils.RollupPollIntervalFlag, utils.RollupPollIntervalFlag,
utils.RollupStateDumpPathFlag, utils.RollupStateDumpPathFlag,
...@@ -171,7 +167,6 @@ var ( ...@@ -171,7 +167,6 @@ var (
utils.RollupMinL2GasLimitFlag, utils.RollupMinL2GasLimitFlag,
utils.RollupFeeThresholdDownFlag, utils.RollupFeeThresholdDownFlag,
utils.RollupFeeThresholdUpFlag, utils.RollupFeeThresholdUpFlag,
utils.GasPriceOracleOwnerAddress,
} }
rpcFlags = []cli.Flag{ rpcFlags = []cli.Flag{
......
...@@ -68,12 +68,8 @@ var AppHelpFlagGroups = []flagGroup{ ...@@ -68,12 +68,8 @@ var AppHelpFlagGroups = []flagGroup{
Flags: []cli.Flag{ Flags: []cli.Flag{
utils.Eth1SyncServiceEnable, utils.Eth1SyncServiceEnable,
utils.Eth1CanonicalTransactionChainDeployHeightFlag, utils.Eth1CanonicalTransactionChainDeployHeightFlag,
utils.Eth1L1CrossDomainMessengerAddressFlag,
utils.Eth1L1FeeWalletAddressFlag,
utils.Eth1StandardBridgeAddressFlag,
utils.Eth1ChainIdFlag, utils.Eth1ChainIdFlag,
utils.RollupClientHttpFlag, utils.RollupClientHttpFlag,
utils.RollupAddressManagerOwnerAddressFlag,
utils.RollupEnableVerifierFlag, utils.RollupEnableVerifierFlag,
utils.RollupTimstampRefreshFlag, utils.RollupTimstampRefreshFlag,
utils.RollupPollIntervalFlag, utils.RollupPollIntervalFlag,
...@@ -84,7 +80,6 @@ var AppHelpFlagGroups = []flagGroup{ ...@@ -84,7 +80,6 @@ var AppHelpFlagGroups = []flagGroup{
utils.RollupMinL2GasLimitFlag, utils.RollupMinL2GasLimitFlag,
utils.RollupFeeThresholdDownFlag, utils.RollupFeeThresholdDownFlag,
utils.RollupFeeThresholdUpFlag, utils.RollupFeeThresholdUpFlag,
utils.GasPriceOracleOwnerAddress,
}, },
}, },
{ {
......
...@@ -817,24 +817,6 @@ var ( ...@@ -817,24 +817,6 @@ var (
Usage: "Deployment of the canonical transaction chain", Usage: "Deployment of the canonical transaction chain",
EnvVar: "ETH1_CTC_DEPLOYMENT_HEIGHT", EnvVar: "ETH1_CTC_DEPLOYMENT_HEIGHT",
} }
Eth1L1CrossDomainMessengerAddressFlag = cli.StringFlag{
Name: "eth1.l1crossdomainmessengeraddress",
Usage: "Deployment address of the L1 cross domain messenger",
Value: "0x0000000000000000000000000000000000000000",
EnvVar: "ETH1_L1_CROSS_DOMAIN_MESSENGER_ADDRESS",
}
Eth1L1FeeWalletAddressFlag = cli.StringFlag{
Name: "eth1.l1feewalletaddress",
Usage: "Address of the L1 wallet that will collect fees",
Value: "0x0000000000000000000000000000000000000000",
EnvVar: "ETH1_L1_FEE_WALLET_ADDRESS",
}
Eth1StandardBridgeAddressFlag = cli.StringFlag{
Name: "eth1.l1standardbridgeaddress",
Usage: "Deployment address of the Standard Bridge",
Value: "0x0000000000000000000000000000000000000000",
EnvVar: "ETH1_L1_STANDARD_BRIDGE_ADDRESS",
}
Eth1ChainIdFlag = cli.Uint64Flag{ Eth1ChainIdFlag = cli.Uint64Flag{
Name: "eth1.chainid", Name: "eth1.chainid",
Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)", Usage: "Network identifier (integer, 1=Frontier, 2=Morden (disused), 3=Ropsten, 4=Rinkeby)",
...@@ -869,12 +851,6 @@ var ( ...@@ -869,12 +851,6 @@ var (
Usage: "Enable the verifier", Usage: "Enable the verifier",
EnvVar: "ROLLUP_VERIFIER_ENABLE", EnvVar: "ROLLUP_VERIFIER_ENABLE",
} }
RollupAddressManagerOwnerAddressFlag = cli.StringFlag{
Name: "rollup.addressmanagerowneraddress",
Usage: "Owner address of the address manager",
Value: "0x0000000000000000000000000000000000000000",
EnvVar: "ROLLUP_ADDRESS_MANAGER_OWNER_ADDRESS",
}
RollupStateDumpPathFlag = cli.StringFlag{ RollupStateDumpPathFlag = cli.StringFlag{
Name: "rollup.statedumppath", Name: "rollup.statedumppath",
Usage: "Path to the state dump", Usage: "Path to the state dump",
...@@ -907,11 +883,6 @@ var ( ...@@ -907,11 +883,6 @@ var (
Usage: "Allow txs with fees above the current fee up to this amount, must be > 1", Usage: "Allow txs with fees above the current fee up to this amount, must be > 1",
EnvVar: "ROLLUP_FEE_THRESHOLD_UP", EnvVar: "ROLLUP_FEE_THRESHOLD_UP",
} }
GasPriceOracleOwnerAddress = cli.StringFlag{
Name: "rollup.gaspriceoracleowneraddress",
Usage: "Owner of the OVM_GasPriceOracle",
EnvVar: "ROLLUP_GAS_PRICE_ORACLE_OWNER_ADDRESS",
}
) )
// MakeDataDir retrieves the currently requested data directory, terminating // MakeDataDir retrieves the currently requested data directory, terminating
...@@ -1142,18 +1113,6 @@ func setEth1(ctx *cli.Context, cfg *rollup.Config) { ...@@ -1142,18 +1113,6 @@ func setEth1(ctx *cli.Context, cfg *rollup.Config) {
height := ctx.GlobalUint64(Eth1CanonicalTransactionChainDeployHeightFlag.Name) height := ctx.GlobalUint64(Eth1CanonicalTransactionChainDeployHeightFlag.Name)
cfg.CanonicalTransactionChainDeployHeight = new(big.Int).SetUint64(height) cfg.CanonicalTransactionChainDeployHeight = new(big.Int).SetUint64(height)
} }
if ctx.GlobalIsSet(Eth1L1CrossDomainMessengerAddressFlag.Name) {
addr := ctx.GlobalString(Eth1L1CrossDomainMessengerAddressFlag.Name)
cfg.L1CrossDomainMessengerAddress = common.HexToAddress(addr)
}
if ctx.GlobalIsSet(Eth1L1FeeWalletAddressFlag.Name) {
addr := ctx.GlobalString(Eth1L1FeeWalletAddressFlag.Name)
cfg.L1FeeWalletAddress = common.HexToAddress(addr)
}
if ctx.GlobalIsSet(Eth1StandardBridgeAddressFlag.Name) {
addr := ctx.GlobalString(Eth1StandardBridgeAddressFlag.Name)
cfg.L1StandardBridgeAddress = common.HexToAddress(addr)
}
if ctx.GlobalIsSet(Eth1ChainIdFlag.Name) { if ctx.GlobalIsSet(Eth1ChainIdFlag.Name) {
cfg.Eth1ChainId = ctx.GlobalUint64(Eth1ChainIdFlag.Name) cfg.Eth1ChainId = ctx.GlobalUint64(Eth1ChainIdFlag.Name)
} }
...@@ -1168,10 +1127,6 @@ func setEth1(ctx *cli.Context, cfg *rollup.Config) { ...@@ -1168,10 +1127,6 @@ func setEth1(ctx *cli.Context, cfg *rollup.Config) {
// UsingOVM // UsingOVM
// setRollup configures the rollup // setRollup configures the rollup
func setRollup(ctx *cli.Context, cfg *rollup.Config) { func setRollup(ctx *cli.Context, cfg *rollup.Config) {
if ctx.GlobalIsSet(RollupAddressManagerOwnerAddressFlag.Name) {
addr := ctx.GlobalString(RollupAddressManagerOwnerAddressFlag.Name)
cfg.AddressManagerOwnerAddress = common.HexToAddress(addr)
}
if ctx.GlobalIsSet(RollupEnableVerifierFlag.Name) { if ctx.GlobalIsSet(RollupEnableVerifierFlag.Name) {
cfg.IsVerifier = true cfg.IsVerifier = true
} }
...@@ -1192,10 +1147,6 @@ func setRollup(ctx *cli.Context, cfg *rollup.Config) { ...@@ -1192,10 +1147,6 @@ func setRollup(ctx *cli.Context, cfg *rollup.Config) {
if ctx.GlobalIsSet(RollupTimstampRefreshFlag.Name) { if ctx.GlobalIsSet(RollupTimstampRefreshFlag.Name) {
cfg.TimestampRefreshThreshold = ctx.GlobalDuration(RollupTimstampRefreshFlag.Name) cfg.TimestampRefreshThreshold = ctx.GlobalDuration(RollupTimstampRefreshFlag.Name)
} }
if ctx.GlobalIsSet(GasPriceOracleOwnerAddress.Name) {
addr := ctx.GlobalString(GasPriceOracleOwnerAddress.Name)
cfg.GasPriceOracleOwnerAddress = common.HexToAddress(addr)
}
if ctx.GlobalIsSet(RollupBackendFlag.Name) { if ctx.GlobalIsSet(RollupBackendFlag.Name) {
val := ctx.GlobalString(RollupBackendFlag.Name) val := ctx.GlobalString(RollupBackendFlag.Name)
backend, err := rollup.NewBackend(val) backend, err := rollup.NewBackend(val)
...@@ -1784,13 +1735,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) { ...@@ -1784,13 +1735,8 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
if gasLimit == 0 { if gasLimit == 0 {
gasLimit = params.GenesisGasLimit gasLimit = params.GenesisGasLimit
} }
xdomainAddress := cfg.Rollup.L1CrossDomainMessengerAddress
l1FeeWalletAddress := cfg.Rollup.L1FeeWalletAddress
addrManagerOwnerAddress := cfg.Rollup.AddressManagerOwnerAddress
l1StandardBridgeAddress := cfg.Rollup.L1StandardBridgeAddress
gpoOwnerAddress := cfg.Rollup.GasPriceOracleOwnerAddress
stateDumpPath := cfg.Rollup.StateDumpPath stateDumpPath := cfg.Rollup.StateDumpPath
cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address, xdomainAddress, l1StandardBridgeAddress, addrManagerOwnerAddress, gpoOwnerAddress, l1FeeWalletAddress, stateDumpPath, chainID, gasLimit) cfg.Genesis = core.DeveloperGenesisBlock(uint64(ctx.GlobalInt(DeveloperPeriodFlag.Name)), developer.Address, stateDumpPath, chainID, gasLimit)
if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) { if !ctx.GlobalIsSet(MinerGasPriceFlag.Name) && !ctx.GlobalIsSet(MinerLegacyGasPriceFlag.Name) {
cfg.Miner.GasPrice = big.NewInt(1) cfg.Miner.GasPrice = big.NewInt(1)
} }
......
...@@ -25,7 +25,6 @@ import ( ...@@ -25,7 +25,6 @@ import (
"io/ioutil" "io/ioutil"
"math/big" "math/big"
"net/http" "net/http"
"sort"
"strings" "strings"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
...@@ -39,7 +38,6 @@ import ( ...@@ -39,7 +38,6 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rollup/dump"
"github.com/ethereum/go-ethereum/rollup/rcfg" "github.com/ethereum/go-ethereum/rollup/rcfg"
) )
...@@ -66,15 +64,6 @@ type Genesis struct { ...@@ -66,15 +64,6 @@ type Genesis struct {
Number uint64 `json:"number"` Number uint64 `json:"number"`
GasUsed uint64 `json:"gasUsed"` GasUsed uint64 `json:"gasUsed"`
ParentHash common.Hash `json:"parentHash"` ParentHash common.Hash `json:"parentHash"`
// OVM Specific, used to initialize the l1XDomainMessengerAddress
// in the genesis state
L1FeeWalletAddress common.Address `json:"-"`
L1CrossDomainMessengerAddress common.Address `json:"-"`
AddressManagerOwnerAddress common.Address `json:"-"`
GasPriceOracleOwnerAddress common.Address `json:"-"`
L1StandardBridgeAddress common.Address `json:"-"`
ChainID *big.Int `json:"-"`
} }
// GenesisAlloc specifies the initial state that is part of the genesis block. // GenesisAlloc specifies the initial state that is part of the genesis block.
...@@ -267,69 +256,6 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig { ...@@ -267,69 +256,6 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
} }
} }
// UsingOVM
// ApplyOvmStateToState applies the initial OVM state to a statedb.
// It inserts a bunch of runtime config into the state.
// It is fragile to storage slots changing as it directly writes to storage
// slots instead of applying messages with well formed calldata.
// This function could be replaced in the future using GenesisAlloc
func ApplyOvmStateToState(statedb *state.StateDB, stateDump *dump.OvmDump, l1XDomainMessengerAddress, l1StandardBridgeAddress, addrManagerOwnerAddress, gpoOwnerAddress, l1FeeWalletAddress common.Address, chainID *big.Int, gasLimit uint64) {
if len(stateDump.Accounts) == 0 {
return
}
acctKeys := make([]string, len(stateDump.Accounts))
i := 0
for k := range stateDump.Accounts {
acctKeys[i] = k
i++
}
sort.Strings(acctKeys)
for _, acctKey := range acctKeys {
account := stateDump.Accounts[acctKey]
statedb.SetCode(account.Address, common.FromHex(account.Code))
statedb.SetNonce(account.Address, account.Nonce)
for key, val := range account.Storage {
statedb.SetState(account.Address, key, common.HexToHash(val))
}
}
AddressManager, ok := stateDump.Accounts["Lib_AddressManager"]
if ok {
// Set the owner of the address manager
ownerSlot := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")
ownerValue := common.BytesToHash(addrManagerOwnerAddress.Bytes())
statedb.SetState(AddressManager.Address, ownerSlot, ownerValue)
log.Info("Setting AddressManager Owner", "owner", addrManagerOwnerAddress.Hex())
// Set the storage slot associated with the cross domain messenger
// to the cross domain messenger address.
log.Info("Setting OVM_L1CrossDomainMessenger in AddressManager", "address", l1XDomainMessengerAddress.Hex())
l1MessengerSlot := common.HexToHash("0x515216935740e67dfdda5cf8e248ea32b3277787818ab59153061ac875c9385e")
l1MessengerValue := common.BytesToHash(l1XDomainMessengerAddress.Bytes())
statedb.SetState(AddressManager.Address, l1MessengerSlot, l1MessengerValue)
}
OVM_L2StandardBridge, ok := stateDump.Accounts["OVM_L2StandardBridge"]
if ok {
log.Info("Setting OVM_L1StandardBridge in OVM_L2StandardBridge", "address", l1StandardBridgeAddress.Hex())
// Set the gateway of OVM_L2StandardBridge at new dump
l1BridgeSlot := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000001")
l1BridgeValue := common.BytesToHash(l1StandardBridgeAddress.Bytes())
statedb.SetState(OVM_L2StandardBridge.Address, l1BridgeSlot, l1BridgeValue)
}
OVM_SequencerFeeVault, ok := stateDump.Accounts["OVM_SequencerFeeVault"]
if ok {
log.Info("Setting l1FeeWallet in OVM_SequencerFeeVault", "wallet", l1FeeWalletAddress.Hex())
l1FeeWalletSlot := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")
l1FeeWalletValue := common.BytesToHash(l1FeeWalletAddress.Bytes())
statedb.SetState(OVM_SequencerFeeVault.Address, l1FeeWalletSlot, l1FeeWalletValue)
GasPriceOracle, ok := stateDump.Accounts["OVM_GasPriceOracle"]
if ok {
ownerSlot := common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000")
ownerValue := common.BytesToHash(gpoOwnerAddress.Bytes())
statedb.SetState(GasPriceOracle.Address, ownerSlot, ownerValue)
log.Info("Setting GasPriceOracle Owner", "owner", gpoOwnerAddress.Hex())
}
}
}
// ToBlock creates the genesis block and writes state of a genesis specification // ToBlock creates the genesis block and writes state of a genesis specification
// to the given database (or discards it if nil). // to the given database (or discards it if nil).
func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
...@@ -338,12 +264,6 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block { ...@@ -338,12 +264,6 @@ func (g *Genesis) ToBlock(db ethdb.Database) *types.Block {
} }
statedb, _ := state.New(common.Hash{}, state.NewDatabase(db)) statedb, _ := state.New(common.Hash{}, state.NewDatabase(db))
// Apply the OVM genesis state, including setting storage dynamically
// in particular system contracts.
if rcfg.UsingOVM {
ApplyOvmStateToState(statedb, g.Config.StateDump, g.L1CrossDomainMessengerAddress, g.L1StandardBridgeAddress, g.AddressManagerOwnerAddress, g.GasPriceOracleOwnerAddress, g.L1FeeWalletAddress, g.ChainID, g.GasLimit)
}
for addr, account := range g.Alloc { for addr, account := range g.Alloc {
statedb.AddBalance(addr, account.Balance) statedb.AddBalance(addr, account.Balance)
statedb.SetCode(addr, account.Code) statedb.SetCode(addr, account.Code)
...@@ -472,7 +392,7 @@ func DefaultGoerliGenesisBlock() *Genesis { ...@@ -472,7 +392,7 @@ func DefaultGoerliGenesisBlock() *Genesis {
// Additional runtime parameters are passed through that impact // Additional runtime parameters are passed through that impact
// the genesis state. An "incompatible genesis block" error means that // the genesis state. An "incompatible genesis block" error means that
// these params were altered since the initial creation of the datadir. // these params were altered since the initial creation of the datadir.
func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress common.Address, l1StandardBridgeAddress common.Address, addrManagerOwnerAddress, gpoOwnerAddress, l1FeeWalletAddress common.Address, stateDumpPath string, chainID *big.Int, gasLimit uint64) *Genesis { func DeveloperGenesisBlock(period uint64, faucet common.Address, stateDumpPath string, chainID *big.Int, gasLimit uint64) *Genesis {
// Override the default period to the user requested one // Override the default period to the user requested one
config := *params.AllCliqueProtocolChanges config := *params.AllCliqueProtocolChanges
config.Clique.Period = period config.Clique.Period = period
...@@ -481,7 +401,7 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm ...@@ -481,7 +401,7 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm
config.ChainID = chainID config.ChainID = chainID
} }
stateDump := dump.OvmDump{} stateDump := GenesisAlloc{}
if rcfg.UsingOVM { if rcfg.UsingOVM {
// Fetch the state dump from the state dump path // Fetch the state dump from the state dump path
// The system cannot start without a state dump as it depends on // The system cannot start without a state dump as it depends on
...@@ -496,12 +416,22 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm ...@@ -496,12 +416,22 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm
if err != nil { if err != nil {
panic(fmt.Sprintf("Cannot fetch state dump: %s", err)) panic(fmt.Sprintf("Cannot fetch state dump: %s", err))
} }
_, ok := stateDump.Accounts["Lib_AddressManager"]
if !ok {
panic("Lib_AddressManager not in state dump")
}
} }
config.StateDump = &stateDump
alloc := GenesisAlloc{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
}
for k, v := range stateDump {
alloc[k] = v
}
// Assemble and return the genesis with the precompiles and faucet pre-funded // Assemble and return the genesis with the precompiles and faucet pre-funded
return &Genesis{ return &Genesis{
...@@ -509,25 +439,7 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm ...@@ -509,25 +439,7 @@ func DeveloperGenesisBlock(period uint64, faucet, l1XDomainMessengerAddress comm
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...), ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
GasLimit: gasLimit, GasLimit: gasLimit,
Difficulty: big.NewInt(1), Difficulty: big.NewInt(1),
Alloc: map[common.Address]GenesisAccount{ Alloc: alloc,
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
},
// UsingOVM
// Add additional properties to the genesis block so that they can
// be added into the initial genesis state at runtime
L1CrossDomainMessengerAddress: l1XDomainMessengerAddress,
L1FeeWalletAddress: l1FeeWalletAddress,
AddressManagerOwnerAddress: addrManagerOwnerAddress,
GasPriceOracleOwnerAddress: gpoOwnerAddress,
L1StandardBridgeAddress: l1StandardBridgeAddress,
ChainID: config.ChainID,
} }
} }
...@@ -547,7 +459,7 @@ func decodePrealloc(data string) GenesisAlloc { ...@@ -547,7 +459,7 @@ func decodePrealloc(data string) GenesisAlloc {
// fetchStateDump will fetch a state dump from a remote HTTP endpoint. // fetchStateDump will fetch a state dump from a remote HTTP endpoint.
// This state dump includes the OVM system contracts as well as previous // This state dump includes the OVM system contracts as well as previous
// user state if the network has previously had a regenesis. // user state if the network has previously had a regenesis.
func fetchStateDump(path string, stateDump *dump.OvmDump) error { func fetchStateDump(path string, stateDump *GenesisAlloc) error {
if stateDump == nil { if stateDump == nil {
return errors.New("Unable to fetch state dump") return errors.New("Unable to fetch state dump")
} }
......
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rollup/dump"
) )
// Genesis hashes to enforce below configs on. // Genesis hashes to enforce below configs on.
...@@ -216,16 +215,16 @@ var ( ...@@ -216,16 +215,16 @@ var (
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // adding flags to the config to also have to set these fields.
AllEthashProtocolChanges = &ChainConfig{big.NewInt(108), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, nil} AllEthashProtocolChanges = &ChainConfig{big.NewInt(108), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus. // and accepted by the Ethereum core developers into the Clique consensus.
// //
// This configuration is intentionally not using keyed fields to force anyone // This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields. // adding flags to the config to also have to set these fields.
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(420), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil} AllCliqueProtocolChanges = &ChainConfig{big.NewInt(420), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}}
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, nil} TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil}
TestRules = TestChainConfig.Rules(new(big.Int)) TestRules = TestChainConfig.Rules(new(big.Int))
) )
...@@ -301,9 +300,6 @@ type ChainConfig struct { ...@@ -301,9 +300,6 @@ type ChainConfig struct {
// Various consensus engines // Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty"` Ethash *EthashConfig `json:"ethash,omitempty"`
Clique *CliqueConfig `json:"clique,omitempty"` Clique *CliqueConfig `json:"clique,omitempty"`
// OVM Specific
StateDump *dump.OvmDump `json:"-"`
} }
// EthashConfig is the consensus engine configs for proof-of-work based sealing. // EthashConfig is the consensus engine configs for proof-of-work based sealing.
......
...@@ -34,6 +34,9 @@ services: ...@@ -34,6 +34,9 @@ services:
# these keys are hardhat's first 2 accounts, DO NOT use in production # these keys are hardhat's first 2 accounts, DO NOT use in production
DEPLOYER_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" DEPLOYER_PRIVATE_KEY: "0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"
SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d" SEQUENCER_PRIVATE_KEY: "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"
GAS_PRICE_ORACLE_OWNER: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
WHITELIST_OWNER: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
L1_FEE_WALLET_ADDRESS: "0x391716d440c151c42cdf1c95c1d83a5427bca52c"
# skip compilation when run in docker-compose, since the contracts # skip compilation when run in docker-compose, since the contracts
# were already compiled in the builder step # were already compiled in the builder step
NO_COMPILE: 1 NO_COMPILE: 1
......
...@@ -3,7 +3,7 @@ FROM ${LOCAL_REGISTRY}/ethereumoptimism/builder AS builder ...@@ -3,7 +3,7 @@ FROM ${LOCAL_REGISTRY}/ethereumoptimism/builder AS builder
FROM node:14-alpine FROM node:14-alpine
RUN apk add --no-cache git curl python bash RUN apk add --no-cache git curl python bash jq
WORKDIR /opt/optimism/ WORKDIR /opt/optimism/
......
...@@ -60,8 +60,6 @@ COPY --from=downloader ovm-solc /root/.cache/hardhat-nodejs/compilers/ovm/0.7.6. ...@@ -60,8 +60,6 @@ COPY --from=downloader ovm-solc /root/.cache/hardhat-nodejs/compilers/ovm/0.7.6.
RUN yarn build RUN yarn build
# build integration tests' contracts # build integration tests' contracts
RUN yarn workspace @eth-optimism/integration-tests build:integration RUN yarn workspace @eth-optimism/integration-tests build:integration
# get the dump
RUN yarn --cwd ./packages/contracts ts-node bin/take-dump.ts
# TODO: Consider thinning up the container by trimming non-production # TODO: Consider thinning up the container by trimming non-production
# dependencies # dependencies
......
...@@ -18,5 +18,24 @@ curl \ ...@@ -18,5 +18,24 @@ curl \
yarn run deploy yarn run deploy
function envSet() {
VAR=$1
export $VAR=$(cat ./dist/dumps/addresses.json | jq -r ".$2")
}
# set the address to the proxy gateway if possible
envSet L1_STANDARD_BRIDGE_ADDRESS Proxy__OVM_L1StandardBridge
if [ $L1_STANDARD_BRIDGE_ADDRESS == null ]; then
envSet L1_STANDARD_BRIDGE_ADDRESS OVM_L1StandardBridge
fi
envSet L1_CROSS_DOMAIN_MESSENGER_ADDRESS Proxy__OVM_L1CrossDomainMessenger
if [ $L1_CROSS_DOMAIN_MESSENGER_ADDRESS == null ]; then
envSet L1_CROSS_DOMAIN_MESSENGER_ADDRESS OVM_L1CrossDomainMessenger
fi
# build the dump file
yarn run build:dump
# serve the addrs and the state dump # serve the addrs and the state dump
exec ./bin/serve_dump.sh exec ./bin/serve_dump.sh
...@@ -3,25 +3,27 @@ import * as fs from 'fs' ...@@ -3,25 +3,27 @@ import * as fs from 'fs'
import * as path from 'path' import * as path from 'path'
import * as mkdirp from 'mkdirp' import * as mkdirp from 'mkdirp'
const env = process.env
const GAS_PRICE_ORACLE_OWNER =
env.GAS_PRICE_ORACLE_OWNER || '0x' + 'FF'.repeat(20)
/* Internal Imports */ /* Internal Imports */
import { makeStateDump } from '../src/state-dump/make-dump' import { makeStateDump } from '../src/make-dump'
import { RollupDeployConfig } from '../src/contract-deployment'
;(async () => { ;(async () => {
const outdir = path.resolve(__dirname, '../dist/dumps') const outdir = path.resolve(__dirname, '../dist/dumps')
const outfile = path.join(outdir, 'state-dump.latest.json') const outfile = path.join(outdir, 'state-dump.latest.json')
mkdirp.sync(outdir) mkdirp.sync(outdir)
const config = { const dump = await makeStateDump({
whitelistConfig: {
owner: process.env.WHITELIST_OWNER,
allowArbitraryContractDeployment: true,
},
gasPriceOracleConfig: { gasPriceOracleConfig: {
owner: GAS_PRICE_ORACLE_OWNER, owner: process.env.GAS_PRICE_ORACLE_OWNER,
initialGasPrice: 0, initialGasPrice: 0,
}, },
} l1StandardBridgeAddress: process.env.L1_STANDARD_BRIDGE_ADDRESS,
l1FeeWalletAddress: process.env.L1_FEE_WALLET_ADDRESS,
l1CrossDomainMessengerAddress:
process.env.L1_CROSS_DOMAIN_MESSENGER_ADDRESS,
})
const dump = await makeStateDump(config as RollupDeployConfig)
fs.writeFileSync(outfile, JSON.stringify(dump, null, 4)) fs.writeFileSync(outfile, JSON.stringify(dump, null, 4))
})() })()
...@@ -3,8 +3,8 @@ pragma solidity >0.5.0 <0.8.0; ...@@ -3,8 +3,8 @@ pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2; pragma experimental ABIEncoderV2;
/* Library Imports */ /* Library Imports */
import { Lib_AddressResolver } from "../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_CrossDomainUtils } from "../../libraries/bridge/Lib_CrossDomainUtils.sol"; import { Lib_CrossDomainUtils } from "../../libraries/bridge/Lib_CrossDomainUtils.sol";
import { Lib_PredeployAddresses } from "../../libraries/constants/Lib_PredeployAddresses.sol";
/* Interface Imports */ /* Interface Imports */
import { iOVM_L2CrossDomainMessenger } from "./iOVM_L2CrossDomainMessenger.sol"; import { iOVM_L2CrossDomainMessenger } from "./iOVM_L2CrossDomainMessenger.sol";
...@@ -26,7 +26,6 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.s ...@@ -26,7 +26,6 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.s
*/ */
contract OVM_L2CrossDomainMessenger is contract OVM_L2CrossDomainMessenger is
iOVM_L2CrossDomainMessenger, iOVM_L2CrossDomainMessenger,
Lib_AddressResolver,
ReentrancyGuard ReentrancyGuard
{ {
...@@ -48,18 +47,19 @@ contract OVM_L2CrossDomainMessenger is ...@@ -48,18 +47,19 @@ contract OVM_L2CrossDomainMessenger is
mapping (bytes32 => bool) public sentMessages; mapping (bytes32 => bool) public sentMessages;
uint256 public messageNonce; uint256 public messageNonce;
address internal xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; address internal xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;
address public l1CrossDomainMessenger;
/*************** /***************
* Constructor * * Constructor *
***************/ ***************/
/** constructor(
* @param _libAddressManager Address of the Address Manager. address _l1CrossDomainMessenger
*/ )
constructor(address _libAddressManager)
Lib_AddressResolver(_libAddressManager)
ReentrancyGuard() ReentrancyGuard()
{} {
l1CrossDomainMessenger = _l1CrossDomainMessenger;
}
/******************** /********************
* Public Functions * * Public Functions *
...@@ -141,7 +141,7 @@ contract OVM_L2CrossDomainMessenger is ...@@ -141,7 +141,7 @@ contract OVM_L2CrossDomainMessenger is
// Prevent calls to OVM_L2ToL1MessagePasser, which would enable // Prevent calls to OVM_L2ToL1MessagePasser, which would enable
// an attacker to maliciously craft the _message to spoof // an attacker to maliciously craft the _message to spoof
// a call from any L2 account. // a call from any L2 account.
if(_target == resolve("OVM_L2ToL1MessagePasser")){ if (_target == Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER) {
// Write to the successfulMessages mapping and return immediately. // Write to the successfulMessages mapping and return immediately.
successfulMessages[xDomainCalldataHash] = true; successfulMessages[xDomainCalldataHash] = true;
return; return;
...@@ -191,8 +191,8 @@ contract OVM_L2CrossDomainMessenger is ...@@ -191,8 +191,8 @@ contract OVM_L2CrossDomainMessenger is
{ {
return ( return (
iOVM_L1MessageSender( iOVM_L1MessageSender(
resolve("OVM_L1MessageSender") Lib_PredeployAddresses.L1_MESSAGE_SENDER
).getL1MessageSender() == resolve("OVM_L1CrossDomainMessenger") ).getL1MessageSender() == l1CrossDomainMessenger
); );
} }
...@@ -207,6 +207,8 @@ contract OVM_L2CrossDomainMessenger is ...@@ -207,6 +207,8 @@ contract OVM_L2CrossDomainMessenger is
) )
internal internal
{ {
iOVM_L2ToL1MessagePasser(resolve("OVM_L2ToL1MessagePasser")).passMessageToL1(_message); iOVM_L2ToL1MessagePasser(
Lib_PredeployAddresses.L2_TO_L1_MESSAGE_PASSER
).passMessageToL1(_message);
} }
} }
// SPDX-License-Identifier: MIT
// @unsupported: ovm
pragma solidity >0.5.0 <0.8.0;
/**
* @title OVM_L1MessageSender
* @dev The L1MessageSender is a predeploy contract running on L2. During the execution of cross
* domain transaction from L1 to L2, it returns the address of the L1 account (either an EOA or
* contract) which sent the message to L2 via the Canonical Transaction Chain's `enqueue()`
* function.
*
* This contract exclusively serves as a getter for the ovmL1TXORIGIN operation. This is necessary
* because there is no corresponding operation in the EVM which the the optimistic solidity compiler
* can be replaced with a call to the ExecutionManager's ovmL1TXORIGIN() function.
*
* Runtime target: OVM
*/
contract OVM_L1MessageSender {
constructor() {
// By using the low-level assembly `return` we can dictate the final code of this contract
// directly. Any call to this contract will simply return the L1MessageSender address.
// Code of this contract will be:
// 4A - L1MESSAGESENDER
// 60 - PUSH1
// 00
// 52 - MSTORE (store L1MESSAGESENDER at memory location 0x00)
// 60 - PUSH1
// 20
// 60 - PUSH1
// 00
// F3 - RETURN (return memory at 0x00...0x20)
bytes memory code = hex"4A60005260206000F3";
assembly {
return(add(code, 0x20), mload(code))
}
}
}
...@@ -56,6 +56,7 @@ ...@@ -56,6 +56,7 @@
}, },
"devDependencies": { "devDependencies": {
"@codechecks/client": "^0.1.11", "@codechecks/client": "^0.1.11",
"@defi-wonderland/smock": "^2.0.2",
"@eth-optimism/smock": "^1.1.10", "@eth-optimism/smock": "^1.1.10",
"@ethersproject/transactions": "^5.4.0", "@ethersproject/transactions": "^5.4.0",
"@nomiclabs/hardhat-ethers": "^2.0.2", "@nomiclabs/hardhat-ethers": "^2.0.2",
...@@ -91,7 +92,6 @@ ...@@ -91,7 +92,6 @@
"eslint-plugin-unicorn": "^32.0.1", "eslint-plugin-unicorn": "^32.0.1",
"ethereum-waffle": "^3.3.0", "ethereum-waffle": "^3.3.0",
"ethers": "^5.4.5", "ethers": "^5.4.5",
"ganache-core": "^2.13.2",
"hardhat": "^2.3.0", "hardhat": "^2.3.0",
"hardhat-deploy": "^0.7.4", "hardhat-deploy": "^0.7.4",
"hardhat-gas-reporter": "^1.0.4", "hardhat-gas-reporter": "^1.0.4",
......
...@@ -17,7 +17,6 @@ interface L2Contracts { ...@@ -17,7 +17,6 @@ interface L2Contracts {
messagePasser: Contract messagePasser: Contract
messageSender: Contract messageSender: Contract
deployerWhiteList: Contract deployerWhiteList: Contract
addressManager: Contract
} }
/** /**
...@@ -97,6 +96,5 @@ export const connectL2Contracts = async ( ...@@ -97,6 +96,5 @@ export const connectL2Contracts = async (
messagePasser: toEthersContract(l2ContractData.OVM_L2ToL1MessagePasser), messagePasser: toEthersContract(l2ContractData.OVM_L2ToL1MessagePasser),
messageSender: toEthersContract(l2ContractData.OVM_L1MessageSender), messageSender: toEthersContract(l2ContractData.OVM_L1MessageSender),
deployerWhiteList: toEthersContract(l2ContractData.OVM_DeployerWhitelist), deployerWhiteList: toEthersContract(l2ContractData.OVM_DeployerWhitelist),
addressManager: toEthersContract(l2ContractData.Lib_AddressManager),
} }
} }
...@@ -67,9 +67,8 @@ export const getL1ContractData = (network: Network) => { ...@@ -67,9 +67,8 @@ export const getL1ContractData = (network: Network) => {
const OVM_ETH = require('../artifacts/contracts/L2/predeploys/OVM_ETH.sol/OVM_ETH.json') const OVM_ETH = require('../artifacts/contracts/L2/predeploys/OVM_ETH.sol/OVM_ETH.json')
const OVM_L2CrossDomainMessenger = require('../artifacts/contracts/L2/messaging/OVM_L2CrossDomainMessenger.sol/OVM_L2CrossDomainMessenger.json') const OVM_L2CrossDomainMessenger = require('../artifacts/contracts/L2/messaging/OVM_L2CrossDomainMessenger.sol/OVM_L2CrossDomainMessenger.json')
const OVM_L2ToL1MessagePasser = require('../artifacts/contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol/OVM_L2ToL1MessagePasser.json') const OVM_L2ToL1MessagePasser = require('../artifacts/contracts/L2/predeploys/OVM_L2ToL1MessagePasser.sol/OVM_L2ToL1MessagePasser.json')
const OVM_L1MessageSender = require('../artifacts/contracts/L2/predeploys/OVM_L1MessageSender.sol/OVM_L1MessageSender.json') const OVM_L1MessageSender = require('../artifacts/contracts/L2/predeploys/iOVM_L1MessageSender.sol/iOVM_L1MessageSender.json')
const OVM_DeployerWhitelist = require('../artifacts/contracts/L2/predeploys/OVM_DeployerWhitelist.sol/OVM_DeployerWhitelist.json') const OVM_DeployerWhitelist = require('../artifacts/contracts/L2/predeploys/OVM_DeployerWhitelist.sol/OVM_DeployerWhitelist.json')
const Lib_AddressManager = require('../artifacts/contracts/libraries/resolver/Lib_AddressManager.sol/Lib_AddressManager.json')
export const getL2ContractData = () => { export const getL2ContractData = () => {
return { return {
...@@ -93,9 +92,5 @@ export const getL2ContractData = () => { ...@@ -93,9 +92,5 @@ export const getL2ContractData = () => {
abi: OVM_DeployerWhitelist.abi, abi: OVM_DeployerWhitelist.abi,
address: l2Addresses.OVM_DeployerWhitelist, address: l2Addresses.OVM_DeployerWhitelist,
}, },
Lib_AddressManager: {
abi: Lib_AddressManager.abi,
address: l2Addresses.Lib_AddressManager,
},
} }
} }
/* External Imports */
import { Signer, ContractFactory, Contract, constants } from 'ethers'
import { TransactionResponse } from '@ethersproject/abstract-provider'
import { Overrides } from '@ethersproject/contracts'
/* Internal Imports */
import { getContractFactory } from '../contract-defs'
import { predeploys } from '../predeploys'
export interface RollupDeployConfig {
deploymentSigner: Signer
whitelistConfig: {
owner: string | Signer
allowArbitraryContractDeployment: boolean
}
gasPriceOracleConfig: {
owner: string | Signer
initialGasPrice: number
}
addressManager?: string
dependencies?: string[]
deployOverrides: Overrides
waitForReceipts: boolean
}
export interface ContractDeployParameters {
factory: ContractFactory
params?: any[]
afterDeploy?: (contracts?: { [name: string]: Contract }) => Promise<void>
}
export interface ContractDeployConfig {
[name: string]: ContractDeployParameters
}
export const makeContractDeployConfig = async (
config: RollupDeployConfig,
AddressManager: Contract
): Promise<ContractDeployConfig> => {
return {
OVM_L2CrossDomainMessenger: {
factory: getContractFactory('OVM_L2CrossDomainMessenger'),
params: [AddressManager.address],
},
OVM_L2StandardBridge: {
factory: getContractFactory('OVM_L2StandardBridge'),
params: [
predeploys.OVM_L2CrossDomainMessenger,
constants.AddressZero, // we'll set this to the L1 Bridge address in genesis.go
],
},
OVM_DeployerWhitelist: {
factory: getContractFactory('OVM_DeployerWhitelist'),
params: [],
},
OVM_L1MessageSender: {
factory: getContractFactory('OVM_L1MessageSender'),
params: [],
},
OVM_L2ToL1MessagePasser: {
factory: getContractFactory('OVM_L2ToL1MessagePasser'),
params: [],
},
OVM_ETH: {
factory: getContractFactory('OVM_ETH'),
params: [],
},
OVM_GasPriceOracle: {
factory: getContractFactory('OVM_GasPriceOracle'),
params: [
(() => {
if (typeof config.gasPriceOracleConfig.owner !== 'string') {
return config.gasPriceOracleConfig.owner.getAddress()
}
return config.gasPriceOracleConfig.owner
})(),
config.gasPriceOracleConfig.initialGasPrice,
],
},
OVM_SequencerFeeVault: {
factory: getContractFactory('OVM_SequencerFeeVault'),
params: [`0x${'11'.repeat(20)}`],
},
}
}
/* External Imports */
import { Contract } from 'ethers'
/* Internal Imports */
import { RollupDeployConfig, makeContractDeployConfig } from './config'
import { getContractFactory } from '../contract-defs'
export interface DeployResult {
AddressManager: Contract
failedDeployments: string[]
contracts: {
[name: string]: Contract
}
}
export const deploy = async (
config: RollupDeployConfig
): Promise<DeployResult> => {
let AddressManager: Contract
if (config.addressManager) {
// console.log(`Connecting to existing address manager.`) //console.logs currently break our deployer
AddressManager = getContractFactory(
'Lib_AddressManager',
config.deploymentSigner
).attach(config.addressManager)
} else {
// console.log(
// `Address manager wasn't provided, so we're deploying a new one.`
// ) //console.logs currently break our deployer
AddressManager = await getContractFactory(
'Lib_AddressManager',
config.deploymentSigner
).deploy()
if (config.waitForReceipts) {
await AddressManager.deployTransaction.wait()
}
}
const contractDeployConfig = await makeContractDeployConfig(
config,
AddressManager
)
const failedDeployments: string[] = []
const contracts: {
[name: string]: Contract
} = {}
for (const [name, contractDeployParameters] of Object.entries(
contractDeployConfig
)) {
if (config.dependencies && !config.dependencies.includes(name)) {
continue
}
try {
contracts[name] = await contractDeployParameters.factory
.connect(config.deploymentSigner)
.deploy(
...(contractDeployParameters.params || []),
config.deployOverrides
)
if (config.waitForReceipts) {
await contracts[name].deployTransaction.wait()
}
const res = await AddressManager.setAddress(name, contracts[name].address)
if (config.waitForReceipts) {
await res.wait()
}
} catch (err) {
console.error(`Error deploying ${name}: ${err}`)
failedDeployments.push(name)
}
}
for (const [name, contractDeployParameters] of Object.entries(
contractDeployConfig
)) {
if (config.dependencies && !config.dependencies.includes(name)) {
continue
}
if (contractDeployParameters.afterDeploy) {
await contractDeployParameters.afterDeploy(contracts)
}
}
return {
AddressManager,
failedDeployments,
contracts,
}
}
export { RollupDeployConfig } from './config'
export { deploy } from './deploy'
export * from './contract-defs' export * from './contract-defs'
export * from './state-dump/get-dump'
export * from './contract-deployment'
export * from './predeploys' export * from './predeploys'
export * from './connect-contracts' export * from './connect-contracts'
/* External Imports */
import { Signer } from 'ethers'
import {
computeStorageSlots,
getStorageLayout,
} from '@defi-wonderland/smock/dist/src/utils'
/* Internal Imports */
import { predeploys } from './predeploys'
import { getContractArtifact } from './contract-artifacts'
export interface RollupDeployConfig {
whitelistConfig: {
owner: string | Signer
allowArbitraryContractDeployment: boolean
}
gasPriceOracleConfig: {
owner: string | Signer
initialGasPrice: number
}
l1StandardBridgeAddress: string
l1FeeWalletAddress: string
l1CrossDomainMessengerAddress: string
}
/**
* Generates the initial state for the L2 system by injecting the relevant L2 system contracts.
*
* @param cfg Configuration for the L2 system.
* @returns Generated L2 genesis state.
*/
export const makeStateDump = async (cfg: RollupDeployConfig): Promise<any> => {
const variables = {
OVM_DeployerWhitelist: {
initialized: true,
allowArbitraryDeployment:
cfg.whitelistConfig.allowArbitraryContractDeployment,
owner: cfg.whitelistConfig.owner,
},
OVM_GasPriceOracle: {
_owner: cfg.gasPriceOracleConfig.owner,
gasPrice: cfg.gasPriceOracleConfig.initialGasPrice,
},
OVM_L2StandardBridge: {
l1TokenBridge: cfg.l1StandardBridgeAddress,
messenger: predeploys.OVM_L2CrossDomainMessenger,
},
OVM_SequencerFeeVault: {
l1FeeWallet: cfg.l1FeeWalletAddress,
},
OVM_ETH: {
l2Bridge: predeploys.OVM_L2StandardBridge,
_name: 'Ether',
_symbol: 'ETH',
_decimals: 18,
},
OVM_L2CrossDomainMessenger: {
_status: 1,
l1CrossDomainMessenger: cfg.l1CrossDomainMessengerAddress,
},
}
const dump = {}
for (const predeployName of Object.keys(predeploys)) {
const predeployAddress = predeploys[predeployName]
dump[predeployAddress] = {
balance: '00',
storage: {},
}
if (predeployName === 'OVM_L1MessageSender') {
// OVM_L1MessageSender is a special case where we just inject a specific bytecode string.
// We do this because it uses the custom L1MESSAGESENDER opcode (0x4A) which cannot be
// directly used in Solidity (yet). This bytecode string simply executes the 0x4A opcode
// and returns the address given by that opcode.
dump[predeployAddress].code = '0x4A60005260206000F3'
} else {
const artifact = getContractArtifact(predeployName)
dump[predeployAddress].code = artifact.deployedBytecode
}
// Compute and set the required storage slots for each contract that needs it.
if (predeployName in variables) {
const storageLayout = await getStorageLayout(predeployName)
const slots = computeStorageSlots(storageLayout, variables[predeployName])
for (const slot of slots) {
dump[predeployAddress].storage[slot.key] = slot.val
}
}
}
return dump
}
...@@ -13,7 +13,6 @@ export const predeploys = { ...@@ -13,7 +13,6 @@ export const predeploys = {
OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002', OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002',
OVM_ETH: '0x4200000000000000000000000000000000000006', OVM_ETH: '0x4200000000000000000000000000000000000006',
OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007', OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007',
Lib_AddressManager: '0x4200000000000000000000000000000000000008',
OVM_GasPriceOracle: '0x420000000000000000000000000000000000000F', OVM_GasPriceOracle: '0x420000000000000000000000000000000000000F',
OVM_L2StandardBridge: '0x4200000000000000000000000000000000000010', OVM_L2StandardBridge: '0x4200000000000000000000000000000000000010',
OVM_SequencerFeeVault: '0x4200000000000000000000000000000000000011', OVM_SequencerFeeVault: '0x4200000000000000000000000000000000000011',
......
/* External Imports */
import * as path from 'path'
export interface StorageDump {
[key: string]: string
}
export interface StateDump {
accounts: {
[name: string]: {
address: string
code: string
codeHash: string
storage: StorageDump
abi: any
}
}
}
export const getLatestStateDump = (): StateDump => {
return require(path.join(__dirname, '../dumps', `state-dump.latest.json`))
}
/* External Imports */
import { ethers } from 'ethers'
import * as Ganache from 'ganache-core'
import { keccak256 } from 'ethers/lib/utils'
import { fromHexString, toHexString, remove0x } from '@eth-optimism/core-utils'
/* Internal Imports */
import { StorageDump, StateDump } from './get-dump'
import { deploy, RollupDeployConfig } from '../contract-deployment'
import { getContractDefinition } from '../contract-defs'
import { predeploys } from '../predeploys'
/**
* Generates a storage dump for a given address.
*
* @param cStateManager Instance of the callback-based internal vm StateManager.
* @param address Address to generate a state dump for.
*/
const getStorageDump = async (
cStateManager: any,
address: string
): Promise<StorageDump> => {
return new Promise<StorageDump>((resolve, reject) => {
cStateManager._getStorageTrie(address, (err: any, trie: any) => {
if (err) {
reject(err)
}
const storage: StorageDump = {}
const stream = trie.createReadStream()
stream.on('data', (val: any) => {
const storageSlotValue = ethers.utils.RLP.decode(
'0x' + val.value.toString('hex')
)
storage['0x' + val.key.toString('hex')] = storageSlotValue
})
stream.on('end', () => {
resolve(storage)
})
})
})
}
/**
* Replaces old addresses found in a storage dump with new ones.
*
* @param storageDump Storage dump to sanitize.
* @param accounts Set of accounts to sanitize with.
* @returns Sanitized storage dump.
*/
const sanitizeStorageDump = (
storageDump: StorageDump,
accounts: Array<{
originalAddress: string
deadAddress: string
}>
): StorageDump => {
for (const account of accounts) {
account.originalAddress = remove0x(account.originalAddress).toLowerCase()
account.deadAddress = remove0x(account.deadAddress).toLowerCase()
}
for (const [key, value] of Object.entries(storageDump)) {
let parsedKey = key
let parsedValue = value
for (const account of accounts) {
const re = new RegExp(`${account.originalAddress}`, 'g')
parsedValue = parsedValue.replace(re, account.deadAddress)
parsedKey = parsedKey.replace(re, account.deadAddress)
}
if (parsedKey !== key) {
delete storageDump[key]
}
storageDump[parsedKey] = parsedValue
}
return storageDump
}
export const makeStateDump = async (cfg: RollupDeployConfig): Promise<any> => {
const ganache = (Ganache as any).provider({
gasLimit: 100_000_000,
allowUnlimitedContractSize: true,
accounts: [
{
secretKey:
'0x29f3edee0ad3abf8e2699402e0e28cd6492c9be7eaab00d732a791c33552f797',
balance: 10000000000000000000000000000000000,
},
],
})
const provider = new ethers.providers.Web3Provider(ganache)
const signer = provider.getSigner(0)
let config: RollupDeployConfig = {
deploymentSigner: signer,
whitelistConfig: {
owner: signer,
allowArbitraryContractDeployment: true,
},
dependencies: [
'Lib_AddressManager',
'OVM_DeployerWhitelist',
'OVM_L1MessageSender',
'OVM_L2ToL1MessagePasser',
'OVM_L2CrossDomainMessenger',
'OVM_ETH',
'OVM_GasPriceOracle',
'OVM_SequencerFeeVault',
'OVM_L2StandardBridge',
],
deployOverrides: {},
waitForReceipts: false,
gasPriceOracleConfig: {
owner: signer,
initialGasPrice: 0,
},
}
config = { ...config, ...cfg }
const deploymentResult = await deploy(config)
deploymentResult.contracts['Lib_AddressManager'] =
deploymentResult.AddressManager
if (deploymentResult.failedDeployments.length > 0) {
throw new Error(
`Could not generate state dump, deploy failed for: ${deploymentResult.failedDeployments}`
)
}
const pStateManager = ganache.engine.manager.state.blockchain.vm.pStateManager
const cStateManager = pStateManager._wrapped
const dump: StateDump = {
accounts: {},
}
for (let i = 0; i < Object.keys(deploymentResult.contracts).length; i++) {
const name = Object.keys(deploymentResult.contracts)[i]
const contract = deploymentResult.contracts[name]
const codeBuf = await pStateManager.getContractCode(
fromHexString(contract.address)
)
const code = toHexString(codeBuf)
const deadAddress =
predeploys[name] ||
`0xdeaddeaddeaddeaddeaddeaddeaddeaddead${i.toString(16).padStart(4, '0')}`
const def = getContractDefinition(name.replace('Proxy__', ''))
dump.accounts[name] = {
address: deadAddress,
code,
codeHash: keccak256(code),
storage: await getStorageDump(cStateManager, contract.address),
abi: def.abi,
}
}
const addressMap = Object.keys(dump.accounts).map((name) => {
return {
originalAddress: deploymentResult.contracts[name].address,
deadAddress: dump.accounts[name].address,
}
})
for (const name of Object.keys(dump.accounts)) {
dump.accounts[name].storage = sanitizeStorageDump(
dump.accounts[name].storage,
addressMap
)
}
return dump
}
...@@ -22,7 +22,6 @@ describe('connectL1Contracts', () => { ...@@ -22,7 +22,6 @@ describe('connectL1Contracts', () => {
'messagePasser', 'messagePasser',
'messageSender', 'messageSender',
'deployerWhiteList', 'deployerWhiteList',
'addressManager',
] ]
before(async () => { before(async () => {
......
...@@ -8,14 +8,12 @@ import { solidityKeccak256 } from 'ethers/lib/utils' ...@@ -8,14 +8,12 @@ import { solidityKeccak256 } from 'ethers/lib/utils'
/* Internal Imports */ /* Internal Imports */
import { import {
makeAddressManager,
setProxyTarget,
NON_NULL_BYTES32, NON_NULL_BYTES32,
NON_ZERO_ADDRESS, NON_ZERO_ADDRESS,
encodeXDomainCalldata, encodeXDomainCalldata,
getNextBlockNumber, getNextBlockNumber,
} from '../../../helpers' } from '../../../helpers'
import { getContractInterface } from '../../../../src' import { getContractInterface, predeploys } from '../../../../src'
describe('OVM_L2CrossDomainMessenger', () => { describe('OVM_L2CrossDomainMessenger', () => {
let signer: Signer let signer: Signer
...@@ -23,11 +21,6 @@ describe('OVM_L2CrossDomainMessenger', () => { ...@@ -23,11 +21,6 @@ describe('OVM_L2CrossDomainMessenger', () => {
;[signer] = await ethers.getSigners() ;[signer] = await ethers.getSigners()
}) })
let AddressManager: Contract
before(async () => {
AddressManager = await makeAddressManager()
})
let Mock__TargetContract: MockContract let Mock__TargetContract: MockContract
let Mock__OVM_L1CrossDomainMessenger: MockContract let Mock__OVM_L1CrossDomainMessenger: MockContract
let Mock__OVM_L1MessageSender: MockContract let Mock__OVM_L1MessageSender: MockContract
...@@ -40,26 +33,12 @@ describe('OVM_L2CrossDomainMessenger', () => { ...@@ -40,26 +33,12 @@ describe('OVM_L2CrossDomainMessenger', () => {
await ethers.getContractFactory('OVM_L1CrossDomainMessenger') await ethers.getContractFactory('OVM_L1CrossDomainMessenger')
) )
Mock__OVM_L1MessageSender = await smockit( Mock__OVM_L1MessageSender = await smockit(
getContractInterface('iOVM_L1MessageSender') getContractInterface('iOVM_L1MessageSender'),
{ address: predeploys.OVM_L1MessageSender }
) )
Mock__OVM_L2ToL1MessagePasser = await smockit( Mock__OVM_L2ToL1MessagePasser = await smockit(
await ethers.getContractFactory('OVM_L2ToL1MessagePasser') await ethers.getContractFactory('OVM_L2ToL1MessagePasser'),
) { address: predeploys.OVM_L2ToL1MessagePasser }
await AddressManager.setAddress(
'OVM_L1CrossDomainMessenger',
Mock__OVM_L1CrossDomainMessenger.address
)
await setProxyTarget(
AddressManager,
'OVM_L1MessageSender',
Mock__OVM_L1MessageSender
)
await setProxyTarget(
AddressManager,
'OVM_L2ToL1MessagePasser',
Mock__OVM_L2ToL1MessagePasser
) )
}) })
...@@ -73,7 +52,9 @@ describe('OVM_L2CrossDomainMessenger', () => { ...@@ -73,7 +52,9 @@ describe('OVM_L2CrossDomainMessenger', () => {
let OVM_L2CrossDomainMessenger: Contract let OVM_L2CrossDomainMessenger: Contract
beforeEach(async () => { beforeEach(async () => {
OVM_L2CrossDomainMessenger = OVM_L2CrossDomainMessenger =
await Factory__OVM_L2CrossDomainMessenger.deploy(AddressManager.address) await Factory__OVM_L2CrossDomainMessenger.deploy(
Mock__OVM_L1CrossDomainMessenger.address
)
}) })
describe('sendMessage', () => { describe('sendMessage', () => {
...@@ -164,7 +145,7 @@ describe('OVM_L2CrossDomainMessenger', () => { ...@@ -164,7 +145,7 @@ describe('OVM_L2CrossDomainMessenger', () => {
Mock__OVM_L1MessageSender.smocked.getL1MessageSender.will.return.with( Mock__OVM_L1MessageSender.smocked.getL1MessageSender.will.return.with(
Mock__OVM_L1CrossDomainMessenger.address Mock__OVM_L1CrossDomainMessenger.address
) )
target = await AddressManager.getAddress('OVM_L2ToL1MessagePasser') target = predeploys.OVM_L2ToL1MessagePasser
message = Mock__OVM_L2ToL1MessagePasser.interface.encodeFunctionData( message = Mock__OVM_L2ToL1MessagePasser.interface.encodeFunctionData(
'passMessageToL1(bytes)', 'passMessageToL1(bytes)',
[NON_NULL_BYTES32] [NON_NULL_BYTES32]
......
...@@ -446,6 +446,17 @@ ...@@ -446,6 +446,17 @@
dependencies: dependencies:
"@cspotcode/source-map-consumer" "0.8.0" "@cspotcode/source-map-consumer" "0.8.0"
"@defi-wonderland/smock@^2.0.2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@defi-wonderland/smock/-/smock-2.0.2.tgz#0be863a61420fb162190c9be8798befada179f30"
integrity sha512-nZtnUftPkMmFedqDzBqQrZWX+6Q3fK5MNMK3R6mLTg8Ig087A7ifs1KH9vGGpZ3p9RdgC+scUy9KfDASp2SKxg==
dependencies:
diff "^5.0.0"
lodash.isequal "^4.5.0"
lodash.isequalwith "^4.4.0"
rxjs "^7.2.0"
semver "^7.3.5"
"@ensdomains/ens@^0.4.4": "@ensdomains/ens@^0.4.4":
version "0.4.5" version "0.4.5"
resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc"
...@@ -5646,7 +5657,7 @@ diff@3.5.0, diff@^3.1.0: ...@@ -5646,7 +5657,7 @@ diff@3.5.0, diff@^3.1.0:
resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12"
integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==
diff@5.0.0: diff@5.0.0, diff@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b"
integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==
...@@ -9730,6 +9741,16 @@ lodash.get@^4.4.2: ...@@ -9730,6 +9741,16 @@ lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=
lodash.isequal@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isequalwith@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.isequalwith/-/lodash.isequalwith-4.4.0.tgz#266726ddd528f854f21f4ea98a065606e0fbc6b0"
integrity sha1-Jmcm3dUo+FTyH06pigZWBuD7xrA=
lodash.ismatch@^4.4.0: lodash.ismatch@^4.4.0:
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37"
...@@ -12868,6 +12889,13 @@ rxjs@6, rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.7: ...@@ -12868,6 +12889,13 @@ rxjs@6, rxjs@^6.4.0, rxjs@^6.6.0, rxjs@^6.6.7:
dependencies: dependencies:
tslib "^1.9.0" tslib "^1.9.0"
rxjs@^7.2.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.3.0.tgz#39fe4f3461dc1e50be1475b2b85a0a88c1e938c6"
integrity sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==
dependencies:
tslib "~2.1.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2" version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
...@@ -14377,6 +14405,11 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3: ...@@ -14377,6 +14405,11 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@~2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
tsort@0.0.1: tsort@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786"
......
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