evm: balance and nonce invariants (#661)
* evm: balance and nonce invariants * nonce invariant * changelog * use iterator on export
This commit is contained in:
parent
6001baed80
commit
a1386eec09
@ -37,13 +37,19 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
## Unreleased
|
||||
|
||||
### API Breaking
|
||||
|
||||
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) `Balance` field has been removed from the evm module's `GenesisState`.
|
||||
|
||||
### Improvements
|
||||
|
||||
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Add invariant check for account balance and account nonce.
|
||||
* (deps) [\#654](https://github.com/cosmos/ethermint/pull/654) Bump go-ethereum version to [v1.9.25](https://github.com/ethereum/go-ethereum/releases/tag/v1.9.25)
|
||||
* (evm) [\#627](https://github.com/cosmos/ethermint/issues/627) Add extra EIPs parameter to apply custom EVM jump tables.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* (evm) [\#661](https://github.com/cosmos/ethermint/pull/661) Set nonce to the EVM account on genesis initialization.
|
||||
* (evm) [\#621](https://github.com/cosmos/ethermint/issues/621) EVM `GenesisAccount` fields now share the same format as the auth module `Account`.
|
||||
* (evm) [\#618](https://github.com/cosmos/ethermint/issues/618) Add missing EVM `Context` `GetHash` field that retrieves a the header hash from a given block height.
|
||||
* (app) [\#617](https://github.com/cosmos/ethermint/issues/617) Fix genesis export functionality.
|
||||
|
@ -280,7 +280,7 @@ func NewEthermintApp(
|
||||
app.mm.SetOrderInitGenesis(
|
||||
auth.ModuleName, distr.ModuleName, staking.ModuleName, bank.ModuleName,
|
||||
slashing.ModuleName, gov.ModuleName, mint.ModuleName, supply.ModuleName,
|
||||
crisis.ModuleName, genutil.ModuleName, evidence.ModuleName, evm.ModuleName,
|
||||
evm.ModuleName, crisis.ModuleName, genutil.ModuleName, evidence.ModuleName,
|
||||
faucet.ModuleName,
|
||||
)
|
||||
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
@ -20,7 +21,6 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
|
||||
for _, account := range data.Accounts {
|
||||
address := ethcmn.HexToAddress(account.Address)
|
||||
accAddress := sdk.AccAddress(address.Bytes())
|
||||
|
||||
// check that the EVM balance the matches the account balance
|
||||
acc := accountKeeper.GetAccount(ctx, accAddress)
|
||||
if acc == nil {
|
||||
@ -37,17 +37,11 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
|
||||
}
|
||||
|
||||
evmBalance := acc.GetCoins().AmountOf(evmDenom)
|
||||
if !evmBalance.Equal(account.Balance) {
|
||||
panic(
|
||||
fmt.Errorf(
|
||||
"balance mismatch for account %s, expected %s%s, got %s%s",
|
||||
account.Address, evmBalance, evmDenom, account.Balance, evmDenom,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
k.SetBalance(ctx, address, account.Balance.BigInt())
|
||||
k.SetNonce(ctx, address, acc.GetSequence())
|
||||
k.SetBalance(ctx, address, evmBalance.BigInt())
|
||||
k.SetCode(ctx, address, account.Code)
|
||||
|
||||
for _, storage := range account.Storage {
|
||||
k.SetState(ctx, address, storage.Key, storage.Value)
|
||||
}
|
||||
@ -83,12 +77,11 @@ func InitGenesis(ctx sdk.Context, k Keeper, accountKeeper types.AccountKeeper, d
|
||||
func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisState {
|
||||
// nolint: prealloc
|
||||
var ethGenAccounts []types.GenesisAccount
|
||||
accounts := ak.GetAllAccounts(ctx)
|
||||
|
||||
for _, account := range accounts {
|
||||
ak.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
continue
|
||||
// ignore non EthAccounts
|
||||
return false
|
||||
}
|
||||
|
||||
addr := ethAccount.EthAddress()
|
||||
@ -98,18 +91,15 @@ func ExportGenesis(ctx sdk.Context, k Keeper, ak types.AccountKeeper) GenesisSta
|
||||
panic(err)
|
||||
}
|
||||
|
||||
balanceInt := k.GetBalance(ctx, addr)
|
||||
balance := sdk.NewIntFromBigInt(balanceInt)
|
||||
|
||||
genAccount := types.GenesisAccount{
|
||||
Address: addr.String(),
|
||||
Balance: balance,
|
||||
Code: k.GetCode(ctx, addr),
|
||||
Storage: storage,
|
||||
}
|
||||
|
||||
ethGenAccounts = append(ethGenAccounts, genAccount)
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
config, _ := k.GetChainConfig(ctx)
|
||||
|
||||
|
@ -54,7 +54,6 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
Accounts: []types.GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.OneInt(),
|
||||
Storage: types.Storage{
|
||||
{Key: common.BytesToHash([]byte("key")), Value: common.BytesToHash([]byte("value"))},
|
||||
},
|
||||
@ -87,25 +86,6 @@ func (suite *EvmTestSuite) TestInitGenesis() {
|
||||
Accounts: []types.GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.OneInt(),
|
||||
},
|
||||
},
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"balance mismatch",
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
},
|
||||
types.GenesisState{
|
||||
Params: types.DefaultParams(),
|
||||
Accounts: []types.GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.OneInt(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
100
x/evm/keeper/invariants.go
Normal file
100
x/evm/keeper/invariants.go
Normal file
@ -0,0 +1,100 @@
|
||||
package keeper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authexported "github.com/cosmos/cosmos-sdk/x/auth/exported"
|
||||
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
"github.com/cosmos/ethermint/x/evm/types"
|
||||
)
|
||||
|
||||
const (
|
||||
balanceInvariant = "balance"
|
||||
nonceInvariant = "nonce"
|
||||
)
|
||||
|
||||
// RegisterInvariants registers the evm module invariants
|
||||
func RegisterInvariants(ir sdk.InvariantRegistry, k Keeper) {
|
||||
ir.RegisterRoute(types.ModuleName, balanceInvariant, k.BalanceInvariant())
|
||||
ir.RegisterRoute(types.ModuleName, nonceInvariant, k.NonceInvariant())
|
||||
}
|
||||
|
||||
// BalanceInvariant checks that all auth module's EthAccounts in the application have the same balance
|
||||
// as the EVM one.
|
||||
func (k Keeper) BalanceInvariant() sdk.Invariant {
|
||||
return func(ctx sdk.Context) (string, bool) {
|
||||
var (
|
||||
msg string
|
||||
count int
|
||||
)
|
||||
|
||||
k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
// ignore non EthAccounts
|
||||
return false
|
||||
}
|
||||
|
||||
evmDenom := k.GetParams(ctx).EvmDenom
|
||||
accountBalance := ethAccount.GetCoins().AmountOf(evmDenom)
|
||||
evmBalance := k.GetBalance(ctx, ethAccount.EthAddress())
|
||||
|
||||
if evmBalance.Cmp(accountBalance.BigInt()) != 0 {
|
||||
count++
|
||||
msg += fmt.Sprintf(
|
||||
"\tbalance mismatch for address %s: account balance %s, evm balance %s\n",
|
||||
account.GetAddress(), accountBalance.String(), evmBalance.String(),
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
broken := count != 0
|
||||
|
||||
return sdk.FormatInvariant(
|
||||
types.ModuleName, balanceInvariant,
|
||||
fmt.Sprintf("account balances mismatches found %d\n%s", count, msg),
|
||||
), broken
|
||||
}
|
||||
}
|
||||
|
||||
// NonceInvariant checks that all auth module's EthAccounts in the application have the same nonce
|
||||
// sequence as the EVM.
|
||||
func (k Keeper) NonceInvariant() sdk.Invariant {
|
||||
return func(ctx sdk.Context) (string, bool) {
|
||||
var (
|
||||
msg string
|
||||
count int
|
||||
)
|
||||
|
||||
k.accountKeeper.IterateAccounts(ctx, func(account authexported.Account) bool {
|
||||
ethAccount, ok := account.(*ethermint.EthAccount)
|
||||
if !ok {
|
||||
// ignore non EthAccounts
|
||||
return false
|
||||
}
|
||||
|
||||
evmNonce := k.GetNonce(ctx, ethAccount.EthAddress())
|
||||
|
||||
if evmNonce != ethAccount.Sequence {
|
||||
count++
|
||||
msg += fmt.Sprintf(
|
||||
"\nonce mismatch for address %s: account nonce %d, evm nonce %d\n",
|
||||
account.GetAddress(), ethAccount.Sequence, evmNonce,
|
||||
)
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
broken := count != 0
|
||||
|
||||
return sdk.FormatInvariant(
|
||||
types.ModuleName, nonceInvariant,
|
||||
fmt.Sprintf("account nonces mismatches found %d\n%s", count, msg),
|
||||
), broken
|
||||
}
|
||||
}
|
139
x/evm/keeper/invariants_test.go
Normal file
139
x/evm/keeper/invariants_test.go
Normal file
@ -0,0 +1,139 @@
|
||||
package keeper_test
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
ethermint "github.com/cosmos/ethermint/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func (suite *KeeperTestSuite) TestBalanceInvariant() {
|
||||
privkey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
address := ethcmn.HexToAddress(privkey.PubKey().Address().String())
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expBroken bool
|
||||
}{
|
||||
{
|
||||
"balance mismatch",
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(1000))
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"balance ok",
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetCoins(sdk.NewCoins(ethermint.NewPhotonCoinInt64(1)))
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.EvmKeeper.SetBalance(suite.ctx, address, big.NewInt(1))
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid account type",
|
||||
func() {
|
||||
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset values
|
||||
|
||||
tc.malleate()
|
||||
|
||||
_, broken := suite.app.EvmKeeper.BalanceInvariant()(suite.ctx)
|
||||
if tc.expBroken {
|
||||
suite.Require().True(broken)
|
||||
} else {
|
||||
suite.Require().False(broken)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (suite *KeeperTestSuite) TestNonceInvariant() {
|
||||
privkey, err := ethsecp256k1.GenerateKey()
|
||||
suite.Require().NoError(err)
|
||||
|
||||
address := ethcmn.HexToAddress(privkey.PubKey().Address().String())
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
malleate func()
|
||||
expBroken bool
|
||||
}{
|
||||
{
|
||||
"nonce mismatch",
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetSequence(1)
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.EvmKeeper.SetNonce(suite.ctx, address, 100)
|
||||
},
|
||||
true,
|
||||
},
|
||||
{
|
||||
"nonce ok",
|
||||
func() {
|
||||
acc := suite.app.AccountKeeper.NewAccountWithAddress(suite.ctx, address.Bytes())
|
||||
suite.Require().NotNil(acc)
|
||||
err := acc.SetSequence(1)
|
||||
suite.Require().NoError(err)
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, acc)
|
||||
|
||||
suite.app.EvmKeeper.SetNonce(suite.ctx, address, 1)
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"invalid account type",
|
||||
func() {
|
||||
acc := authtypes.NewBaseAccountWithAddress(address.Bytes())
|
||||
suite.app.AccountKeeper.SetAccount(suite.ctx, &acc)
|
||||
},
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
suite.Run(tc.name, func() {
|
||||
suite.SetupTest() // reset values
|
||||
|
||||
tc.malleate()
|
||||
|
||||
_, broken := suite.app.EvmKeeper.NonceInvariant()(suite.ctx)
|
||||
if tc.expBroken {
|
||||
suite.Require().True(broken)
|
||||
} else {
|
||||
suite.Require().False(broken)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -30,6 +30,8 @@ type Keeper struct {
|
||||
// - storing block height -> bloom filter map. Needed for the Web3 API.
|
||||
// - storing block hash -> block height map. Needed for the Web3 API.
|
||||
storeKey sdk.StoreKey
|
||||
// Account Keeper for fetching accounts
|
||||
accountKeeper types.AccountKeeper
|
||||
// Ethermint concrete implementation on the EVM StateDB interface
|
||||
CommitStateDB *types.CommitStateDB
|
||||
// Transaction counter in a block. Used on StateSB's Prepare function.
|
||||
@ -52,6 +54,7 @@ func NewKeeper(
|
||||
return Keeper{
|
||||
cdc: cdc,
|
||||
storeKey: storeKey,
|
||||
accountKeeper: ak,
|
||||
CommitStateDB: types.NewCommitStateDB(sdk.Context{}, storeKey, paramSpace, ak),
|
||||
TxCount: 0,
|
||||
Bloom: big.NewInt(0),
|
||||
|
@ -197,12 +197,8 @@ func queryExportAccount(ctx sdk.Context, path []string, keeper Keeper) ([]byte,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
balanceInt := keeper.GetBalance(ctx, addr)
|
||||
balance := sdk.NewIntFromBigInt(balanceInt)
|
||||
|
||||
res := types.GenesisAccount{
|
||||
Address: hexAddress,
|
||||
Balance: balance,
|
||||
Code: keeper.GetCode(ctx, addr),
|
||||
Storage: storage,
|
||||
}
|
||||
|
@ -88,7 +88,9 @@ func (AppModule) Name() string {
|
||||
}
|
||||
|
||||
// RegisterInvariants interface for registering invariants
|
||||
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {}
|
||||
func (am AppModule) RegisterInvariants(ir sdk.InvariantRegistry) {
|
||||
keeper.RegisterInvariants(ir, am.keeper)
|
||||
}
|
||||
|
||||
// Route specifies path for transactions
|
||||
func (am AppModule) Route() string {
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
type AccountKeeper interface {
|
||||
NewAccountWithAddress(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
||||
GetAllAccounts(ctx sdk.Context) (accounts []authexported.Account)
|
||||
IterateAccounts(ctx sdk.Context, cb func(account authexported.Account) bool)
|
||||
GetAccount(ctx sdk.Context, addr sdk.AccAddress) authexported.Account
|
||||
SetAccount(ctx sdk.Context, account authexported.Account)
|
||||
RemoveAccount(ctx sdk.Context, account authexported.Account)
|
||||
|
@ -4,8 +4,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
ethcmn "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
)
|
||||
@ -22,9 +20,9 @@ type (
|
||||
// GenesisAccount defines an account to be initialized in the genesis state.
|
||||
// Its main difference between with Geth's GenesisAccount is that it uses a custom
|
||||
// storage type and that it doesn't contain the private key field.
|
||||
// NOTE: balance is omitted as it is imported from the auth account balance.
|
||||
GenesisAccount struct {
|
||||
Address string `json:"address"`
|
||||
Balance sdk.Int `json:"balance"`
|
||||
Code hexutil.Bytes `json:"code,omitempty"`
|
||||
Storage Storage `json:"storage,omitempty"`
|
||||
}
|
||||
@ -35,12 +33,6 @@ func (ga GenesisAccount) Validate() error {
|
||||
if ga.Address == (ethcmn.Address{}.String()) {
|
||||
return fmt.Errorf("address cannot be the zero address %s", ga.Address)
|
||||
}
|
||||
if ga.Balance.IsNil() {
|
||||
return errors.New("balance cannot be nil")
|
||||
}
|
||||
if ga.Balance.IsNegative() {
|
||||
return errors.New("balance cannot be negative")
|
||||
}
|
||||
if ga.Code != nil && len(ga.Code) == 0 {
|
||||
return errors.New("code bytes cannot be empty")
|
||||
}
|
||||
|
@ -9,8 +9,6 @@ import (
|
||||
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto/ethsecp256k1"
|
||||
)
|
||||
|
||||
@ -26,7 +24,6 @@ func TestValidateGenesisAccount(t *testing.T) {
|
||||
"valid genesis account",
|
||||
GenesisAccount{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{1, 2, 3},
|
||||
Storage: Storage{
|
||||
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
||||
@ -38,23 +35,6 @@ func TestValidateGenesisAccount(t *testing.T) {
|
||||
"empty account address bytes",
|
||||
GenesisAccount{
|
||||
Address: ethcmn.Address{}.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil account balance",
|
||||
GenesisAccount{
|
||||
Address: address.String(),
|
||||
Balance: sdk.Int{},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nil account balance",
|
||||
GenesisAccount{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(-1),
|
||||
},
|
||||
false,
|
||||
},
|
||||
@ -62,7 +42,6 @@ func TestValidateGenesisAccount(t *testing.T) {
|
||||
"empty code bytes",
|
||||
GenesisAccount{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{},
|
||||
},
|
||||
false,
|
||||
@ -101,7 +80,6 @@ func TestValidateGenesis(t *testing.T) {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{1, 2, 3},
|
||||
Storage: Storage{
|
||||
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
||||
@ -153,7 +131,6 @@ func TestValidateGenesis(t *testing.T) {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{1, 2, 3},
|
||||
Storage: Storage{
|
||||
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
||||
@ -161,7 +138,6 @@ func TestValidateGenesis(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{1, 2, 3},
|
||||
Storage: Storage{
|
||||
NewState(ethcmn.BytesToHash([]byte{1, 2, 3}), ethcmn.BytesToHash([]byte{1, 2, 3})),
|
||||
@ -177,7 +153,6 @@ func TestValidateGenesis(t *testing.T) {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{1, 2, 3},
|
||||
Storage: Storage{
|
||||
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
||||
@ -227,7 +202,6 @@ func TestValidateGenesis(t *testing.T) {
|
||||
Accounts: []GenesisAccount{
|
||||
{
|
||||
Address: address.String(),
|
||||
Balance: sdk.NewInt(1),
|
||||
Code: []byte{1, 2, 3},
|
||||
Storage: Storage{
|
||||
{Key: ethcmn.BytesToHash([]byte{1, 2, 3})},
|
||||
|
Loading…
Reference in New Issue
Block a user