diff --git a/dap-sdk b/dap-sdk
index b6ead51e413671d2416f98796b8ac7d397e2e0ed..8b1659a2f3561c513f1864e17522a98f10a335e4 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit b6ead51e413671d2416f98796b8ac7d397e2e0ed
+Subproject commit 8b1659a2f3561c513f1864e17522a98f10a335e4
diff --git a/modules/chain/dap_chain_srv.c b/modules/chain/dap_chain_srv.c
index cfd839651c307b6766b0bd6c2aec2eff915925f6..28018c525b406784544e234c9ee4f79712a11f02 100644
--- a/modules/chain/dap_chain_srv.c
+++ b/modules/chain/dap_chain_srv.c
@@ -216,6 +216,13 @@ dap_chain_srv_hardfork_state_t *dap_chain_srv_hardfork_all(dap_chain_net_id_t a_
     return ret;
 }
 
+int dap_chain_srv_load_state(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_srv_uid, byte_t *a_state, uint64_t a_state_size, uint32_t a_state_count)
+{
+    struct service_list *l_service = s_service_find(a_srv_uid);
+    if (s_net_service_find(l_service, a_net_id))
+        return l_service->callbacks.hardfork_load(a_net_id, a_state, a_state_size, a_state_count);
+    return -404;
+}
 /**
  * @brief dap_chain_srv_get_fees
  * @param a_net_id
diff --git a/modules/chain/include/dap_chain_srv.h b/modules/chain/include/dap_chain_srv.h
index 91be1dda009513ffeb53c7e4829bd23049cc28e2..7b69cd6a51dda90d6061aaa0ba2905d5412e537c 100644
--- a/modules/chain/include/dap_chain_srv.h
+++ b/modules/chain/include/dap_chain_srv.h
@@ -120,4 +120,5 @@ dap_list_t *dap_chain_srv_list(dap_chain_net_id_t a_net_id);
 int dap_chain_srv_purge(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_srv_uid);
 int dap_chain_srv_purge_all(dap_chain_net_id_t a_net_id);
 dap_chain_srv_hardfork_state_t *dap_chain_srv_hardfork_all(dap_chain_net_id_t a_net_id);
+int dap_chain_srv_load_state(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_srv_uid, byte_t *a_state, uint64_t a_state_size, uint32_t a_state_count);
 json_object *dap_chain_srv_get_fees(dap_chain_net_id_t a_net_id);
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index 6e18ff6e92337f462ca3135c24cb751f4ce70cf8..e2e0abc27612718a020d5f65ad55246b4b9476df 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -527,7 +527,7 @@ int dap_ledger_test_add_new_datum (uint16_t a_datum_type, void* a_datum, size_t
 {
     dap_chain_datum_t* l_new_datum = dap_chain_datum_create(a_datum_type, a_datum, a_datum_size);
     size_t l_new_datum_size = a_datum_size + sizeof(l_new_datum->header);
-    int status = dap_chain_datum_add(a_chain, l_new_datum, l_new_datum_size, a_datum_hash, NULL);
+    int status = dap_chain_datum_add(a_chain, l_new_datum, l_new_datum_size, a_datum_hash, NULL, false);
     dap_assert(status == 0, "Test of transaction adding to ledger:");
     return status;
 }
@@ -567,7 +567,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_assert(l_second_tx, "Test of creating second tx:");  
     dap_chain_hash_fast_t l_second_tx_hash = {0};
     dap_hash_fast(l_second_tx, dap_chain_datum_tx_get_size(l_second_tx), &l_second_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false, NULL), "Test of second transaction adding to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false, NULL, false), "Test of second transaction adding to ledger:");
     dap_ledger_test_print_balance(a_ledger, &l_addr);
 
     // try to remove spent tx
@@ -584,7 +584,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_assert_PIF(l_cond_tx, "Test of creating conditional transaction:");  
     dap_chain_hash_fast_t l_cond_tx_hash = {0};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_first_tx), &l_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL), "Test of conditional transaction adding to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL, false), "Test of conditional transaction adding to ledger:");
     dap_ledger_test_print_balance(a_ledger, &l_addr);
     dap_assert(!dap_ledger_tx_remove(a_ledger, l_cond_tx, &l_cond_tx_hash), "Test of conditional transaction removing from ledger:");
     l_balance_after = dap_ledger_test_print_balance(a_ledger, &l_addr);
@@ -597,7 +597,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_assert_PIF(l_cond_tx, "Test of creating conditional transaction:"); 
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL), "Test of conditional transaction adding to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL, false), "Test of conditional transaction adding to ledger:");
     dap_ledger_test_print_balance(a_ledger, &l_addr);
 
     dap_cert_t *l_cond_spender_cert = dap_cert_generate_mem_with_seed("newCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, "FMknbirh8*^#$RYU*q", 18);
@@ -607,7 +607,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_spendind_tx = dap_ledger_test_create_spend_tx_cond(a_from_key, &l_cond_tx_hash, l_cond_spender_cert->enc_key, dap_chain_uint256_from(1U),a_ledger);
     dap_chain_hash_fast_t l_spend_cond_tx_hash = {0};
     dap_hash_fast(l_cond_spendind_tx, dap_chain_datum_tx_get_size(l_cond_spendind_tx), &l_spend_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_spendind_tx, &l_spend_cond_tx_hash, false, NULL), "Test adding of transaction spending to a conditional transaction  to ledger:");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_spendind_tx, &l_spend_cond_tx_hash, false, NULL, false), "Test adding of transaction spending to a conditional transaction  to ledger:");
     uint256_t l_cond_spending_balance_after = dap_ledger_test_print_balance(a_ledger, &l_cond_spender_addr);
     dap_assert(!compare256(l_cond_spending_balance_after, dap_chain_uint256_from(1U)), "Check balance after spending:");
     dap_ledger_test_print_balance(a_ledger, &l_cond_spender_addr);
@@ -624,7 +624,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_tx = dap_ledger_test_create_tx_cond(a_from_key, a_prev_hash, &l_addr_first, dap_chain_uint256_from(2U),a_ledger);
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
-    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL), "Adding of cond transaction to ledger is");
+    dap_assert(!dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL, false), "Adding of cond transaction to ledger is");
 
     dap_cert_t *l_cond_spending_cert = dap_cert_generate_mem_with_seed("newCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, "FMknbirh8*^#$RYU*q", 18);
     dap_chain_addr_t l_cond_spending_addr = {0};
@@ -633,7 +633,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_returning_tx = dap_ledger_test_create_return_from_tx_cond(&l_cond_tx_hash, a_from_key ,a_ledger);
     dap_chain_hash_fast_t l_cond_returning_tx_hash = {0};
     dap_hash_fast(l_cond_returning_tx, dap_chain_datum_tx_get_size(l_cond_returning_tx), &l_cond_returning_tx_hash);
-    int err_code = dap_ledger_tx_add(a_ledger, l_cond_returning_tx, &l_cond_returning_tx_hash, false, NULL);
+    int err_code = dap_ledger_tx_add(a_ledger, l_cond_returning_tx, &l_cond_returning_tx_hash, false, NULL, false);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Returning of funds from cond transaction is");
     uint256_t l_cond_spending_balance_after = dap_ledger_test_print_balance(a_ledger, &l_cond_spending_addr);
@@ -653,7 +653,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_cond_tx = dap_ledger_test_create_stake_tx_cond(a_from_key, a_prev_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_cond_tx_hash = {};
     dap_hash_fast(l_cond_tx, dap_chain_datum_tx_get_size(l_cond_tx), &l_cond_tx_hash);
-    int err_code = dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL);
+    int err_code = dap_ledger_tx_add(a_ledger, l_cond_tx, &l_cond_tx_hash, false, NULL, false);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of stake cond transaction to ledger is");
 
@@ -668,7 +668,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_stake_cond_tx = dap_ledger_test_create_stake_tx_cond(a_from_key, a_prev_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_stake_cond_tx_hash = {};
     dap_hash_fast(l_stake_cond_tx, dap_chain_datum_tx_get_size(l_stake_cond_tx), &l_stake_cond_tx_hash);
-    int err_code = dap_ledger_tx_add(a_ledger, l_stake_cond_tx, &l_stake_cond_tx_hash, false, NULL);
+    int err_code = dap_ledger_tx_add(a_ledger, l_stake_cond_tx, &l_stake_cond_tx_hash, false, NULL, false);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of stake cond transaction to ledger is");
     sleep(3);
@@ -680,7 +680,7 @@ void dap_ledger_test_datums_removing(dap_ledger_t *a_ledger, dap_hash_fast_t *a_
     dap_chain_datum_tx_t *l_unstake_cond_tx = dap_ledger_test_create_unstake_tx_cond(a_from_key, &l_stake_cond_tx_hash, dap_chain_uint256_from(20U), a_ledger);
     dap_hash_fast_t l_unstake_cond_tx_hash = {};
     dap_hash_fast(l_unstake_cond_tx, dap_chain_datum_tx_get_size(l_unstake_cond_tx), &l_unstake_cond_tx_hash);
-    err_code = dap_ledger_tx_add(a_ledger, l_unstake_cond_tx, &l_unstake_cond_tx_hash, false, NULL);
+    err_code = dap_ledger_tx_add(a_ledger, l_unstake_cond_tx, &l_unstake_cond_tx_hash, false, NULL, false);
     printf("err_code = %s\n", dap_ledger_check_error_str(err_code));
     dap_assert(!err_code, "Adding of unstake cond transaction to ledger is");
     uint256_t l_balance_delegated_after_unstaking = dap_ledger_test_print_delegate_balance(a_ledger, &l_addr);
@@ -730,14 +730,14 @@ dap_hash_fast_t dap_ledger_test_double_spending(
     dap_assert_PIF(l_first_tx, "Can't creating base transaction.");
     dap_chain_hash_fast_t l_first_tx_hash = {0};
     dap_hash_fast(l_first_tx, dap_chain_datum_tx_get_size(l_first_tx), &l_first_tx_hash);
-    dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_first_tx, &l_first_tx_hash, false, NULL), "Can't add first transaction on ledger");
+    dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_first_tx, &l_first_tx_hash, false, NULL, false), "Can't add first transaction on ledger");
     //uint256_t l_balance = dap_ledger_calc_balance(a_ledger, &l_addr_first, s_token_ticker);
     // Second tx
     dap_chain_datum_tx_t *l_second_tx = dap_ledger_test_create_tx(a_from_key, a_prev_hash,
                                                                        &a_addr_to, dap_chain_uint256_from(s_standard_value_tx - s_fee));
     dap_chain_hash_fast_t l_second_tx_hash = {0};
     dap_hash_fast(l_second_tx, dap_chain_datum_tx_get_size(l_second_tx), &l_second_tx_hash);
-    dap_assert_PIF(dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false, NULL), "Added second transaction on ledger");
+    dap_assert_PIF(dap_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false, NULL, false), "Added second transaction on ledger");
     dap_pass_msg("The verification test is not able to make two normal transactions per one basic transaction.");
     return l_first_tx_hash; 
 }
@@ -867,7 +867,7 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
                                                                                       *l_addr_1->addr, a_cert);
         dap_hash_fast_t l_btx_addr1_hash = {0};
         dap_hash_fast(l_btx_addr1, dap_chain_datum_tx_get_size(l_btx_addr1), &l_btx_addr1_hash);
-        int l_ledger_add_code = dap_ledger_tx_add(a_ledger, l_btx_addr1, &l_btx_addr1_hash, false, NULL);
+        int l_ledger_add_code = dap_ledger_tx_add(a_ledger, l_btx_addr1, &l_btx_addr1_hash, false, NULL, false);
         char *l_ledger_tx_add_str = dap_strdup_printf("Can't add base tx in white address. Code: %d", l_ledger_add_code);
         dap_assert_PIF(!l_ledger_add_code, l_ledger_tx_add_str);
         DAP_DELETE(l_ledger_tx_add_str);
@@ -875,13 +875,13 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
         dap_chain_datum_tx_t *l_tx_to_addr4 = dap_ledger_test_create_tx(l_addr_1->enc_key, &l_btx_addr1_hash,
                                                                               l_addr_4->addr, dap_chain_uint256_from(s_total_supply-s_fee));
         dap_hash_fast(l_tx_to_addr4, dap_chain_datum_tx_get_size(l_tx_to_addr4), &l_tx_addr4_hash);
-        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_tx_to_addr4, &l_tx_addr4_hash, false, NULL),
+        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_tx_to_addr4, &l_tx_addr4_hash, false, NULL, false),
                        "Can't add transaction to address from white list in ledger");
         dap_chain_datum_tx_t *l_tx_to_addr3 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_tx_addr4_hash,
                                                                               l_addr_3->addr, dap_chain_uint256_from(s_total_supply-s_fee));
         dap_hash_fast_t l_tx_addr3_hash = {0};
         dap_hash_fast(l_tx_to_addr3, dap_chain_datum_tx_get_size(l_tx_to_addr3), &l_tx_addr3_hash);
-        int res_add_tx = dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL);
+        int res_add_tx = dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL, false);
         if (!res_add_tx) {
             dap_fail("It was possible to carry out a transaction to a forbidden address");
         } else {
@@ -981,20 +981,20 @@ void dap_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a_cert,
                                                                                        *l_addr_2->addr, a_cert);
         dap_hash_fast_t l_btx_addr2_hash = {0};
         dap_hash_fast(l_btx_addr2, dap_chain_datum_tx_get_size(l_btx_addr2), &l_btx_addr2_hash);
-        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_btx_addr2, &l_btx_addr2_hash, false, NULL),
+        dap_assert_PIF(!dap_ledger_tx_add(a_ledger, l_btx_addr2, &l_btx_addr2_hash, false, NULL, false),
                        "Can't add base tx in white address");
         //Check tx in addr from block list
         dap_chain_datum_tx_t *l_tx_to_addr1 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_btx_addr2_hash,
                                                                               l_addr_1->addr, dap_chain_uint256_from(s_total_supply));
         dap_hash_fast_t l_tx_addr1_hash = {0};
         dap_hash_fast(l_tx_to_addr1, dap_chain_datum_tx_get_size(l_tx_to_addr1), &l_tx_addr1_hash);
-        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr1, &l_tx_addr1_hash, false, NULL), "Transfer test to a forbidden address.");
+        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr1, &l_tx_addr1_hash, false, NULL, false), "Transfer test to a forbidden address.");
         //Check tx in addr from list
         dap_chain_datum_tx_t *l_tx_to_addr3 = dap_ledger_test_create_tx(l_addr_4->enc_key, &l_tx_addr1_hash,
                                                                               l_addr_3->addr, dap_chain_uint256_from(s_total_supply));
         dap_hash_fast_t l_tx_addr3_hash = {0};
         dap_hash_fast(l_tx_to_addr3, dap_chain_datum_tx_get_size(l_tx_to_addr3), &l_tx_addr3_hash);
-        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL), "Transfer test to a not forbidden address.");
+        dap_assert(dap_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false, NULL, false), "Transfer test to a not forbidden address.");
     }
 }
 
@@ -1077,7 +1077,7 @@ void dap_ledger_test_run(void){
     dap_hash_fast_t l_hash_btx = {0};
     dap_hash_fast(l_base_tx, l_base_tx_size, &l_hash_btx);
     dap_assert_PIF(!dap_ledger_tx_add_check(l_ledger, l_base_tx, l_base_tx_size, &l_hash_btx), "Check can added base tx in ledger");
-    dap_assert_PIF(!dap_ledger_tx_add(l_ledger, l_base_tx, &l_hash_btx, false, NULL), "Added base tx in ledger.");
+    dap_assert_PIF(!dap_ledger_tx_add(l_ledger, l_base_tx, &l_hash_btx, false, NULL, false), "Added base tx in ledger.");
     uint256_t l_balance_example = dap_chain_uint256_from(s_standard_value_tx);
     uint256_t l_balance = dap_ledger_calc_balance(l_ledger, &l_addr, s_token_ticker);
 	uint256_t l_fee = dap_chain_uint256_from(s_fee);
@@ -1093,7 +1093,7 @@ void dap_ledger_test_run(void){
     if (dap_ledger_tx_add_check(l_ledger, l_base_tx_second, l_base_tx_size2, &l_hash_btx_second)) {
         dap_pass_msg("Checking can added second base tx in ledger");
     }
-    if (dap_ledger_tx_add(l_ledger, l_base_tx_second, &l_hash_btx_second, false, NULL)){
+    if (dap_ledger_tx_add(l_ledger, l_base_tx_second, &l_hash_btx_second, false, NULL, false)) {
         dap_pass_msg("Checking for a failure to add a second base transaction for the same issue to the ledger.");
     } else {
         dap_fail("Checking for a failure to add a second base transaction for the same issue to the ledger.");
diff --git a/modules/datum/include/dap_chain_datum_service_state.h b/modules/datum/include/dap_chain_datum_service_state.h
index 5d47dd556b2164e902ed99d69da9876dda66cadb..fec31dcf70d973c6cd41c67a0fd7c95b0a3f0d53 100644
--- a/modules/datum/include/dap_chain_datum_service_state.h
+++ b/modules/datum/include/dap_chain_datum_service_state.h
@@ -26,5 +26,6 @@
 typedef struct dap_chain_datum_service_state {
     dap_chain_srv_uid_t srv_uid;
     uint32_t states_count;
+    uint64_t state_size;
     byte_t states[];
 } DAP_ALIGN_PACKED dap_chain_datum_service_state_t;
diff --git a/modules/ledger/dap_chain_ledger.c b/modules/ledger/dap_chain_ledger.c
index c99d32f9d91838dc277635ec7e8cc5b975d041e0..569634b55a490b77327c0412a3710f0695382266 100644
--- a/modules/ledger/dap_chain_ledger.c
+++ b/modules/ledger/dap_chain_ledger.c
@@ -649,7 +649,7 @@ void dap_ledger_pvt_threshold_txs_proc(dap_ledger_t *a_ledger)
         l_success = false;
         dap_ledger_tx_item_t *l_tx_item, *l_tx_tmp;
         HASH_ITER(hh, l_ledger_pvt->threshold_txs, l_tx_item, l_tx_tmp) {
-            int l_res = dap_ledger_tx_add(a_ledger, l_tx_item->tx, &l_tx_item->tx_hash_fast, true, NULL);
+            int l_res = dap_ledger_tx_add(a_ledger, l_tx_item->tx, &l_tx_item->tx_hash_fast, true, NULL, false);
             if (l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION &&
                     l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS) {
                 HASH_DEL(l_ledger_pvt->threshold_txs, l_tx_item);
diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c
index aa34639687f1cc6e808e4ff7b3afedeaa982d69d..38e05df59f59951a04d63832babf4de8f138a50d 100644
--- a/modules/ledger/dap_chain_ledger_tx.c
+++ b/modules/ledger/dap_chain_ledger_tx.c
@@ -887,10 +887,14 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
         case TX_ITEM_TYPE_OUT_COND: {
             dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t *)it;
             if (l_multichannel) {
-                if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)
+                if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE ||
+                        l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STACK)
                     l_token = (char *)a_ledger->net->pub.native_ticker;
-                else if (l_main_ticker)
+                else if (l_main_ticker || (a_main_ticker && *a_main_ticker)) {
+                    if (!l_main_ticker)
+                        l_main_ticker = a_main_ticker; // It should be only in hardfork state
                     l_token = l_main_ticker;
+                }
                 else {
                     log_it(L_WARNING, "No conditional output support for multichannel transaction");
                     l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER;
@@ -1060,7 +1064,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
         }
     }
 
-    if (a_main_ticker && !l_err_num)
+    if (a_main_ticker && !l_err_num && (a_main_ticker != l_main_ticker))
         dap_strncpy(a_main_ticker, l_main_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
 
     HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
@@ -1209,7 +1213,7 @@ dap_list_t *s_trackers_aggregate(dap_ledger_t *a_ledger, dap_list_t *a_trackers,
  * @param a_from_threshold
  * @return return 1 OK, -1 error
  */
