diff --git a/x/evm/keeper/statedb.go b/x/evm/keeper/statedb.go
index 8255056cdd..890e53e4ce 100644
--- a/x/evm/keeper/statedb.go
+++ b/x/evm/keeper/statedb.go
@@ -29,7 +29,6 @@ import (
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/ethereum/go-ethereum/common"
ethermint "github.com/evmos/ethermint/types"
- "github.com/evmos/ethermint/x/evm/legacystatedb"
"github.com/evmos/ethermint/x/evm/statedb"
"github.com/evmos/ethermint/x/evm/types"
)
@@ -51,23 +50,6 @@ func (k *Keeper) GetAccount(ctx sdk.Context, addr common.Address) *statedb.Accou
return acct
}
-func (k *Keeper) GetAccountLegacy(ctx sdk.Context, addr common.Address) *legacystatedb.Account {
- acct := k.GetAccountWithoutBalance(ctx, addr)
- if acct == nil {
- return nil
- }
-
- bal := k.GetBalance(ctx, addr)
-
- legacyAcct := &legacystatedb.Account{
- Nonce: acct.Nonce,
- Balance: bal,
- CodeHash: acct.CodeHash,
- }
-
- return legacyAcct
-}
-
// GetState loads contract state from database, implements `statedb.Keeper` interface.
func (k *Keeper) GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash {
store := prefix.NewStore(ctx.KVStore(k.storeKey), types.AddressStoragePrefix(addr))
@@ -138,17 +120,6 @@ func (k *Keeper) SetBalance(ctx sdk.Context, addr common.Address, amount *big.In
return nil
}
-func (k *Keeper) SetAccountLegacy(ctx sdk.Context, addr common.Address, account legacystatedb.Account) error {
- if err := k.SetAccount(ctx, addr, statedb.Account{
- Nonce: account.Nonce,
- CodeHash: account.CodeHash,
- }); err != nil {
- return err
- }
-
- return k.SetBalance(ctx, addr, account.Balance)
-}
-
// SetAccount updates nonce/balance/codeHash together.
func (k *Keeper) SetAccount(ctx sdk.Context, addr common.Address, account statedb.Account) error {
// update account
diff --git a/x/evm/legacystatedb/access_list.go b/x/evm/legacystatedb/access_list.go
deleted file mode 100644
index 31e4458426..0000000000
--- a/x/evm/legacystatedb/access_list.go
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2020 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package legacystatedb
-
-import (
- "github.com/ethereum/go-ethereum/common"
-)
-
-type accessList struct {
- addresses map[common.Address]int
- slots []map[common.Hash]struct{}
-}
-
-// ContainsAddress returns true if the address is in the access list.
-func (al *accessList) ContainsAddress(address common.Address) bool {
- _, ok := al.addresses[address]
- return ok
-}
-
-// Contains checks if a slot within an account is present in the access list, returning
-// separate flags for the presence of the account and the slot respectively.
-func (al *accessList) Contains(address common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
- idx, ok := al.addresses[address]
- if !ok {
- // no such address (and hence zero slots)
- return false, false
- }
- if idx == -1 {
- // address yes, but no slots
- return true, false
- }
- _, slotPresent = al.slots[idx][slot]
- return true, slotPresent
-}
-
-// newAccessList creates a new accessList.
-func newAccessList() *accessList {
- return &accessList{
- addresses: make(map[common.Address]int),
- }
-}
-
-// AddAddress adds an address to the access list, and returns 'true' if the operation
-// caused a change (addr was not previously in the list).
-func (al *accessList) AddAddress(address common.Address) bool {
- if _, present := al.addresses[address]; present {
- return false
- }
- al.addresses[address] = -1
- return true
-}
-
-// AddSlot adds the specified (addr, slot) combo to the access list.
-// Return values are:
-// - address added
-// - slot added
-// For any 'true' value returned, a corresponding journal entry must be made.
-func (al *accessList) AddSlot(address common.Address, slot common.Hash) (addrChange bool, slotChange bool) {
- idx, addrPresent := al.addresses[address]
- if !addrPresent || idx == -1 {
- // Address not present, or addr present but no slots there
- al.addresses[address] = len(al.slots)
- slotmap := map[common.Hash]struct{}{slot: {}}
- al.slots = append(al.slots, slotmap)
- return !addrPresent, true
- }
- // There is already an (address,slot) mapping
- slotmap := al.slots[idx]
- if _, ok := slotmap[slot]; !ok {
- slotmap[slot] = struct{}{}
- // Journal add slot change
- return false, true
- }
- // No changes required
- return false, false
-}
-
-// DeleteSlot removes an (address, slot)-tuple from the access list.
-// This operation needs to be performed in the same order as the addition happened.
-// This method is meant to be used by the journal, which maintains ordering of
-// operations.
-func (al *accessList) DeleteSlot(address common.Address, slot common.Hash) {
- idx, addrOk := al.addresses[address]
- if !addrOk {
- panic("reverting slot change, address not present in list")
- }
- slotmap := al.slots[idx]
- delete(slotmap, slot)
- // If that was the last (first) slot, remove it
- // Since additions and rollbacks are always performed in order,
- // we can delete the item without worrying about screwing up later indices
- if len(slotmap) == 0 {
- al.slots = al.slots[:idx]
- al.addresses[address] = -1
- }
-}
-
-// DeleteAddress removes an address from the access list. This operation
-// needs to be performed in the same order as the addition happened.
-// This method is meant to be used by the journal, which maintains ordering of
-// operations.
-func (al *accessList) DeleteAddress(address common.Address) {
- delete(al.addresses, address)
-}
diff --git a/x/evm/legacystatedb/config.go b/x/evm/legacystatedb/config.go
deleted file mode 100644
index 1e3ca62af2..0000000000
--- a/x/evm/legacystatedb/config.go
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2021 Evmos Foundation
-// This file is part of Evmos' Ethermint library.
-//
-// The Ethermint library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Ethermint library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Ethermint library. If not, see https://github.com/evmos/ethermint/blob/main/LICENSE
-package legacystatedb
-
-import (
- "math/big"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/params"
- "github.com/evmos/ethermint/x/evm/types"
-)
-
-// TxConfig encapulates the readonly information of current tx for `StateDB`.
-type TxConfig struct {
- BlockHash common.Hash // hash of current block
- TxHash common.Hash // hash of current tx
- TxIndex uint // the index of current transaction
- LogIndex uint // the index of next log within current block
-}
-
-// NewTxConfig returns a TxConfig
-func NewTxConfig(bhash, thash common.Hash, txIndex, logIndex uint) TxConfig {
- return TxConfig{
- BlockHash: bhash,
- TxHash: thash,
- TxIndex: txIndex,
- LogIndex: logIndex,
- }
-}
-
-// NewEmptyTxConfig construct an empty TxConfig,
-// used in context where there's no transaction, e.g. `eth_call`/`eth_estimateGas`.
-func NewEmptyTxConfig(bhash common.Hash) TxConfig {
- return TxConfig{
- BlockHash: bhash,
- TxHash: common.Hash{},
- TxIndex: 0,
- LogIndex: 0,
- }
-}
-
-// EVMConfig encapsulates common parameters needed to create an EVM to execute a message
-// It's mainly to reduce the number of method parameters
-type EVMConfig struct {
- Params types.Params
- ChainConfig *params.ChainConfig
- CoinBase common.Address
- BaseFee *big.Int
-}
diff --git a/x/evm/legacystatedb/interfaces.go b/x/evm/legacystatedb/interfaces.go
deleted file mode 100644
index c8b26dd806..0000000000
--- a/x/evm/legacystatedb/interfaces.go
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2021 Evmos Foundation
-// This file is part of Evmos' Ethermint library.
-//
-// The Ethermint library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Ethermint library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Ethermint library. If not, see https://github.com/evmos/ethermint/blob/main/LICENSE
-package legacystatedb
-
-import (
- sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/core/vm"
-)
-
-// ExtStateDB defines an extension to the interface provided by the go-ethereum
-// codebase to support additional state transition functionalities. In particular
-// it supports appending a new entry to the state journal through
-// AppendJournalEntry so that the state can be reverted after running
-// stateful precompiled contracts.
-type ExtStateDB interface {
- vm.StateDB
- AppendJournalEntry(JournalEntry)
-}
-
-// Keeper provide underlying storage of StateDB
-type Keeper interface {
- // Read methods
- GetAccountLegacy(ctx sdk.Context, addr common.Address) *Account
- GetState(ctx sdk.Context, addr common.Address, key common.Hash) common.Hash
- GetCode(ctx sdk.Context, codeHash common.Hash) []byte
- // the callback returns false to break early
- ForEachStorage(ctx sdk.Context, addr common.Address, cb func(key, value common.Hash) bool)
-
- // Write methods, only called by `StateDB.Commit()`
- SetAccountLegacy(ctx sdk.Context, addr common.Address, account Account) error
- SetState(ctx sdk.Context, addr common.Address, key common.Hash, value []byte)
- SetCode(ctx sdk.Context, codeHash []byte, code []byte)
- DeleteAccount(ctx sdk.Context, addr common.Address) error
-}
diff --git a/x/evm/legacystatedb/journal.go b/x/evm/legacystatedb/journal.go
deleted file mode 100644
index f34b41625f..0000000000
--- a/x/evm/legacystatedb/journal.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2016 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package legacystatedb
-
-import (
- "bytes"
- "math/big"
- "sort"
-
- "github.com/ethereum/go-ethereum/common"
-)
-
-// JournalEntry is a modification entry in the state change journal that can be
-// Reverted on demand.
-type JournalEntry interface {
- // Revert undoes the changes introduced by this journal entry.
- Revert(*StateDB)
-
- // Dirtied returns the Ethereum address modified by this journal entry.
- Dirtied() *common.Address
-}
-
-// journal contains the list of state modifications applied since the last state
-// commit. These are tracked to be able to be reverted in the case of an execution
-// exception or request for reversal.
-type journal struct {
- entries []JournalEntry // Current changes tracked by the journal
- dirties map[common.Address]int // Dirty accounts and the number of changes
-}
-
-// newJournal creates a new initialized journal.
-func newJournal() *journal {
- return &journal{
- dirties: make(map[common.Address]int),
- }
-}
-
-// sortedDirties sort the dirty addresses for deterministic iteration
-func (j *journal) sortedDirties() []common.Address {
- keys := make([]common.Address, len(j.dirties))
- i := 0
- for k := range j.dirties {
- keys[i] = k
- i++
- }
- sort.Slice(keys, func(i, j int) bool {
- return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) < 0
- })
- return keys
-}
-
-// append inserts a new modification entry to the end of the change journal.
-func (j *journal) append(entry JournalEntry) {
- j.entries = append(j.entries, entry)
- if addr := entry.Dirtied(); addr != nil {
- j.dirties[*addr]++
- }
-}
-
-// Revert undoes a batch of journalled modifications along with any Reverted
-// dirty handling too.
-func (j *journal) Revert(statedb *StateDB, snapshot int) {
- for i := len(j.entries) - 1; i >= snapshot; i-- {
- // Undo the changes made by the operation
- j.entries[i].Revert(statedb)
-
- // Drop any dirty tracking induced by the change
- if addr := j.entries[i].Dirtied(); addr != nil {
- if j.dirties[*addr]--; j.dirties[*addr] == 0 {
- delete(j.dirties, *addr)
- }
- }
- }
- j.entries = j.entries[:snapshot]
-}
-
-// length returns the current number of entries in the journal.
-func (j *journal) length() int {
- return len(j.entries)
-}
-
-type (
- // Changes to the account trie.
- createObjectChange struct {
- account *common.Address
- }
- resetObjectChange struct {
- prev *stateObject
- }
- suicideChange struct {
- account *common.Address
- prev bool // whether account had already suicided
- prevbalance *big.Int
- }
-
- // Changes to individual accounts.
- balanceChange struct {
- account *common.Address
- prev *big.Int
- }
- nonceChange struct {
- account *common.Address
- prev uint64
- }
- storageChange struct {
- account *common.Address
- key, prevalue common.Hash
- }
- codeChange struct {
- account *common.Address
- prevcode, prevhash []byte
- }
-
- // Changes to other state values.
- refundChange struct {
- prev uint64
- }
- addLogChange struct{}
-
- // Changes to the access list
- accessListAddAccountChange struct {
- address *common.Address
- }
- accessListAddSlotChange struct {
- address *common.Address
- slot *common.Hash
- }
-)
-
-func (ch createObjectChange) Revert(s *StateDB) {
- delete(s.stateObjects, *ch.account)
-}
-
-func (ch createObjectChange) Dirtied() *common.Address {
- return ch.account
-}
-
-func (ch resetObjectChange) Revert(s *StateDB) {
- s.setStateObject(ch.prev)
-}
-
-func (ch resetObjectChange) Dirtied() *common.Address {
- return nil
-}
-
-func (ch suicideChange) Revert(s *StateDB) {
- obj := s.getStateObject(*ch.account)
- if obj != nil {
- obj.suicided = ch.prev
- obj.setBalance(ch.prevbalance)
- }
-}
-
-func (ch suicideChange) Dirtied() *common.Address {
- return ch.account
-}
-
-func (ch balanceChange) Revert(s *StateDB) {
- s.getStateObject(*ch.account).setBalance(ch.prev)
-}
-
-func (ch balanceChange) Dirtied() *common.Address {
- return ch.account
-}
-
-func (ch nonceChange) Revert(s *StateDB) {
- s.getStateObject(*ch.account).setNonce(ch.prev)
-}
-
-func (ch nonceChange) Dirtied() *common.Address {
- return ch.account
-}
-
-func (ch codeChange) Revert(s *StateDB) {
- s.getStateObject(*ch.account).setCode(common.BytesToHash(ch.prevhash), ch.prevcode)
-}
-
-func (ch codeChange) Dirtied() *common.Address {
- return ch.account
-}
-
-func (ch storageChange) Revert(s *StateDB) {
- s.getStateObject(*ch.account).setState(ch.key, ch.prevalue)
-}
-
-func (ch storageChange) Dirtied() *common.Address {
- return ch.account
-}
-
-func (ch refundChange) Revert(s *StateDB) {
- s.refund = ch.prev
-}
-
-func (ch refundChange) Dirtied() *common.Address {
- return nil
-}
-
-func (ch addLogChange) Revert(s *StateDB) {
- s.logs = s.logs[:len(s.logs)-1]
-}
-
-func (ch addLogChange) Dirtied() *common.Address {
- return nil
-}
-
-func (ch accessListAddAccountChange) Revert(s *StateDB) {
- /*
- One important invariant here, is that whenever a (addr, slot) is added, if the
- addr is not already present, the add causes two journal entries:
- - one for the address,
- - one for the (address,slot)
- Therefore, when unrolling the change, we can always blindly delete the
- (addr) at this point, since no storage adds can remain when come upon
- a single (addr) change.
- */
- s.accessList.DeleteAddress(*ch.address)
-}
-
-func (ch accessListAddAccountChange) Dirtied() *common.Address {
- return nil
-}
-
-func (ch accessListAddSlotChange) Revert(s *StateDB) {
- s.accessList.DeleteSlot(*ch.address, *ch.slot)
-}
-
-func (ch accessListAddSlotChange) Dirtied() *common.Address {
- return nil
-}
diff --git a/x/evm/legacystatedb/state_object.go b/x/evm/legacystatedb/state_object.go
deleted file mode 100644
index bdd138d592..0000000000
--- a/x/evm/legacystatedb/state_object.go
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2021 Evmos Foundation
-// This file is part of Evmos' Ethermint library.
-//
-// The Ethermint library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Ethermint library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Ethermint library. If not, see https://github.com/evmos/ethermint/blob/main/LICENSE
-package legacystatedb
-
-import (
- "bytes"
- "math/big"
- "sort"
-
- "github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/crypto"
-)
-
-var emptyCodeHash = crypto.Keccak256(nil)
-
-// Account is the Ethereum consensus representation of accounts.
-// These objects are stored in the storage of auth module.
-type Account = struct {
- Balance *big.Int
- Nonce uint64
- CodeHash []byte
-}
-
-// NewEmptyAccount returns an empty account.
-func NewEmptyAccount() *Account {
- return &Account{
- Balance: new(big.Int),
- CodeHash: emptyCodeHash,
- }
-}
-
-// Storage represents in-memory cache/buffer of contract storage.
-type Storage map[common.Hash]common.Hash
-
-// SortedKeys sort the keys for deterministic iteration
-func (s Storage) SortedKeys() []common.Hash {
- keys := make([]common.Hash, len(s))
- i := 0
- for k := range s {
- keys[i] = k
- i++
- }
- sort.Slice(keys, func(i, j int) bool {
- return bytes.Compare(keys[i].Bytes(), keys[j].Bytes()) < 0
- })
- return keys
-}
-
-// stateObject is the state of an acount
-type stateObject struct {
- db *StateDB
-
- account Account
- code []byte
-
- // state storage
- originStorage Storage
- dirtyStorage Storage
-
- address common.Address
-
- // flags
- dirtyCode bool
- suicided bool
-}
-
-// newObject creates a state object.
-func newObject(db *StateDB, address common.Address, account Account) *stateObject {
- if account.Balance == nil {
- account.Balance = new(big.Int)
- }
- if account.CodeHash == nil {
- account.CodeHash = emptyCodeHash
- }
- return &stateObject{
- db: db,
- address: address,
- account: account,
- originStorage: make(Storage),
- dirtyStorage: make(Storage),
- }
-}
-
-// empty returns whether the account is considered empty.
-func (s *stateObject) empty() bool {
- return s.account.Nonce == 0 && s.account.Balance.Sign() == 0 && bytes.Equal(s.account.CodeHash, emptyCodeHash)
-}
-
-func (s *stateObject) markSuicided() {
- s.suicided = true
-}
-
-// AddBalance adds amount to s's balance.
-// It is used to add funds to the destination account of a transfer.
-func (s *stateObject) AddBalance(amount *big.Int) {
- if amount.Sign() == 0 {
- return
- }
- s.SetBalance(new(big.Int).Add(s.Balance(), amount))
-}
-
-// SubBalance removes amount from s's balance.
-// It is used to remove funds from the origin account of a transfer.
-func (s *stateObject) SubBalance(amount *big.Int) {
- if amount.Sign() == 0 {
- return
- }
- s.SetBalance(new(big.Int).Sub(s.Balance(), amount))
-}
-
-// SetBalance update account balance.
-func (s *stateObject) SetBalance(amount *big.Int) {
- s.db.journal.append(balanceChange{
- account: &s.address,
- prev: new(big.Int).Set(s.account.Balance),
- })
- s.setBalance(amount)
-}
-
-func (s *stateObject) setBalance(amount *big.Int) {
- s.account.Balance = amount
-}
-
-//
-// Attribute accessors
-//
-
-// Returns the address of the contract/account
-func (s *stateObject) Address() common.Address {
- return s.address
-}
-
-// Code returns the contract code associated with this object, if any.
-func (s *stateObject) Code() []byte {
- if s.code != nil {
- return s.code
- }
- if bytes.Equal(s.CodeHash(), emptyCodeHash) {
- return nil
- }
- code := s.db.keeper.GetCode(s.db.ctx, common.BytesToHash(s.CodeHash()))
- s.code = code
- return code
-}
-
-// CodeSize returns the size of the contract code associated with this object,
-// or zero if none.
-func (s *stateObject) CodeSize() int {
- return len(s.Code())
-}
-
-// SetCode set contract code to account
-func (s *stateObject) SetCode(codeHash common.Hash, code []byte) {
- prevcode := s.Code()
- s.db.journal.append(codeChange{
- account: &s.address,
- prevhash: s.CodeHash(),
- prevcode: prevcode,
- })
- s.setCode(codeHash, code)
-}
-
-func (s *stateObject) setCode(codeHash common.Hash, code []byte) {
- s.code = code
- s.account.CodeHash = codeHash[:]
- s.dirtyCode = true
-}
-
-// SetCode set nonce to account
-func (s *stateObject) SetNonce(nonce uint64) {
- s.db.journal.append(nonceChange{
- account: &s.address,
- prev: s.account.Nonce,
- })
- s.setNonce(nonce)
-}
-
-func (s *stateObject) setNonce(nonce uint64) {
- s.account.Nonce = nonce
-}
-
-// CodeHash returns the code hash of account
-func (s *stateObject) CodeHash() []byte {
- return s.account.CodeHash
-}
-
-// Balance returns the balance of account
-func (s *stateObject) Balance() *big.Int {
- return s.account.Balance
-}
-
-// Nonce returns the nonce of account
-func (s *stateObject) Nonce() uint64 {
- return s.account.Nonce
-}
-
-// GetCommittedState query the committed state
-func (s *stateObject) GetCommittedState(key common.Hash) common.Hash {
- if value, cached := s.originStorage[key]; cached {
- return value
- }
- // If no live objects are available, load it from keeper
- value := s.db.keeper.GetState(s.db.ctx, s.Address(), key)
- s.originStorage[key] = value
- return value
-}
-
-// GetState query the current state (including dirty state)
-func (s *stateObject) GetState(key common.Hash) common.Hash {
- if value, dirty := s.dirtyStorage[key]; dirty {
- return value
- }
- return s.GetCommittedState(key)
-}
-
-// SetState sets the contract state
-func (s *stateObject) SetState(key common.Hash, value common.Hash) {
- // If the new value is the same as old, don't set
- prev := s.GetState(key)
- if prev == value {
- return
- }
- // New value is different, update and journal the change
- s.db.journal.append(storageChange{
- account: &s.address,
- key: key,
- prevalue: prev,
- })
- s.setState(key, value)
-}
-
-func (s *stateObject) setState(key, value common.Hash) {
- s.dirtyStorage[key] = value
-}
diff --git a/x/evm/legacystatedb/statedb.go b/x/evm/legacystatedb/statedb.go
deleted file mode 100644
index ac0e093b60..0000000000
--- a/x/evm/legacystatedb/statedb.go
+++ /dev/null
@@ -1,479 +0,0 @@
-// Copyright 2021 Evmos Foundation
-// This file is part of Evmos' Ethermint library.
-//
-// The Ethermint library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The Ethermint library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the Ethermint library. If not, see https://github.com/evmos/ethermint/blob/main/LICENSE
-package legacystatedb
-
-import (
- "fmt"
- "math/big"
- "sort"
-
- errorsmod "cosmossdk.io/errors"
- sdk "github.com/cosmos/cosmos-sdk/types"
- "github.com/ethereum/go-ethereum/common"
- ethtypes "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/core/vm"
- "github.com/ethereum/go-ethereum/crypto"
- "github.com/evmos/ethermint/x/evm/statedb"
-)
-
-// revision is the identifier of a version of state.
-// it consists of an auto-increment id and a journal index.
-// it's safer to use than using journal index alone.
-type revision struct {
- id int
- journalIndex int
-}
-
-var _ vm.StateDB = &StateDB{}
-
-// StateDB structs within the ethereum protocol are used to store anything
-// within the merkle trie. StateDBs take care of caching and storing
-// nested states. It's the general query interface to retrieve:
-// * Contracts
-// * Accounts
-type StateDB struct {
- keeper Keeper
- ctx sdk.Context
-
- // Journal of state modifications. This is the backbone of
- // Snapshot and RevertToSnapshot.
- journal *journal
- validRevisions []revision
- nextRevisionID int
-
- stateObjects map[common.Address]*stateObject
-
- txConfig statedb.TxConfig
-
- // The refund counter, also used by state transitioning.
- refund uint64
-
- // Per-transaction logs
- logs []*ethtypes.Log
-
- // Per-transaction access list
- accessList *accessList
-}
-
-// New creates a new state from a given trie.
-func New(ctx sdk.Context, keeper Keeper, txConfig statedb.TxConfig) *StateDB {
- return &StateDB{
- keeper: keeper,
- ctx: ctx,
- stateObjects: make(map[common.Address]*stateObject),
- journal: newJournal(),
- accessList: newAccessList(),
-
- txConfig: txConfig,
- }
-}
-
-// Keeper returns the underlying `Keeper`
-func (s *StateDB) Keeper() Keeper {
- return s.keeper
-}
-
-// AddLog adds a log, called by evm.
-func (s *StateDB) AddLog(log *ethtypes.Log) {
- s.journal.append(addLogChange{})
-
- log.TxHash = s.txConfig.TxHash
- log.BlockHash = s.txConfig.BlockHash
- log.TxIndex = s.txConfig.TxIndex
- log.Index = s.txConfig.LogIndex + uint(len(s.logs))
- s.logs = append(s.logs, log)
-}
-
-// Logs returns the logs of current transaction.
-func (s *StateDB) Logs() []*ethtypes.Log {
- return s.logs
-}
-
-// AddRefund adds gas to the refund counter
-func (s *StateDB) AddRefund(gas uint64) {
- s.journal.append(refundChange{prev: s.refund})
- s.refund += gas
-}
-
-// SubRefund removes gas from the refund counter.
-// This method will panic if the refund counter goes below zero
-func (s *StateDB) SubRefund(gas uint64) {
- s.journal.append(refundChange{prev: s.refund})
- if gas > s.refund {
- panic(fmt.Sprintf("Refund counter below zero (gas: %d > refund: %d)", gas, s.refund))
- }
- s.refund -= gas
-}
-
-// Exist reports whether the given account address exists in the state.
-// Notably this also returns true for suicided accounts.
-func (s *StateDB) Exist(addr common.Address) bool {
- return s.getStateObject(addr) != nil
-}
-
-// Empty returns whether the state object is either non-existent
-// or empty according to the EIP161 specification (balance = nonce = code = 0)
-func (s *StateDB) Empty(addr common.Address) bool {
- so := s.getStateObject(addr)
- return so == nil || so.empty()
-}
-
-// GetBalance retrieves the balance from the given address or 0 if object not found
-func (s *StateDB) GetBalance(addr common.Address) *big.Int {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.Balance()
- }
- return common.Big0
-}
-
-// GetNonce returns the nonce of account, 0 if not exists.
-func (s *StateDB) GetNonce(addr common.Address) uint64 {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.Nonce()
- }
-
- return 0
-}
-
-// GetCode returns the code of account, nil if not exists.
-func (s *StateDB) GetCode(addr common.Address) []byte {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.Code()
- }
- return nil
-}
-
-// GetCodeSize returns the code size of account.
-func (s *StateDB) GetCodeSize(addr common.Address) int {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.CodeSize()
- }
- return 0
-}
-
-// GetCodeHash returns the code hash of account.
-func (s *StateDB) GetCodeHash(addr common.Address) common.Hash {
- stateObject := s.getStateObject(addr)
- if stateObject == nil {
- return common.Hash{}
- }
- return common.BytesToHash(stateObject.CodeHash())
-}
-
-// GetState retrieves a value from the given account's storage trie.
-func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.GetState(hash)
- }
- return common.Hash{}
-}
-
-// GetCommittedState retrieves a value from the given account's committed storage trie.
-func (s *StateDB) GetCommittedState(addr common.Address, hash common.Hash) common.Hash {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.GetCommittedState(hash)
- }
- return common.Hash{}
-}
-
-// GetRefund returns the current value of the refund counter.
-func (s *StateDB) GetRefund() uint64 {
- return s.refund
-}
-
-// HasSuicided returns if the contract is suicided in current transaction.
-func (s *StateDB) HasSuicided(addr common.Address) bool {
- stateObject := s.getStateObject(addr)
- if stateObject != nil {
- return stateObject.suicided
- }
- return false
-}
-
-// AddPreimage records a SHA3 preimage seen by the VM.
-// AddPreimage performs a no-op since the EnablePreimageRecording flag is disabled
-// on the vm.Config during state transitions. No store trie preimages are written
-// to the database.
-func (s *StateDB) AddPreimage(hash common.Hash, preimage []byte) {} //nolint: revive
-
-// getStateObject retrieves a state object given by the address, returning nil if
-// the object is not found.
-func (s *StateDB) getStateObject(addr common.Address) *stateObject {
- // Prefer live objects if any is available
- if obj := s.stateObjects[addr]; obj != nil {
- return obj
- }
- // If no live objects are available, load it from keeper
- account := s.keeper.GetAccountLegacy(s.ctx, addr)
- if account == nil {
- return nil
- }
- // Insert into the live set
- obj := newObject(s, addr, *account)
- s.setStateObject(obj)
- return obj
-}
-
-// getOrNewStateObject retrieves a state object or create a new state object if nil.
-func (s *StateDB) getOrNewStateObject(addr common.Address) *stateObject {
- stateObject := s.getStateObject(addr)
- if stateObject == nil {
- stateObject, _ = s.createObject(addr)
- }
- return stateObject
-}
-
-// createObject creates a new state object. If there is an existing account with
-// the given address, it is overwritten and returned as the second return value.
-func (s *StateDB) createObject(addr common.Address) (newobj, prev *stateObject) {
- prev = s.getStateObject(addr)
-
- newobj = newObject(s, addr, Account{})
- if prev == nil {
- s.journal.append(createObjectChange{account: &addr})
- } else {
- s.journal.append(resetObjectChange{prev: prev})
- }
- s.setStateObject(newobj)
- if prev != nil {
- return newobj, prev
- }
- return newobj, nil
-}
-
-// CreateAccount explicitly creates a state object. If a state object with the address
-// already exists the balance is carried over to the new account.
-//
-// CreateAccount is called during the EVM CREATE operation. The situation might arise that
-// a contract does the following:
-//
-// 1. sends funds to sha(account ++ (nonce + 1))
-// 2. tx_create(sha(account ++ nonce)) (note that this gets the address of 1)
-//
-// Carrying over the balance ensures that Ether doesn't disappear.
-func (s *StateDB) CreateAccount(addr common.Address) {
- newObj, prev := s.createObject(addr)
- if prev != nil {
- newObj.setBalance(prev.account.Balance)
- }
-}
-
-// ForEachStorage iterate the contract storage, the iteration order is not defined.
-func (s *StateDB) ForEachStorage(addr common.Address, cb func(key, value common.Hash) bool) error {
- so := s.getStateObject(addr)
- if so == nil {
- return nil
- }
- s.keeper.ForEachStorage(s.ctx, addr, func(key, value common.Hash) bool {
- if value, dirty := so.dirtyStorage[key]; dirty {
- return cb(key, value)
- }
- if len(value) > 0 {
- return cb(key, value)
- }
- return true
- })
- return nil
-}
-
-func (s *StateDB) setStateObject(object *stateObject) {
- s.stateObjects[object.Address()] = object
-}
-
-/*
- * SETTERS
- */
-
-// AddBalance adds amount to the account associated with addr.
-func (s *StateDB) AddBalance(addr common.Address, amount *big.Int) {
- stateObject := s.getOrNewStateObject(addr)
- if stateObject != nil {
- stateObject.AddBalance(amount)
- }
-}
-
-// SubBalance subtracts amount from the account associated with addr.
-func (s *StateDB) SubBalance(addr common.Address, amount *big.Int) {
- stateObject := s.getOrNewStateObject(addr)
- if stateObject != nil {
- stateObject.SubBalance(amount)
- }
-}
-
-// SetNonce sets the nonce of account.
-func (s *StateDB) SetNonce(addr common.Address, nonce uint64) {
- stateObject := s.getOrNewStateObject(addr)
- if stateObject != nil {
- stateObject.SetNonce(nonce)
- }
-}
-
-// SetCode sets the code of account.
-func (s *StateDB) SetCode(addr common.Address, code []byte) {
- stateObject := s.getOrNewStateObject(addr)
- if stateObject != nil {
- stateObject.SetCode(crypto.Keccak256Hash(code), code)
- }
-}
-
-// SetState sets the contract state.
-func (s *StateDB) SetState(addr common.Address, key, value common.Hash) {
- stateObject := s.getOrNewStateObject(addr)
- if stateObject != nil {
- stateObject.SetState(key, value)
- }
-}
-
-// Suicide marks the given account as suicided.
-// This clears the account balance.
-//
-// The account's state object is still available until the state is committed,
-// getStateObject will return a non-nil account after Suicide.
-func (s *StateDB) Suicide(addr common.Address) bool {
- stateObject := s.getStateObject(addr)
- if stateObject == nil {
- return false
- }
- s.journal.append(suicideChange{
- account: &addr,
- prev: stateObject.suicided,
- prevbalance: new(big.Int).Set(stateObject.Balance()),
- })
- stateObject.markSuicided()
- stateObject.account.Balance = new(big.Int)
-
- return true
-}
-
-// PrepareAccessList handles the preparatory steps for executing a state transition with
-// regards to both EIP-2929 and EIP-2930:
-//
-// - Add sender to access list (2929)
-// - Add destination to access list (2929)
-// - Add precompiles to access list (2929)
-// - Add the contents of the optional tx access list (2930)
-//
-// This method should only be called if Yolov3/Berlin/2929+2930 is applicable at the current number.
-func (s *StateDB) PrepareAccessList(sender common.Address, dst *common.Address, precompiles []common.Address, list ethtypes.AccessList) {
- s.AddAddressToAccessList(sender)
- if dst != nil {
- s.AddAddressToAccessList(*dst)
- // If it's a create-tx, the destination will be added inside evm.create
- }
- for _, addr := range precompiles {
- s.AddAddressToAccessList(addr)
- }
- for _, el := range list {
- s.AddAddressToAccessList(el.Address)
- for _, key := range el.StorageKeys {
- s.AddSlotToAccessList(el.Address, key)
- }
- }
-}
-
-// AddAddressToAccessList adds the given address to the access list
-func (s *StateDB) AddAddressToAccessList(addr common.Address) {
- if s.accessList.AddAddress(addr) {
- s.journal.append(accessListAddAccountChange{&addr})
- }
-}
-
-// AddSlotToAccessList adds the given (address, slot)-tuple to the access list
-func (s *StateDB) AddSlotToAccessList(addr common.Address, slot common.Hash) {
- addrMod, slotMod := s.accessList.AddSlot(addr, slot)
- if addrMod {
- // In practice, this should not happen, since there is no way to enter the
- // scope of 'address' without having the 'address' become already added
- // to the access list (via call-variant, create, etc).
- // Better safe than sorry, though
- s.journal.append(accessListAddAccountChange{&addr})
- }
- if slotMod {
- s.journal.append(accessListAddSlotChange{
- address: &addr,
- slot: &slot,
- })
- }
-}
-
-// AddressInAccessList returns true if the given address is in the access list.
-func (s *StateDB) AddressInAccessList(addr common.Address) bool {
- return s.accessList.ContainsAddress(addr)
-}
-
-// SlotInAccessList returns true if the given (address, slot)-tuple is in the access list.
-func (s *StateDB) SlotInAccessList(addr common.Address, slot common.Hash) (addressPresent bool, slotPresent bool) {
- return s.accessList.Contains(addr, slot)
-}
-
-// Snapshot returns an identifier for the current revision of the state.
-func (s *StateDB) Snapshot() int {
- id := s.nextRevisionID
- s.nextRevisionID++
- s.validRevisions = append(s.validRevisions, revision{id, s.journal.length()})
- return id
-}
-
-// RevertToSnapshot reverts all state changes made since the given revision.
-func (s *StateDB) RevertToSnapshot(revid int) {
- // Find the snapshot in the stack of valid snapshots.
- idx := sort.Search(len(s.validRevisions), func(i int) bool {
- return s.validRevisions[i].id >= revid
- })
- if idx == len(s.validRevisions) || s.validRevisions[idx].id != revid {
- panic(fmt.Errorf("revision id %v cannot be reverted", revid))
- }
- snapshot := s.validRevisions[idx].journalIndex
-
- // Replay the journal to undo changes and remove invalidated snapshots
- s.journal.Revert(s, snapshot)
- s.validRevisions = s.validRevisions[:idx]
-}
-
-// Commit writes the dirty states to keeper
-// the StateDB object should be discarded after committed.
-func (s *StateDB) Commit() error {
- for _, addr := range s.journal.sortedDirties() {
- obj := s.stateObjects[addr]
- if obj.suicided {
- if err := s.keeper.DeleteAccount(s.ctx, obj.Address()); err != nil {
- return errorsmod.Wrap(err, "failed to delete account")
- }
- } else {
- if obj.code != nil && obj.dirtyCode {
- s.keeper.SetCode(s.ctx, obj.CodeHash(), obj.code)
- }
- if err := s.keeper.SetAccountLegacy(s.ctx, obj.Address(), obj.account); err != nil {
- return errorsmod.Wrap(err, "failed to set account")
- }
- for _, key := range obj.dirtyStorage.SortedKeys() {
- value := obj.dirtyStorage[key]
- // Skip noop changes, persist actual changes
- if value == obj.originStorage[key] {
- continue
- }
- s.keeper.SetState(s.ctx, obj.Address(), key, value.Bytes())
- }
- }
- }
- return nil
-}