diff --git a/core/chain_makers.go b/core/chain_makers.go
index 26714845ebc8..e74b5c2ea3e5 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -384,7 +384,7 @@ func GenerateChain(config *params.ChainConfig, parent *types.Block, engine conse
 			blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
 			blockContext.Random = &common.Hash{} // enable post-merge instruction set
 			evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
-			ProcessParentBlockHash(b.header.ParentHash, evm)
+			ProcessParentBlockHash(b.header.ParentHash, evm, false)
 		}
 
 		// Execute any user modifications to the block
@@ -492,7 +492,7 @@ func GenerateVerkleChain(config *params.ChainConfig, parent *types.Block, engine
 			// EIP-2935
 			blockContext := NewEVMBlockContext(b.header, cm, &b.header.Coinbase)
 			evm := vm.NewEVM(blockContext, statedb, cm.config, vm.Config{})
-			ProcessParentBlockHash(b.header.ParentHash, evm)
+			ProcessParentBlockHash(b.header.ParentHash, evm, false)
 		}
 
 		// Execute any user modifications to the block.
diff --git a/core/state/statedb_hooked.go b/core/state/statedb_hooked.go
index 31bdd06b462c..25d823cc8770 100644
--- a/core/state/statedb_hooked.go
+++ b/core/state/statedb_hooked.go
@@ -157,6 +157,10 @@ func (s *hookedStateDB) Witness() *stateless.Witness {
 	return s.inner.Witness()
 }
 
