From 7a3480c4157abde607921a0475878d35a799f5a2 Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 10:44:13 +0800 Subject: [PATCH 1/9] ADD stateErr on keeper --- x/evm/keeper/keeper.go | 3 + x/evm/keeper/statedb.go | 134 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 135 insertions(+), 2 deletions(-) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 8e08b14367..6bc559a178 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -57,6 +57,9 @@ type Keeper struct { // EVM Hooks for tx post-processing hooks types.EvmHooks + + // error from previous state operation + stateErr error } // NewKeeper generates new evm module keeper diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 7c45097e7e..a6f3ac2a90 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -28,6 +28,10 @@ var _ vm.StateDB = &Keeper{} // this function also resets any preexisting code and storage associated with that // address. func (k *Keeper) CreateAccount(addr common.Address) { + if k.HasStateError() { + return + } + cosmosAddr := sdk.AccAddress(addr.Bytes()) ctx := k.Ctx() account := k.accountKeeper.GetAccount(ctx, cosmosAddr) @@ -57,6 +61,10 @@ func (k *Keeper) CreateAccount(addr common.Address) { // coins and transferring them to the address. The coin denomination is obtained // from the module parameters. func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) { + if k.HasStateError() { + return + } + ctx := k.Ctx() if amount.Sign() != 1 { @@ -86,6 +94,7 @@ func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) { "cosmos-address", cosmosAddr.String(), "error", err, ) + k.stateErr = err return } @@ -96,6 +105,7 @@ func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) { "cosmos-address", cosmosAddr.String(), "error", err, ) + k.stateErr = err return } @@ -111,6 +121,10 @@ func (k *Keeper) AddBalance(addr common.Address, amount *big.Int) { // from the module parameters. This function performs a no-op if the amount is negative // or the user doesn't have enough funds for the transfer. func (k *Keeper) SubBalance(addr common.Address, amount *big.Int) { + if k.HasStateError() { + return + } + ctx := k.Ctx() if amount.Sign() != 1 { @@ -152,6 +166,7 @@ func (k *Keeper) SubBalance(addr common.Address, amount *big.Int) { "cosmos-address", cosmosAddr.String(), "error", err, ) + k.stateErr = err return } @@ -165,6 +180,10 @@ func (k *Keeper) SubBalance(addr common.Address, amount *big.Int) { // GetBalance returns the EVM denomination balance of the provided address. The // denomination is obtained from the module parameters. func (k *Keeper) GetBalance(addr common.Address) *big.Int { + if k.HasStateError() { + return &big.Int{} + } + ctx := k.Ctx() cosmosAddr := sdk.AccAddress(addr.Bytes()) @@ -181,6 +200,10 @@ func (k *Keeper) GetBalance(addr common.Address) *big.Int { // GetNonce retrieves the account with the given address and returns the tx // sequence (i.e nonce). The function performs a no-op if the account is not found. func (k *Keeper) GetNonce(addr common.Address) uint64 { + if k.HasStateError() { + return 0 + } + ctx := k.Ctx() cosmosAddr := sdk.AccAddress(addr.Bytes()) @@ -192,6 +215,7 @@ func (k *Keeper) GetNonce(addr common.Address) uint64 { "cosmos-address", cosmosAddr.String(), "error", err, ) + k.stateErr = err } return nonce @@ -200,6 +224,10 @@ func (k *Keeper) GetNonce(addr common.Address) uint64 { // SetNonce sets the given nonce as the sequence of the address' account. If the // account doesn't exist, a new one will be created from the address. func (k *Keeper) SetNonce(addr common.Address, nonce uint64) { + if k.HasStateError() { + return + } + ctx := k.Ctx() cosmosAddr := sdk.AccAddress(addr.Bytes()) @@ -223,7 +251,7 @@ func (k *Keeper) SetNonce(addr common.Address, nonce uint64) { "nonce", nonce, "error", err, ) - + k.stateErr = err return } @@ -244,6 +272,10 @@ func (k *Keeper) SetNonce(addr common.Address, nonce uint64) { // GetCodeHash fetches the account from the store and returns its code hash. If the account doesn't // exist or is not an EthAccount type, GetCodeHash returns the empty code hash value. func (k *Keeper) GetCodeHash(addr common.Address) common.Hash { + if k.HasStateError() { + return common.Hash{} + } + ctx := k.Ctx() cosmosAddr := sdk.AccAddress(addr.Bytes()) @@ -263,6 +295,10 @@ func (k *Keeper) GetCodeHash(addr common.Address) common.Hash { // GetCode returns the code byte array associated with the given address. // If the code hash from the account is empty, this function returns nil. func (k *Keeper) GetCode(addr common.Address) []byte { + if k.HasStateError() { + return []byte{} + } + ctx := k.Ctx() hash := k.GetCodeHash(addr) @@ -287,6 +323,10 @@ func (k *Keeper) GetCode(addr common.Address) []byte { // SetCode stores the code byte array to the application KVStore and sets the // code hash to the given account. The code is deleted from the store if it is empty. func (k *Keeper) SetCode(addr common.Address, code []byte) { + if k.HasStateError() { + return + } + ctx := k.Ctx() if bytes.Equal(code, types.EmptyCodeHash) { @@ -308,6 +348,7 @@ func (k *Keeper) SetCode(addr common.Address, code []byte) { "ethereum-address", addr.Hex(), "code-hash", hash.Hex(), ) + k.stateErr = fmt.Errorf("invalid account type, ethereum-address %v, code-hash %v", addr.Hex(), hash.Hex()) return } @@ -336,6 +377,10 @@ func (k *Keeper) SetCode(addr common.Address, code []byte) { // GetCodeSize returns the size of the contract code associated with this object, // or zero if none. func (k *Keeper) GetCodeSize(addr common.Address) int { + if k.HasStateError() { + return 0 + } + code := k.GetCode(addr) return len(code) } @@ -351,6 +396,10 @@ func (k *Keeper) GetCodeSize(addr common.Address) int { // AddRefund adds the given amount of gas to the refund transient value. func (k *Keeper) AddRefund(gas uint64) { + if k.HasStateError() { + return + } + ctx := k.Ctx() refund := k.GetRefund() @@ -363,6 +412,10 @@ func (k *Keeper) AddRefund(gas uint64) { // SubRefund subtracts the given amount of gas from the transient refund value. This function // will panic if gas amount is greater than the stored refund. func (k *Keeper) SubRefund(gas uint64) { + if k.HasStateError() { + return + } + ctx := k.Ctx() refund := k.GetRefund() @@ -380,6 +433,10 @@ func (k *Keeper) SubRefund(gas uint64) { // GetRefund returns the amount of gas available for return after the tx execution // finalizes. This value is reset to 0 on every transaction. func (k *Keeper) GetRefund() uint64 { + if k.HasStateError() { + return 0 + } + ctx := k.Ctx() store := ctx.TransientStore(k.transientKey) @@ -410,12 +467,20 @@ func doGetState(ctx sdk.Context, storeKey sdk.StoreKey, addr common.Address, has // GetCommittedState returns the value set in store for the given key hash. If the key is not registered // this function returns the empty hash. func (k *Keeper) GetCommittedState(addr common.Address, hash common.Hash) common.Hash { + if k.HasStateError() { + return common.Hash{} + } + return doGetState(k.ctxStack.initialCtx, k.storeKey, addr, hash) } // GetState returns the committed state for the given key hash, as all changes are committed directly // to the KVStore. func (k *Keeper) GetState(addr common.Address, hash common.Hash) common.Hash { + if k.HasStateError() { + return common.Hash{} + } + ctx := k.Ctx() return doGetState(ctx, k.storeKey, addr, hash) } @@ -423,6 +488,10 @@ func (k *Keeper) GetState(addr common.Address, hash common.Hash) common.Hash { // SetState sets the given hashes (key, value) to the KVStore. If the value hash is empty, this // function deletes the key from the store. func (k *Keeper) SetState(addr common.Address, key, value common.Hash) { + if k.HasStateError() { + return + } + ctx := k.Ctx() store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr)) key = types.KeyAddressStorage(addr, key) @@ -449,6 +518,10 @@ func (k *Keeper) SetState(addr common.Address, key, value common.Hash) { // Suicide marks the given account as suicided and clears the account balance of // the EVM tokens. func (k *Keeper) Suicide(addr common.Address) bool { + if k.HasStateError() { + return false + } + ctx := k.Ctx() prev := k.HasSuicided(addr) @@ -466,7 +539,7 @@ func (k *Keeper) Suicide(addr common.Address) bool { "cosmos-address", cosmosAddr.String(), "error", err, ) - + k.stateErr = err return false } @@ -492,6 +565,10 @@ func (k Keeper) setSuicided(ctx sdk.Context, addr common.Address) { // current block. Accounts that are suicided will be returned as non-nil during queries and "cleared" // after the block has been committed. func (k *Keeper) HasSuicided(addr common.Address) bool { + if k.HasStateError() { + return false + } + ctx := k.Ctx() store := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientSuicided) return store.Has(addr.Bytes()) @@ -504,6 +581,10 @@ func (k *Keeper) HasSuicided(addr common.Address) bool { // Exist returns true if the given account exists in store or if it has been // marked as suicided in the transient store. func (k *Keeper) Exist(addr common.Address) bool { + if k.HasStateError() { + return false + } + ctx := k.Ctx() // return true if the account has suicided if k.HasSuicided(addr) { @@ -522,6 +603,10 @@ func (k *Keeper) Exist(addr common.Address) bool { // // Non-ethereum accounts are considered not empty func (k *Keeper) Empty(addr common.Address) bool { + if k.HasStateError() { + return true + } + ctx := k.Ctx() nonce := uint64(0) codeHash := types.EmptyCodeHash @@ -560,6 +645,10 @@ func (k *Keeper) Empty(addr common.Address) bool { // // This method should only be called if Yolov3/Berlin/2929+2930 is applicable at the current number. func (k *Keeper) PrepareAccessList(sender common.Address, dest *common.Address, precompiles []common.Address, txAccesses ethtypes.AccessList) { + if k.HasStateError() { + return + } + k.AddAddressToAccessList(sender) if dest != nil { k.AddAddressToAccessList(*dest) @@ -578,6 +667,10 @@ func (k *Keeper) PrepareAccessList(sender common.Address, dest *common.Address, // AddressInAccessList returns true if the address is registered on the transient store. func (k *Keeper) AddressInAccessList(addr common.Address) bool { + if k.HasStateError() { + return false + } + ctx := k.Ctx() ts := prefix.NewStore(ctx.TransientStore(k.transientKey), types.KeyPrefixTransientAccessListAddress) return ts.Has(addr.Bytes()) @@ -585,6 +678,10 @@ func (k *Keeper) AddressInAccessList(addr common.Address) bool { // SlotInAccessList checks if the address and the slots are registered in the transient store func (k *Keeper) SlotInAccessList(addr common.Address, slot common.Hash) (addressOk, slotOk bool) { + if k.HasStateError() { + return false, false + } + addressOk = k.AddressInAccessList(addr) slotOk = k.addressSlotInAccessList(addr, slot) return addressOk, slotOk @@ -601,6 +698,10 @@ func (k *Keeper) addressSlotInAccessList(addr common.Address, slot common.Hash) // AddAddressToAccessList adds the given address to the access list. If the address is already // in the access list, this function performs a no-op. func (k *Keeper) AddAddressToAccessList(addr common.Address) { + if k.HasStateError() { + return + } + if k.AddressInAccessList(addr) { return } @@ -613,6 +714,10 @@ func (k *Keeper) AddAddressToAccessList(addr common.Address) { // AddSlotToAccessList adds the given (address, slot) to the access list. If the address and slot are // already in the access list, this function performs a no-op. func (k *Keeper) AddSlotToAccessList(addr common.Address, slot common.Hash) { + if k.HasStateError() { + return + } + k.AddAddressToAccessList(addr) if k.addressSlotInAccessList(addr, slot) { return @@ -630,11 +735,19 @@ func (k *Keeper) AddSlotToAccessList(addr common.Address, slot common.Hash) { // Snapshot return the index in the cached context stack func (k *Keeper) Snapshot() int { + if k.HasStateError() { + return -1 + } + return k.ctxStack.Snapshot() } // RevertToSnapshot pop all the cached contexts after(including) the snapshot func (k *Keeper) RevertToSnapshot(target int) { + if k.HasStateError() { + return + } + k.ctxStack.RevertToSnapshot(target) } @@ -646,6 +759,10 @@ func (k *Keeper) RevertToSnapshot(target int) { // context. This function also fills in the tx hash, block hash, tx index and log index fields before setting the log // to store. func (k *Keeper) AddLog(log *ethtypes.Log) { + if k.HasStateError() { + return + } + ctx := k.Ctx() log.BlockHash = common.BytesToHash(ctx.HeaderHash()) @@ -679,6 +796,10 @@ func (k *Keeper) AddPreimage(_ common.Hash, _ []byte) {} // ForEachStorage uses the store iterator to iterate over all the state keys and perform a callback // function on each of them. func (k *Keeper) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error { + if k.HasStateError() { + return k.stateErr + } + ctx := k.Ctx() store := ctx.KVStore(k.storeKey) prefix := types.AddressStoragePrefix(addr) @@ -700,3 +821,12 @@ func (k *Keeper) ForEachStorage(addr common.Address, cb func(key, value common.H return nil } + +// HasStateError return the previous error for any state operations +func (k *Keeper) HasStateError() bool { + return k.stateErr != nil +} + +func (k *Keeper) ClearStateError() { + k.stateErr = nil +} From 6856500483e8a466b9dc6293065d9a7854eb5f5b Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 10:49:55 +0800 Subject: [PATCH 2/9] UPDATE init stateErr --- x/evm/keeper/keeper.go | 1 + 1 file changed, 1 insertion(+) diff --git a/x/evm/keeper/keeper.go b/x/evm/keeper/keeper.go index 6bc559a178..a437be653d 100644 --- a/x/evm/keeper/keeper.go +++ b/x/evm/keeper/keeper.go @@ -90,6 +90,7 @@ func NewKeeper( transientKey: transientKey, tracer: tracer, debug: debug, + stateErr: nil, } } From 1c538d571196282c653c670287bff9a914f79a16 Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 11:47:29 +0800 Subject: [PATCH 3/9] UPDATE test case --- x/evm/keeper/statedb.go | 3 +-- x/evm/keeper/statedb_test.go | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index a6f3ac2a90..47fcd0ae42 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -215,7 +215,6 @@ func (k *Keeper) GetNonce(addr common.Address) uint64 { "cosmos-address", cosmosAddr.String(), "error", err, ) - k.stateErr = err } return nonce @@ -296,7 +295,7 @@ func (k *Keeper) GetCodeHash(addr common.Address) common.Hash { // If the code hash from the account is empty, this function returns nil. func (k *Keeper) GetCode(addr common.Address) []byte { if k.HasStateError() { - return []byte{} + return nil } ctx := k.Ctx() diff --git a/x/evm/keeper/statedb_test.go b/x/evm/keeper/statedb_test.go index e711f91882..f25bc59bd7 100644 --- a/x/evm/keeper/statedb_test.go +++ b/x/evm/keeper/statedb_test.go @@ -305,6 +305,8 @@ func (suite *KeeperTestSuite) TestSetCode() { } suite.Require().Equal(len(post), suite.app.EvmKeeper.GetCodeSize(tc.address)) + + suite.app.EvmKeeper.ClearStateError() }) } } From fa2dcde81e354c9a877af40fdeeacd17782c506d Mon Sep 17 00:00:00 2001 From: davcrypto <88310031+davcrypto@users.noreply.github.com> Date: Thu, 16 Sep 2021 15:35:10 +0800 Subject: [PATCH 4/9] Update x/evm/keeper/statedb.go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> --- x/evm/keeper/statedb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 7945567f41..8032eb79fe 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -181,7 +181,7 @@ func (k *Keeper) SubBalance(addr common.Address, amount *big.Int) { // denomination is obtained from the module parameters. func (k *Keeper) GetBalance(addr common.Address) *big.Int { if k.HasStateError() { - return &big.Int{} + return big.NewInt(0) } ctx := k.Ctx() From 644fa4880f7948a2f2b50d009de0db24e74d4241 Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 16:09:31 +0800 Subject: [PATCH 5/9] ADD comment --- CHANGELOG.md | 1 + x/evm/keeper/statedb.go | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 852335f393..f890804a6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Improvements * (evm) [tharsis#461](https://github.com/tharsis/ethermint/pull/461) Increase performance of `StateDB` transaction log storage (r/w). +* (evm) [tharsis#566](https://github.com/tharsis/ethermint/pull/566) Introduce `stateErr` store in `StateDB` to avoid meaningless operations if any error happened before ## [v0.5.0] - 2021-08-20 diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 8032eb79fe..1a94f6697b 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -735,7 +735,7 @@ func (k *Keeper) AddSlotToAccessList(addr common.Address, slot common.Hash) { // Snapshot return the index in the cached context stack func (k *Keeper) Snapshot() int { if k.HasStateError() { - return -1 + return 0 } return k.ctxStack.Snapshot() @@ -826,6 +826,7 @@ func (k *Keeper) HasStateError() bool { return k.stateErr != nil } +// ClearStateError reset the previous state operation error to nil func (k *Keeper) ClearStateError() { k.stateErr = nil } From e9533c97f42b832318ac0a1480ecca33e938e4aa Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 16:58:20 +0800 Subject: [PATCH 6/9] UPDATE clear evm state error --- x/evm/keeper/state_transition.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index 7f2a2139fb..c8d9ec5ef4 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -133,6 +133,8 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT ctx := k.Ctx() params := k.GetParams(ctx) + defer k.ClearStateError() + // return error if contract creation or call are disabled through governance if !params.EnableCreate && tx.To() == nil { return nil, stacktrace.Propagate(types.ErrCreateDisabled, "failed to create new contract") @@ -248,6 +250,8 @@ func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message, cfg *params.ChainCo vmErr error // vm errors do not effect consensus and are therefore not assigned to err ) + defer k.ClearStateError() + sender := vm.AccountRef(msg.From()) contractCreation := msg.To() == nil @@ -390,6 +394,8 @@ func (k *Keeper) resetGasMeterAndConsumeGas(gasUsed uint64) { // GetCoinbaseAddress returns the block proposer's validator operator address. func (k Keeper) GetCoinbaseAddress(ctx sdk.Context) (common.Address, error) { + defer k.ClearStateError() + consAddr := sdk.ConsAddress(ctx.BlockHeader().ProposerAddress) validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr) if !found { From b7d6637df484ef762132453a189b384ab83df136 Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 17:03:31 +0800 Subject: [PATCH 7/9] REMOVE unnecessary clear --- x/evm/keeper/state_transition.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index c8d9ec5ef4..0971dcde03 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -394,8 +394,6 @@ func (k *Keeper) resetGasMeterAndConsumeGas(gasUsed uint64) { // GetCoinbaseAddress returns the block proposer's validator operator address. func (k Keeper) GetCoinbaseAddress(ctx sdk.Context) (common.Address, error) { - defer k.ClearStateError() - consAddr := sdk.ConsAddress(ctx.BlockHeader().ProposerAddress) validator, found := k.stakingKeeper.GetValidatorByConsAddr(ctx, consAddr) if !found { From 521acec15d630c744513ca0f8de530625f9fb759 Mon Sep 17 00:00:00 2001 From: davidso Date: Thu, 16 Sep 2021 17:09:13 +0800 Subject: [PATCH 8/9] ADD comment --- x/evm/keeper/state_transition.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x/evm/keeper/state_transition.go b/x/evm/keeper/state_transition.go index 0971dcde03..be77ad58b2 100644 --- a/x/evm/keeper/state_transition.go +++ b/x/evm/keeper/state_transition.go @@ -133,6 +133,7 @@ func (k *Keeper) ApplyTransaction(tx *ethtypes.Transaction) (*types.MsgEthereumT ctx := k.Ctx() params := k.GetParams(ctx) + // ensure keeper state error is cleared defer k.ClearStateError() // return error if contract creation or call are disabled through governance @@ -250,6 +251,7 @@ func (k *Keeper) ApplyMessage(evm *vm.EVM, msg core.Message, cfg *params.ChainCo vmErr error // vm errors do not effect consensus and are therefore not assigned to err ) + // ensure keeper state error is cleared defer k.ClearStateError() sender := vm.AccountRef(msg.From()) From 6e05382a7150436a3f67f4eb680940c618118f8d Mon Sep 17 00:00:00 2001 From: davidso Date: Fri, 17 Sep 2021 09:12:19 +0800 Subject: [PATCH 9/9] UPDATE false value --- x/evm/keeper/statedb.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go index 1a94f6697b..7b3ad72461 100644 --- a/x/evm/keeper/statedb.go +++ b/x/evm/keeper/statedb.go @@ -215,6 +215,9 @@ func (k *Keeper) GetNonce(addr common.Address) uint64 { "cosmos-address", cosmosAddr.String(), "error", err, ) + // since adding state error here will break some logic in the go-ethereum (unwanted panic), no + // state error will be store here + // Refer panic: https://github.com/ethereum/go-ethereum/blob/991384a7f6719e1125ca0be7fb27d0c4d1c5d2d3/core/vm/operations_acl.go#L66 } return nonce @@ -603,7 +606,7 @@ func (k *Keeper) Exist(addr common.Address) bool { // Non-ethereum accounts are considered not empty func (k *Keeper) Empty(addr common.Address) bool { if k.HasStateError() { - return true + return false } ctx := k.Ctx()