From 210d5222d7fd6e9637a1c870305c7426654131fe Mon Sep 17 00:00:00 2001 From: yihuang Date: Wed, 20 Aug 2025 12:58:49 +0800 Subject: [PATCH] Problem: no efficient GetStorageRoot impl in cosmos/evm Solution: - create a new method IsStorageEmpty to use in core evm --- core/state/statedb.go | 6 ++++++ core/state/statedb_hooked.go | 4 ++++ core/vm/evm.go | 4 ++-- core/vm/interface.go | 1 + 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 7aa6780cfa2..e34dd5906be 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -335,6 +335,12 @@ func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash { return common.Hash{} } +// IsStorageEmpty returns if the contract storage is empty +func (s *StateDB) IsStorageEmpty(addr common.Address) bool { + storageRoot := s.GetStorageRoot(addr) + return storageRoot == (common.Hash{}) || storageRoot == types.EmptyRootHash +} + // TxIndex returns the current transaction index set by SetTxContext. func (s *StateDB) TxIndex() int { return s.txIndex diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go index 3d1ef150318..f5c2eab13f5 100644 --- a/core/state/statedb_hooked.go +++ b/core/state/statedb_hooked.go @@ -97,6 +97,10 @@ func (s *hookedStateDB) GetStorageRoot(addr common.Address) common.Hash { return s.inner.GetStorageRoot(addr) } +func (s *hookedStateDB) IsStorageEmpty(addr common.Address) bool { + return s.inner.IsStorageEmpty(addr) +} + func (s *hookedStateDB) GetTransientState(addr common.Address, key common.Hash) common.Hash { return s.inner.GetTransientState(addr, key) } diff --git a/core/vm/evm.go b/core/vm/evm.go index b91254f9fed..c283c041e97 100644 --- a/core/vm/evm.go +++ b/core/vm/evm.go @@ -499,10 +499,10 @@ func (evm *EVM) create(caller common.Address, code []byte, gas uint64, value *ui // - the code is non-empty // - the storage is non-empty contractHash := evm.StateDB.GetCodeHash(address) - storageRoot := evm.StateDB.GetStorageRoot(address) + isStorageEmpty := evm.StateDB.IsStorageEmpty(address) if evm.StateDB.GetNonce(address) != 0 || (contractHash != (common.Hash{}) && contractHash != types.EmptyCodeHash) || // non-empty code - (storageRoot != (common.Hash{}) && storageRoot != types.EmptyRootHash) { // non-empty storage + !isStorageEmpty { // non-empty storage if evm.Config.Tracer != nil && evm.Config.Tracer.OnGasChange != nil { evm.Config.Tracer.OnGasChange(gas, 0, tracing.GasChangeCallFailedExecution) } diff --git a/core/vm/interface.go b/core/vm/interface.go index 7c9bb04d135..7506bd8857b 100644 --- a/core/vm/interface.go +++ b/core/vm/interface.go @@ -54,6 +54,7 @@ type StateDB interface { GetState(common.Address, common.Hash) common.Hash SetState(common.Address, common.Hash, common.Hash) common.Hash GetStorageRoot(addr common.Address) common.Hash + IsStorageEmpty(addr common.Address) bool GetTransientState(addr common.Address, key common.Hash) common.Hash SetTransientState(addr common.Address, key, value common.Hash)