-int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data)
+int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data, bool a_hardfork_related)
 {
     if(!a_tx) {
         debug_if(g_debug_ledger, L_ERROR, "NULL tx detected");
@@ -1222,6 +1226,37 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     char l_main_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX] = { '\0' };
 
     bool l_from_threshold = a_from_threshold;
+    dap_hash_fast_t l_tx_hash = *a_tx_hash;
+    byte_t *l_item = NULL;
+    size_t l_tx_item_size = 0;
+
+    if (a_hardfork_related) {
+        TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) {
+            if (*l_item != TX_ITEM_TYPE_TSD)
+                continue;
+            dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd;
+            switch (l_tsd->type) {
+            case DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TX_HASH: {
+                if (l_tsd->size != sizeof(dap_hash_fast_t)) {
+                    log_it(L_WARNING, "Incorrect size of TSD tracker section %u (need %zu)", l_tsd->size, sizeof(dap_hash_fast_t));
+                    break;
+                }
+                l_tx_hash = *(dap_hash_fast_t *)l_tsd->data;
+            } break;
+            case DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TICKER: {
+                if (!l_tsd->size || l_tsd->size > DAP_CHAIN_TICKER_SIZE_MAX) {
+                    log_it(L_WARNING, "Illegal harfork datum tx TSD TICKER size %u", l_tsd->size);
+                    break;
+                }
+                dap_strncpy(l_main_token_ticker, (char *)l_tsd->data, DAP_CHAIN_TICKER_SIZE_MAX);
+            } break;
+            default:
+                log_it(L_WARNING, "Illegal harfork datum tx TSD item type %d", l_tsd->type);
+                break;
+            }
+        }
+    }
+
     char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
     dap_chain_hash_fast_to_str(a_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str));
 
