diff --git a/cmd/evm/runner.go b/cmd/evm/runner.go
index b4de1651d6faa13d715a26637b08cd3453f4ef07..5efd30b65137ade7b469497e4855ecb88fcefc37 100644
--- a/cmd/evm/runner.go
+++ b/cmd/evm/runner.go
@@ -135,19 +135,22 @@ func runCmd(ctx *cli.Context) error {
 	} else {
 		debugLogger = vm.NewStructLogger(logconfig)
 	}
-	db := kv.NewMemDatabase()
+	db := kv.NewMemKV()
 	if ctx.GlobalString(GenesisFlag.Name) != "" {
 		gen := readGenesis(ctx.GlobalString(GenesisFlag.Name))
-		_, err := gen.Commit(db, false)
-		if err != nil {
-			return err
-		}
+		gen.MustCommit(db)
 		genesisConfig = gen
 		chainConfig = gen.Config
 	} else {
 		genesisConfig = new(core.Genesis)
 	}
-	statedb = state.New(state.NewPlainStateReader(db))
+	tx, err := db.BeginRw(context.Background())
+	if err != nil {
+		return err
+	}
+	defer tx.Rollback()
+
+	statedb = state.New(state.NewPlainStateReader(tx))
 	if ctx.GlobalString(SenderFlag.Name) != "" {
 		sender = common.HexToAddress(ctx.GlobalString(SenderFlag.Name))
 	}
@@ -281,11 +284,6 @@ func runCmd(ctx *cli.Context) error {
 			fmt.Println("Could not commit state: ", err)
 			os.Exit(1)
 		}
-		tx, err1 := db.RwKV().BeginRo(context.Background())
-		if err1 != nil {
-			return fmt.Errorf("transition cannot open tx: %v", err1)
-		}
-		defer tx.Rollback()
 		fmt.Println(string(state.NewDumper(tx, 0).DefaultDump()))
 	}
 
diff --git a/cmd/rpctest/rpctest/account_range_verify.go b/cmd/rpctest/rpctest/account_range_verify.go
index 476c1efe15fe8bbab0966ea8403bc23749eced25..c49c9a26a72b11bcdaf1b27120b67c5c3faef27e 100644
--- a/cmd/rpctest/rpctest/account_range_verify.go
+++ b/cmd/rpctest/rpctest/account_range_verify.go
@@ -33,8 +33,6 @@ func CompareAccountRange(erigonURL, gethURL, tmpDataDir, gethDataDir string, blo
 	}
 	resultsKV := kv.NewMDBX().Path(tmpDataDir).MustOpen()
 	gethKV := kv.NewMDBX().Path(gethDataDir).MustOpen()
