diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
index 7bf277cea45ad08f281122d67db1faf7f3caa7ef..e042e897cf286f54025455136a1c6b34a09c1b8c 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c
@@ -109,6 +109,10 @@ struct srv_stake {
     dap_chain_net_srv_stake_item_t *itemlist;
     dap_chain_net_srv_stake_item_t *tx_itemlist;
     struct cache_item *cache;
+    struct {
+        bool in_process;
+        dap_chain_net_srv_stake_item_t *sandbox;
+    } hardfork;
 };
 
 static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply);
@@ -179,7 +183,10 @@ static dap_pkey_t *s_get_pkey_by_hash_callback(const uint8_t *a_hash)
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
     for ( ; l_srv_stake_list && !l_stake; l_srv_stake_list = l_srv_stake_list->next) {
         struct srv_stake *l_srv_stake = l_srv_stake_list->data;
-        HASH_FIND(hh, l_srv_stake->itemlist, a_hash, sizeof(dap_hash_fast_t), l_stake);
+        if (l_srv_stake->hardfork.in_process)
+            HASH_FIND(hh, l_srv_stake->hardfork.sandbox, a_hash, sizeof(dap_hash_fast_t), l_stake);
+        else
+            HASH_FIND(hh, l_srv_stake->itemlist, a_hash, sizeof(dap_hash_fast_t), l_stake);
     }
     return l_stake ? l_stake->pkey : NULL; 
 }
@@ -275,13 +282,15 @@ static void s_pos_delegate_delete(void *a_service_internal)
         HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake);
     }
     HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) {
-        // Clang bug at this, l_stake should change at every loop cycle
         HASH_DEL(l_srv_stake->itemlist, l_stake);
         s_srv_stake_item_free((void *)l_stake);
     }
+    HASH_ITER(hh, l_srv_stake->hardfork.sandbox, l_stake, l_tmp) {
+        HASH_DEL(l_srv_stake->hardfork.sandbox, l_stake);
+        s_srv_stake_item_free((void *)l_stake);
+    }
     struct cache_item *l_cache_item = NULL, *l_cache_tmp = NULL;
     HASH_ITER(hh, l_srv_stake->cache, l_cache_item, l_cache_tmp) {
-        // Clang bug at this, l_stake should change at every loop cycle
         HASH_DEL(l_srv_stake->cache, l_cache_item);
         DAP_DELETE(l_cache_item);
     }
@@ -484,6 +493,29 @@ static void s_stake_recalculate_weights(dap_chain_net_id_t a_net_id)
     while (s_weights_truncate(l_srv_stake, l_limit_min));
 }
 
+static void s_stake_key_delegate_sandbox(struct srv_stake *a_srv_stake, dap_chain_addr_t *a_signing_addr, dap_pkey_t *a_pkey)
+{
+    dap_return_if_pass(!a_srv_stake || !a_signing_addr || !a_pkey);
+    log_it(L_NOTICE, "Add key %s delegation in hardfork process", dap_hash_fast_to_str_static(&a_signing_addr->data.hash_fast));
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    bool l_found = false;
+    HASH_FIND(hh, a_srv_stake->hardfork.sandbox, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
+    if (!l_stake)
+        l_stake = DAP_NEW_Z_RET_IF_FAIL(dap_chain_net_srv_stake_item_t);
+    else
+        l_found = true;
+    if (dap_pkey_get_size(l_stake->pkey)) {
+        log_it(L_DEBUG, "Full pkey by hash %s was replaced", dap_hash_fast_to_str_static(&a_signing_addr->data.hash_fast));
+        DAP_DELETE(l_stake->pkey);
+    }
+    l_stake->pkey = DAP_DUP_SIZE(a_pkey, dap_pkey_get_size(a_pkey));
+    if (!l_found) {
+        l_stake->signing_addr = *a_signing_addr;
+        HASH_ADD(hh, a_srv_stake->hardfork.sandbox, signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake);
+    }
+    return;
+}
+
 void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_chain_datum_decree_t *a_decree,
                                           uint256_t a_value, dap_chain_node_addr_t *a_node_addr, dap_pkey_t *a_pkey)
 {
@@ -4302,6 +4334,10 @@ int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, da
     struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
     if (!l_srv_stake)
         return -2;
+    if (l_srv_stake->hardfork.in_process && l_srv_stake->hardfork.sandbox) {
+        log_it(L_ERROR, "Temp hardfork table already existed in net %"DAP_UINT64_FORMAT_U, a_net_id.uint64);
+        return -3;
+    }
     dap_chain_net_srv_stake_item_t *l_stake, *l_tmp;
     HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) {
         if (dap_hash_fast_is_blank(&l_stake->tx_hash)) {
@@ -4310,11 +4346,17 @@ int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, da
         }
     }
     // clean prev table