@@ -1229,14 +1264,14 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     dap_chain_srv_uid_t l_tag =  { .uint64 = 0 };
     dap_chain_tx_tag_action_type_t l_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
 
-    if( (l_ret_check = s_tx_cache_check(a_ledger, a_tx, a_tx_hash, a_from_threshold,
+    if( (l_ret_check = s_tx_cache_check(a_ledger, a_tx, &l_tx_hash, a_from_threshold,
                                                        &l_list_bound_items, &l_list_tx_out,
                                                        l_main_token_ticker, &l_tag, &l_action, false))) {
         if ((l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS ||
                 l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION) &&
                 l_ledger_pvt->threshold_enabled && !dap_chain_net_get_load_mode(a_ledger->net)) {
             if (!l_from_threshold)
-                dap_ledger_pvt_threshold_txs_add(a_ledger, a_tx, a_tx_hash);
+                dap_ledger_pvt_threshold_txs_add(a_ledger, a_tx, &l_tx_hash);
         } else {
             debug_if(g_debug_ledger, L_WARNING, "dap_ledger_tx_add() tx %s not passed the check: %s ", l_tx_hash_str,
                         dap_ledger_check_error_str(l_ret_check));
@@ -1292,7 +1327,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         switch (l_type) {
         case TX_ITEM_TYPE_IN_EMS:
             // Mark it as used with current tx hash
-            l_bound_item->emission_item->tx_used_out = *a_tx_hash;
+            l_bound_item->emission_item->tx_used_out = l_tx_hash;
             dap_ledger_pvt_emission_cache_update(a_ledger, l_bound_item->emission_item);
             l_outs_used--; // Do not calc this output with tx used items
             continue;
@@ -1300,7 +1335,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         case TX_ITEM_TYPE_IN_EMS_LOCK:
             if (l_bound_item->stake_lock_item) { // Legacy stake lock emission
                 // Mark it as used with current tx hash
-                l_bound_item->stake_lock_item->tx_used_out = *a_tx_hash;
+                l_bound_item->stake_lock_item->tx_used_out = l_tx_hash;
                 s_ledger_stake_lock_cache_update(a_ledger, l_bound_item->stake_lock_item);
             }
             l_outs_used--; // Do not calc this output with tx used items
@@ -1314,7 +1349,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
                 goto FIN;
             }
             l_item->key = l_bound_item->reward_key;
-            l_item->spender_tx = *a_tx_hash;
+            l_item->spender_tx = l_tx_hash;
             pthread_rwlock_wrlock(&l_ledger_pvt->rewards_rwlock);
             HASH_ADD(hh, l_ledger_pvt->rewards, key, sizeof(l_item->key), l_item);
             pthread_rwlock_unlock(&l_ledger_pvt->rewards_rwlock);
@@ -1352,7 +1387,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
             HASH_FIND_INT(s_verificators, &l_tmp, l_verificator);
             pthread_rwlock_unlock(&s_verificators_rwlock);
             if (l_verificator && l_verificator->callback_in_add)
-                l_verificator->callback_in_add(a_ledger, a_tx, a_tx_hash, l_bound_item->cond);
+                l_verificator->callback_in_add(a_ledger, a_tx, &l_tx_hash, l_bound_item->cond);
         } break;
 
         default:
@@ -1362,7 +1397,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
 
         // Gather colour information from previous outputs
         dap_ledger_tx_item_t *l_prev_item_out = l_bound_item->prev_item;
-        l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].tx_spent_hash_fast = *a_tx_hash;
+        l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].tx_spent_hash_fast = l_tx_hash;
         l_trackers_mover = s_trackers_aggregate(a_ledger, l_trackers_mover,
                                                   l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].trackers, a_tx->header.ts_created);
         // add a used output
@@ -1421,7 +1456,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
             HASH_FIND_INT(s_verificators, &l_tmp, l_verificator);
             pthread_rwlock_unlock(&s_verificators_rwlock);
             if (l_verificator && l_verificator->callback_out_add)
-                l_verificator->callback_out_add(a_ledger, a_tx, a_tx_hash, l_cond);
+                l_verificator->callback_out_add(a_ledger, a_tx, &l_tx_hash, l_cond);
             SUM_256_256(l_native_value, l_cond->header.value, &l_native_value);
             continue;   // balance raise will be with next conditional transaction
         }
