diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go
index a70f7bb3a..064453ca5 100644
--- a/pkg/core/blockchain.go
+++ b/pkg/core/blockchain.go
@@ -1012,9 +1012,14 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage)
 
 func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error {
 	for _, c := range bc.contracts.Contracts {
-		err := c.InitializeCache(blockHeight, d)
-		if err != nil {
-			return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err)
+		for _, h := range c.Metadata().UpdateHistory {
+			if blockHeight >= h { // check that contract was deployed.
+				err := c.InitializeCache(blockHeight, d)
+				if err != nil {
+					return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err)
+				}
+				break
+			}
 		}
 	}
 	return nil
diff --git a/pkg/core/blockchain_neotest_test.go b/pkg/core/blockchain_neotest_test.go
index 8a99ad04d..f5e2edcbf 100644
--- a/pkg/core/blockchain_neotest_test.go
+++ b/pkg/core/blockchain_neotest_test.go
@@ -299,6 +299,71 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
 	})
 }
 
+// This test enables Notary native contract at non-zero height and checks that no
+// Notary cache initialization is performed before that height on node restart.
+func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) {
+	const notaryEnabledHeight = 3
+	ps, path := newLevelDBForTestingWithPath(t, "")
+	customConfig := func(c *config.Blockchain) {
+		c.P2PSigExtensions = true
+		c.NativeUpdateHistories = make(map[string][]uint32)
+		for _, n := range []string{
+			nativenames.Neo,
+			nativenames.Gas,
+			nativenames.Designation,
+			nativenames.Management,
+			nativenames.CryptoLib,
+			nativenames.Ledger,
+			nativenames.Management,
+			nativenames.Oracle,
+			nativenames.Policy,
+			nativenames.StdLib,
+			nativenames.Notary,
+		} {
+			if n == nativenames.Notary {
+				c.NativeUpdateHistories[n] = []uint32{notaryEnabledHeight}
+			} else {
+				c.NativeUpdateHistories[n] = []uint32{0}
+			}
+		}
+	}
+	bc, validators, committee, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, ps)
+	require.NoError(t, err)
+	go bc.Run()
+	e := neotest.NewExecutor(t, bc, validators, committee)
+	e.AddNewBlock(t)
+	bc.Close() // Ensure persist is done and persistent store is properly closed.
+
+	ps, _ = newLevelDBForTestingWithPath(t, path)
+
+	// If NativeActivations are not taken into account during native cache initialization,
+	// bs.init() will panic on Notary cache initialization as it's not deployed yet.
+	require.NotPanics(t, func() {
+		bc, _, _, err = chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, ps)
+		require.NoError(t, err)
+	})
+	go bc.Run()
+	defer bc.Close()
+	e = neotest.NewExecutor(t, bc, validators, committee)
+	h := e.Chain.BlockHeight()
+
+	// Notary isn't initialized yet, so accessing Notary cache should panic.
+	require.Panics(t, func() {
+		_ = e.Chain.GetMaxNotValidBeforeDelta()
+	})
+
+	// Ensure Notary will be properly initialized and accessing Notary cache works
+	// as expected.
+	for i := 0; i < notaryEnabledHeight; i++ {
+		require.NotPanics(t, func() {
+			e.AddNewBlock(t)
+		}, h+uint32(i)+1)
+	}
+	require.NotPanics(t, func() {
+		_ = e.Chain.GetMaxNotValidBeforeDelta()
+	})
+}
+
 func TestBlockchain_AddHeaders(t *testing.T) {
 	bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
 		c.StateRootInHeader = true