-    s_pos_delegate_purge(a_net_id);
+    if (!l_srv_stake->hardfork.in_process)
+        s_pos_delegate_purge(a_net_id);
+    
     // restore poa keys
     for ( dap_list_t* l_iter = dap_list_first(l_current_list); l_iter; l_iter = l_iter->next) {
         l_stake = (dap_chain_net_srv_stake_item_t *)l_iter->data;
-        dap_chain_net_srv_stake_key_delegate(l_net, &l_stake->signing_addr, NULL, l_stake->value, &l_stake->node_addr, l_stake->pkey);
+        if (l_srv_stake->hardfork.in_process) {
+            s_stake_key_delegate_sandbox(l_srv_stake, &l_stake->signing_addr, l_stake->pkey);
+        } else {
+            dap_chain_net_srv_stake_key_delegate(l_net, &l_stake->signing_addr, NULL, l_stake->value, &l_stake->node_addr, l_stake->pkey);
+        }
     }
     dap_list_free_full(l_current_list, s_srv_stake_item_free);
 
@@ -4341,9 +4383,39 @@ int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, da
             dap_list_free_full(l_current_list, NULL);
             return -4;
         }
-        dap_chain_net_srv_stake_key_delegate(l_net, &l_addr, l_current_decree, l_value, &l_node_addr, dap_chain_datum_decree_get_pkey(l_current_decree));
-        dap_chain_net_srv_stake_add_approving_decree_info(l_current_decree, l_net);
+        if (l_srv_stake->hardfork.in_process) {
+            s_stake_key_delegate_sandbox(l_srv_stake, &l_addr, dap_chain_datum_decree_get_pkey(l_current_decree));
+        } else {
+            dap_chain_net_srv_stake_key_delegate(l_net, &l_addr, l_current_decree, l_value, &l_node_addr, dap_chain_datum_decree_get_pkey(l_current_decree));
+            dap_chain_net_srv_stake_add_approving_decree_info(l_current_decree, l_net);
+        }
     }
     dap_list_free_full(l_current_list, NULL);
     return 0;
 }
+
+/**
+ * @brief switch key delegate table
+ * @param a_net_id net id to switch
+ * @param a_to_temp true - to sandbox, false - to main
+ * @return if OK - 0, other if error
+ */
+int dap_chain_net_srv_stake_switch_table(dap_chain_net_id_t a_net_id, bool a_to_sandbox)
+{
+    struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    if (!l_srv_stake)
+        return -1;
+    if (l_srv_stake->hardfork.in_process == a_to_sandbox) {
+        log_it(L_DEBUG, "Key delegate table already switched to %s table", a_to_sandbox ? "sandbox" : "main");
+        return -2;
+    }
+    if (!a_to_sandbox) { // free temp table if switch to main
+        dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL;
+        HASH_ITER(hh, l_srv_stake->hardfork.sandbox, l_stake, l_tmp) {
+            HASH_DEL(l_srv_stake->itemlist, l_stake);
+            s_srv_stake_item_free((void *)l_stake);
+        }
+    }
+    l_srv_stake->hardfork.in_process = a_to_sandbox;
+    return 0;
+}
\ No newline at end of file
diff --git a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
index d8d3ba97859c37f2d1199f993467dc9d330a0bdc..ff21ac8e41c4caab0192b6ba5f7be946bee551ab 100644
--- a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
+++ b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h
@@ -82,3 +82,4 @@ void dap_chain_net_srv_stake_add_approving_decree_info(dap_chain_datum_decree_t
 void dap_chain_net_srv_stake_remove_approving_decree_info(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr);
 int dap_chain_net_srv_stake_hardfork_data_export(dap_chain_net_t *a_net, dap_list_t **a_out);
 int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_hardfork_decree_hash);