@@ -1496,9 +1531,9 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
     int l_err_num = 0;
     if (s_voting_callbacks.voting_callback) {
         if (l_action == DAP_CHAIN_TX_TAG_ACTION_VOTING)
-            l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTING, a_tx, a_tx_hash, true);
+            l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTING, a_tx, &l_tx_hash, true);
         else if (l_action == DAP_CHAIN_TX_TAG_ACTION_VOTE)
-            l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, a_tx_hash, true);
+            l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, &l_tx_hash, true);
     }
     assert(!l_err_num);
 
@@ -1509,7 +1544,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         l_ret = -1;
         goto FIN;
     }
-    l_tx_item->tx_hash_fast = *a_tx_hash;
+    l_tx_item->tx_hash_fast = l_tx_hash;
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
     l_tx_item->tx = l_ledger_pvt->mapped ? a_tx : DAP_DUP_SIZE(a_tx, l_tx_size);
     l_tx_item->cache_data.n_outs = l_outs_count;
@@ -1575,6 +1610,21 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         }
     }
 
+    if (a_hardfork_related) {
+        TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) {
+            if (*l_item != TX_ITEM_TYPE_TSD)
+                continue;
+            dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd;
+            if (l_tsd->type != DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER)
+                continue;
+            if (l_tsd->size != sizeof(dap_ledger_tracker_t)) {
+                log_it(L_WARNING, "Incorrect size of TSD tracker section %u (need %zu)", l_tsd->size, sizeof(dap_ledger_tracker_t));
+                break;
+            }
+            l_tx_item->out_metadata[0].trackers = dap_list_append(l_tx_item->out_metadata[0].trackers, l_tsd->data);
+        }
+    }
+
     l_tx_item->cache_data.multichannel = l_multichannel;
     l_tx_item->ts_added = dap_nanotime_now();
     pthread_rwlock_wrlock(&l_ledger_pvt->ledger_rwlock);
