Commit 9d15e1ad authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

contracts-bedrock: remove fund dev accounts (#3285)

* contracts-bedrock: always fund dev accounts

Reduces config complexity

* op-chain-ops: clean up genesis package
Co-authored-by: default avatarMatthew Slipper <me@matthewslipper.com>
parent 2106bdb7
...@@ -36,7 +36,6 @@ type DeployConfig struct { ...@@ -36,7 +36,6 @@ type DeployConfig struct {
CliqueSignerAddress common.Address `json:"cliqueSignerAddress"` CliqueSignerAddress common.Address `json:"cliqueSignerAddress"`
OptimismBaseFeeRecipient common.Address `json:"optimismBaseFeeRecipient"` OptimismBaseFeeRecipient common.Address `json:"optimismBaseFeeRecipient"`
OptimismL1FeeRecipient common.Address `json:"optimismL1FeeRecipient"` OptimismL1FeeRecipient common.Address `json:"optimismL1FeeRecipient"`
FundDevAccounts bool `json:"fundDevAccounts"`
GasPriceOracleOwner common.Address `json:"gasPriceOracleOwner"` GasPriceOracleOwner common.Address `json:"gasPriceOracleOwner"`
GasPriceOracleOverhead uint `json:"gasPriceOracleOverhead"` GasPriceOracleOverhead uint `json:"gasPriceOracleOverhead"`
GasPriceOracleScalar uint `json:"gasPriceOracleScalar"` GasPriceOracleScalar uint `json:"gasPriceOracleScalar"`
......
...@@ -6,16 +6,10 @@ import ( ...@@ -6,16 +6,10 @@ import (
"fmt" "fmt"
"math/big" "math/big"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/immutables"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
...@@ -64,111 +58,6 @@ var DevAccounts = []common.Address{ ...@@ -64,111 +58,6 @@ var DevAccounts = []common.Address{
// The devBalance is the amount of wei that a dev account is funded with. // The devBalance is the amount of wei that a dev account is funded with.
var devBalance = hexutil.MustDecodeBig("0x200000000000000000000000000000000000000000000000000000000000000") var devBalance = hexutil.MustDecodeBig("0x200000000000000000000000000000000000000000000000000000000000000")
// FundDevAccounts will fund each of the development accounts.
func FundDevAccounts(db vm.StateDB) {
for _, account := range DevAccounts {
db.CreateAccount(account)
db.AddBalance(account, devBalance)
}
}
// SetProxies will set each of the proxies in the state. It requires
// a Proxy and ProxyAdmin deployment present so that the Proxy bytecode
// can be set in state and the ProxyAdmin can be set as the admin of the
// Proxy.
func SetProxies(hh *hardhat.Hardhat, db vm.StateDB) error {
proxy, err := hh.GetArtifact("Proxy")
if err != nil {
return err
}
proxyAdmin, err := hh.GetDeployment("ProxyAdmin")
if err != nil {
return err
}
for i := uint64(0); i <= 2048; i++ {
bigAddr := new(big.Int).Or(bigPredeployNamespace, new(big.Int).SetUint64(i))
addr := common.BigToAddress(bigAddr)
// There is no proxy at the governance token address
if addr == predeploys.GovernanceTokenAddr {
continue
}
db.CreateAccount(addr)
db.SetCode(addr, proxy.DeployedBytecode)
db.SetState(addr, AdminSlot, proxyAdmin.Address.Hash())
}
return nil
}
// SetImplementations will set the implmentations of the contracts in the state
// and configure the proxies to point to the implementations. It also sets
// the appropriate storage values for each contract at the proxy address.
func SetImplementations(hh *hardhat.Hardhat, db vm.StateDB, storage StorageConfig) error {
deployResults, err := immutables.BuildOptimism()
if err != nil {
return err
}
for name, address := range predeploys.Predeploys {
// Get the hardhat artifact to access the deployed bytecode
artifact, err := hh.GetArtifact(name)
if err != nil {
return err
}
// Convert the address to the code address
var addr common.Address
switch *address {
case predeploys.GovernanceTokenAddr:
addr = predeploys.GovernanceTokenAddr
case predeploys.LegacyERC20ETHAddr:
addr = predeploys.LegacyERC20ETHAddr
default:
addr, err = AddressToCodeNamespace(*address)
if err != nil {
return err
}
// Set the implmentation slot in the predeploy proxy
db.SetState(*address, ImplementationSlot, addr.Hash())
}
// Create the account
db.CreateAccount(addr)
// Use the genrated bytecode when there are immutables
// otherwise use the artifact deployed bytecode
if bytecode, ok := deployResults[name]; ok {
db.SetCode(addr, bytecode)
} else {
db.SetCode(addr, artifact.DeployedBytecode)
}
// Set the storage values
if storageConfig, ok := storage[name]; ok {
layout, err := hh.GetStorageLayout(name)
if err != nil {
return err
}
slots, err := state.ComputeStorageSlots(layout, storageConfig)
if err != nil {
return err
}
// The storage values must go in the proxy address
for _, slot := range slots {
db.SetState(*address, slot.Key, slot.Value)
}
}
code := db.GetCode(addr)
if len(code) == 0 {
return fmt.Errorf("code not set for %s", name)
}
}
return nil
}
// AddressToCodeNamespace takes a predeploy address and computes // AddressToCodeNamespace takes a predeploy address and computes
// the implmentation address that the implementation should be deployed at // the implmentation address that the implementation should be deployed at
func AddressToCodeNamespace(addr common.Address) (common.Address, error) { func AddressToCodeNamespace(addr common.Address) (common.Address, error) {
...@@ -181,37 +70,6 @@ func AddressToCodeNamespace(addr common.Address) (common.Address, error) { ...@@ -181,37 +70,6 @@ func AddressToCodeNamespace(addr common.Address) (common.Address, error) {
return common.BigToAddress(num), nil return common.BigToAddress(num), nil
} }
// Get the storage layout of the L2ToL1MessagePasser
// Iterate over the storage layout to know which storage slots to ignore
// Iterate over each storage slot, compute the migration
func MigrateDepositHashes(hh *hardhat.Hardhat, db vm.StateDB) error {
layout, err := hh.GetStorageLayout("L2ToL1MessagePasser")
if err != nil {
return err
}
// Build a list of storage slots to ignore. The values in the
// mapping are guaranteed to not be in this list because they are
// hashes.
ignore := make(map[common.Hash]bool)
for _, entry := range layout.Storage {
encoded, err := state.EncodeUintValue(entry.Slot, 0)
if err != nil {
return err
}
ignore[encoded] = true
}
db.ForEachStorage(predeploys.L2ToL1MessagePasserAddr, func(key, value common.Hash) bool {
if _, ok := ignore[key]; ok {
return true
}
// TODO(tynes): Do the value migration here
return true
})
return nil
}
// getBlockFromTag will resolve a Block given an rpc block tag // getBlockFromTag will resolve a Block given an rpc block tag
func getBlockFromTag(chain ethereum.ChainReader, tag rpc.BlockNumberOrHash) (*types.Block, error) { func getBlockFromTag(chain ethereum.ChainReader, tag rpc.BlockNumberOrHash) (*types.Block, error) {
if hash, ok := tag.Hash(); ok { if hash, ok := tag.Hash(); ok {
......
...@@ -15,8 +15,7 @@ func BuildL1DeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig) (*core.G ...@@ -15,8 +15,7 @@ func BuildL1DeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig) (*core.G
db := state.NewMemoryStateDB(genesis) db := state.NewMemoryStateDB(genesis)
if config.FundDevAccounts {
FundDevAccounts(db) FundDevAccounts(db)
}
return db.Genesis(), nil return db.Genesis(), nil
} }
...@@ -8,19 +8,23 @@ import ( ...@@ -8,19 +8,23 @@ import (
"github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core"
) )
// BuildOptimismGenesis // BuildOptimismDeveloperGenesis will build the developer Optimism Genesis
func BuildOptimismGenesis(hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.ChainReader) (*core.Genesis, error) { // Block. Suitable for devnets.
genesis, err := NewL2Genesis(config, chain) func BuildOptimismDeveloperGenesis(hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.ChainReader) (*core.Genesis, error) {
genspec, err := NewL2Genesis(config, chain)
if err != nil { if err != nil {
return nil, err return nil, err
} }
db := state.NewMemoryStateDB(genesis) db := state.NewMemoryStateDB(genspec)
if config.FundDevAccounts {
FundDevAccounts(db) FundDevAccounts(db)
}
return BuildOptimismGenesis(db, hh, config, chain)
}
// BuildOptimismGenesis will build the L2 Optimism Genesis Block
func BuildOptimismGenesis(db *state.MemoryStateDB, hh *hardhat.Hardhat, config *DeployConfig, chain ethereum.ChainReader) (*core.Genesis, error) {
// TODO(tynes): need a function for clearing old, unused storage slots. // TODO(tynes): need a function for clearing old, unused storage slots.
// Each deployed contract on L2 needs to have its existing storage // Each deployed contract on L2 needs to have its existing storage
// inspected and then cleared if they are no longer used. // inspected and then cleared if they are no longer used.
......
...@@ -46,12 +46,14 @@ func TestBuildOptimismGenesis(t *testing.T) { ...@@ -46,12 +46,14 @@ func TestBuildOptimismGenesis(t *testing.T) {
15000000, 15000000,
) )
gen, err := genesis.BuildOptimismGenesis(hh, config, backend) gen, err := genesis.BuildOptimismDeveloperGenesis(hh, config, backend)
require.Nil(t, err) require.Nil(t, err)
require.NotNil(t, gen) require.NotNil(t, gen)
proxyAdmin, err := hh.GetDeployment("ProxyAdmin") proxyAdmin, err := hh.GetDeployment("ProxyAdmin")
require.Nil(t, err) require.Nil(t, err)
proxy, err := hh.GetArtifact("Proxy")
require.Nil(t, err)
for name, address := range predeploys.Predeploys { for name, address := range predeploys.Predeploys {
addr := *address addr := *address
...@@ -67,6 +69,7 @@ func TestBuildOptimismGenesis(t *testing.T) { ...@@ -67,6 +69,7 @@ func TestBuildOptimismGenesis(t *testing.T) {
adminSlot, ok := account.Storage[genesis.AdminSlot] adminSlot, ok := account.Storage[genesis.AdminSlot]
require.Equal(t, ok, true) require.Equal(t, ok, true)
require.Equal(t, adminSlot, proxyAdmin.Address.Hash()) require.Equal(t, adminSlot, proxyAdmin.Address.Hash())
require.Equal(t, account.Code, []byte(proxy.DeployedBytecode))
} }
if writeFile { if writeFile {
......
package genesis
import (
"fmt"
"math/big"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/hardhat"
"github.com/ethereum-optimism/optimism/op-chain-ops/immutables"
"github.com/ethereum-optimism/optimism/op-chain-ops/state"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/vm"
)
// FundDevAccounts will fund each of the development accounts.
func FundDevAccounts(db vm.StateDB) {
for _, account := range DevAccounts {
db.CreateAccount(account)
db.AddBalance(account, devBalance)
}
}
// SetProxies will set each of the proxies in the state. It requires
// a Proxy and ProxyAdmin deployment present so that the Proxy bytecode
// can be set in state and the ProxyAdmin can be set as the admin of the
// Proxy.
func SetProxies(hh *hardhat.Hardhat, db vm.StateDB) error {
proxy, err := hh.GetArtifact("Proxy")
if err != nil {
return err
}
proxyAdmin, err := hh.GetDeployment("ProxyAdmin")
if err != nil {
return err
}
for i := uint64(0); i <= 2048; i++ {
bigAddr := new(big.Int).Or(bigPredeployNamespace, new(big.Int).SetUint64(i))
addr := common.BigToAddress(bigAddr)
// There is no proxy at the governance token address
if addr == predeploys.GovernanceTokenAddr {
continue
}
db.CreateAccount(addr)
db.SetCode(addr, proxy.DeployedBytecode)
db.SetState(addr, AdminSlot, proxyAdmin.Address.Hash())
}
return nil
}
// SetImplementations will set the implmentations of the contracts in the state
// and configure the proxies to point to the implementations. It also sets
// the appropriate storage values for each contract at the proxy address.
func SetImplementations(hh *hardhat.Hardhat, db vm.StateDB, storage StorageConfig) error {
deployResults, err := immutables.BuildOptimism()
if err != nil {
return err
}
for name, address := range predeploys.Predeploys {
// Get the hardhat artifact to access the deployed bytecode
artifact, err := hh.GetArtifact(name)
if err != nil {
return err
}
// Convert the address to the code address
var addr common.Address
switch *address {
case predeploys.GovernanceTokenAddr:
addr = predeploys.GovernanceTokenAddr
case predeploys.LegacyERC20ETHAddr:
addr = predeploys.LegacyERC20ETHAddr
default:
addr, err = AddressToCodeNamespace(*address)
if err != nil {
return err
}
// Set the implmentation slot in the predeploy proxy
db.SetState(*address, ImplementationSlot, addr.Hash())
}
// Create the account
db.CreateAccount(addr)
// Use the genrated bytecode when there are immutables
// otherwise use the artifact deployed bytecode
if bytecode, ok := deployResults[name]; ok {
db.SetCode(addr, bytecode)
} else {
db.SetCode(addr, artifact.DeployedBytecode)
}
// Set the storage values
if storageConfig, ok := storage[name]; ok {
layout, err := hh.GetStorageLayout(name)
if err != nil {
return err
}
slots, err := state.ComputeStorageSlots(layout, storageConfig)
if err != nil {
return err
}
// The storage values must go in the proxy address
for _, slot := range slots {
db.SetState(*address, slot.Key, slot.Value)
}
}
code := db.GetCode(addr)
if len(code) == 0 {
return fmt.Errorf("code not set for %s", name)
}
}
return nil
}
// Get the storage layout of the L2ToL1MessagePasser
// Iterate over the storage layout to know which storage slots to ignore
// Iterate over each storage slot, compute the migration
func MigrateDepositHashes(hh *hardhat.Hardhat, db vm.StateDB) error {
layout, err := hh.GetStorageLayout("L2ToL1MessagePasser")
if err != nil {
return err
}
// Build a list of storage slots to ignore. The values in the
// mapping are guaranteed to not be in this list because they are
// hashes.
ignore := make(map[common.Hash]bool)
for _, entry := range layout.Storage {
encoded, err := state.EncodeUintValue(entry.Slot, 0)
if err != nil {
return err
}
ignore[encoded] = true
}
db.ForEachStorage(predeploys.L2ToL1MessagePasserAddr, func(key, value common.Hash) bool {
if _, ok := ignore[key]; ok {
return true
}
// TODO(tynes): Do the value migration here
return true
})
return nil
}
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
"optimismBaseFeeRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096", "optimismBaseFeeRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"optimismL1FeeRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788", "optimismL1FeeRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"fundDevAccounts": true,
"deploymentWaitConfirmations": 1 "deploymentWaitConfirmations": 1
} }
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
"optimismBaseFeeRecipient": "0xf116a24056b647e3211d095c667e951536cdebaa", "optimismBaseFeeRecipient": "0xf116a24056b647e3211d095c667e951536cdebaa",
"optimismL1FeeRecipient": "0xc731837b696ca3d9720d23336925368ceaa58f83", "optimismL1FeeRecipient": "0xc731837b696ca3d9720d23336925368ceaa58f83",
"fundDevAccounts": true,
"deploymentWaitConfirmations": 1 "deploymentWaitConfirmations": 1
} }
...@@ -17,7 +17,5 @@ ...@@ -17,7 +17,5 @@
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleOwner": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", "l2OutputOracleOwner": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"fundDevAccounts": true,
"deploymentWaitConfirmations": 1 "deploymentWaitConfirmations": 1
} }
...@@ -320,10 +320,6 @@ const config: HardhatUserConfig = { ...@@ -320,10 +320,6 @@ const config: HardhatUserConfig = {
type: 'number', type: 'number',
default: 6, default: 6,
}, },
fundDevAccounts: {
type: 'boolean',
default: false,
},
deploymentWaitConfirmations: { deploymentWaitConfirmations: {
type: 'number', type: 'number',
default: 1, default: 1,
......
...@@ -39,7 +39,6 @@ task('genesis-l1', 'create a genesis config') ...@@ -39,7 +39,6 @@ task('genesis-l1', 'create a genesis config')
} }
} }
if (deployConfig.fundDevAccounts) {
const accounts = [ const accounts = [
'0x14dC79964da2C08b23698B3D3cc7Ca32193d9955', '0x14dC79964da2C08b23698B3D3cc7Ca32193d9955',
'0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65', '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65',
...@@ -70,7 +69,6 @@ task('genesis-l1', 'create a genesis config') ...@@ -70,7 +69,6 @@ task('genesis-l1', 'create a genesis config')
'0x200000000000000000000000000000000000000000000000000000000000000', '0x200000000000000000000000000000000000000000000000000000000000000',
} }
} }
}
const genesis: Genesis = { const genesis: Genesis = {
config: { config: {
......
...@@ -380,7 +380,6 @@ task('genesis-l2', 'create a genesis config') ...@@ -380,7 +380,6 @@ task('genesis-l2', 'create a genesis config')
} }
} }
if (deployConfig.fundDevAccounts) {
const accounts = [ const accounts = [
'0x14dC79964da2C08b23698B3D3cc7Ca32193d9955', '0x14dC79964da2C08b23698B3D3cc7Ca32193d9955',
'0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65', '0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65',
...@@ -411,7 +410,6 @@ task('genesis-l2', 'create a genesis config') ...@@ -411,7 +410,6 @@ task('genesis-l2', 'create a genesis config')
'0x200000000000000000000000000000000000000000000000000000000000000', '0x200000000000000000000000000000000000000000000000000000000000000',
} }
} }
}
// Note: this currently only supports up to 32 byte values. // Note: this currently only supports up to 32 byte values.
// Things less than 32 bytes will be left padded with 0 bytes // Things less than 32 bytes will be left padded with 0 bytes
......
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