+func (s *hookedStateDB) AccessEvents() *AccessEvents {
+	return s.inner.AccessEvents()
+}
+
 func (s *hookedStateDB) SubBalance(addr common.Address, amount *uint256.Int, reason tracing.BalanceChangeReason) uint256.Int {
 	prev := s.inner.SubBalance(addr, amount, reason)
 	if s.hooks.OnBalanceChange != nil && !amount.IsZero() {
diff --git a/core/state_processor.go b/core/state_processor.go
index 3eb83a673a96..2fca17563060 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -17,6 +17,7 @@
 package core
 
 import (
+	"encoding/binary"
 	"fmt"
 	"math/big"
 
@@ -86,7 +87,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
 		ProcessBeaconBlockRoot(*beaconRoot, evm)
 	}
 	if p.config.IsPrague(block.Number(), block.Time()) {
-		ProcessParentBlockHash(block.ParentHash(), evm)
+		ProcessParentBlockHash(block.ParentHash(), evm, p.config.IsVerkle(block.Number(), block.Time()))
 	}
 
 	// Iterate over and process the individual transactions
@@ -234,14 +235,24 @@ func ProcessBeaconBlockRoot(beaconRoot common.Hash, evm *vm.EVM) {
 }
 
 // ProcessParentBlockHash stores the parent block hash in the history storage contract
-// as per EIP-2935.
-func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM) {
+// as per EIP-2935/7709.
+func ProcessParentBlockHash(prevHash common.Hash, evm *vm.EVM, is7709 bool) {
 	if tracer := evm.Config.Tracer; tracer != nil {
 		onSystemCallStart(tracer, evm.GetVMContext())
 		if tracer.OnSystemCallEnd != nil {
 			defer tracer.OnSystemCallEnd()
 		}
 	}
+	if is7709 {
+		// currently 8192 for kautinen7, to be changed to 8 (and made a constant) for kaustinen8
+		ringIndex := (evm.Context.BlockNumber.Uint64() - 1) % params.HistoryServeWindow
+		var key common.Hash
+		binary.BigEndian.PutUint64(key[24:], ringIndex)
+		evm.StateDB.SetState(params.SystemAddress, key, prevHash)
+		evm.StateDB.AccessEvents().SlotGas(params.SystemAddress, key, true)
+		evm.StateDB.Finalise(false)
+		return
+	}
 	msg := &Message{
 		From:      params.SystemAddress,
 		GasLimit:  30_000_000,
diff --git a/core/verkle_witness_test.go b/core/verkle_witness_test.go
index 508823120749..c57eb73827f6 100644
--- a/core/verkle_witness_test.go
+++ b/core/verkle_witness_test.go
@@ -217,7 +217,7 @@ func TestProcessParentBlockHash(t *testing.T) {
 	// block 1 parent hash is 0x0100....
 	// block 2 parent hash is 0x0200....
 	// etc
-	checkBlockHashes := func(statedb *state.StateDB) {
+	checkBlockHashes := func(statedb *state.StateDB, isVerkle bool) {
 		statedb.SetNonce(params.HistoryStorageAddress, 1)
 		statedb.SetCode(params.HistoryStorageAddress, params.HistoryStorageCode)
 		// Process n blocks, from 1 .. num
@@ -226,19 +226,19 @@ func TestProcessParentBlockHash(t *testing.T) {
 			header := &types.Header{ParentHash: common.Hash{byte(i)}, Number: big.NewInt(int64(i)), Difficulty: new(big.Int)}
 			vmContext := NewEVMBlockContext(header, nil, new(common.Address))
 			evm := vm.NewEVM(vmContext, statedb, params.MergedTestChainConfig, vm.Config{})
-			ProcessParentBlockHash(header.ParentHash, evm)
+			ProcessParentBlockHash(header.ParentHash, evm, isVerkle)
 		}
 		// Read block hashes for block 0 .. num-1
 		for i := 0; i < num; i++ {
-			have, want := getContractStoredBlockHash(statedb, uint64(i)), common.Hash{byte(i + 1)}
+			have, want := getContractStoredBlockHash(statedb, uint64(i), isVerkle), common.Hash{byte(i + 1)}
 			if have != want {
-				t.Errorf("block %d, have parent hash %v, want %v", i, have, want)
+				t.Errorf("block %d, verkle=%v, have parent hash %v, want %v", i, isVerkle, have, want)
 			}
 		}
 	}
 	t.Run("MPT", func(t *testing.T) {
 		statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting())
-		checkBlockHashes(statedb)
+		checkBlockHashes(statedb, false)
 	})
 	t.Run("Verkle", func(t *testing.T) {
 		db := rawdb.NewMemoryDatabase()
@@ -246,15 +246,18 @@ func TestProcessParentBlockHash(t *testing.T) {
 		cacheConfig.SnapshotLimit = 0
 		triedb := triedb.NewDatabase(db, cacheConfig.triedbConfig(true))
 		statedb, _ := state.New(types.EmptyVerkleHash, state.NewDatabase(triedb, nil))
-		checkBlockHashes(statedb)
+		checkBlockHashes(statedb, true)
 	})
 }
 
 // getContractStoredBlockHash is a utility method which reads the stored parent blockhash for block 'number'
-func getContractStoredBlockHash(statedb *state.StateDB, number uint64) common.Hash {
+func getContractStoredBlockHash(statedb *state.StateDB, number uint64, isVerkle bool) common.Hash {
 	ringIndex := number % params.HistoryServeWindow
 	var key common.Hash
 	binary.BigEndian.PutUint64(key[24:], ringIndex)
+	if isVerkle {
+		return statedb.GetState(params.SystemAddress, key)
+	}
 	return statedb.GetState(params.HistoryStorageAddress, key)
 }
 
diff --git a/core/vm/interface.go b/core/vm/interface.go
index 011541dde301..3488526fc4dc 100644
--- a/core/vm/interface.go
+++ b/core/vm/interface.go
@@ -20,6 +20,7 @@ import (
 	"math/big"
 
 	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core/state"
 	"github.com/ethereum/go-ethereum/core/stateless"
 	"github.com/ethereum/go-ethereum/core/tracing"
 	"github.com/ethereum/go-ethereum/core/types"
@@ -98,6 +99,8 @@ type StateDB interface {
 
 	Witness() *stateless.Witness
 
+	AccessEvents() *state.AccessEvents
+
 	// Finalise must be invoked at the end of a transaction
 	Finalise(bool)
 }
diff --git a/eth/state_accessor.go b/eth/state_accessor.go
index 0749d7379115..35ec0829b65a 100644
--- a/eth/state_accessor.go
+++ b/eth/state_accessor.go
@@ -242,7 +242,7 @@ func (eth *Ethereum) stateAtTransaction(ctx context.Context, block *types.Block,
 	}
 	// If prague hardfork, insert parent block hash in the state as per EIP-2935.
 	if eth.blockchain.Config().IsPrague(block.Number(), block.Time()) {
-		core.ProcessParentBlockHash(block.ParentHash(), evm)
+		core.ProcessParentBlockHash(block.ParentHash(), evm, eth.blockchain.Config().IsVerkle(block.Number(), block.Time()))
 	}
 	if txIndex == 0 && len(block.Transactions()) == 0 {
 		return nil, vm.BlockContext{}, statedb, release, nil
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 22163030de0b..1bea4835d604 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -386,7 +386,7 @@ func (api *API) traceChain(start, end *types.Block, config *TraceConfig, closed
 			}
 			// Insert parent hash in history contract.
 			if api.backend.ChainConfig().IsPrague(next.Number(), next.Time()) {
-				core.ProcessParentBlockHash(next.ParentHash(), evm)
+				core.ProcessParentBlockHash(next.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(next.Number(), next.Time()))
 			}
 			// Clean out any pending release functions of trace state. Note this
 			// step must be done after constructing tracing state, because the
@@ -541,7 +541,7 @@ func (api *API) IntermediateRoots(ctx context.Context, hash common.Hash, config
 		core.ProcessBeaconBlockRoot(*beaconRoot, evm)
 	}
 	if chainConfig.IsPrague(block.Number(), block.Time()) {
-		core.ProcessParentBlockHash(block.ParentHash(), evm)
+		core.ProcessParentBlockHash(block.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(block.Number(), block.Time()))
 	}
 	for i, tx := range block.Transactions() {
 		if err := ctx.Err(); err != nil {
@@ -605,7 +605,7 @@ func (api *API) traceBlock(ctx context.Context, block *types.Block, config *Trac
 		core.ProcessBeaconBlockRoot(*beaconRoot, evm)
 	}
 	if api.backend.ChainConfig().IsPrague(block.Number(), block.Time()) {
-		core.ProcessParentBlockHash(block.ParentHash(), evm)
+		core.ProcessParentBlockHash(block.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(block.Number(), block.Time()))
 	}
 
 	// JS tracers have high overhead. In this case run a parallel
@@ -782,7 +782,7 @@ func (api *API) standardTraceBlockToFile(ctx context.Context, block *types.Block
 		core.ProcessBeaconBlockRoot(*beaconRoot, evm)
 	}
 	if chainConfig.IsPrague(block.Number(), block.Time()) {
-		core.ProcessParentBlockHash(block.ParentHash(), evm)
+		core.ProcessParentBlockHash(block.ParentHash(), evm, api.backend.ChainConfig().IsVerkle(block.Number(), block.Time()))
 	}
 	for i, tx := range block.Transactions() {
 		// Prepare the transaction for un-traced execution
diff --git a/miner/worker.go b/miner/worker.go
index b5aa08002591..d4b7e0b39930 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -231,7 +231,7 @@ func (miner *Miner) prepareWork(genParams *generateParams, witness bool) (*envir
 		core.ProcessBeaconBlockRoot(*header.ParentBeaconRoot, env.evm)
 	}
 	if miner.chainConfig.IsPrague(header.Number, header.Time) {
-		core.ProcessParentBlockHash(header.ParentHash, env.evm)
+		core.ProcessParentBlockHash(header.ParentHash, env.evm, false)
 	}
 	return env, nil
 }