@@ -1594,7 +1644,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         dap_list_t *l_notifier;
         DL_FOREACH(PVT(a_ledger)->bridged_tx_notifiers, l_notifier) {
             dap_ledger_bridged_tx_notifier_t *l_notify = l_notifier->data;
-            l_notify->callback(a_ledger, a_tx, a_tx_hash, l_notify->arg, DAP_LEDGER_NOTIFY_OPCODE_ADDED);
+            l_notify->callback(a_ledger, a_tx, &l_tx_hash, l_notify->arg, DAP_LEDGER_NOTIFY_OPCODE_ADDED);
         }
     }
     if (PVT(a_ledger)->cached) {
@@ -1932,7 +1982,7 @@ FIN:
     return l_ret;
 }
 
-int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data)
+int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data, bool a_hardfork_related)
 {
 #ifndef DAP_LEDGER_TEST
     if (dap_chain_net_get_load_mode(a_ledger->net)) {
@@ -1948,32 +1998,7 @@ int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_c
             return DAP_LEDGER_CHECK_ALREADY_CACHED;
     }
 #endif
-    return dap_ledger_tx_add(a_ledger, a_tx, a_tx_hash, false, a_datum_index_data);
-}
-
-int dap_ledger_tx_load_hardfork_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data)
-{
-    dap_return_val_if_fail(a_ledger && a_tx && a_tx_hash, -1);
-
-    byte_t *l_item = NULL;
-    size_t l_tx_item_size = 0;
-    TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) {
-        if (*l_item != TX_ITEM_TYPE_TSD)
-            continue;
-        dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd;
-        if (l_tsd->type != DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER)
-            continue;
-        if (l_tsd->size != sizeof(dap_ledger_tracker_t))
-            return log_it(L_ERROR, "Incorrect size of TSD tracker section %u (need %zu)", l_tsd->size, sizeof(dap_ledger_tracker_t)), -2;
-        dap_ledger_tx_item_t *l_item_tx = NULL;
-        s_tx_find_by_hash(a_ledger, a_tx_hash, &l_item_tx, true);
-        if (!l_item_tx)
-            return log_it(L_ERROR, "Can't find hardfork tx %s in ledger", dap_hash_fast_to_str_static(a_tx_hash)), -3;
-        if (l_item_tx->cache_data.n_outs != 1)
-            return log_it(L_ERROR, "Can't add hardfork data to tx %s cause it's not a single-out tx", dap_hash_fast_to_str_static(a_tx_hash)), -4;
-        l_item_tx->out_metadata[0].trackers = dap_list_append(l_item_tx->out_metadata[0].trackers, l_tsd->data);
-    }
-    return 0;
+    return dap_ledger_tx_add(a_ledger, a_tx, a_tx_hash, false, a_datum_index_data, a_hardfork_related);
 }
 
 static void s_ledger_stake_lock_cache_update(dap_ledger_t *a_ledger, dap_ledger_stake_lock_item_t *a_stake_lock_item)
diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h
index 4ebf36ffd58529b49fa66e9d1a9b37af3f762392..9a5b500f551bfa354f54c286efd454eb87a3b73c 100644
--- a/modules/ledger/include/dap_chain_ledger.h
+++ b/modules/ledger/include/dap_chain_ledger.h
@@ -310,9 +310,8 @@ DAP_STATIC_INLINE char *dap_ledger_get_gdb_group(dap_ledger_t *a_ledger, const c
  *
  * return 1 OK, -1 error
  */
-int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data);
-int dap_ledger_tx_load_hardfork_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data);
-int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data);
+int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data, bool a_hardfork_related);
+int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data, bool a_hardfork_related);
 int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash);
 int dap_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, size_t a_datum_size, dap_hash_fast_t *a_datum_hash);
 
@@ -517,4 +516,4 @@ dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_
 
 #ifdef __cplusplus
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 2d1ea5caf4796dfd11f9877d6f4c4b630ba56135..937a7abe479f50ca18a944458c9918d5431bdd8f 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -80,6 +80,7 @@
 #include "dap_chain_cell.h"
 #include "dap_chain_datum_decree.h"
 #include "dap_chain_datum_anchor.h"
+#include "dap_chain_datum_service_state.h"
 #include "dap_chain_node_client.h"
 #include "dap_chain_mempool.h"
 #include "dap_chain_net.h"
@@ -2744,6 +2745,12 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d
     return l_list;
 }
 
+static int s_load_state_from_datum(dap_chain_net_id_t a_net_id, dap_chain_datum_t *a_datum, dap_hash_fast_t *a_datum_hash)
+{
+    dap_chain_datum_service_state_t *l_state = (dap_chain_datum_service_state_t *)a_datum->data;
+    return dap_chain_srv_load_state(a_net_id, l_state->srv_uid, l_state->states, l_state->state_size, l_state->states_count);
+}
+
 /**
  * @brief Add datum to the ledger or smth else
  * @param a_chain
@@ -2751,11 +2758,11 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d
  * @param a_datum_size
  * @return
  */