-	resultsDB := kv.NewObjectDatabase(resultsKV)
-	gethResultsDB := kv.NewObjectDatabase(gethKV)
 
 	var client = &http.Client{
 		Timeout: time.Minute * 60,
@@ -58,7 +56,7 @@ func CompareAccountRange(erigonURL, gethURL, tmpDataDir, gethDataDir string, blo
 		Result state.IteratorDump `json:"result"`
 	}
 
-	f := func(url string, db ethdb.Database) error {
+	f := func(url string, db ethdb.RwTx) error {
 		i := uint64(0)
 		reqGen := &RequestGenerator{
 			client: client,
@@ -97,13 +95,17 @@ func CompareAccountRange(erigonURL, gethURL, tmpDataDir, gethDataDir string, blo
 			next = ar.Result.Next
 		}
 	}
-	err = f(erigonURL, resultsDB)
+	err = resultsKV.Update(context.Background(), func(tx ethdb.RwTx) error {
+		return f(erigonURL, tx)
+	})
 	if err != nil {
 		log.Fatal(err)
 	}
 
 	if !notRegenerateGethData {
-		err = f(gethURL, gethResultsDB)
+		err = gethKV.Update(context.Background(), func(tx ethdb.RwTx) error {
+			return f(erigonURL, tx)
+		})
 		if err != nil {
 			log.Fatal(err)
 		}
diff --git a/common/etl/etl_test.go b/common/etl/etl_test.go
index 55e786a52614771a18bff91b0dcdafe401a39106..2588501881dcdc1f11a5e84225c124c3e850edbd 100644
--- a/common/etl/etl_test.go
+++ b/common/etl/etl_test.go
@@ -2,7 +2,6 @@ package etl
 
 import (
 	"bytes"
-	"context"
 	"fmt"
 	"io"
 	"os"
@@ -132,19 +131,14 @@ func TestRAMDataProviders(t *testing.T) {
 
 func TestTransformRAMOnly(t *testing.T) {
 	// test invariant when we only have one buffer and it fits into RAM (exactly 1 buffer)
-	db := kv.NewTestDB(t)
-	tx, err := db.Begin(context.Background(), ethdb.RW)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer tx.Rollback()
+	_, tx := kv.NewTestTx(t)
 
 	sourceBucket := dbutils.Buckets[0]
 	destBucket := dbutils.Buckets[1]
 	generateTestData(t, tx, sourceBucket, 20)
-	err = Transform(
+	err := Transform(
 		"logPrefix",
-		tx.(ethdb.HasTx).Tx().(ethdb.RwTx),
+		tx,
 		sourceBucket,
 		destBucket,
 		"", // temp dir
@@ -157,17 +151,12 @@ func TestTransformRAMOnly(t *testing.T) {
 }
 
 func TestEmptySourceBucket(t *testing.T) {
-	db := kv.NewTestDB(t)
-	tx, err := db.Begin(context.Background(), ethdb.RW)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer tx.Rollback()
+	_, tx := kv.NewTestTx(t)
 	sourceBucket := dbutils.Buckets[0]
 	destBucket := dbutils.Buckets[1]
-	err = Transform(
+	err := Transform(
 		"logPrefix",
-		tx.(ethdb.HasTx).Tx().(ethdb.RwTx),
+		tx,
 		sourceBucket,
 		destBucket,
 		"", // temp dir
@@ -181,18 +170,13 @@ func TestEmptySourceBucket(t *testing.T) {
 
 func TestTransformExtractStartKey(t *testing.T) {
 	// test invariant when we only have one buffer and it fits into RAM (exactly 1 buffer)
-	db := kv.NewTestDB(t)
-	tx, err := db.Begin(context.Background(), ethdb.RW)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer tx.Rollback()
+	_, tx := kv.NewTestTx(t)
 	sourceBucket := dbutils.Buckets[0]
 	destBucket := dbutils.Buckets[1]
 	generateTestData(t, tx, sourceBucket, 10)
-	err = Transform(
+	err := Transform(
 		"logPrefix",
-		tx.(ethdb.HasTx).Tx().(ethdb.RwTx),
+		tx,
 		sourceBucket,
 		destBucket,
 		"", // temp dir
@@ -206,18 +190,13 @@ func TestTransformExtractStartKey(t *testing.T) {
 
 func TestTransformThroughFiles(t *testing.T) {
 	// test invariant when we go through files (> 1 buffer)
-	db := kv.NewTestDB(t)
-	tx, err := db.Begin(context.Background(), ethdb.RW)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer tx.Rollback()
+	_, tx := kv.NewTestTx(t)
 	sourceBucket := dbutils.Buckets[0]
 	destBucket := dbutils.Buckets[1]
 	generateTestData(t, tx, sourceBucket, 10)
-	err = Transform(
+	err := Transform(
 		"logPrefix",
-		tx.(ethdb.HasTx).Tx().(ethdb.RwTx),
+		tx,
 		sourceBucket,
 		destBucket,
 		"", // temp dir
@@ -233,18 +212,13 @@ func TestTransformThroughFiles(t *testing.T) {
 
 func TestTransformDoubleOnExtract(t *testing.T) {
 	// test invariant when extractFunc multiplies the data 2x
-	db := kv.NewTestDB(t)
-	tx, err := db.Begin(context.Background(), ethdb.RW)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer tx.Rollback()
+	_, tx := kv.NewTestTx(t)
 	sourceBucket := dbutils.Buckets[0]
 	destBucket := dbutils.Buckets[1]
 	generateTestData(t, tx, sourceBucket, 10)
-	err = Transform(
+	err := Transform(
 		"logPrefix",
-		tx.(ethdb.HasTx).Tx().(ethdb.RwTx),
+		tx,
 		sourceBucket,
 		destBucket,
 		"", // temp dir
@@ -258,18 +232,13 @@ func TestTransformDoubleOnExtract(t *testing.T) {
 
 func TestTransformDoubleOnLoad(t *testing.T) {
 	// test invariant when loadFunc multiplies the data 2x
-	db := kv.NewTestDB(t)
-	tx, err := db.Begin(context.Background(), ethdb.RW)
-	if err != nil {
-		t.Fatal(err)
-	}
-	defer tx.Rollback()
+	_, tx := kv.NewTestTx(t)
 	sourceBucket := dbutils.Buckets[0]
 	destBucket := dbutils.Buckets[1]
 	generateTestData(t, tx, sourceBucket, 10)
-	err = Transform(
+	err := Transform(
 		"logPrefix",
-		tx.(ethdb.HasTx).Tx().(ethdb.RwTx),
+		tx,
 		sourceBucket,
 		destBucket,
 		"", // temp dir
@@ -355,7 +324,7 @@ func testLoadFromMapDoubleFunc(k []byte, v []byte, _ CurrentTableReader, next Lo
 	return next(k, append(k, 0xBB), append(realValue, 0xBB))
 }
 
-func compareBuckets(t *testing.T, db ethdb.Database, b1, b2 string, startKey []byte) {
+func compareBuckets(t *testing.T, db ethdb.Tx, b1, b2 string, startKey []byte) {
 	t.Helper()
 	b1Map := make(map[string]string)
 	err := db.ForEach(b1, startKey, func(k, v []byte) error {
@@ -372,7 +341,7 @@ func compareBuckets(t *testing.T, db ethdb.Database, b1, b2 string, startKey []b
 	assert.Equal(t, b1Map, b2Map)
 }
 
-func compareBucketsDouble(t *testing.T, db ethdb.Database, b1, b2 string) {
+func compareBucketsDouble(t *testing.T, db ethdb.Tx, b1, b2 string) {
 	t.Helper()
 	b1Map := make(map[string]string)
 	err := db.ForEach(b1, nil, func(k, v []byte) error {
diff --git a/core/state/database_test.go b/core/state/database_test.go
index 913eb7c33c6d6cb82a3a4bbd5c624f0768296e3c..bf24e8349507b54f55768ee828a00427f585410d 100644
--- a/core/state/database_test.go
+++ b/core/state/database_test.go
@@ -20,11 +20,11 @@ import (
 	"bytes"
 	"context"
 	"errors"
-	"fmt"
 	"math/big"
 	"testing"
 
 	"github.com/holiman/uint256"
+	"github.com/ledgerwatch/erigon/common/dbutils"
 	"github.com/ledgerwatch/erigon/ethdb/kv"
 	"github.com/ledgerwatch/erigon/turbo/stages"
 	"github.com/ledgerwatch/erigon/turbo/trie"
@@ -34,7 +34,6 @@ import (
 	"github.com/ledgerwatch/erigon/accounts/abi/bind"
 	"github.com/ledgerwatch/erigon/accounts/abi/bind/backends"
 	"github.com/ledgerwatch/erigon/common"
-	"github.com/ledgerwatch/erigon/common/dbutils"
 	"github.com/ledgerwatch/erigon/core"
 	"github.com/ledgerwatch/erigon/core/rawdb"
 	"github.com/ledgerwatch/erigon/core/state"
@@ -72,8 +71,6 @@ func TestCreate2Revive(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -132,23 +129,31 @@ func TestCreate2Revive(t *testing.T) {
 		t.Fatalf("generate blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 2
 	if err = m.InsertChain(chain.Slice(1, 2)); err != nil {
@@ -165,26 +170,36 @@ func TestCreate2Revive(t *testing.T) {
 	if it.Event.D != create2address {
 		t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(create2address) {
-		t.Error("expected create2address to exist at the block 2", create2address.String())
-	}
-	// We expect number 0x42 in the position [2], because it is the block number 2
-	key2 := common.BigToHash(big.NewInt(2))
+
+	var key2 common.Hash
 	var check2 uint256.Int
-	st.GetState(create2address, &key2, &check2)
-	if check2.Uint64() != 0x42 {
-		t.Errorf("expected 0x42 in position 2, got: %x", check2.Uint64())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(create2address) {
+			t.Error("expected create2address to exist at the block 2", create2address.String())
+		}
+		// We expect number 0x42 in the position [2], because it is the block number 2
+		key2 = common.BigToHash(big.NewInt(2))
+		st.GetState(create2address, &key2, &check2)
+		if check2.Uint64() != 0x42 {
+			t.Errorf("expected 0x42 in position 2, got: %x", check2.Uint64())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 3
 	if err = m.InsertChain(chain.Slice(2, 3)); err != nil {
 		t.Fatal(err)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if st.Exist(create2address) {
-		t.Error("expected create2address to be self-destructed at the block 3", create2address.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if st.Exist(create2address) {
+			t.Error("expected create2address to be self-destructed at the block 3", create2address.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 4
 	if err = m.InsertChain(chain.Slice(3, 4)); err != nil {
@@ -200,22 +215,27 @@ func TestCreate2Revive(t *testing.T) {
 	if it.Event.D != create2address {
 		t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(create2address) {
-		t.Error("expected create2address to exist at the block 2", create2address.String())
-	}
-	// We expect number 0x42 in the position [4], because it is the block number 4
-	key4 := common.BigToHash(big.NewInt(4))
-	var check4 uint256.Int
-	st.GetState(create2address, &key4, &check4)
-	if check4.Uint64() != 0x42 {
-		t.Errorf("expected 0x42 in position 4, got: %x", check4.Uint64())
-	}
-	// We expect number 0x0 in the position [2], because it is the block number 4
-	st.GetState(create2address, &key2, &check2)
-	if !check2.IsZero() {
-		t.Errorf("expected 0x0 in position 2, got: %x", check2)
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(create2address) {
+			t.Error("expected create2address to exist at the block 2", create2address.String())
+		}
+		// We expect number 0x42 in the position [4], because it is the block number 4
+		key4 := common.BigToHash(big.NewInt(4))
+		var check4 uint256.Int
+		st.GetState(create2address, &key4, &check4)
+		if check4.Uint64() != 0x42 {
+			t.Errorf("expected 0x42 in position 4, got: %x", check4.Uint64())
+		}
+		// We expect number 0x0 in the position [2], because it is the block number 4
+		st.GetState(create2address, &key2, &check2)
+		if !check2.IsZero() {
+			t.Errorf("expected 0x0 in position 2, got: %x", check2)
+		}
+		return nil
+	})
+	require.NoError(t, err)
+
 }
 
 // Polymorthic contracts via CREATE2
@@ -243,8 +263,6 @@ func TestCreate2Polymorth(t *testing.T) {
 		signer = types.LatestSignerForChainID(nil)
 	)
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -337,23 +355,33 @@ func TestCreate2Polymorth(t *testing.T) {
 		t.Fatalf("generate blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 2
 	if err = m.InsertChain(chain.Slice(1, 2)); err != nil {
@@ -370,25 +398,33 @@ func TestCreate2Polymorth(t *testing.T) {
 	if it.Event.D != create2address {
 		t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(create2address) {
-		t.Error("expected create2address to exist at the block 2", create2address.String())
-	}
-	if !bytes.Equal(st.GetCode(create2address), common.FromHex("6002ff")) {
-		t.Errorf("Expected CREATE2 deployed code 6002ff, got %x", st.GetCode(create2address))
-	}
-	if st.GetIncarnation(create2address) != 1 {
-		t.Errorf("expected incarnation 1, got %d", st.GetIncarnation(create2address))
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(create2address) {
+			t.Error("expected create2address to exist at the block 2", create2address.String())
+		}
+		if !bytes.Equal(st.GetCode(create2address), common.FromHex("6002ff")) {
+			t.Errorf("Expected CREATE2 deployed code 6002ff, got %x", st.GetCode(create2address))
+		}
+		if st.GetIncarnation(create2address) != 1 {
+			t.Errorf("expected incarnation 1, got %d", st.GetIncarnation(create2address))
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 3
 	if err = m.InsertChain(chain.Slice(2, 3)); err != nil {
 		t.Fatal(err)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if st.Exist(create2address) {
-		t.Error("expected create2address to be self-destructed at the block 3", create2address.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if st.Exist(create2address) {
+			t.Error("expected create2address to be self-destructed at the block 3", create2address.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 4
 	if err = m.InsertChain(chain.Slice(3, 4)); err != nil {
@@ -404,16 +440,21 @@ func TestCreate2Polymorth(t *testing.T) {
 	if it.Event.D != create2address {
 		t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(create2address) {
-		t.Error("expected create2address to exist at the block 4", create2address.String())
-	}
-	if !bytes.Equal(st.GetCode(create2address), common.FromHex("6004ff")) {
-		t.Errorf("Expected CREATE2 deployed code 6004ff, got %x", st.GetCode(create2address))
-	}
-	if st.GetIncarnation(create2address) != 2 {
-		t.Errorf("expected incarnation 2, got %d", st.GetIncarnation(create2address))
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(create2address) {
+			t.Error("expected create2address to exist at the block 4", create2address.String())
+		}
+		if !bytes.Equal(st.GetCode(create2address), common.FromHex("6004ff")) {
+			t.Errorf("Expected CREATE2 deployed code 6004ff, got %x", st.GetCode(create2address))
+		}
+		if st.GetIncarnation(create2address) != 2 {
+			t.Errorf("expected incarnation 2, got %d", st.GetIncarnation(create2address))
+		}
+
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 5
 	if err = m.InsertChain(chain.Slice(4, 5)); err != nil {
@@ -429,16 +470,21 @@ func TestCreate2Polymorth(t *testing.T) {
 	if it.Event.D != create2address {
 		t.Errorf("Wrong create2address: %x, expected %x", it.Event.D, create2address)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(create2address) {
-		t.Error("expected create2address to exist at the block 5", create2address.String())
-	}
-	if !bytes.Equal(st.GetCode(create2address), common.FromHex("6005ff")) {
-		t.Errorf("Expected CREATE2 deployed code 6005ff, got %x", st.GetCode(create2address))
-	}
-	if st.GetIncarnation(create2address) != 4 {
-		t.Errorf("expected incarnation 4 (two self-destructs and two-recreations within a block), got %d", st.GetIncarnation(create2address))
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(create2address) {
+			t.Error("expected create2address to exist at the block 5", create2address.String())
+		}
+		if !bytes.Equal(st.GetCode(create2address), common.FromHex("6005ff")) {
+			t.Errorf("Expected CREATE2 deployed code 6005ff, got %x", st.GetCode(create2address))
+		}
+		if st.GetIncarnation(create2address) != 4 {
+			t.Errorf("expected incarnation 4 (two self-destructs and two-recreations within a block), got %d", st.GetIncarnation(create2address))
+		}
+		return nil
+	})
+	require.NoError(t, err)
+
 }
 
 func TestReorgOverSelfDestruct(t *testing.T) {
@@ -464,8 +510,6 @@ func TestReorgOverSelfDestruct(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -529,54 +573,68 @@ func TestReorgOverSelfDestruct(t *testing.T) {
 		t.Fatalf("generate long blocks")
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
 
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
-
-	// Remember value of field "x" (storage item 0) after the first block, to check after rewinding
 	var key0 common.Hash
 	var correctValueX uint256.Int
-	st.GetState(contractAddress, &key0, &correctValueX)
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+
+		// Remember value of field "x" (storage item 0) after the first block, to check after rewinding
+		st.GetState(contractAddress, &key0, &correctValueX)
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCKS 2 + 3
 	if err = m.InsertChain(chain.Slice(1, chain.Length)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist at the block 3", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist at the block 3", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// REORG of block 2 and 3, and insert new (empty) BLOCK 2, 3, and 4
 	if err = m.InsertChain(longerChain.Slice(1, 4)); err != nil {
 		t.Fatal(err)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 4", contractAddress.String())
-	}
-
-	st = state.New(state.NewPlainStateReader(db))
-	var valueX uint256.Int
-	st.GetState(contractAddress, &key0, &valueX)
-	if valueX != correctValueX {
-		t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX)
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 4", contractAddress.String())
+		}
+		var valueX uint256.Int
+		st.GetState(contractAddress, &key0, &valueX)
+		if valueX != correctValueX {
+			t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 func TestReorgOverStateChange(t *testing.T) {
@@ -602,8 +660,6 @@ func TestReorgOverStateChange(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -660,28 +716,36 @@ func TestReorgOverStateChange(t *testing.T) {
 		t.Fatalf("generate longer blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
-
-	// Remember value of field "x" (storage item 0) after the first block, to check after rewinding
 	var key0 common.Hash
 	var correctValueX uint256.Int
-	st.GetState(contractAddress, &key0, &correctValueX)
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+
+		// Remember value of field "x" (storage item 0) after the first block, to check after rewinding
+		st.GetState(contractAddress, &key0, &correctValueX)
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 2
 	if err = m.InsertChain(chain.Slice(1, chain.Length)); err != nil {
@@ -692,18 +756,22 @@ func TestReorgOverStateChange(t *testing.T) {
 	if err = m.InsertChain(longerChain.Slice(1, 3)); err != nil {
 		t.Fatal(err)
 	}
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 4", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 4", contractAddress.String())
+		}
+
+		// Reload blockchain from the database
+		var valueX uint256.Int
+		st.GetState(contractAddress, &key0, &valueX)
+		if valueX != correctValueX {
+			t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
-	// Reload blockchain from the database
-	st = state.New(state.NewPlainStateReader(db))
-	var valueX uint256.Int
-	st.GetState(contractAddress, &key0, &valueX)
-	if valueX != correctValueX {
-		t.Fatalf("storage value has changed after reorg: %x, expected %x", valueX, correctValueX)
-	}
 }
 
 type BucketsStats struct {
@@ -746,8 +814,6 @@ func TestCreateOnExistingStorage(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	var err error
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
@@ -760,6 +826,7 @@ func TestCreateOnExistingStorage(t *testing.T) {
 	transactOpts.GasLimit = 1000000
 
 	var contractAddress common.Address
+
 	// There is one block, and it ends up deploying Revive contract (could be any other contract, it does not really matter)
 	// On the address contractAddr, where there is a storage item in the genesis, but no contract code
 	// We expect the pre-existing storage items to be removed by the deployment
@@ -780,31 +847,38 @@ func TestCreateOnExistingStorage(t *testing.T) {
 		t.Fatalf("generate blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if contractAddress != contractAddr {
-		t.Errorf("expected contract address to be %x, got: %x", contractAddr, contractAddress)
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if contractAddress != contractAddr {
+			t.Errorf("expected contract address to be %x, got: %x", contractAddr, contractAddress)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
-
 	var key0 common.Hash
 	var check0 uint256.Int
-	st.GetState(contractAddress, &key0, &check0)
-	fmt.Printf("c:%t,%x\n", check0.IsZero(), check0.Bytes())
-	if !check0.IsZero() {
-		t.Errorf("expected 0x00 in position 0, got: %x", check0.Bytes())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+
+		st.GetState(contractAddress, &key0, &check0)
+		if !check0.IsZero() {
+			t.Errorf("expected 0x00 in position 0, got: %x", check0.Bytes())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 func TestReproduceCrash(t *testing.T) {
@@ -821,9 +895,9 @@ func TestReproduceCrash(t *testing.T) {
 	storageKey2 := common.HexToHash("0x0e4c0e7175f9d22279a4f63ff74f7fa28b7a954a6454debaa62ce43dd9132542")
 	value2 := uint256.NewInt(0x58c00a51)
 
-	db := kv.NewTestDB(t)
-	tsw := state.NewPlainStateWriter(db, nil, 0)
-	intraBlockState := state.New(state.NewPlainStateReader(db))
+	_, tx := kv.NewTestTx(t)
+	tsw := state.NewPlainStateWriter(tx, nil, 0)
+	intraBlockState := state.New(state.NewPlainKvState(tx, 0))
 	// Start the 1st transaction
 	intraBlockState.CreateAccount(contract, true)
 	if err := intraBlockState.FinalizeTx(params.Rules{}, tsw); err != nil {
@@ -873,8 +947,6 @@ func TestEip2200Gas(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -911,30 +983,39 @@ func TestEip2200Gas(t *testing.T) {
 		t.Fatalf("generate blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
-	}
-	balanceBefore := st.GetBalance(address)
+	var balanceBefore *uint256.Int
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+		}
+		balanceBefore = st.GetBalance(address)
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
-	balanceAfter := st.GetBalance(address)
-	gasSpent := big.NewInt(0).Sub(balanceBefore.ToBig(), balanceAfter.ToBig())
-	expectedGasSpent := big.NewInt(190373) //(192245) // In the incorrect version, it is 179645
-	if gasSpent.Cmp(expectedGasSpent) != 0 {
-		t.Errorf("Expected gas spent: %d, got %d", expectedGasSpent, gasSpent)
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+		balanceAfter := st.GetBalance(address)
+		gasSpent := big.NewInt(0).Sub(balanceBefore.ToBig(), balanceAfter.ToBig())
+		expectedGasSpent := big.NewInt(190373) //(192245) // In the incorrect version, it is 179645
+		if gasSpent.Cmp(expectedGasSpent) != 0 {
+			t.Errorf("Expected gas spent: %d, got %d", expectedGasSpent, gasSpent)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 //Create contract, drop trie, reload trie from disk and add block with contract call
@@ -959,8 +1040,6 @@ func TestWrongIncarnation(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -994,63 +1073,63 @@ func TestWrongIncarnation(t *testing.T) {
 		t.Fatalf("generate blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
-	if st.Exist(contractAddress) {
-		t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		if st.Exist(contractAddress) {
+			t.Error("expected contractAddress to not exist before block 0", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
 		t.Fatal(err)
 	}
 
-	addrHash := crypto.Keccak256(contractAddress[:])
 	var acc accounts.Account
-	ok, err := rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !ok {
-		t.Fatal(errors.New("acc not found"))
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		ok, err := rawdb.ReadAccount(tx, contractAddress, &acc)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !ok {
+			t.Fatal(errors.New("acc not found"))
+		}
 
-	if acc.Incarnation != state.FirstContractIncarnation {
-		t.Fatal("Incorrect incarnation", acc.Incarnation)
-	}
+		if acc.Incarnation != state.FirstContractIncarnation {
+			t.Fatal("Incorrect incarnation", acc.Incarnation)
+		}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCKS 2
 	if err = m.InsertChain(chain.Slice(1, 2)); err != nil {
 		t.Fatal(err)
 	}
-	addrHash = crypto.Keccak256(contractAddress[:])
-	ok, err = rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !ok {
-		t.Fatal(errors.New("acc not found"))
-	}
-	if acc.Incarnation != state.FirstContractIncarnation {
-		t.Fatal("Incorrect incarnation", acc.Incarnation)
-	}
-
-	var startKey [common.HashLength + 8 + common.HashLength]byte
-	copy(startKey[:], addrHash)
-	err = db.Walk(dbutils.HashedStorageBucket, startKey[:], 8*common.HashLength, func(k, v []byte) (bool, error) {
-		fmt.Printf("%x: %x\n", k, v)
-		return true, nil
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		ok, err := rawdb.ReadAccount(tx, contractAddress, &acc)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !ok {
+			t.Fatal(errors.New("acc not found"))
+		}
+		if acc.Incarnation != state.FirstContractIncarnation {
+			t.Fatal("Incorrect incarnation", acc.Incarnation)
+		}
+		return nil
 	})
-	if err != nil {
-		t.Fatal(err)
-	}
+	require.NoError(t, err)
 }
 
 //create acc, deploy to it contract, reorg to state without contract
@@ -1078,8 +1157,6 @@ func TestWrongIncarnation2(t *testing.T) {
 	knownContractAddress := common.HexToAddress("0xdb7d6ab1f17c6b31909ae466702703daef9269cf")
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
@@ -1145,10 +1222,14 @@ func TestWrongIncarnation2(t *testing.T) {
 		t.Fatalf("generate longer blocks: %v", err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(address) {
-		t.Error("expected account to exist")
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(address) {
+			t.Error("expected account to exist")
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// BLOCK 1
 	if err = m.InsertChain(chain.Slice(0, 1)); err != nil {
@@ -1160,38 +1241,45 @@ func TestWrongIncarnation2(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(contractAddress) {
-		t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
-	}
-
-	addrHash := crypto.Keccak256(contractAddress[:])
 	var acc accounts.Account
-	ok, err := rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !ok {
-		t.Fatal(errors.New("acc not found"))
-	}
-	if acc.Incarnation != state.FirstContractIncarnation {
-		t.Fatal("wrong incarnation")
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(contractAddress) {
+			t.Error("expected contractAddress to exist at the block 1", contractAddress.String())
+		}
+
+		ok, err := rawdb.ReadAccount(tx, contractAddress, &acc)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !ok {
+			t.Fatal(errors.New("acc not found"))
+		}
+		if acc.Incarnation != state.FirstContractIncarnation {
+			t.Fatal("wrong incarnation")
+		}
+		return nil
+	})
+	require.NoError(t, err)
 	// REORG of block 2 and 3, and insert new (empty) BLOCK 2, 3, and 4
 	if err = m.InsertChain(longerChain.Slice(1, longerChain.Length)); err != nil {
 		t.Fatal(err)
 	}
 
-	ok, err = rawdb.ReadAccountDeprecated(db, common.BytesToHash(addrHash), &acc)
-	if err != nil {
-		t.Fatal(err)
-	}
-	if !ok {
-		t.Fatal(errors.New("acc not found"))
-	}
-	if acc.Incarnation != state.NonContractIncarnation {
-		t.Fatal("wrong incarnation", acc.Incarnation)
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		ok, err := rawdb.ReadAccount(tx, contractAddress, &acc)
+		if err != nil {
+			t.Fatal(err)
+		}
+		if !ok {
+			t.Fatal(errors.New("acc not found"))
+		}
+		if acc.Incarnation != state.NonContractIncarnation {
+			t.Fatal("wrong incarnation", acc.Incarnation)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 }
 
@@ -1239,8 +1327,8 @@ func TestCacheCodeSizeSeparately(t *testing.T) {
 	contract := common.HexToAddress("0x71dd1027069078091B3ca48093B00E4735B20624")
 	//root := common.HexToHash("0xb939e5bcf5809adfb87ab07f0795b05b95a1d64a90f0eddd0c3123ac5b433854")
 
-	db := kv.NewTestDB(t)
-	r, w := state.NewPlainStateReader(db), state.NewPlainStateWriter(db, nil, 0)
+	_, tx := kv.NewTestTx(t)
+	r, w := state.NewPlainKvState(tx, 0), state.NewPlainStateWriter(tx, nil, 0)
 	intraBlockState := state.New(r)
 	// Start the 1st transaction
 	intraBlockState.CreateAccount(contract, true)
@@ -1272,10 +1360,9 @@ func TestCacheCodeSizeInTrie(t *testing.T) {
 	contract := common.HexToAddress("0x71dd1027069078091B3ca48093B00E4735B20624")
 	root := common.HexToHash("0xb939e5bcf5809adfb87ab07f0795b05b95a1d64a90f0eddd0c3123ac5b433854")
 
-	db := kv.NewTestDB(t)
-	r, w := state.NewPlainStateReader(db), state.NewPlainStateWriter(db, nil, 0)
+	_, tx := kv.NewTestTx(t)
+	r, w := state.NewPlainKvState(tx, 0), state.NewPlainStateWriter(tx, nil, 0)
 	intraBlockState := state.New(r)
-	ctx := context.Background()
 	// Start the 1st transaction
 	intraBlockState.CreateAccount(contract, true)
 
@@ -1290,32 +1377,24 @@ func TestCacheCodeSizeInTrie(t *testing.T) {
 		t.Errorf("error committing block: %v", err)
 	}
 
-	err := db.RwKV().View(ctx, func(tx ethdb.Tx) error {
-		r2, err := trie.CalcRoot("test", tx)
-		require.NoError(t, err)
-		require.Equal(t, root, r2)
-		return nil
-	})
+	r2, err := trie.CalcRoot("test", tx)
 	require.NoError(t, err)
+	require.Equal(t, root, r2)
 
 	codeHash := common.BytesToHash(crypto.Keccak256(code))
 	codeSize, err := r.ReadAccountCodeSize(contract, 1, codeHash)
 	assert.NoError(t, err, "you can receive the code size ")
 	assert.Equal(t, len(code), codeSize, "you can receive the code size")
 
-	assert.NoError(t, db.Delete(dbutils.CodeBucket, codeHash[:], nil), nil)
+	assert.NoError(t, tx.Delete(dbutils.CodeBucket, codeHash[:], nil), nil)
 
 	codeSize2, err := r.ReadAccountCodeSize(contract, 1, codeHash)
 	assert.NoError(t, err, "you can still receive code size even with empty DB")
 	assert.Equal(t, len(code), codeSize2, "code size should be received even with empty DB")
 
-	err = db.RwKV().View(ctx, func(tx ethdb.Tx) error {
-		r2, err := trie.CalcRoot("test", tx)
-		require.NoError(t, err)
-		require.Equal(t, root, r2)
-		return nil
-	})
+	r2, err = trie.CalcRoot("test", tx)
 	require.NoError(t, err)
+	require.Equal(t, root, r2)
 }
 
 func TestRecreateAndRewind(t *testing.T) {
@@ -1333,8 +1412,6 @@ func TestRecreateAndRewind(t *testing.T) {
 	)
 
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 	contractBackend := backends.NewSimulatedBackendWithConfig(gspec.Alloc, gspec.Config, gspec.GasLimit)
 	defer contractBackend.Close()
 	transactOpts := bind.NewKeyedTransactor(key)
@@ -1466,45 +1543,57 @@ func TestRecreateAndRewind(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	st := state.New(state.NewPlainStateReader(db))
-	if !st.Exist(phoenixAddress) {
-		t.Errorf("expected phoenix %x to exist after first insert", phoenixAddress)
-	}
-
 	var key0 common.Hash
 	var check0 uint256.Int
-	st.GetState(phoenixAddress, &key0, &check0)
-	if check0.Cmp(uint256.NewInt(2)) != 0 {
-		t.Errorf("expected 0x02 in position 0, got: 0x%x", check0.Bytes())
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(phoenixAddress) {
+			t.Errorf("expected phoenix %x to exist after first insert", phoenixAddress)
+		}
+
+		st.GetState(phoenixAddress, &key0, &check0)
+		if check0.Cmp(uint256.NewInt(2)) != 0 {
+			t.Errorf("expected 0x02 in position 0, got: 0x%x", check0.Bytes())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// Block 3 and 4
 	if err = m.InsertChain(chain.Slice(2, chain.Length)); err != nil {
 		t.Fatal(err)
 	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(phoenixAddress) {
-		t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress)
-	}
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(phoenixAddress) {
+			t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress)
+		}
 
-	st.GetState(phoenixAddress, &key0, &check0)
-	if check0.Cmp(uint256.NewInt(1)) != 0 {
-		t.Errorf("expected 0x01 in position 0, got: 0x%x", check0.Bytes())
-	}
+		st.GetState(phoenixAddress, &key0, &check0)
+		if check0.Cmp(uint256.NewInt(1)) != 0 {
+			t.Errorf("expected 0x01 in position 0, got: 0x%x", check0.Bytes())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
 	// Reorg
 	if err = m.InsertChain(longerChain); err != nil {
 		t.Fatal(err)
 	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		st := state.New(state.NewPlainStateReader(tx))
+		if !st.Exist(phoenixAddress) {
+			t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress)
+		}
 
-	st = state.New(state.NewPlainStateReader(db))
-	if !st.Exist(phoenixAddress) {
-		t.Errorf("expected phoenix %x to exist after second insert", phoenixAddress)
-	}
+		st.GetState(phoenixAddress, &key0, &check0)
+		if check0.Cmp(uint256.NewInt(0)) != 0 {
+			t.Errorf("expected 0x00 in position 0, got: 0x%x", check0.Bytes())
+		}
+		return nil
+	})
+	require.NoError(t, err)
 
-	st.GetState(phoenixAddress, &key0, &check0)
-	if check0.Cmp(uint256.NewInt(0)) != 0 {
-		t.Errorf("expected 0x00 in position 0, got: 0x%x", check0.Bytes())
-	}
 }
diff --git a/core/state/intra_block_state_test.go b/core/state/intra_block_state_test.go
index 0d3b859d370e5116b78efa061fbc80d8fbe33dcc..8d80affd3c11a96c41376298206e338fce03a100 100644
--- a/core/state/intra_block_state_test.go
+++ b/core/state/intra_block_state_test.go
@@ -18,6 +18,7 @@ package state
 
 import (
 	"bytes"
+	"context"
 	"encoding/binary"
 	"fmt"
 	"math"
@@ -225,10 +226,16 @@ func (test *snapshotTest) String() string {
 
 func (test *snapshotTest) run() bool {
 	// Run all actions and create snapshots.
-	db := kv.NewMemDatabase()
+	db := kv.NewMemKV()
 	defer db.Close()
+	tx, err := db.BeginRw(context.Background())
+	if err != nil {
+		test.err = err
+		return false
+	}
+	defer tx.Rollback()
 	var (
-		ds           = NewDbStateReader(db)
+		ds           = NewPlainKvState(tx, 0)
 		state        = New(ds)
 		snapshotRevs = make([]int, len(test.snapshots))
 		sindex       = 0
@@ -243,7 +250,7 @@ func (test *snapshotTest) run() bool {
 	// Revert all snapshots in reverse order. Each revert must yield a state
 	// that is equivalent to fresh state with all actions up the snapshot applied.
 	for sindex--; sindex >= 0; sindex-- {
-		checkds := NewDbStateReader(db)
+		checkds := NewPlainKvState(tx, 0)
 		checkstate := New(checkds)
 		for _, action := range test.actions[:test.snapshots[sindex]] {
 			action.fn(action, checkstate)
@@ -354,8 +361,8 @@ func TestAccessList(t *testing.T) {
 		return common.HexToHash(a)
 	}
 
-	db := kv.NewTestDB(t)
-	state := New(NewPlainStateReader(db))
+	_, tx := kv.NewTestTx(t)
+	state := New(NewPlainKvState(tx, 0))
 	state.accessList = newAccessList()
 
 	verifyAddrs := func(astrings ...string) {
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 7a7df83f68d7f612e4f38d03c4579b2b99b75ea2..3c11e5b86112cdac1279ae29182831f6a0066642 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -35,8 +35,8 @@ import (
 var toAddr = common.BytesToAddress
 
 type StateSuite struct {
-	db    ethdb.Database
-	kv    ethdb.RwKV // Same as db, but with a different interface
+	kv    ethdb.RwKV
+	tx    ethdb.RwTx
 	state *IntraBlockState
 	r     StateReader
 	w     StateWriter
@@ -102,14 +102,22 @@ func (s *StateSuite) TestDump(c *checker.C) {
 }
 
 func (s *StateSuite) SetUpTest(c *checker.C) {
-	db := kv.NewMemDatabase()
-	s.db = db
-	s.kv = db.RwKV()
-	s.r = NewDbStateReader(s.db)
-	s.w = NewDbStateWriter(s.db, 0)
+	s.kv = kv.NewMemKV()
+	tx, err := s.kv.BeginRw(context.Background())
+	if err != nil {
+		panic(err)
+	}
+	s.tx = tx
+	s.r = NewPlainKvState(tx, 0)
+	s.w = NewPlainKvState(tx, 0)
 	s.state = New(s.r)
 }
 
+func (s *StateSuite) TearDownTest(c *checker.C) {
+	s.tx.Rollback()
+	s.kv.Close()
+}
+
 func (s *StateSuite) TestNull(c *checker.C) {
 	address := common.HexToAddress("0x823140710bf13990e4500136726d8b55")
 	s.state.CreateAccount(address, true)
@@ -168,10 +176,9 @@ func (s *StateSuite) TestSnapshotEmpty(c *checker.C) {
 // use testing instead of checker because checker does not support
 // printing/logging in tests (-check.vv does not work)
 func TestSnapshot2(t *testing.T) {
-
-	db := kv.NewMemDatabase()
-	w := NewDbStateWriter(db, 0)
-	state := New(NewDbStateReader(db))
+	_, tx := kv.NewTestTx(t)
+	w := NewPlainKvState(tx, 0)
+	state := New(NewPlainKvState(tx, 0))
 
 	stateobjaddr0 := toAddr([]byte("so0"))
 	stateobjaddr1 := toAddr([]byte("so1"))
@@ -196,7 +203,7 @@ func TestSnapshot2(t *testing.T) {
 	if err != nil {
 		t.Fatal("error while finalizing transaction", err)
 	}
-	w = NewDbStateWriter(db, 1)
+	w = NewPlainKvState(tx, 1)
 
 	err = state.CommitBlock(params.Rules{}, w)
 	if err != nil {
diff --git a/core/vm/runtime/runtime_test.go b/core/vm/runtime/runtime_test.go
index 627f2d7828ce57ebdfe18ddabd7b85519214b51c..375be3e84ca530d340b982cf15920af8f164c9b7 100644
--- a/core/vm/runtime/runtime_test.go
+++ b/core/vm/runtime/runtime_test.go
@@ -159,10 +159,9 @@ func BenchmarkCall(b *testing.B) {
 	}
 }
 func benchmarkEVM_Create(bench *testing.B, code string) {
-	db := kv.NewMemDatabase()
-	defer db.Close()
+	_, tx := kv.NewTestTx(bench)
 	var (
-		statedb  = state.New(state.NewPlainStateReader(db))
+		statedb  = state.New(state.NewPlainKvState(tx, 0))
 		sender   = common.BytesToAddress([]byte("sender"))
 		receiver = common.BytesToAddress([]byte("receiver"))
 	)
@@ -330,9 +329,8 @@ func TestBlockhash(t *testing.T) {
 func benchmarkNonModifyingCode(gas uint64, code []byte, name string, b *testing.B) { //nolint:unparam
 	cfg := new(Config)
 	setDefaults(cfg)
-	db := kv.NewMemDatabase()
-	defer db.Close()
-	cfg.State = state.New(state.NewDbStateReader(db))
+	_, tx := kv.NewTestTx(b)
+	cfg.State = state.New(state.NewPlainKvState(tx, 0))
 	cfg.GasLimit = gas
 	var (
 		destination = common.BytesToAddress([]byte("contract"))
diff --git a/eth/fetcher/block_fetcher_test.go b/eth/fetcher/block_fetcher_test.go
index 13da00a43a3c9f5779a5245d199f6fe734ce4854..eb9d53f3b66d3ce0780f3bffdc56fc8f3739cd0f 100644
--- a/eth/fetcher/block_fetcher_test.go
+++ b/eth/fetcher/block_fetcher_test.go
@@ -36,10 +36,10 @@ import (
 )
 
 var (
-	testdb       = kv.NewMemDatabase()
+	testdb       = kv.NewMemKV()
 	testKey, _   = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
 	testAddress  = crypto.PubkeyToAddress(testKey.PublicKey)
-	genesis      = core.GenesisBlockForTesting(testdb.RwKV(), testAddress, big.NewInt(1000000000))
+	genesis      = core.GenesisBlockForTesting(testdb, testAddress, big.NewInt(1000000000))
 	unknownBlock = types.NewBlock(&types.Header{GasLimit: params.GenesisGasLimit}, nil, nil, nil)
 )
 
diff --git a/eth/stagedsync/stage_indexes_test.go b/eth/stagedsync/stage_indexes_test.go
index bad6f56566ea189cbef2657bab996c65dd7041e4..e23e5ee1fb9feac1de3e10b205e1fa3bc33ed841 100644
--- a/eth/stagedsync/stage_indexes_test.go
+++ b/eth/stagedsync/stage_indexes_test.go
@@ -25,10 +25,8 @@ import (
 
 func TestIndexGenerator_GenerateIndex_SimpleCase(t *testing.T) {
 	log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StreamHandler(os.Stderr, log.TerminalFormat(true))))
-	db := kv2.NewMemDatabase()
-	defer db.Close()
-	kv := db.RwKV()
-	cfg := StageHistoryCfg(db.RwKV(), t.TempDir())
+	kv := kv2.NewTestKV(t)
+	cfg := StageHistoryCfg(kv, t.TempDir())
 	test := func(blocksNum int, csBucket string) func(t *testing.T) {
 		return func(t *testing.T) {
 			tx, err := kv.BeginRw(context.Background())
diff --git a/ethdb/kv/kv_mdbx.go b/ethdb/kv/kv_mdbx.go
index 08716a4b45541070894d2f1171e339862786c189..d2f43f09d665b0d4040d8a7639de7b51183dcf0f 100644
--- a/ethdb/kv/kv_mdbx.go
+++ b/ethdb/kv/kv_mdbx.go
@@ -24,8 +24,6 @@ import (
 	"github.com/torquem-ch/mdbx-go/mdbx"
 )
 
-var _ DbCopier = &MdbxKV{}
-
 const expectMdbxVersionMajor = 0
 const expectMdbxVersionMinor = 10
 const pageSize = 4 * 1024
@@ -306,11 +304,6 @@ type MdbxKV struct {
 	txSize  uint64
 }
 
-func (db *MdbxKV) NewDbWithTheSameParameters() *ObjectDatabase {
-	opts := db.opts
-	return NewObjectDatabase(NewMDBX().Set(opts).MustOpen())
-}
-
 // Close closes db
 // All transactions must be closed before closing the database.
 func (db *MdbxKV) Close() {
diff --git a/ethdb/kv/mutation.go b/ethdb/kv/mutation.go
index fafa3261a164ddc761dd2032252e77f909114069..48702e85832de016e634a320559e5afc620fad1a 100644
--- a/ethdb/kv/mutation.go
+++ b/ethdb/kv/mutation.go
@@ -356,11 +356,6 @@ func (m *mutation) panicOnEmptyDB() {
 	}
 }
 
-func (m *mutation) MemCopy() ethdb.Database {
-	m.panicOnEmptyDB()
-	return m.db
-}
-
 func (m *mutation) SetRwKV(kv ethdb.RwKV) {
 	m.db.(ethdb.HasRwKV).SetRwKV(kv)
 }
diff --git a/ethdb/kv/object_db.go b/ethdb/kv/object_db.go
index 6287c08039f61afb8c0d3395b917f5f193bca413..1851cfc9ea27a58df82f5816fa4cecc6b0870dfa 100644
--- a/ethdb/kv/object_db.go
+++ b/ethdb/kv/object_db.go
@@ -24,16 +24,11 @@ import (
 
 	"github.com/google/btree"
 	"github.com/ledgerwatch/erigon/common"
-	"github.com/ledgerwatch/erigon/common/dbutils"
 	"github.com/ledgerwatch/erigon/ethdb"
 	"github.com/ledgerwatch/erigon/log"
 	"github.com/torquem-ch/mdbx-go/mdbx"
 )
 
-type DbCopier interface {
-	NewDbWithTheSameParameters() *ObjectDatabase
-}
-
 // ObjectDatabase - is an object-style interface of DB accessing
 type ObjectDatabase struct {
 	kv ethdb.RwKV
@@ -288,48 +283,6 @@ func (db *ObjectDatabase) SetRwKV(kv ethdb.RwKV) {
 	db.kv = kv
 }
 
-func (db *ObjectDatabase) MemCopy() *ObjectDatabase {
-	var mem *ObjectDatabase
-	// Open the db and recover any potential corruptions
-	switch t := db.kv.(type) {
-	case DbCopier:
-		mem = t.NewDbWithTheSameParameters()
-	default:
-		panic(fmt.Sprintf("MemCopy is not implemented for type %T", t))
-	}
-
-	if err := db.kv.View(context.Background(), func(readTx ethdb.Tx) error {
-		for _, name := range dbutils.Buckets {
-			name := name
-			if err := mem.kv.Update(context.Background(), func(writeTx ethdb.RwTx) error {
-				newBucketToWrite, err := writeTx.RwCursor(name)
-				if err != nil {
-					return err
-				}
-				defer newBucketToWrite.Close()
-				readC, err := readTx.Cursor(name)
-				if err != nil {
-					return err
-				}
-				defer readC.Close()
-				return ethdb.ForEach(readC, func(k, v []byte) (bool, error) {
-					if err := newBucketToWrite.Put(common.CopyBytes(k), common.CopyBytes(v)); err != nil {
-						return false, err
-					}
-					return true, nil
-				})
-			}); err != nil {
-				return err
-			}
-		}
-		return nil
-	}); err != nil {
-		panic(err)
-	}
-
-	return mem
-}
-
 func (db *ObjectDatabase) NewBatch() ethdb.DbWithPendingMutations {
 	m := &mutation{
 		db:   db,
diff --git a/migrations/migrations.go b/migrations/migrations.go
index e398479e8f7705206206812b24bfacf4019fe816..e8081e580a9000e3f1556ad4d544cdb1a76f1b0d 100644
--- a/migrations/migrations.go
+++ b/migrations/migrations.go
@@ -248,7 +248,7 @@ func (m *Migrator) Apply(kv ethdb.RwKV, datadir string) error {
 	return nil
 }
 
-func MarshalMigrationPayload(db ethdb.Getter) ([]byte, error) {
+func MarshalMigrationPayload(db ethdb.KVGetter) ([]byte, error) {
 	s := map[string][]byte{}
 
 	buf := bytes.NewBuffer(nil)
diff --git a/migrations/migrations_test.go b/migrations/migrations_test.go
index c31027b6bee1a75ef10549eb32e32b4841a6060e..191a2919f77821fe1bdc6c92fdf26c8d051434f9 100644
--- a/migrations/migrations_test.go
+++ b/migrations/migrations_test.go
@@ -169,12 +169,13 @@ func TestWhenNonFirstMigrationAlreadyApplied(t *testing.T) {
 }
 
 func TestMarshalStages(t *testing.T) {
-	require, db := require.New(t), kv.NewTestDB(t)
+	require := require.New(t)
+	_, tx := kv.NewTestTx(t)
 
-	err := stages.SaveStageProgress(db, stages.Execution, 42)
+	err := stages.SaveStageProgress(tx, stages.Execution, 42)
 	require.NoError(err)
 
-	data, err := MarshalMigrationPayload(db)
+	data, err := MarshalMigrationPayload(tx)
 	require.NoError(err)
 
 	res, err := UnmarshalMigrationPayload(data)
diff --git a/turbo/stages/blockchain_test.go b/turbo/stages/blockchain_test.go
index 4c7c48825088c50d22f646afc0391910ed26be0c..f08b93ea548bd1f1be09907af2ce27290ef75518 100644
--- a/turbo/stages/blockchain_test.go
+++ b/turbo/stages/blockchain_test.go
@@ -364,8 +364,6 @@ func testBadHashes(t *testing.T) {
 	t.Skip("to support this error in Erigon")
 	// Create a pristine chain and database
 	m := newCanonical(t, 0)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 	var err error
 
 	// Create a chain, ban a hash and try to import
@@ -1271,8 +1269,6 @@ func TestDeleteRecreateSlots(t *testing.T) {
 		},
 	}
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 	chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) {
 		b.SetCoinbase(common.Address{1})
 		// One transaction to AA, to kill it
@@ -1291,31 +1287,35 @@ func TestDeleteRecreateSlots(t *testing.T) {
 	if err := m.InsertChain(chain); err != nil {
 		t.Fatalf("failed to insert into chain: %v", err)
 	}
-	statedb := state.New(state.NewDbStateReader(db))
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		statedb := state.New(state.NewPlainKvState(tx, 1))
 
-	// If all is correct, then slot 1 and 2 are zero
-	key1 := common.HexToHash("01")
-	var got uint256.Int
-	statedb.GetState(aa, &key1, &got)
-	if !got.IsZero() {
-		t.Errorf("got %d exp %d", got.Uint64(), 0)
-	}
-	key2 := common.HexToHash("02")
-	statedb.GetState(aa, &key2, &got)
-	if !got.IsZero() {
-		t.Errorf("got %d exp %d", got.Uint64(), 0)
-	}
-	// Also, 3 and 4 should be set
-	key3 := common.HexToHash("03")
-	statedb.GetState(aa, &key3, &got)
-	if got.Uint64() != 3 {
-		t.Errorf("got %d exp %d", got.Uint64(), 3)
-	}
-	key4 := common.HexToHash("04")
-	statedb.GetState(aa, &key4, &got)
-	if got.Uint64() != 4 {
-		t.Errorf("got %d exp %d", got.Uint64(), 4)
-	}
+		// If all is correct, then slot 1 and 2 are zero
+		key1 := common.HexToHash("01")
+		var got uint256.Int
+		statedb.GetState(aa, &key1, &got)
+		if !got.IsZero() {
+			t.Errorf("got %d exp %d", got.Uint64(), 0)
+		}
+		key2 := common.HexToHash("02")
+		statedb.GetState(aa, &key2, &got)
+		if !got.IsZero() {
+			t.Errorf("got %d exp %d", got.Uint64(), 0)
+		}
+		// Also, 3 and 4 should be set
+		key3 := common.HexToHash("03")
+		statedb.GetState(aa, &key3, &got)
+		if got.Uint64() != 3 {
+			t.Errorf("got %d exp %d", got.Uint64(), 3)
+		}
+		key4 := common.HexToHash("04")
+		statedb.GetState(aa, &key4, &got)
+		if got.Uint64() != 4 {
+			t.Errorf("got %d exp %d", got.Uint64(), 4)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 // TestDeleteRecreateAccount tests a state-transition that contains deletion of a
@@ -1353,8 +1353,6 @@ func TestDeleteRecreateAccount(t *testing.T) {
 		},
 	}
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) {
 		b.SetCoinbase(common.Address{1})
@@ -1374,20 +1372,24 @@ func TestDeleteRecreateAccount(t *testing.T) {
 	if err := m.InsertChain(chain); err != nil {
 		t.Fatalf("failed to insert into chain: %v", err)
 	}
-	statedb := state.New(state.NewDbStateReader(db))
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		statedb := state.New(state.NewPlainKvState(tx, 1))
 
-	// If all is correct, then both slots are zero
-	key1 := common.HexToHash("01")
-	var got uint256.Int
-	statedb.GetState(aa, &key1, &got)
-	if !got.IsZero() {
-		t.Errorf("got %x exp %x", got, 0)
-	}
-	key2 := common.HexToHash("02")
-	statedb.GetState(aa, &key2, &got)
-	if !got.IsZero() {
-		t.Errorf("got %x exp %x", got, 0)
-	}
+		// If all is correct, then both slots are zero
+		key1 := common.HexToHash("01")
+		var got uint256.Int
+		statedb.GetState(aa, &key1, &got)
+		if !got.IsZero() {
+			t.Errorf("got %x exp %x", got, 0)
+		}
+		key2 := common.HexToHash("02")
+		statedb.GetState(aa, &key2, &got)
+		if !got.IsZero() {
+			t.Errorf("got %x exp %x", got, 0)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 // TestDeleteRecreateSlotsAcrossManyBlocks tests multiple state-transition that contains both deletion
@@ -1664,8 +1666,6 @@ func TestInitThenFailCreateContract(t *testing.T) {
 		},
 	}
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 	nonce := uint64(0)
 
 	chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 4, func(i int, b *core.BlockGen) {
@@ -1680,28 +1680,33 @@ func TestInitThenFailCreateContract(t *testing.T) {
 		t.Fatalf("generate blocks: %v", err)
 	}
 
-	// Import the canonical chain
-	statedb := state.New(state.NewPlainStateReader(db))
-	if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp {
-		t.Fatalf("Genesis err, got %v exp %v", got, exp)
-	}
-	// First block tries to create, but fails
-	{
-		block := chain.Blocks[0]
-		if err := m.InsertChain(chain.Slice(0, 1)); err != nil {
-			t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
-		}
-		statedb = state.New(state.NewPlainStateReader(db))
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+
+		// Import the canonical chain
+		statedb := state.New(state.NewPlainKvState(tx, 1))
 		if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp {
-			t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp)
+			t.Fatalf("Genesis err, got %v exp %v", got, exp)
 		}
-	}
-	// Import the rest of the blocks
-	for i, block := range chain.Blocks[1:] {
-		if err := m.InsertChain(chain.Slice(1+i, 2+i)); err != nil {
-			t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
+		// First block tries to create, but fails
+		{
+			block := chain.Blocks[0]
+			if err := m.InsertChain(chain.Slice(0, 1)); err != nil {
+				t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
+			}
+			statedb = state.New(state.NewPlainKvState(tx, 0))
+			if got, exp := statedb.GetBalance(aa), uint64(100000); got.Uint64() != exp {
+				t.Fatalf("block %d: got %v exp %v", block.NumberU64(), got, exp)
+			}
 		}
-	}
+		// Import the rest of the blocks
+		for i, block := range chain.Blocks[1:] {
+			if err := m.InsertChain(chain.Slice(1+i, 2+i)); err != nil {
+				t.Fatalf("block %d: failed to insert into chain: %v", block.NumberU64(), err)
+			}
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 // TestEIP2718Transition tests that an EIP-2718 transaction will be accepted
@@ -1738,8 +1743,6 @@ func TestEIP2718Transition(t *testing.T) {
 		}
 	)
 	m := stages.MockWithGenesis(t, gspec, key)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) {
 		b.SetCoinbase(common.Address{1})
@@ -1835,8 +1838,6 @@ func TestEIP1559Transition(t *testing.T) {
 		signer = types.LatestSigner(gspec.Config)
 	)
 	m := stages.MockWithGenesis(t, gspec, key1)
-	db := kv.NewObjectDatabase(m.DB)
-	defer db.Close()
 
 	chain, err := core.GenerateChain(m.ChainConfig, m.Genesis, m.Engine, m.DB, 501, func(i int, b *core.BlockGen) {
 		if i == 500 {
@@ -1887,24 +1888,29 @@ func TestEIP1559Transition(t *testing.T) {
 		t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed())
 	}
 
-	statedb := state.New(state.NewPlainStateReader(db))
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		statedb := state.New(state.NewPlainKvState(tx, 0))
 
-	// 3: Ensure that miner received only the tx's tip.
-	actual := statedb.GetBalance(block.Coinbase())
-	expected := new(uint256.Int).Add(
-		new(uint256.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GetPrice().Uint64()),
-		ethash.ConstantinopleBlockReward,
-	)
-	if actual.Cmp(expected) != 0 {
-		t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
-	}
+		// 3: Ensure that miner received only the tx's tip.
+		actual := statedb.GetBalance(block.Coinbase())
+		expected := new(uint256.Int).Add(
+			new(uint256.Int).SetUint64(block.GasUsed()*block.Transactions()[0].GetPrice().Uint64()),
+			ethash.ConstantinopleBlockReward,
+		)
+		if actual.Cmp(expected) != 0 {
+			t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
+		}
 
-	// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
-	actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr1))
-	expected = new(uint256.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GetPrice().Uint64() + block.BaseFee().Uint64()))
-	if actual.Cmp(expected) != 0 {
-		t.Fatalf("sender expenditure incorrect: expected %d, got %d", expected, actual)
-	}
+		// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
+		actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr1))
+		expected = new(uint256.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GetPrice().Uint64() + block.BaseFee().Uint64()))
+		if actual.Cmp(expected) != 0 {
+			t.Fatalf("sender expenditure incorrect: expected %d, got %d", expected, actual)
+		}
+
+		return nil
+	})
+	require.NoError(t, err)
 
 	chain, err = core.GenerateChain(m.ChainConfig, block, m.Engine, m.DB, 1, func(i int, b *core.BlockGen) {
 		b.SetCoinbase(common.Address{2})
@@ -1923,25 +1929,29 @@ func TestEIP1559Transition(t *testing.T) {
 	}
 
 	block = chain.Blocks[0]
-	statedb = state.New(state.NewPlainStateReader(db))
-	effectiveTip := block.Transactions()[0].GetPrice().Uint64() - block.BaseFee().Uint64()
-
-	// 6+5: Ensure that miner received only the tx's effective tip.
-	actual = statedb.GetBalance(block.Coinbase())
-	expected = new(uint256.Int).Add(
-		new(uint256.Int).SetUint64(block.GasUsed()*effectiveTip),
-		ethash.ConstantinopleBlockReward,
-	)
-	if actual.Cmp(expected) != 0 {
-		t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
-	}
+	err = m.DB.View(context.Background(), func(tx ethdb.Tx) error {
+		statedb := state.New(state.NewPlainKvState(tx, 0))
+		effectiveTip := block.Transactions()[0].GetPrice().Uint64() - block.BaseFee().Uint64()
+
+		// 6+5: Ensure that miner received only the tx's effective tip.
+		actual := statedb.GetBalance(block.Coinbase())
+		expected := new(uint256.Int).Add(
+			new(uint256.Int).SetUint64(block.GasUsed()*effectiveTip),
+			ethash.ConstantinopleBlockReward,
+		)
+		if actual.Cmp(expected) != 0 {
+			t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
+		}
 
-	// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
-	actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr2))
-	expected = new(uint256.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
-	if actual.Cmp(expected) != 0 {
-		t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
-	}
+		// 4: Ensure the tx sender paid for the gasUsed * (effectiveTip + block baseFee).
+		actual = new(uint256.Int).Sub(funds, statedb.GetBalance(addr2))
+		expected = new(uint256.Int).SetUint64(block.GasUsed() * (effectiveTip + block.BaseFee().Uint64()))
+		if actual.Cmp(expected) != 0 {
+			t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
+		}
+		return nil
+	})
+	require.NoError(t, err)
 }
 
 func current(kv ethdb.RwKV) *types.Block {
diff --git a/turbo/trie/structural_branch_test.go b/turbo/trie/structural_branch_test.go
index 6f65055b3f5d9fb0ae4f3050d539858348c77d1a..c1e28d41b8c1f88509748f3306c80e1b7efbf88f 100644
--- a/turbo/trie/structural_branch_test.go
+++ b/turbo/trie/structural_branch_test.go
@@ -17,7 +17,6 @@
 package trie_test
 
 import (
-	"context"
 	"fmt"
 	"testing"
 
@@ -31,7 +30,8 @@ import (
 )
 
 func TestIHCursor(t *testing.T) {
-	db, require := kv.NewTestDB(t), require.New(t)
+	_, tx := kv.NewTestTx(t)
+	require := require.New(t)
 	hash := common.HexToHash(fmt.Sprintf("%064d", 0))
 
 	newV := make([]byte, 0, 1024)
@@ -39,7 +39,7 @@ func TestIHCursor(t *testing.T) {
 		k := common.FromHex(ks)
 		integrity.AssertSubset(k, hasTree, hasState)
 		integrity.AssertSubset(k, hasHash, hasState)
-		_ = db.Put(dbutils.TrieOfAccountsBucket, k, common.CopyBytes(trie.MarshalTrieNodeTyped(hasState, hasTree, hasHash, hashes, newV)))
+		_ = tx.Put(dbutils.TrieOfAccountsBucket, k, common.CopyBytes(trie.MarshalTrieNodeTyped(hasState, hasTree, hasHash, hashes, newV)))
 	}
 
 	put("00", 0b0000000000000010, 0b0000000000000000, 0b0000000000000010, []common.Hash{hash})
@@ -56,10 +56,6 @@ func TestIHCursor(t *testing.T) {
 	put("05000f", 0b0000000000000001, 0b0000000000000000, 0b0000000000000001, []common.Hash{hash})
 	put("06", 0b0000000000000001, 0b0000000000000000, 0b0000000000000001, []common.Hash{hash})
 
-	tx, err := db.RwKV().BeginRw(context.Background())
-	require.NoError(err)
-	defer tx.Rollback()
-
 	integrity.Trie(tx, false, nil)
 
 	cursor, err := tx.Cursor(dbutils.TrieOfAccountsBucket)