+int dap_chain_net_srv_stake_switch_table(dap_chain_net_id_t a_net_id, bool a_to_sandbox);
\ No newline at end of file
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index b23851f2cf86a4c9939c4015c5bee53b78cecd07..147849011ffd827960211c6ac5186481d543c996 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -1735,8 +1735,9 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
         dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
         assert(l_net);
         if ( !dap_chain_net_get_load_mode(l_net) ) {
-            if ( (ret = dap_chain_atom_save(l_cell, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL)) < 0 ) {
-                log_it(L_ERROR, "Can't save atom to file, code %d", ret);
+            if ( dap_chain_atom_save(l_cell, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL) < 0 ) {
+                log_it(L_ERROR, "Can't save atom to file");
+                dap_chain_net_srv_stake_switch_table(a_chain->net_id, false);
                 return ATOM_REJECT;
             } else if (a_chain->is_mapped) {
                 l_block = (dap_chain_block_t*)( l_cell->map_pos += sizeof(uint64_t) );  // Switching to mapped area
@@ -1748,6 +1749,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
         l_block_cache = dap_chain_block_cache_new(&l_block_hash, l_block, a_atom_size, PVT(l_blocks)->blocks_count + 1, !a_chain->is_mapped);
         if (!l_block_cache) {
             log_it(L_DEBUG, "%s", "... corrupted block");
+            dap_chain_net_srv_stake_switch_table(a_chain->net_id, false);
             return ATOM_REJECT;
         }
         debug_if(s_debug_more, L_DEBUG, "... new block %s", l_block_cache->block_hash_str);
@@ -1838,6 +1840,10 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
                     log_it(L_ERROR, "Can't find hardfork decree hash in candidate block meta");
                     return ATOM_REJECT;
                 }
+                if (dap_chain_net_srv_stake_switch_table(a_chain->net_id, false)) { // to main
+                    log_it(L_CRITICAL, "Can't accept hardfork genesis block %s: error in switching to main table", dap_hash_fast_to_str_static(a_atom_hash));
+                    return ATOM_REJECT;
+                }
                 if (dap_chain_net_srv_stake_hardfork_data_import(a_chain->net_id, l_hardfork_decree_hash)) { // True import
                     log_it(L_ERROR, "Can't accept hardfork genesis block %s: error in hardfork data restoring", dap_hash_fast_to_str_static(a_atom_hash));
                     return ATOM_REJECT;
@@ -2008,7 +2014,14 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain,
                 log_it(L_ERROR, "Can't find hardfork decree hash in candidate block meta");
                 return ATOM_REJECT;
             }
+            if (dap_chain_net_srv_stake_switch_table(a_chain->net_id, true)) { // to Sandbox
+                log_it(L_ERROR, "Can't accept hardfork genesis block %s: error in switching to sandbox table", dap_hash_fast_to_str_static(a_atom_hash));
+                return ATOM_REJECT;
+            }
             if (dap_chain_net_srv_stake_hardfork_data_import(a_chain->net_id, l_hardfork_decree_hash)) { // Sandbox
+                if (dap_chain_net_srv_stake_switch_table(a_chain->net_id, false)) {  // return to main
+                    log_it(L_CRITICAL, "Can't accept hardfork genesis block %s: error in switching to main table", dap_hash_fast_to_str_static(a_atom_hash));
+                }
                 log_it(L_ERROR, "Can't accept hardfork genesis block %s: error in hardfork data restoring", dap_hash_fast_to_str_static(a_atom_hash));
                 return ATOM_REJECT;
             }