-int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data)
+int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data, bool a_hardfork_related)
 {
     size_t l_datum_data_size = a_datum->header.data_size;
-    if (a_datum_size < l_datum_data_size + sizeof(a_datum->header)) {
-        log_it(L_INFO,"Corrupted datum rejected: wrong size %zd not equal or less than datum size %zd",a_datum->header.data_size+ sizeof (a_datum->header),
+    if (a_datum_size != l_datum_data_size + sizeof(a_datum->header)) {
+        log_it(L_INFO,"Corrupted datum rejected: wrong size %zd not equal datum size %zd", l_datum_data_size + sizeof(a_datum->header),
                a_datum_size );
         return -101;
     }
@@ -2794,11 +2801,12 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t
                 log_it(L_WARNING, "Corrupted transaction, datum size %zd is not equal to size of TX %zd", l_datum_data_size, l_tx_size);
                 return -102;
             }
-            return dap_ledger_tx_load(l_ledger, l_tx, a_datum_hash, (dap_ledger_datum_iter_data_t*)a_datum_index_data);
+            return dap_ledger_tx_load(l_ledger, l_tx, a_datum_hash, (dap_ledger_datum_iter_data_t*)a_datum_index_data, a_hardfork_related);
         }
         case DAP_CHAIN_DATUM_CA:
             return dap_cert_chain_file_save(a_datum, a_chain->net_name);
-
+        case DAP_CHAIN_DATUM_SERVICE_STATE:
+            return a_hardfork_related ? s_load_state_from_datum(a_chain->net_id, a_datum, a_datum_hash) : -601;
         case DAP_CHAIN_DATUM_SIGNER:
         case DAP_CHAIN_DATUM_CUSTOM:
             break;
@@ -2808,21 +2816,6 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t
     return 0;
 }
 
-int dap_chain_datum_add_hardfork_data(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data)
-{
-    int ret = dap_chain_datum_add(a_chain, a_datum, a_datum_size, a_datum_hash, a_datum_index_data);
-    if (ret)
-        return ret;
-    dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
-    switch (a_datum->header.type_id) {
-    case DAP_CHAIN_DATUM_TX: {
-        return dap_ledger_tx_load_hardfork_data(l_ledger, (dap_chain_datum_tx_t *)a_datum->data, a_datum_hash, (dap_ledger_datum_iter_data_t *)a_datum_index_data);
-    }
-    default: return -601;
-    }
-    return 0;
-}
-
 /**
  * @brief Add datum to the ledger or smth else
  * @param a_chain
diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c
index b5f7ad6d6c92e26f8e66dd69c36f635201b1508f..cbcc87a62afbf271a767861e4e5f09302eaf3454 100644
--- a/modules/net/dap_chain_node.c
+++ b/modules/net/dap_chain_node.c
@@ -524,6 +524,7 @@ dap_chain_datum_t **s_service_state_datums_create(dap_chain_srv_hardfork_state_t
         }
         dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SERVICE_STATE, l_ptr, sizeof(dap_chain_datum_service_state_t) + l_cur_step_size);
         ((dap_chain_datum_service_state_t *)l_datum->data)->srv_uid = a_state->uid;
+        ((dap_chain_datum_service_state_t *)l_datum->data)->state_size = a_state->size;
         ((dap_chain_datum_service_state_t *)l_datum->data)->states_count = i;
         ret = DAP_REALLOC_RET_VAL_IF_FAIL(ret, sizeof(dap_chain_datum_t *) * (++l_datums_count), NULL, NULL);
         ret[l_datums_count - 1] = l_datum;
@@ -937,6 +938,10 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_
                     l_conitional.hash = *(dap_hash_fast_t *)l_tsd->data;
                     break;
                 case DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TICKER:
+                    if (!l_tsd->size || l_tsd->size > DAP_CHAIN_TICKER_SIZE_MAX) {
+                        log_it(L_WARNING, "Illegal harfork datum tx TSD TICKER size %u", l_tsd->size);
+                        return -8;
+                    }
                     dap_stpcpy((char *)l_conitional.ticker, (char *)l_tsd->data);
                     break;
                 case DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER:
diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h
index 1a0b3594fc7f1e6e65981e76d7e5786c13e5db7c..04a60cc6ee3e407e35cdfbf44495dfcf61209e6a 100644
--- a/modules/net/include/dap_chain_net.h
+++ b/modules/net/include/dap_chain_net.h
@@ -205,8 +205,7 @@ void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_sto
  */
 dap_list_t *dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_chain_datum_filter_func_t *a_filter_func, void *a_filter_func_param);
 
-int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data);
-int dap_chain_datum_add_hardfork_data(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data);
+int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data, bool a_hardfork_related);
 int dap_chain_datum_remove(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash);
 
 bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net);
diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c
index 4a6e837e72ef054994ae82d38e6c680adfe44fed..c64211062d051d410c40dfbb3e0d7f98caf4d8ca 100644
--- a/modules/service/voting/dap_chain_net_srv_voting.c
+++ b/modules/service/voting/dap_chain_net_srv_voting.c
@@ -65,6 +65,7 @@ struct srv_voting {
 static void *s_callback_start(dap_chain_net_id_t UNUSED_ARG a_net_id, dap_config_t UNUSED_ARG *a_config);
 static void s_callback_delete(void *a_service_internal);
 static byte_t *s_votings_backup(dap_chain_net_id_t a_net_id, uint64_t *a_state_size, uint32_t *a_state_count);
+static int s_votings_restore(dap_chain_net_id_t a_net_id, byte_t *a_state, uint64_t a_state_size, uint32_t a_states_count);
 
 static int s_voting_ledger_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply);
 static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash);
@@ -101,7 +102,7 @@ int dap_chain_net_srv_voting_init()
 
     
     dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VOTING_ID };
