diff --git a/cmd/prometheus/dashboards/erigon.json b/cmd/prometheus/dashboards/erigon.json
index 2dfe84dd4c613abfd2db40ceb0fa0b9c6000b275..4b0562176fa8f5adc12927a36215c4c64fcf1d00 100644
--- a/cmd/prometheus/dashboards/erigon.json
+++ b/cmd/prometheus/dashboards/erigon.json
@@ -22,7 +22,7 @@
   "gnetId": null,
   "graphTooltip": 0,
   "id": 1,
-  "iteration": 1632101487032,
+  "iteration": 1632801657282,
   "links": [],
   "panels": [
     {
@@ -3008,7 +3008,7 @@
       "type": "timeseries"
     },
     {
-      "collapsed": true,
+      "collapsed": false,
       "datasource": null,
       "gridPos": {
         "h": 1,
@@ -3016,6 +3016,191 @@
         "x": 0,
         "y": 79
       },
+      "id": 183,
+      "panels": [],
+      "title": "RPC",
+      "type": "row"
+    },
+    {
+      "datasource": null,
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          },
+          "unit": "s"
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 0,
+        "y": 80
+      },
+      "id": 185,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "last"
+          ],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "rpc_duration_seconds{quantile=\"$quantile\",instance=~\"$instance\"}",
+          "interval": "",
+          "legendFormat": "rpc_duration_seconds: {{ method }} {{ instance }}",
+          "refId": "A"
+        }
+      ],
+      "title": "Timings",
+      "transformations": [],
+      "type": "timeseries"
+    },
+    {
+      "datasource": null,
+      "fieldConfig": {
+        "defaults": {
+          "color": {
+            "mode": "palette-classic"
+          },
+          "custom": {
+            "axisLabel": "",
+            "axisPlacement": "auto",
+            "barAlignment": 0,
+            "drawStyle": "line",
+            "fillOpacity": 0,
+            "gradientMode": "none",
+            "hideFrom": {
+              "legend": false,
+              "tooltip": false,
+              "viz": false
+            },
+            "lineInterpolation": "linear",
+            "lineWidth": 1,
+            "pointSize": 5,
+            "scaleDistribution": {
+              "type": "linear"
+            },
+            "showPoints": "auto",
+            "spanNulls": false,
+            "stacking": {
+              "group": "A",
+              "mode": "none"
+            },
+            "thresholdsStyle": {
+              "mode": "off"
+            }
+          },
+          "mappings": [],
+          "thresholds": {
+            "mode": "absolute",
+            "steps": [
+              {
+                "color": "green",
+                "value": null
+              },
+              {
+                "color": "red",
+                "value": 80
+              }
+            ]
+          }
+        },
+        "overrides": []
+      },
+      "gridPos": {
+        "h": 8,
+        "w": 12,
+        "x": 12,
+        "y": 80
+      },
+      "id": 184,
+      "options": {
+        "legend": {
+          "calcs": [
+            "mean",
+            "last"
+          ],
+          "displayMode": "list",
+          "placement": "bottom"
+        },
+        "tooltip": {
+          "mode": "single"
+        }
+      },
+      "targets": [
+        {
+          "exemplar": true,
+          "expr": "sum(delta(cache_total{result=\"hit\",name=\"rpc\",instance=~\"$instance\"}[1m]))/sum(delta(cache_total{name=\"rpc\",instance=~\"$instance\"}[1m])) ",
+          "hide": false,
+          "interval": "",
+          "legendFormat": "hit rate: {{ instance }} ",
+          "refId": "A"
+        }
+      ],
+      "title": "Cache hit-rate",
+      "type": "timeseries"
+    },
+    {
+      "collapsed": true,
+      "datasource": null,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 88
+      },
       "id": 146,
       "panels": [
         {
@@ -3713,7 +3898,7 @@
         "h": 1,
         "w": 24,
         "x": 0,
-        "y": 80
+        "y": 89
       },
       "id": 75,
       "panels": [],
@@ -3777,7 +3962,7 @@
         "h": 6,
         "w": 12,
         "x": 0,
-        "y": 81
+        "y": 90
       },
       "id": 96,
       "links": [],
@@ -3880,7 +4065,7 @@
         "h": 6,
         "w": 12,
         "x": 12,
-        "y": 81
+        "y": 90
       },
       "id": 77,
       "links": [],
@@ -3938,7 +4123,7 @@
         "h": 1,
         "w": 24,
         "x": 0,
-        "y": 87
+        "y": 96
       },
       "id": 4,
       "panels": [],
@@ -3982,7 +4167,7 @@
         "h": 3,
         "w": 4,
         "x": 0,
-        "y": 88
+        "y": 97
       },
       "id": 108,
       "interval": null,
@@ -4061,7 +4246,7 @@
         "h": 3,
         "w": 4,
         "x": 4,
-        "y": 88
+        "y": 97
       },
       "id": 111,
       "interval": null,
@@ -4141,7 +4326,7 @@
         "h": 3,
         "w": 4,
         "x": 8,
-        "y": 88
+        "y": 97
       },
       "id": 109,
       "interval": null,
@@ -4221,7 +4406,7 @@
         "h": 3,
         "w": 4,
         "x": 12,
-        "y": 88
+        "y": 97
       },
       "id": 113,
       "interval": null,
@@ -4300,7 +4485,7 @@
         "h": 3,
         "w": 4,
         "x": 16,
-        "y": 88
+        "y": 97
       },
       "id": 114,
       "interval": null,
@@ -4379,7 +4564,7 @@
         "h": 3,
         "w": 4,
         "x": 20,
-        "y": 88
+        "y": 97
       },
       "id": 115,
       "interval": null,
@@ -4479,7 +4664,7 @@
         "h": 6,
         "w": 12,
         "x": 0,
-        "y": 91
+        "y": 100
       },
       "id": 110,
       "links": [],
@@ -4583,7 +4768,7 @@
         "h": 6,
         "w": 12,
         "x": 12,
-        "y": 91
+        "y": 100
       },
       "id": 116,
       "links": [],
@@ -4687,7 +4872,7 @@
         "h": 7,
         "w": 24,
         "x": 0,
-        "y": 97
+        "y": 106
       },
       "id": 117,
       "links": [],
@@ -4815,7 +5000,7 @@
         "h": 1,
         "w": 24,
         "x": 0,
-        "y": 104
+        "y": 113
       },
       "id": 138,
       "panels": [
@@ -4980,9 +5165,15 @@
       {
         "allValue": null,
         "current": {
-          "selected": false,
-          "text": "All",
-          "value": "$__all"
+          "selected": true,
+          "text": [
+            "turbogeth16c.weblogix.it:6060",
+            "turbogeth16c.weblogix.it:6061"
+          ],
+          "value": [
+            "turbogeth16c.weblogix.it:6060",
+            "turbogeth16c.weblogix.it:6061"
+          ]
         },
         "datasource": "Prometheus",
         "definition": "go_goroutines",
@@ -5087,7 +5278,7 @@
     ]
   },
   "time": {
-    "from": "now-12h",
+    "from": "now-2m",
     "to": "now"
   },
   "timepicker": {
@@ -5117,5 +5308,5 @@
   "timezone": "",
   "title": "Erigon Prometheus",
   "uid": "FPpjH6Hik",
-  "version": 40
+  "version": 45
 }
\ No newline at end of file
diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go
index e3433dd28cdce6950a25612992b22725b1c9dd83..cea4c8269c01099c2690efd96b8c53a511f17d72 100644
--- a/cmd/rpcdaemon/cli/config.go
+++ b/cmd/rpcdaemon/cli/config.go
@@ -3,7 +3,9 @@ package cli
 import (
 	"context"
 	"encoding/binary"
+	"errors"
 	"fmt"
+	"io"
 	"net/http"
 	"path"
 	"time"
@@ -12,6 +14,7 @@ import (
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil"
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/remote"
 	"github.com/ledgerwatch/erigon-lib/kv"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	kv2 "github.com/ledgerwatch/erigon-lib/kv/mdbx"
 	"github.com/ledgerwatch/erigon-lib/kv/remotedb"
 	"github.com/ledgerwatch/erigon-lib/kv/remotedbserver"
@@ -24,6 +27,9 @@ import (
 	"github.com/ledgerwatch/erigon/rpc"
 	"github.com/ledgerwatch/log/v3"
 	"github.com/spf13/cobra"
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
 )
 
 type Flags struct {
@@ -51,6 +57,7 @@ type Flags struct {
 	TraceCompatibility   bool // Bug for bug compatibility for trace_ routines with OpenEthereum
 	TxPoolV2             bool
 	TxPoolApiAddr        string
+	StateCache           kvcache.CoherentConfig
 }
 
 var rootCmd = &cobra.Command{
@@ -124,15 +131,66 @@ func RootCommand() (*cobra.Command, *Flags) {
 		return nil
 	}
 
+	cfg.StateCache.MetricsLabel = "rpc"
+
 	return rootCmd, cfg
 }
 
-func checkDbCompatibility(db kv.RoDB) error {
+type StateChangesClient interface {
+	StateChanges(ctx context.Context, in *remote.StateChangeRequest, opts ...grpc.CallOption) (remote.KV_StateChangesClient, error)
+}
+
+func subscribeToStateChangesLoop(ctx context.Context, client StateChangesClient, cache kvcache.Cache) {
+	go func() {
+		for {
+			select {
+			case <-ctx.Done():
+				return
+			default:
+			}
+			if err := subscribeToStateChanges(ctx, client, cache); err != nil {
+				if s, ok := status.FromError(err); ok && retryLater(s.Code()) {
+					time.Sleep(time.Second)
+					continue
+				}
+				if errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) {
+					continue
+				}
+				log.Warn("[txpool.handleStateChanges]", "err", err)
+			}
+		}
+	}()
+}
+
+func retryLater(code codes.Code) bool {
+	return code == codes.Unavailable || code == codes.Canceled || code == codes.ResourceExhausted
+}
+
+func subscribeToStateChanges(ctx context.Context, client StateChangesClient, cache kvcache.Cache) error {
+	streamCtx, cancel := context.WithCancel(ctx)
+	defer cancel()
+	stream, err := client.StateChanges(streamCtx, &remote.StateChangeRequest{WithStorage: true, WithTransactions: false}, grpc.WaitForReady(true))
+	if err != nil {
+		return err
+	}
+	for req, err := stream.Recv(); ; req, err = stream.Recv() {
+		if err != nil {
+			return err
+		}
+		if req == nil {
+			return nil
+		}
+
+		cache.OnNewBlock(req)
+	}
+}
+
+func checkDbCompatibility(ctx context.Context, db kv.RoDB) error {
 	// DB schema version compatibility check
 	var version []byte
 	var compatErr error
 	var compatTx kv.Tx
-	if compatTx, compatErr = db.BeginRo(context.Background()); compatErr != nil {
+	if compatTx, compatErr = db.BeginRo(ctx); compatErr != nil {
 		return fmt.Errorf("open Ro Tx for DB schema compability check: %w", compatErr)
 	}
 	defer compatTx.Rollback()
@@ -164,9 +222,9 @@ func checkDbCompatibility(db kv.RoDB) error {
 	return nil
 }
 
-func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCancel context.CancelFunc) (db kv.RoDB, eth services.ApiBackend, txPool *services.TxPoolService, mining *services.MiningService, err error) {
+func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCancel context.CancelFunc) (db kv.RoDB, eth services.ApiBackend, txPool *services.TxPoolService, mining *services.MiningService, stateCache kvcache.Cache, err error) {
 	if !cfg.SingleNodeMode && cfg.PrivateApiAddr == "" {
-		return nil, nil, nil, nil, fmt.Errorf("either remote db or local db must be specified")
+		return nil, nil, nil, nil, nil, fmt.Errorf("either remote db or local db must be specified")
 	}
 	// Do not change the order of these checks. Chaindata needs to be checked first, because PrivateApiAddr has default value which is not ""
 	// If PrivateApiAddr is checked first, the Chaindata option will never work
@@ -174,60 +232,68 @@ func RemoteServices(ctx context.Context, cfg Flags, logger log.Logger, rootCance
 		var rwKv kv.RwDB
 		rwKv, err = kv2.NewMDBX(logger).Path(cfg.Chaindata).Readonly().Open()
 		if err != nil {
-			return nil, nil, nil, nil, err
+			return nil, nil, nil, nil, nil, err
 		}
-		if compatErr := checkDbCompatibility(rwKv); compatErr != nil {
-			return nil, nil, nil, nil, compatErr
+		if compatErr := checkDbCompatibility(ctx, rwKv); compatErr != nil {
+			return nil, nil, nil, nil, nil, compatErr
 		}
 		db = rwKv
-	} else {
-		log.Info("if you run RPCDaemon on same machine with Erigon add --datadir option")
+		stateCache = kvcache.NewDummy()
+		return db, eth, txPool, mining, stateCache, nil
 	}
-	if cfg.PrivateApiAddr != "" {
-		creds, err := grpcutil.TLS(cfg.TLSCACert, cfg.TLSCertfile, cfg.TLSKeyFile)
+	log.Info("if you run RPCDaemon on same machine with Erigon add --datadir option")
+
+	if cfg.PrivateApiAddr == "" {
+		return db, eth, txPool, mining, stateCache, nil
+	}
+
+	creds, err := grpcutil.TLS(cfg.TLSCACert, cfg.TLSCertfile, cfg.TLSKeyFile)
+	if err != nil {
+		return nil, nil, nil, nil, nil, fmt.Errorf("open tls cert: %w", err)
+	}
+	conn, err := grpcutil.Connect(creds, cfg.PrivateApiAddr)
+	if err != nil {
+		return nil, nil, nil, nil, nil, fmt.Errorf("could not connect to execution service privateApi: %w", err)
+	}
+
+	kvClient := remote.NewKVClient(conn)
+	remoteKv, err := remotedb.NewRemote(gointerfaces.VersionFromProto(remotedbserver.KvServiceAPIVersion), logger, kvClient).Open()
+	if err != nil {
+		return nil, nil, nil, nil, nil, fmt.Errorf("could not connect to remoteKv: %w", err)
+	}
+
+	stateCache = kvcache.New(cfg.StateCache)
+	subscribeToStateChangesLoop(ctx, kvClient, stateCache)
+
+	remoteEth := services.NewRemoteBackend(conn)
+	txpoolConn := conn
+	if cfg.TxPoolV2 {
+		txpoolConn, err = grpcutil.Connect(creds, cfg.TxPoolApiAddr)
 		if err != nil {
-			return nil, nil, nil, nil, fmt.Errorf("open tls cert: %w", err)
+			return nil, nil, nil, nil, nil, fmt.Errorf("could not connect to txpool api: %w", err)
 		}
-		conn, err := grpcutil.Connect(creds, cfg.PrivateApiAddr)
-		if err != nil {
-			return nil, nil, nil, nil, fmt.Errorf("could not connect to execution service privateApi: %w", err)
+	}
+	mining = services.NewMiningService(txpoolConn)
+	txPool = services.NewTxPoolService(txpoolConn)
+	if db == nil {
+		db = remoteKv
+	}
+	eth = remoteEth
+	go func() {
+		if !remoteKv.EnsureVersionCompatibility() {
+			rootCancel()
 		}
-
-		kvClient := remote.NewKVClient(conn)
-		remoteKv, err := remotedb.NewRemote(gointerfaces.VersionFromProto(remotedbserver.KvServiceAPIVersion), logger, kvClient).Open()
-		if err != nil {
-			return nil, nil, nil, nil, fmt.Errorf("could not connect to remoteKv: %w", err)
+		if !remoteEth.EnsureVersionCompatibility() {
+			rootCancel()
 		}
-		remoteEth := services.NewRemoteBackend(conn)
-		txpoolConn := conn
-		if cfg.TxPoolV2 {
-			txpoolConn, err = grpcutil.Connect(creds, cfg.TxPoolApiAddr)
-			if err != nil {
-				return nil, nil, nil, nil, fmt.Errorf("could not connect to txpool api: %w", err)
-			}
+		if mining != nil && !mining.EnsureVersionCompatibility() {
+			rootCancel()
 		}
-		mining = services.NewMiningService(txpoolConn)
-		txPool = services.NewTxPoolService(txpoolConn)
-		if db == nil {
-			db = remoteKv
+		if !txPool.EnsureVersionCompatibility() {
+			rootCancel()
 		}
-		eth = remoteEth
-		go func() {
-			if !remoteKv.EnsureVersionCompatibility() {
-				rootCancel()
-			}
-			if !remoteEth.EnsureVersionCompatibility() {
-				rootCancel()
-			}
-			if mining != nil && !mining.EnsureVersionCompatibility() {
-				rootCancel()
-			}
-			if !txPool.EnsureVersionCompatibility() {
-				rootCancel()
-			}
-		}()
-	}
-	return db, eth, txPool, mining, err
+	}()
+	return db, eth, txPool, mining, stateCache, err
 }
 
 func StartRpcServer(ctx context.Context, cfg Flags, rpcAPI []rpc.API) error {
diff --git a/cmd/rpcdaemon/commands/call_traces_test.go b/cmd/rpcdaemon/commands/call_traces_test.go
index bdb972f78f981f4965ac135ef78e758ba5f592a3..736c13535e91554c72d6ca10669047fe677f0ea1 100644
--- a/cmd/rpcdaemon/commands/call_traces_test.go
+++ b/cmd/rpcdaemon/commands/call_traces_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	jsoniter "github.com/json-iterator/go"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli"
 	"github.com/ledgerwatch/erigon/common"
 	"github.com/ledgerwatch/erigon/common/hexutil"
@@ -44,7 +45,7 @@ func TestCallTraceOneByOne(t *testing.T) {
 	if err != nil {
 		t.Fatalf("generate chain: %v", err)
 	}
-	api := NewTraceAPI(NewBaseApi(nil), m.DB, &cli.Flags{})
+	api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig)), m.DB, &cli.Flags{})
 	// Insert blocks 1 by 1, to tirgget possible "off by one" errors
 	for i := 0; i < chain.Length; i++ {
 		if err = m.InsertChain(chain.Slice(i, i+1)); err != nil {
@@ -89,7 +90,7 @@ func TestCallTraceUnwind(t *testing.T) {
 	if err != nil {
 		t.Fatalf("generate chainB: %v", err)
 	}
-	api := NewTraceAPI(NewBaseApi(nil), m.DB, &cli.Flags{})
+	api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig)), m.DB, &cli.Flags{})
 	if err = m.InsertChain(chainA); err != nil {
 		t.Fatalf("inserting chainA: %v", err)
 	}
@@ -149,7 +150,7 @@ func TestFilterNoAddresses(t *testing.T) {
 	if err != nil {
 		t.Fatalf("generate chain: %v", err)
 	}
-	api := NewTraceAPI(NewBaseApi(nil), m.DB, &cli.Flags{})
+	api := NewTraceAPI(NewBaseApi(nil, kvcache.New(kvcache.DefaultCoherentConfig)), m.DB, &cli.Flags{})
 	// Insert blocks 1 by 1, to tirgget possible "off by one" errors
 	for i := 0; i < chain.Length; i++ {
 		if err = m.InsertChain(chain.Slice(i, i+1)); err != nil {
diff --git a/cmd/rpcdaemon/commands/corner_cases_support_test.go b/cmd/rpcdaemon/commands/corner_cases_support_test.go
index 36c678cbcda5faa4621a3856489b15a441661b7a..858723e6d24fe1f66482937fd8494375ccf44802 100644
--- a/cmd/rpcdaemon/commands/corner_cases_support_test.go
+++ b/cmd/rpcdaemon/commands/corner_cases_support_test.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"testing"
 
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/common"
 	"github.com/ledgerwatch/erigon/rpc"
@@ -16,7 +17,8 @@ func TestNotFoundMustReturnNil(t *testing.T) {
 	require := require.New(t)
 	db := rpcdaemontest.CreateTestKV(t)
 	defer db.Close()
-	api := NewEthAPI(NewBaseApi(nil), db, nil, nil, nil, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewEthAPI(NewBaseApi(nil, stateCache), db, nil, nil, nil, 5000000)
 	ctx := context.Background()
 
 	a, err := api.GetTransactionByBlockNumberAndIndex(ctx, 10_000, 1)
diff --git a/cmd/rpcdaemon/commands/daemon.go b/cmd/rpcdaemon/commands/daemon.go
index d6dbe316bcb9616c6ccc680f1c0c804ef6c24f1e..6c84e68e6efae07e8796e8129cead07026529ae7 100644
--- a/cmd/rpcdaemon/commands/daemon.go
+++ b/cmd/rpcdaemon/commands/daemon.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
 	"github.com/ledgerwatch/erigon-lib/kv"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/services"
@@ -12,10 +13,12 @@ import (
 )
 
 // APIList describes the list of available RPC apis
-func APIList(ctx context.Context, db kv.RoDB, eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, filters *filters.Filters, cfg cli.Flags, customAPIList []rpc.API) []rpc.API {
+func APIList(ctx context.Context, db kv.RoDB,
+	eth services.ApiBackend, txPool txpool.TxpoolClient, mining txpool.MiningClient, filters *filters.Filters, stateCache kvcache.Cache,
+	cfg cli.Flags, customAPIList []rpc.API) []rpc.API {
 	var defaultAPIList []rpc.API
 
-	base := NewBaseApi(filters)
+	base := NewBaseApi(filters, stateCache)
 	ethImpl := NewEthAPI(base, db, eth, txPool, mining, cfg.Gascap)
 	erigonImpl := NewErigonAPI(base, db)
 	txpoolImpl := NewTxPoolAPI(base, db, txPool)
diff --git a/cmd/rpcdaemon/commands/debug_api_test.go b/cmd/rpcdaemon/commands/debug_api_test.go
index e2c3e816a3d0eb228d009965f4692f999c7ec7d6..a8c31922ad438d4d29b3ebcb191a51fa3a9db277 100644
--- a/cmd/rpcdaemon/commands/debug_api_test.go
+++ b/cmd/rpcdaemon/commands/debug_api_test.go
@@ -7,6 +7,7 @@ import (
 	"testing"
 
 	jsoniter "github.com/json-iterator/go"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/common"
 	"github.com/ledgerwatch/erigon/eth/tracers"
@@ -37,7 +38,8 @@ var debugTraceTransactionNoRefundTests = []struct {
 
 func TestTraceTransaction(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewPrivateDebugAPI(NewBaseApi(nil), db, 0)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewPrivateDebugAPI(NewBaseApi(nil, stateCache), db, 0)
 	for _, tt := range debugTraceTransactionTests {
 		var buf bytes.Buffer
 		stream := jsoniter.NewStream(jsoniter.ConfigDefault, &buf, 4096)
@@ -66,7 +68,8 @@ func TestTraceTransaction(t *testing.T) {
 
 func TestTraceTransactionNoRefund(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewPrivateDebugAPI(NewBaseApi(nil), db, 0)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewPrivateDebugAPI(NewBaseApi(nil, stateCache), db, 0)
 	for _, tt := range debugTraceTransactionNoRefundTests {
 		var buf bytes.Buffer
 		stream := jsoniter.NewStream(jsoniter.ConfigDefault, &buf, 4096)
diff --git a/cmd/rpcdaemon/commands/eth_api.go b/cmd/rpcdaemon/commands/eth_api.go
index 1cd4a0172fadaf7b40c3f3aab9efaab7dcbe9d54..9e1797a7b34edb6409863fe120ef0ae7357a3b17 100644
--- a/cmd/rpcdaemon/commands/eth_api.go
+++ b/cmd/rpcdaemon/commands/eth_api.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/holiman/uint256"
 	"github.com/ledgerwatch/erigon-lib/kv"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/consensus/misc"
 
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
@@ -97,14 +98,15 @@ type EthAPI interface {
 }
 
 type BaseAPI struct {
+	stateCache   kvcache.Cache
 	filters      *filters.Filters
 	_chainConfig *params.ChainConfig
 	_genesis     *types.Block
 	_genesisLock sync.RWMutex
 }
 
-func NewBaseApi(f *filters.Filters) *BaseAPI {
-	return &BaseAPI{filters: f}
+func NewBaseApi(f *filters.Filters, stateCache kvcache.Cache) *BaseAPI {
+	return &BaseAPI{filters: f, stateCache: stateCache}
 }
 
 func (api *BaseAPI) chainConfig(tx kv.Tx) (*params.ChainConfig, error) {
diff --git a/cmd/rpcdaemon/commands/eth_api_test.go b/cmd/rpcdaemon/commands/eth_api_test.go
index 52ec7c9a17e411f25478c98d033483ccc52a01b8..ff1d0479d345a4896bb05fc2d39d49c5ca84b13d 100644
--- a/cmd/rpcdaemon/commands/eth_api_test.go
+++ b/cmd/rpcdaemon/commands/eth_api_test.go
@@ -9,13 +9,15 @@ import (
 	"github.com/stretchr/testify/assert"
 	"testing"
 
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/common"
 )
 
 func TestGetTransactionReceipt(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewEthAPI(NewBaseApi(nil), db, nil, nil, nil, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewEthAPI(NewBaseApi(nil, stateCache), db, nil, nil, nil, 5000000)
 	// Call GetTransactionReceipt for transaction which is not in the database
 	if _, err := api.GetTransactionReceipt(context.Background(), common.Hash{}); err != nil {
 		t.Errorf("calling GetTransactionReceipt with empty hash: %v", err)
@@ -24,7 +26,8 @@ func TestGetTransactionReceipt(t *testing.T) {
 
 func TestGetTransactionReceiptUnprotected(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewEthAPI(NewBaseApi(nil), db, nil, nil, nil, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewEthAPI(NewBaseApi(nil, stateCache), db, nil, nil, nil, 5000000)
 	// Call GetTransactionReceipt for un-protected transaction
 	if _, err := api.GetTransactionReceipt(context.Background(), common.HexToHash("0x3f3cb8a0e13ed2481f97f53f7095b9cbc78b6ffb779f2d3e565146371a8830ea")); err != nil {
 		t.Errorf("calling GetTransactionReceipt for unprotected tx: %v", err)
diff --git a/cmd/rpcdaemon/commands/eth_block.go b/cmd/rpcdaemon/commands/eth_block.go
index c2f3710f0b3534db07584a9d33c03bee17be7b92..6817b31c56ba30df62b1d51bf470d93f7812074f 100644
--- a/cmd/rpcdaemon/commands/eth_block.go
+++ b/cmd/rpcdaemon/commands/eth_block.go
@@ -60,7 +60,11 @@ func (api *APIImpl) CallBundle(ctx context.Context, txHashes []common.Hash, stat
 
 	var stateReader state.StateReader
 	if num, ok := stateBlockNumberOrHash.Number(); ok && num == rpc.LatestBlockNumber {
-		stateReader = state.NewPlainStateReader(tx)
+		cacheView, err := api.stateCache.View(ctx, tx)
+		if err != nil {
+			return nil, err
+		}
+		stateReader = state.NewCachedReader2(cacheView, tx)
 	} else {
 		stateReader = state.NewPlainState(tx, stateBlockNumber)
 	}
diff --git a/cmd/rpcdaemon/commands/eth_call.go b/cmd/rpcdaemon/commands/eth_call.go
index 32e7a66cf215f2fd1ada5a1c4ac5b93a8f259ac6..13ee8509e02a4e3b5dfbff03f34a978c4233b6bf 100644
--- a/cmd/rpcdaemon/commands/eth_call.go
+++ b/cmd/rpcdaemon/commands/eth_call.go
@@ -41,7 +41,7 @@ func (api *APIImpl) Call(ctx context.Context, args ethapi.CallArgs, blockNrOrHas
 
 	contractHasTEVM := ethdb.GetHasTEVM(tx)
 
-	result, err := transactions.DoCall(ctx, args, tx, blockNrOrHash, overrides, api.GasCap, chainConfig, api.filters, contractHasTEVM)
+	result, err := transactions.DoCall(ctx, args, tx, blockNrOrHash, overrides, api.GasCap, chainConfig, api.filters, api.stateCache, contractHasTEVM)
 	if err != nil {
 		return nil, err
 	}
@@ -128,7 +128,11 @@ func (api *APIImpl) EstimateGas(ctx context.Context, args ethapi.CallArgs, block
 
 	// Recap the highest gas limit with account's available balance.
 	if args.GasPrice != nil && args.GasPrice.ToInt().Uint64() != 0 {
-		stateReader := state.NewPlainStateReader(dbtx)
+		cacheView, err := api.stateCache.View(ctx, dbtx)
+		if err != nil {
+			return 0, err
+		}
+		stateReader := state.NewCachedReader2(cacheView, dbtx)
 		state := state.New(stateReader)
 		if state == nil {
 			return 0, fmt.Errorf("can't get the current state")
@@ -172,7 +176,8 @@ func (api *APIImpl) EstimateGas(ctx context.Context, args ethapi.CallArgs, block
 	executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
 		args.Gas = (*hexutil.Uint64)(&gas)
 
-		result, err := transactions.DoCall(ctx, args, dbtx, rpc.BlockNumberOrHash{BlockNumber: &lastBlockNum}, nil, api.GasCap, chainConfig, api.filters, contractHasTEVM)
+		result, err := transactions.DoCall(ctx, args, dbtx, rpc.BlockNumberOrHash{BlockNumber: &lastBlockNum}, nil,
+			api.GasCap, chainConfig, api.filters, api.stateCache, contractHasTEVM)
 		if err != nil {
 			if errors.Is(err, core.ErrIntrinsicGas) {
 				// Special case, raise gas limit
diff --git a/cmd/rpcdaemon/commands/eth_call_test.go b/cmd/rpcdaemon/commands/eth_call_test.go
index d276172f0acf03496d5c130ff0f54ea321546450..653a767550e8090181a33428e2f25fba581f829d 100644
--- a/cmd/rpcdaemon/commands/eth_call_test.go
+++ b/cmd/rpcdaemon/commands/eth_call_test.go
@@ -5,6 +5,7 @@ import (
 	"fmt"
 	"testing"
 
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/common"
 	"github.com/ledgerwatch/erigon/internal/ethapi"
@@ -13,7 +14,8 @@ import (
 
 func TestEstimateGas(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewEthAPI(NewBaseApi(nil), db, nil, nil, nil, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewEthAPI(NewBaseApi(nil, stateCache), db, nil, nil, nil, 5000000)
 	var from = common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")
 	var to = common.HexToAddress("0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e")
 	if _, err := api.EstimateGas(context.Background(), ethapi.CallArgs{
@@ -26,7 +28,8 @@ func TestEstimateGas(t *testing.T) {
 
 func TestEthCallNonCanonical(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewEthAPI(NewBaseApi(nil), db, nil, nil, nil, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewEthAPI(NewBaseApi(nil, stateCache), db, nil, nil, nil, 5000000)
 	var from = common.HexToAddress("0x71562b71999873db5b286df957af199ec94617f7")
 	var to = common.HexToAddress("0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e")
 	if _, err := api.Call(context.Background(), ethapi.CallArgs{
diff --git a/cmd/rpcdaemon/commands/eth_ming_test.go b/cmd/rpcdaemon/commands/eth_ming_test.go
index 4d8868491f2f4d82b1af0c881fa3ad000a0a80a4..b1bad5b716fbc535cbce8da2ee2a4eb253b48dfb 100644
--- a/cmd/rpcdaemon/commands/eth_ming_test.go
+++ b/cmd/rpcdaemon/commands/eth_ming_test.go
@@ -6,6 +6,7 @@ import (
 	"time"
 
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/core/types"
@@ -18,7 +19,8 @@ func TestPendingBlock(t *testing.T) {
 	ctx, conn := rpcdaemontest.CreateTestGrpcConn(t, stages.Mock(t))
 	mining := txpool.NewMiningClient(conn)
 	ff := filters.New(ctx, nil, nil, mining)
-	api := NewEthAPI(NewBaseApi(ff), nil, nil, nil, mining, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewEthAPI(NewBaseApi(ff, stateCache), nil, nil, nil, mining, 5000000)
 	expect := uint64(12345)
 	b, err := rlp.EncodeToBytes(types.NewBlockWithHeader(&types.Header{Number: big.NewInt(int64(expect))}))
 	require.NoError(t, err)
diff --git a/cmd/rpcdaemon/commands/send_transaction_test.go b/cmd/rpcdaemon/commands/send_transaction_test.go
index c2eec7fc44f34f625fbe4c6525f243bc718a57b8..9634ca113fd1fb2dd38058c1e88cb36728d3f7b4 100644
--- a/cmd/rpcdaemon/commands/send_transaction_test.go
+++ b/cmd/rpcdaemon/commands/send_transaction_test.go
@@ -9,6 +9,7 @@ import (
 	"github.com/holiman/uint256"
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/sentry"
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/commands"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
@@ -69,7 +70,8 @@ func TestSendRawTransaction(t *testing.T) {
 	ctx, conn := rpcdaemontest.CreateTestGrpcConn(t, m)
 	txPool := txpool.NewTxpoolClient(conn)
 	ff := filters.New(ctx, nil, txPool, txpool.NewMiningClient(conn))
-	api := commands.NewEthAPI(commands.NewBaseApi(ff), m.DB, nil, txPool, nil, 5000000)
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := commands.NewEthAPI(commands.NewBaseApi(ff, stateCache), m.DB, nil, txPool, nil, 5000000)
 
 	buf := bytes.NewBuffer(nil)
 	err = txn.MarshalBinary(buf)
diff --git a/cmd/rpcdaemon/commands/trace_adhoc.go b/cmd/rpcdaemon/commands/trace_adhoc.go
index f60e6201c1d45ac6a59104d468c877a1c669080c..691dd69f694fd16615624569b9d8acfa4dda64fa 100644
--- a/cmd/rpcdaemon/commands/trace_adhoc.go
+++ b/cmd/rpcdaemon/commands/trace_adhoc.go
@@ -864,7 +864,11 @@ func (api *TraceAPIImpl) Call(ctx context.Context, args TraceCallParam, traceTyp
 	}
 	var stateReader state.StateReader
 	if num, ok := blockNrOrHash.Number(); ok && num == rpc.LatestBlockNumber {
-		stateReader = state.NewPlainStateReader(tx)
+		cacheView, err := api.stateCache.View(ctx, tx)
+		if err != nil {
+			return nil, err
+		}
+		stateReader = state.NewCachedReader2(cacheView, tx)
 	} else {
 		stateReader = state.NewPlainState(tx, blockNumber)
 	}
@@ -1062,7 +1066,11 @@ func (api *TraceAPIImpl) doCallMany(ctx context.Context, dbtx kv.Tx, msgs []type
 	}
 	var stateReader state.StateReader
 	if num, ok := parentNrOrHash.Number(); ok && num == rpc.LatestBlockNumber {
-		stateReader = state.NewPlainStateReader(dbtx)
+		cacheView, err := api.stateCache.View(ctx, dbtx)
+		if err != nil {
+			return nil, err
+		}
+		stateReader = state.NewCachedReader2(cacheView, dbtx)
 	} else {
 		stateReader = state.NewPlainState(dbtx, blockNumber)
 	}
diff --git a/cmd/rpcdaemon/commands/trace_adhoc_test.go b/cmd/rpcdaemon/commands/trace_adhoc_test.go
index a2f8df2008dd1dad48d5106a6ba756a3911afc5d..acc05a706ee6b64bab0f82594e0ab2d9f796f124 100644
--- a/cmd/rpcdaemon/commands/trace_adhoc_test.go
+++ b/cmd/rpcdaemon/commands/trace_adhoc_test.go
@@ -6,6 +6,7 @@ import (
 	"testing"
 
 	"github.com/ledgerwatch/erigon-lib/kv"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/common"
@@ -17,7 +18,8 @@ import (
 
 func TestEmptyQuery(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewTraceAPI(NewBaseApi(nil), db, &cli.Flags{})
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewTraceAPI(NewBaseApi(nil, stateCache), db, &cli.Flags{})
 	// Call GetTransactionReceipt for transaction which is not in the database
 	var latest = rpc.LatestBlockNumber
 	results, err := api.CallMany(context.Background(), json.RawMessage("[]"), &rpc.BlockNumberOrHash{BlockNumber: &latest})
@@ -33,7 +35,8 @@ func TestEmptyQuery(t *testing.T) {
 }
 func TestCoinbaseBalance(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewTraceAPI(NewBaseApi(nil), db, &cli.Flags{})
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewTraceAPI(NewBaseApi(nil, stateCache), db, &cli.Flags{})
 	// Call GetTransactionReceipt for transaction which is not in the database
 	var latest = rpc.LatestBlockNumber
 	results, err := api.CallMany(context.Background(), json.RawMessage(`
@@ -59,7 +62,8 @@ func TestCoinbaseBalance(t *testing.T) {
 
 func TestReplayTransaction(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewTraceAPI(NewBaseApi(nil), db, &cli.Flags{})
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewTraceAPI(NewBaseApi(nil, stateCache), db, &cli.Flags{})
 	var txnHash common.Hash
 	if err := db.View(context.Background(), func(tx kv.Tx) error {
 		b, err := rawdb.ReadBlockByNumber(tx, 6)
@@ -86,7 +90,8 @@ func TestReplayTransaction(t *testing.T) {
 
 func TestReplayBlockTransactions(t *testing.T) {
 	db := rpcdaemontest.CreateTestKV(t)
-	api := NewTraceAPI(NewBaseApi(nil), db, &cli.Flags{})
+	stateCache := kvcache.New(kvcache.DefaultCoherentConfig)
+	api := NewTraceAPI(NewBaseApi(nil, stateCache), db, &cli.Flags{})
 
 	// Call GetTransactionReceipt for transaction which is not in the database
 	n := rpc.BlockNumber(6)
diff --git a/cmd/rpcdaemon/commands/tracing.go b/cmd/rpcdaemon/commands/tracing.go
index d9dce5a2c3ea62e70d3a8b02ee6abc22c3046be6..9b1f4ac1cda3bfa40c9c8a30d0730c4f79a4ca00 100644
--- a/cmd/rpcdaemon/commands/tracing.go
+++ b/cmd/rpcdaemon/commands/tracing.go
@@ -85,7 +85,11 @@ func (api *PrivateDebugAPIImpl) TraceCall(ctx context.Context, args ethapi.CallA
 	}
 	var stateReader state.StateReader
 	if num, ok := blockNrOrHash.Number(); ok && num == rpc.LatestBlockNumber {
-		stateReader = state.NewPlainStateReader(dbtx)
+		cacheView, err := api.stateCache.View(ctx, dbtx)
+		if err != nil {
+			return err
+		}
+		stateReader = state.NewCachedReader2(cacheView, dbtx)
 	} else {
 		stateReader = state.NewPlainState(dbtx, blockNumber)
 	}
diff --git a/cmd/rpcdaemon/commands/txpool_api_test.go b/cmd/rpcdaemon/commands/txpool_api_test.go
index 4162bb548359519c77ec1906d0357def1f3cf649..6ef762550aab6dc02d002dd9f38e61fb04c8fee5 100644
--- a/cmd/rpcdaemon/commands/txpool_api_test.go
+++ b/cmd/rpcdaemon/commands/txpool_api_test.go
@@ -8,6 +8,7 @@ import (
 	"github.com/holiman/uint256"
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/sentry"
 	"github.com/ledgerwatch/erigon-lib/gointerfaces/txpool"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/rpcdaemontest"
 	"github.com/ledgerwatch/erigon/common"
@@ -62,7 +63,7 @@ func TestTxPoolContent(t *testing.T) {
 	ctx, conn := rpcdaemontest.CreateTestGrpcConn(t, m)
 	txPool := txpool.NewTxpoolClient(conn)
 	ff := filters.New(ctx, nil, txPool, txpool.NewMiningClient(conn))
-	api := NewTxPoolAPI(NewBaseApi(ff), m.DB, txPool)
+	api := NewTxPoolAPI(NewBaseApi(ff, kvcache.New(kvcache.DefaultCoherentConfig)), m.DB, txPool)
 
 	expectValue := uint64(1234)
 	txn, err := types.SignTx(types.NewTransaction(0, common.Address{1}, uint256.NewInt(expectValue), params.TxGas, u256.Num1, nil), *types.LatestSignerForChainID(m.ChainConfig.ChainID), m.Key)
diff --git a/cmd/rpcdaemon/main.go b/cmd/rpcdaemon/main.go
index 9e71247a2c826de65c1b0b0bdc8a3e88f53516cb..a9b525d95fbfa7956dd935024411385f3e8e5d5f 100644
--- a/cmd/rpcdaemon/main.go
+++ b/cmd/rpcdaemon/main.go
@@ -16,7 +16,7 @@ func main() {
 	rootCtx, rootCancel := utils.RootContext()
 	cmd.RunE = func(cmd *cobra.Command, args []string) error {
 		logger := log.New()
-		db, backend, txPool, mining, err := cli.RemoteServices(cmd.Context(), *cfg, logger, rootCancel)
+		db, backend, txPool, mining, stateCache, err := cli.RemoteServices(cmd.Context(), *cfg, logger, rootCancel)
 		if err != nil {
 			log.Error("Could not connect to DB", "error", err)
 			return nil
@@ -30,7 +30,7 @@ func main() {
 			log.Info("filters are not supported in chaindata mode")
 		}
 
-		if err := cli.StartRpcServer(cmd.Context(), *cfg, commands.APIList(cmd.Context(), db, backend, txPool, mining, ff, *cfg, nil)); err != nil {
+		if err := cli.StartRpcServer(cmd.Context(), *cfg, commands.APIList(cmd.Context(), db, backend, txPool, mining, ff, stateCache, *cfg, nil)); err != nil {
 			log.Error(err.Error())
 			return nil
 		}
diff --git a/cmd/txpool/main.go b/cmd/txpool/main.go
index d7b4ee11931053debcc9ee36db137aa6fc748028..3dc5fb8adf55475d9f3cd6cadcf11ad3e2a7397a 100644
--- a/cmd/txpool/main.go
+++ b/cmd/txpool/main.go
@@ -98,7 +98,7 @@ var rootCmd = &cobra.Command{
 		cfg.LogEvery = 30 * time.Second
 		cfg.CommitEvery = 30 * time.Second
 
-		cacheConfig := kvcache.DefaultCoherentCacheConfig
+		cacheConfig := kvcache.DefaultCoherentConfig
 		cacheConfig.MetricsLabel = "txpool"
 
 		newTxs := make(chan txpool.Hashes, 1024)
@@ -113,7 +113,7 @@ var rootCmd = &cobra.Command{
 
 		/*
 			var ethashApi *ethash.API
-			if casted, ok := backend.engine.(*ethash.Ethash); ok {
+			sif casted, ok := backend.engine.(*ethash.Ethash); ok {
 				ethashApi = casted.APIs(nil)[1].Service.(*ethash.API)
 			}
 		*/
diff --git a/core/state/cached_reader2.go b/core/state/cached_reader2.go
index f8a05164722a98ca2441a7a0c0e03d8541ecfad7..1f841330c1964ffcdb1923912112f21d9b3a1d64 100644
--- a/core/state/cached_reader2.go
+++ b/core/state/cached_reader2.go
@@ -14,19 +14,18 @@ import (
 // CachedReader2 is a wrapper for an instance of type StateReader
 // This wrapper only makes calls to the underlying reader if the item is not in the cache
 type CachedReader2 struct {
-	r     StateReader
 	cache kvcache.CacheView
 	db    kv.Tx
 }
 
 // NewCachedReader2 wraps a given state reader into the cached reader
-func NewCachedReader2(r StateReader, cache kvcache.CacheView, tx kv.Tx) *CachedReader2 {
-	return &CachedReader2{r: r, cache: cache, db: tx}
+func NewCachedReader2(cache kvcache.CacheView, tx kv.Tx) *CachedReader2 {
+	return &CachedReader2{cache: cache, db: tx}
 }
 
 // ReadAccountData is called when an account needs to be fetched from the state
-func (cr *CachedReader2) ReadAccountData(address common.Address) (*accounts.Account, error) {
-	enc, err := cr.cache.Get(address.Bytes())
+func (r *CachedReader2) ReadAccountData(address common.Address) (*accounts.Account, error) {
+	enc, err := r.cache.Get(address.Bytes())
 	if err != nil {
 		return nil, err
 	}
diff --git a/core/state/plain_readonly.go b/core/state/plain_readonly.go
index cea636df2dece0ef8fe7a2b629aace12f11fc2d0..186aa25709c8056967bc1b0a54f0ba548e163f8c 100644
--- a/core/state/plain_readonly.go
+++ b/core/state/plain_readonly.go
@@ -48,7 +48,6 @@ type PlainState struct {
 }
 
 func NewPlainState(tx kv.Tx, blockNr uint64) *PlainState {
-
 	c1, _ := tx.Cursor(kv.AccountsHistory)
 	c2, _ := tx.Cursor(kv.StorageHistory)
 	c3, _ := tx.CursorDupSort(kv.AccountChangeSet)
diff --git a/docker-compose.yml b/docker-compose.yml
index 207d52419fa25240eab5c78efaa926fd087010f0..e224d238a7d73be45dbee93e3ff8a6695f85c735 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -27,7 +27,7 @@ services:
     restart: unless-stopped
 
   grafana:
-    image: grafana/grafana:8.1.2
+    image: grafana/grafana:8.1.5
     user: 1000:1000 # Uses erigon user from Dockerfile
     ports:
       - "3000:3000"
diff --git a/go.mod b/go.mod
index 14917e744b69c1db1af9b66909082927e173fee3..f39636271ab3f5e8b6d3bd7b66ad3695193df215 100644
--- a/go.mod
+++ b/go.mod
@@ -38,7 +38,7 @@ require (
 	github.com/json-iterator/go v1.1.11
 	github.com/julienschmidt/httprouter v1.3.0
 	github.com/kevinburke/go-bindata v3.21.0+incompatible
-	github.com/ledgerwatch/erigon-lib v0.0.0-20210927124510-ffac34a86fd0
+	github.com/ledgerwatch/erigon-lib v0.0.0-20210928085402-33aa4498f0fc
 	github.com/ledgerwatch/log/v3 v3.3.1
 	github.com/ledgerwatch/secp256k1 v0.0.0-20210626115225-cd5cd00ed72d
 	github.com/logrusorgru/aurora/v3 v3.0.0
diff --git a/go.sum b/go.sum
index 030a57a942b2ec184e21184858b8db9dfde7b2dc..c76277ef4fb8a4d64a7873e89683c6b7ec16da2c 100644
--- a/go.sum
+++ b/go.sum
@@ -498,8 +498,8 @@ github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3P
 github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
 github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
 github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
-github.com/ledgerwatch/erigon-lib v0.0.0-20210927124510-ffac34a86fd0 h1:hthm2WSAmlY//ImGjQjD2AdxKJObDFkQbFoKVmf4Ev0=
-github.com/ledgerwatch/erigon-lib v0.0.0-20210927124510-ffac34a86fd0/go.mod h1:WgyjBACSDhgfepaaDJIbzd2TV868EjOrp2ILnEMKspY=
+github.com/ledgerwatch/erigon-lib v0.0.0-20210928085402-33aa4498f0fc h1:8yRRYOthoMgZsncLCnQXRMQy6mWz9Xl3/iSjqRYrXOQ=
+github.com/ledgerwatch/erigon-lib v0.0.0-20210928085402-33aa4498f0fc/go.mod h1:WgyjBACSDhgfepaaDJIbzd2TV868EjOrp2ILnEMKspY=
 github.com/ledgerwatch/log/v3 v3.3.1 h1:HmvLeTEvtCtqSvtu4t/a5MAdcLfeBcbIeowXbLYuzLc=
 github.com/ledgerwatch/log/v3 v3.3.1/go.mod h1:S3VJqhhVX32rbp1JyyvhJou12twtFwNEPESBgpbNkRk=
 github.com/ledgerwatch/secp256k1 v0.0.0-20210626115225-cd5cd00ed72d h1:/IKMrJdfRsoYNc36PXqP4xMH3vhW/8IQyBKGQbKZUno=
diff --git a/rpc/handler.go b/rpc/handler.go
index 6bc776462a8d4750cfc0218f0941e7279f893c3d..39784cb60b025afe3ef464234883a0c5bb944ffa 100644
--- a/rpc/handler.go
+++ b/rpc/handler.go
@@ -402,7 +402,7 @@ func (h *handler) handleCall(cp *callProc, msg *jsonrpcMessage, stream *jsoniter
 		if answer != nil && answer.Error != nil {
 			failedReqeustGauge.Inc()
 		}
-		newRPCServingTimerMS(msg.Method, answer == nil || answer.Error == nil).Update(float64(time.Since(start).Milliseconds()))
+		newRPCServingTimerMS(msg.Method, answer == nil || answer.Error == nil).UpdateDuration(start)
 	}
 	return answer
 }
diff --git a/turbo/transactions/call.go b/turbo/transactions/call.go
index a249bc5fc721665735fc229fc365b53af0bfa65b..fabbcf5ecf4f5ecc009fd7f50066ecfce14fefa7 100644
--- a/turbo/transactions/call.go
+++ b/turbo/transactions/call.go
@@ -8,6 +8,7 @@ import (
 
 	"github.com/holiman/uint256"
 	"github.com/ledgerwatch/erigon-lib/kv"
+	"github.com/ledgerwatch/erigon-lib/kv/kvcache"
 	"github.com/ledgerwatch/erigon/cmd/rpcdaemon/filters"
 	"github.com/ledgerwatch/erigon/common"
 	"github.com/ledgerwatch/erigon/core"
@@ -24,7 +25,9 @@ import (
 
 const callTimeout = 5 * time.Minute
 
-func DoCall(ctx context.Context, args ethapi.CallArgs, tx kv.Tx, blockNrOrHash rpc.BlockNumberOrHash, overrides *map[common.Address]ethapi.Account, gasCap uint64, chainConfig *params.ChainConfig, filters *filters.Filters, contractHasTEVM func(hash common.Hash) (bool, error)) (*core.ExecutionResult, error) {
+func DoCall(ctx context.Context, args ethapi.CallArgs, tx kv.Tx, blockNrOrHash rpc.BlockNumberOrHash,
+	overrides *map[common.Address]ethapi.Account, gasCap uint64, chainConfig *params.ChainConfig,
+	filters *filters.Filters, stateCache kvcache.Cache, contractHasTEVM func(hash common.Hash) (bool, error)) (*core.ExecutionResult, error) {
 	// todo: Pending state is only known by the miner
 	/*
 		if blockNrOrHash.BlockNumber != nil && *blockNrOrHash.BlockNumber == rpc.PendingBlockNumber {
@@ -38,7 +41,11 @@ func DoCall(ctx context.Context, args ethapi.CallArgs, tx kv.Tx, blockNrOrHash r
 	}
 	var stateReader state.StateReader
 	if num, ok := blockNrOrHash.Number(); ok && num == rpc.LatestBlockNumber {
-		stateReader = state.NewPlainStateReader(tx)
+		cacheView, err := stateCache.View(ctx, tx)
+		if err != nil {
+			return nil, err
+		}
+		stateReader = state.NewCachedReader2(cacheView, tx)
 	} else {
 		stateReader = state.NewPlainState(tx, blockNumber)
 	}