-    dap_chain_static_srv_callbacks_t l_srv_callbacks = { .start = s_callback_start, .delete = s_callback_delete, .hardfork_prepare = s_votings_backup };
+    dap_chain_static_srv_callbacks_t l_srv_callbacks = { .start = s_callback_start, .delete = s_callback_delete, .hardfork_prepare = s_votings_backup, .hardfork_load = s_votings_restore };
     int ret = dap_chain_srv_add(l_uid, "voting", &l_srv_callbacks);
     if (ret) {
         log_it(L_ERROR, "Can't register voting service");
@@ -1453,15 +1454,16 @@ static byte_t *s_votings_backup(dap_chain_net_id_t a_net_id, uint64_t *a_state_s
     return 0;
 }
 
-static int s_votings_restore(dap_chain_net_id_t a_net_id, dap_chain_datum_service_state_t *a_state, size_t a_data_size)
+static int s_votings_restore(dap_chain_net_id_t a_net_id, byte_t *a_state, uint64_t a_state_size, uint32_t a_states_count)
 {
     struct srv_voting *l_service_internal = dap_chain_srv_get_internal(a_net_id, (dap_chain_srv_uid_t) { .uint64 = DAP_CHAIN_NET_SRV_VOTING_ID });
     if (!l_service_internal)
         return -1;
-    byte_t *l_cur_ptr = a_state->states + sizeof(dap_chain_datum_service_state_t);
-    for (uint32_t i = 0; i < a_state->states_count; i++) {
+    byte_t *l_cur_ptr = a_state;
+    size_t l_data_size = a_state_size * a_states_count;
+    for (uint32_t i = 0; i < a_states_count; i++) {
         struct voting_serial *cur = (struct voting_serial *)l_cur_ptr;
-        if (l_cur_ptr + cur->size > (byte_t *)a_state + a_data_size ||
+        if (l_cur_ptr + cur->size > (byte_t *)a_state + l_data_size ||
                 cur->size <  sizeof(struct voting_serial) + sizeof(dap_tsd_t) * 2)
             return -2;
         unsigned l_hash_value;
@@ -1484,7 +1486,7 @@ static int s_votings_restore(dap_chain_net_id_t a_net_id, dap_chain_datum_servic
             dap_tsd_t *l_tsd; size_t l_tsd_size;
             dap_tsd_iter(l_tsd, l_tsd_size,
                          cur->question_n_options_n_votes + sizeof(struct voting_serial),
-                         a_data_size - sizeof(struct voting_serial)) {
+                         l_data_size - sizeof(struct voting_serial)) {
                 switch (l_tsd->type) {
                 case VOTING_TSD_TYPE_QUESTION:
                     l_voting->params->question = DAP_DUP_SIZE((byte_t*)l_tsd->data, l_tsd->size);
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 19609ca5cb7c5aa12d7a377eaedd42914a9c33b9..41b03d6c3abf87cc2975c246a0933810282bf17f 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -1539,10 +1539,8 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca
         }
         dap_hash_fast_t *l_datum_hash = a_block_cache->datum_hash + i;
         dap_ledger_datum_iter_data_t l_datum_index_data = { .token_ticker = "0", .action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN , .uid.uint64 = 0 };
-
-        int l_res = (a_block_cache->generation && a_block_cache->generation == a_blocks->generation)
-                ? dap_chain_datum_add_hardfork_data(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data)
-                : dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data);
+        bool is_hardfork_related_block = a_block_cache->generation && a_block_cache->generation == a_blocks->generation;
+        int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data, is_hardfork_related_block);
         if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX || l_res != DAP_LEDGER_CHECK_ALREADY_CACHED) { // If this is any datum other than a already cached transaction
             l_ret++;
             if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index bef0bb74dec721794975e9e843dc7deda5bf2ecd..7378cc49c4ab3b0148f845a4966e3b8b64ac3dd7 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -416,7 +416,7 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t *a_dag, dap_c
     }
     dap_hash_fast_t l_datum_hash;
     dap_chain_datum_calc_hash(l_datum, &l_datum_hash);
-    int l_ret = dap_chain_datum_add(a_dag->chain, l_datum, l_datum_size, &l_datum_hash, NULL);
+    int l_ret = dap_chain_datum_add(a_dag->chain, l_datum, l_datum_size, &l_datum_hash, NULL, false);
     if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)  // && l_ret == 0
         PVT(a_dag)->tx_count++;
     a_event_item->datum_hash = l_datum_hash;
diff --git a/modules/type/none/dap_chain_cs_none.c b/modules/type/none/dap_chain_cs_none.c
index 2dd15ab55c7a26544a59ba54d17f8cd19f277a2e..3137e4f230fa143f1fb3ce40229ded6d94b767c6 100644
--- a/modules/type/none/dap_chain_cs_none.c
+++ b/modules/type/none/dap_chain_cs_none.c
@@ -327,7 +327,7 @@ static dap_chain_atom_verify_res_t s_nonconsensus_callback_atom_add(dap_chain_t
     dap_nonconsensus_private_t *l_nochain_priv = PVT(l_nochain);
     dap_chain_datum_t *l_datum = (dap_chain_datum_t*) a_atom;
     dap_hash_fast_t l_datum_hash = *a_atom_hash;
-    if(dap_chain_datum_add(a_chain, l_datum, a_atom_size, &l_datum_hash, NULL))
+    if (dap_chain_datum_add(a_chain, l_datum, a_atom_size, &l_datum_hash, NULL, false))
         return ATOM_REJECT;
 
     dap_nonconsensus_datum_hash_item_t * l_hash_item = DAP_NEW_Z(dap_nonconsensus_datum_hash_item_t);