diff --git a/dap-sdk b/dap-sdk
index 1ef6d0e78beed6d36a1a4cdedd913d59c0211b0d..15a26c4c061355b21dba20b56bb0a92efcd49343 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit 1ef6d0e78beed6d36a1a4cdedd913d59c0211b0d
+Subproject commit 15a26c4c061355b21dba20b56bb0a92efcd49343
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index ccaae7c3a5c33a5263fc3d166d335afa3f5701fc..87579e99628e42a39af6031136b753f07efd5cac 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -104,6 +104,8 @@ void dap_chain_deinit(void)
 dap_chain_t * dap_chain_create(dap_ledger_t* a_ledger, const char * a_chain_net_name, const char * a_chain_name, dap_chain_net_id_t a_chain_net_id, dap_chain_id_t a_chain_id )
 {
     dap_chain_t * l_ret = DAP_NEW_Z(dap_chain_t);
+    if ( !l_ret )
+        return log_it(L_ERROR, "Memory allocation error in dap_chain_create, errno=%d", errno), NULL;
     DAP_CHAIN_PVT_LOCAL_NEW(l_ret);
     memcpy(l_ret->id.raw,a_chain_id.raw,sizeof(a_chain_id));
     memcpy(l_ret->net_id.raw,a_chain_net_id.raw,sizeof(a_chain_net_id));
@@ -113,6 +115,10 @@ dap_chain_t * dap_chain_create(dap_ledger_t* a_ledger, const char * a_chain_net_
     pthread_rwlock_init(&l_ret->rwlock, NULL);
     pthread_rwlock_init(&l_ret->cell_rwlock,NULL);
     dap_chain_item_t * l_ret_item = DAP_NEW_Z(dap_chain_item_t);
+    if ( !l_ret_item ){
+        DAP_DELETE(l_ret);
+        return log_it(L_ERROR, "Memory allocation error in dap_chain_create, errno=%d", errno), NULL;
+    }
     l_ret_item->chain = l_ret;
     memcpy(l_ret_item->item_id.id.raw ,a_chain_id.raw,sizeof(a_chain_id));
     memcpy(l_ret_item->item_id.net_id.raw ,a_chain_net_id.raw,sizeof(a_chain_net_id));
@@ -436,7 +442,11 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
                 if (l_datum_types && l_datum_types_count > 0)
 				{
 					l_chain->datum_types = DAP_NEW_SIZE(dap_chain_type_t, l_datum_types_count * sizeof(dap_chain_type_t)); // TODO: pls check counter for recognized types before memory allocation!
-					l_count_recognized = 0;
+                    if ( !l_chain->datum_types ) {
+                        DAP_DELETE(l_chain);
+                        return log_it(L_ERROR, "Memory allocation error in dap_chain_load_from_cfg, errno=%d", errno), NULL;
+                    }
+                    l_count_recognized = 0;
 					for (uint16_t i = 0; i < l_datum_types_count; i++)
 					{
 						dap_chain_type_t l_chain_type = s_chain_type_from_str(l_datum_types[i]);
@@ -454,7 +464,13 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
 				if (l_default_datum_types && l_default_datum_types_count > 0)
 				{
 					l_chain->default_datum_types = DAP_NEW_SIZE(dap_chain_type_t, l_default_datum_types_count * sizeof(dap_chain_type_t)); // TODO: pls check counter for recognized types before memory allocation!
-					l_count_recognized = 0;
+                    if ( !l_chain->default_datum_types ) {
+                        if (l_chain->datum_types)
+                            DAP_DELETE(l_chain->datum_types);
+                        DAP_DELETE(l_chain);
+                        return log_it(L_ERROR, "Memory allocation error in dap_chain_load_from_cfg, errno=%d", errno), NULL;
+                    }
+                    l_count_recognized = 0;
 					for (uint16_t i = 0; i < l_default_datum_types_count; i++)
 					{
 						dap_chain_type_t l_chain_type = s_chain_type_from_str(l_default_datum_types[i]);
@@ -476,7 +492,15 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
 				if (l_datum_types && l_datum_types_count)
 				{
 					l_chain->autoproc_datum_types = DAP_NEW_Z_SIZE(uint16_t, l_chain->datum_types_count * sizeof(uint16_t)); // TODO: pls check counter for recognized types before memory allocation!
-					l_count_recognized = 0;
+                    if ( !l_chain->autoproc_datum_types ) {
+                        if (l_chain->datum_types)
+                            DAP_DELETE(l_chain->datum_types);
+                        if (l_chain->default_datum_types)
+                            DAP_DELETE(l_chain->default_datum_types);
+                        DAP_DELETE(l_chain);
+                        return log_it(L_ERROR, "Memory allocation error in dap_chain_load_from_cfg, errno=%d", errno), NULL;
+                    }
+                    l_count_recognized = 0;
 					for (uint16_t i = 0; i < l_datum_types_count; i++)
 					{
 						if (!dap_strcmp(l_datum_types[i], "all") && l_chain->datum_types_count)
@@ -725,15 +749,25 @@ int dap_cert_chain_file_save(dap_chain_datum_t *datum, char *net_name)
     const char *cert_name = cert->name;
     size_t cert_path_length = dap_strlen(net_name) + dap_strlen(cert_name) + 9 + dap_strlen(s_system_chain_ca_dir);
     char *cert_path = DAP_NEW_STACK_SIZE(char, cert_path_length);
+    if ( !cert_path ) {
+        dap_cert_delete(cert);
+        log_it(L_ERROR, "Memory allocation error in dap_cert_chain_file_save, errno=%d", errno);
+        return -1;
+    }
     snprintf(cert_path, cert_path_length, "%s/%s/%s.dcert", s_system_chain_ca_dir, net_name, cert_name);
     // In cert_path resolve all `..` and `.`s
     char *cert_path_c = dap_canonicalize_filename(cert_path, NULL);
     // Protect the ca folder from using "/.." in cert_name
     if(dap_strncmp(s_system_chain_ca_dir, cert_path_c, dap_strlen(s_system_chain_ca_dir))) {
+        dap_cert_delete(cert);
+        DAP_DELETE(cert_path_c);
+        DAP_DELETE(cert_path);
         log_it(L_ERROR, "Cert path '%s' is not in ca dir: %s", cert_path_c, s_system_chain_ca_dir);
         return -1;
     }
     int l_ret = dap_cert_file_save(cert, cert_path_c);
+    dap_cert_delete(cert);
+    DAP_DELETE(cert_path);
     DAP_DELETE(cert_path_c);
 //  if ( access( l_cert_path, F_OK ) != -1 ) {
 //      log_it (L_ERROR, "File %s is already exists.", l_cert_path);
diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c
index f71399ed40bedf973556dda8b472ca43fbcb4d66..e771db6ae459dc081fd3a04b533c0fdb4bd4efe7 100644
--- a/modules/chain/dap_chain_cell.c
+++ b/modules/chain/dap_chain_cell.c
@@ -101,6 +101,10 @@ dap_chain_cell_t * dap_chain_cell_create_fill(dap_chain_t * a_chain, dap_chain_c
         return l_cell;
     }
     l_cell = DAP_NEW_Z(dap_chain_cell_t);
+    if ( !l_cell ) {
+        pthread_rwlock_unlock(&a_chain->cell_rwlock);
+        return log_it(L_ERROR, "Memory allocation error in dap_chain_cell_create_fill, errno=%d", errno), NULL;
+    }
     l_cell->chain = a_chain;
     l_cell->id.uint64 = a_cell_id.uint64;
     l_cell->file_storage_path = dap_strdup_printf("%0"DAP_UINT64_FORMAT_x".dchaincell", l_cell->id.uint64);
@@ -201,17 +205,17 @@ int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path)
         return -3;
     }
     unsigned long q = 0;
-    while (!feof(l_cell_file)) {
-        uint64_t l_el_size = 0;
-        size_t l_read = fread(&l_el_size, 1, sizeof(l_el_size), l_cell_file);
+    size_t l_read;
+    uint64_t l_el_size = 0;
+    while ((l_read = fread(&l_el_size, 1, sizeof(l_el_size), l_cell_file)) && !feof(l_cell_file)) {
         if (l_read != sizeof(l_el_size) || l_el_size == 0) {
-            log_it(L_ERROR, "Corrupted element size, chain %s is damaged", l_file_path);
+            log_it(L_ERROR, "Corrupted element size %zu, chain %s is damaged", l_el_size, l_file_path);
             ret = -4;
             break;
         }
         dap_chain_atom_ptr_t l_element = DAP_NEW_SIZE(dap_chain_atom_ptr_t, l_el_size);
         if (!l_element) {
-            log_it(L_ERROR, "Out of memory");
+            log_it(L_ERROR, "Memory allocation error in dap_chain_cell_load, errno=%d", errno);
             ret = -5;
             break;
         }
diff --git a/modules/chain/dap_chain_cs.c b/modules/chain/dap_chain_cs.c
index 198e499b4d8af632eda53573d883de08e6cf8444..352092a672ff89b5d5b5f9b4c68defbc5f3de9fe 100644
--- a/modules/chain/dap_chain_cs.c
+++ b/modules/chain/dap_chain_cs.c
@@ -65,6 +65,10 @@ void dap_chain_cs_deinit(void)
 void dap_chain_cs_type_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init)
 {
     dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t );
+    if ( !l_item ) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_type_add, errno=%d", errno);
+        return;
+    }
     strncpy(l_item->name, a_cs_str, sizeof (l_item->name) - 1);
     l_item->name[sizeof (l_item->name) - 1] = '\0';
     l_item->callback_init = a_callback_init;
@@ -101,6 +105,10 @@ int dap_chain_cs_type_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 void dap_chain_cs_add (const char * a_cs_str,  dap_chain_callback_new_cfg_t a_callback_init)
 {
     dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t );
+    if ( !l_item ) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_add, errno=%d", errno);
+        return;
+    }
     strncpy(l_item->name, a_cs_str, sizeof (l_item->name) - 1);
     l_item->name[sizeof (l_item->name) - 1] = '\0';
     l_item->callback_init = a_callback_init;
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 742f44df087d93246d4508c07dfca9c83758feb9..0700873c77619c4cde5d7992c0eea63983b77337 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -24,7 +24,7 @@
  */
 
 #include "dap_common.h"
-
+#include <dirent.h>
 #ifdef _WIN32
 #include <winsock2.h>
 #include <windows.h>
@@ -53,10 +53,11 @@
 #include "dap_global_db.h"
 #include "dap_chain_ledger.h"
 #include "dap_chain_pvt.h"
-#include "json-c/json.h"
-#include "json-c/json_object.h"
+#include "json.h"
+#include "json_object.h"
 #include "dap_notify_srv.h"
 
+
 #define LOG_TAG "dap_chain_ledger"
 
 typedef struct dap_chain_ledger_verificator {
@@ -71,59 +72,65 @@ static  pthread_rwlock_t s_verificators_rwlock;
 
 #define MAX_OUT_ITEMS   10
 
-char* dap_chain_ledger_tx_check_err_str(dap_chain_ledger_tx_check_t a_code){
-    switch (a_code) {
-        case DAP_CHAIN_LEDGER_TX_CHECK_OK:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CHECK_OK");
-        case DAP_CHAIN_LEDGER_TX_CHECK_ERROR_IS_NULL_TX:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CHECK_ERROR_IS_NULL_TX");
-        case DAP_CHAIN_LEDGER_TX_CHECK_ERROR_INVALID_SIZE_TX:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CHECK_ERROR_INVALID_SIZE_TX");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_INPUT_DATA:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_INPUT_DATA");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_SIGN_TX:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_SIGN_TX");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TOKEN:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TOKEN");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_NOT_VALID_STAKE_LOCK:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_NOT_VALID_STAKE_LOCK");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_COND_STAKE_LOCK_FROM_IN_EMS:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_COND_STAKE_LOCK_FROM_IN_EMS");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_MULTIPLICATION_OVERFLOW_EMISSION_LOCKED_EMISSION_RATE:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_MULTIPLICATION_OVERFLOW_EMISSION_LOCKED_EMISSION_RATE");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_OUT_NOR_OUT_EXT_BASE_TX_IN_EMS:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_OUT_NOR_OUT_EXT_BASE_TX_IN_EMS");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_CURRENT_SUPPLY_LOWER_EMISSION_VALUE:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_CURRENT_SUPPLY_LOWER_EMISSION_VALUE");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VALUE_NOT_THATS_EXPECTED_IN_EMS:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VALUE_NOT_THATS_EXPECTED_IN_EMS");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TICKER_FOR_STAKE_LOCK:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TICKER_FOR_STAKE_LOCK");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_DIFFERENT_EXPECTED:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_DIFFERENT_EXPECTED");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_USED_OUT_ITEM:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_USED_OUT_ITEM");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_PREV_OUT_TX:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_PREV_OUT_TX");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_HASH_PKEY_TX_NOT_COMPARE_HASH_PKEY_OUT_ADDR_PREV_TX:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_HASH_PKEY_TX_NOT_COMPARE_HASH_PKEY_OUT_ADDR_PREV_TX");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREVIOUS_TX_OUTPUT_ALREADY_USED_IN_CURRENT_TX:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREVIOUS_TX_OUTPUT_ALREADY_USED_IN_CURRENT_TX");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_NO_VALIDATOR_COND_OUTPUT:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_NO_VALIDATOR_COND_OUTPUT");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_FAIL:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_FAIL");
-        case DAP_CHAIN_LEDGET_TX_CACHE_CHECK_NO_FOUND_TOKEN_TICKER:
-            return dap_strdup("DAP_CHAIN_LEDGET_TX_CACHE_CHECK_NO_FOUND_TOKEN_TICKER");
-        case DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PERMISSION_FAILED:
-            return dap_strdup("DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PERMISSION_FAILED");
-        default:
-            return dap_strdup_printf("Code error: %d undefined", a_code);
-    }
+static const char *s_ledger_tx_check_err_str[] = {
+    [DAP_CHAIN_LEDGER_TX_CHECK_OK] = "DAP_CHAIN_LEDGER_TX_CHECK_OK",
+    [DAP_CHAIN_LEDGER_TX_CHECK_NULL_TX] = "DAP_CHAIN_LEDGER_TX_CHECK_NULL_TX",
+    [DAP_CHAIN_LEDGER_TX_CHECK_INVALID_TX_SIZE] = "DAP_CHAIN_LEDGER_TX_CHECK_INVALID_TX_SIZE",
+    [DAP_CHAIN_LEDGER_TX_ALREADY_CACHED] = "DAP_CHAIN_LEDGER_TX_ALREADY_CACHED",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NULL_TX] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NULL_TX",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_TX_SIGN] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_TX_SIGN",
+    [DAP_CHAIN_LEDGER_TX_CACHE_IN_EMS_ALREADY_USED] = "DAP_CHAIN_LEDGER_TX_CACHE_IN_EMS_ALREADY_USED",
+    [DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_IN_EMS_ALREADY_USED] = "DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_IN_EMS_ALREADY_USED",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_EMISSION_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_EMISSION_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_INPUTS] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_INPUTS",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_INVALID_TOKEN] = "DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_INVALID_TOKEN",
+    [DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS] = "DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS",
+    [DAP_CHAIN_LEDGER_TX_CACHE_MULT256_OVERFLOW_EMS_LOCKED_X_RATE] = "DAP_CHAIN_LEDGER_TX_CACHE_MULT256_OVERFLOW_EMS_LOCKED_X_RATE",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS",
+    [DAP_CHAIN_LEDGER_TX_CACHE_NO_OUT_ITEMS_FOR_BASE_TX] = "DAP_CHAIN_LEDGER_TX_CACHE_NO_OUT_ITEMS_FOR_BASE_TX",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY",
+    [DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_UNEXPECTED_VALUE] = "DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_UNEXPECTED_VALUE",
+    [DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_TICKER_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_TICKER_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_OTHER_TICKER_EXPECTED] = "DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_OTHER_TICKER_EXPECTED",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_OUT_ITEM_ALREADY_USED] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_OUT_ITEM_ALREADY_USED",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TX_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TX_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ITEM_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ITEM_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PKEY_HASHES_DONT_MATCH] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PKEY_HASHES_DONT_MATCH",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_VERIFICATOR_SET] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_VERIFICATOR_SET",
+    [DAP_CHAIN_LEDGER_TX_CACHE_VERIFICATOR_CHECK_FAILURE] = "DAP_CHAIN_LEDGER_TX_CACHE_VERIFICATOR_CHECK_FAILURE",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TICKER_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TICKER_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TOKEN_NOT_FOUND] = "DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TOKEN_NOT_FOUND",
+    [DAP_CHAIN_LEDGER_PERMISSION_CHECK_FAILED] = "DAP_CHAIN_LEDGER_PERMISSION_CHECK_FAILED"
+};
+
+static const char *s_ledger_emission_add_err_str[] = {
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_OK] = "DAP_CHAIN_LEDGER_EMISSION_ADD_OK",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE] = "DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE",
+    [DAP_CHAIN_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED] = "DAP_CHAIN_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED"
+};
+
+static const char *s_ledger_token_decl_err_str[] = {
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK",
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL",
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE",
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK",
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN",
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN",
+    [DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS] = "DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS"
+};
+
+char *dap_chain_ledger_tx_check_err_str(int a_code) {
+    return (a_code >= DAP_CHAIN_LEDGER_TX_CHECK_OK) && (a_code < DAP_CHAIN_LEDGER_TX_CHECK_UNKNOWN)
+            ? (char*)s_ledger_tx_check_err_str[(dap_chain_ledger_tx_check_t)a_code]
+            : dap_itoa(a_code);
 }
 
 typedef struct dap_chain_ledger_stake_lock_item {
@@ -271,6 +278,7 @@ typedef struct dap_ledger_private {
     const char *net_native_ticker;
     uint256_t fee_value;
     dap_chain_addr_t fee_addr;
+    dap_list_t *poa_certs;
     // List of ledger - unspent transactions cache
     dap_chain_ledger_tx_item_t *threshold_txs;
     dap_chain_ledger_token_emission_item_t * threshold_emissions;
@@ -316,6 +324,12 @@ typedef struct dap_ledger_private {
 } dap_ledger_private_t;
 #define PVT(a) ( (dap_ledger_private_t* ) a->_internal )
 
+typedef struct dap_ledger_hal_item {
+    dap_chain_hash_fast_t hash;
+    UT_hash_handle hh;
+} dap_ledger_hal_item_t;
+
+static dap_ledger_hal_item_t *s_hal_items = NULL;
 
 static  dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger,
         const dap_chain_addr_t *a_addr, const char * a_token, dap_chain_hash_fast_t *a_tx_first_hash);
@@ -380,9 +394,17 @@ void dap_chain_ledger_deinit()
 static dap_ledger_t * dap_chain_ledger_handle_new(void)
 {
     dap_ledger_t *l_ledger = DAP_NEW_Z(dap_ledger_t);
+    if ( !l_ledger ) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_handle_new, errno=%d", errno);
+        return NULL;
+    }
     dap_ledger_private_t * l_ledger_pvt;
     l_ledger->_internal = l_ledger_pvt = DAP_NEW_Z(dap_ledger_private_t);
-
+    if ( !l_ledger_pvt ) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_handle_new, errno=%d", errno);
+        DAP_DELETE(l_ledger);
+        return NULL;
+    }
     // Initialize Read/Write Lock Attribute
     pthread_rwlock_init(&l_ledger_pvt->ledger_rwlock, NULL);
     pthread_rwlock_init(&l_ledger_pvt->tokens_rwlock, NULL);
@@ -433,6 +455,8 @@ struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_
     if (pos) {
         size_t l_addr_len = pos - a_bal->key;
         char *l_addr_str = DAP_NEW_STACK_SIZE(char, l_addr_len + 1);
+        if ( !l_addr_str )
+            return log_it(L_ERROR, "Memory allocation error in wallet_info_json_collect, errno=%d", errno), NULL;
         memcpy(l_addr_str, a_bal->key, pos - a_bal->key);
         *(l_addr_str + l_addr_len) = '\0';
         json_object_object_add(l_network, "address", json_object_new_string(l_addr_str));
@@ -475,7 +499,7 @@ static bool s_ledger_token_update_check(dap_chain_ledger_token_item_t *a_cur_tok
     if (l_token_update_item
     &&	a_cur_token_item->last_update_token_time == l_token_update_item->updated_time) {
         if (s_debug_more)
-            log_it(L_WARNING,"This upadate already applied for token with ticker '%s' ", a_token_update->ticker);
+            log_it(L_WARNING,"This update for token '%s' was already applied", a_token_update->ticker);
         return false;
     }
 
@@ -755,32 +779,16 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t *a_ledger, dap_chain_datu
     } else {
         log_it(L_WARNING, "The number of unique token signs %zu is less than total token signs set to %hu.",
                l_signs_unique, a_token->signs_total);
-        return DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_UNIQUE_SIGNS_LESS_TOTAL_SIGNS;
+        return DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS;
     }
-//    dap_sign_t **l_signs = dap_sign_get_unique_signs(a_token->data_n_tsd, a_token->header_native_decl.
     // Checks passed
     return DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK;
 }
 
 char *dap_chain_ledger_token_decl_add_err_code_to_str(int a_code) {
-    switch (a_code) {
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK");
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL");
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE");
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK");
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN");
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN");
-        case DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_UNIQUE_SIGNS_LESS_TOTAL_SIGNS:
-            return dap_strdup("DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_UNIQUE_SIGNS_LESS_TOTAL_SIGNS");
-        default:
-            return dap_strdup_printf("Code error added datum in ledger: %d - has no string representation.", a_code);
-    }
+    return (a_code >= DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK) && (a_code < DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_UNKNOWN)
+            ? (char*)s_ledger_token_decl_err_str[(dap_chain_ledger_token_decl_add_err_t)a_code]
+            : dap_itoa(a_code);
 }
 
 /**
@@ -992,6 +1000,10 @@ void s_ledger_token_cache_update(dap_ledger_t *a_ledger, dap_chain_ledger_token_
     char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TOKENS_STR);
     size_t l_cache_size = l_token_item->datum_token_size + sizeof(uint256_t);
     uint8_t *l_cache = DAP_NEW_STACK_SIZE(uint8_t, l_cache_size);
+    if ( !l_cache ) {
+        log_it(L_ERROR, "Memory allocation error in s_ledger_token_cache_update, errno=%d", errno);
+        return;
+    }
     memcpy(l_cache, &l_token_item->current_supply, sizeof(uint256_t));
     memcpy(l_cache + sizeof(uint256_t), l_token_item->datum_token, l_token_item->datum_token_size);
     if (dap_global_db_set(l_gdb_group, l_token_item->ticker, l_cache, l_cache_size, false, NULL, NULL)) {
@@ -1071,43 +1083,6 @@ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *
         return -1;
     }
 
-    bool update_token = false;
-    if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE)
-        update_token = true;
-
-
-    dap_chain_ledger_token_item_t *l_token_item;
-    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
-    HASH_FIND_STR(PVT(a_ledger)->tokens, a_token->ticker, l_token_item);
-    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-
-    if (l_token_item != NULL) {
-        if (update_token == false) {
-            log_it(L_WARNING, "Duplicate token declaration for ticker '%s' ", a_token->ticker);
-            return -3;
-        } else if (s_ledger_token_update_check(l_token_item, a_token, a_token_size) == true) {
-            if (s_ledger_update_token_add_in_hash_table(l_token_item, a_token, a_token_size) == false) {
-                if (s_debug_more)
-                    log_it(L_ERROR, "Failed to add ticker '%s' to hash-table", a_token->ticker);
-                return -5;
-            }
-            if (!IS_ZERO_256(a_token->total_supply)) {
-                SUBTRACT_256_256(l_token_item->total_supply, l_token_item->current_supply,
-                                 &l_token_item->current_supply);
-                SUBTRACT_256_256(a_token->total_supply, l_token_item->current_supply, &l_token_item->current_supply);
-            } else {
-                l_token_item->current_supply = a_token->total_supply;
-            }
-            l_token_item->total_supply = a_token->total_supply;
-            DAP_DEL_Z(l_token_item->datum_token);
-        } else {
-            return -2;
-        }
-    } else if (l_token_item == NULL && update_token == true) {
-        log_it(L_WARNING, "Can't update token that doesn't exist for ticker '%s' ", a_token->ticker);
-        return -6;
-    }
-
     dap_chain_datum_token_t *l_token = NULL;
     size_t l_token_size = a_token_size;
 
@@ -1122,143 +1097,194 @@ int dap_chain_ledger_token_add(dap_ledger_t *a_ledger, dap_chain_datum_token_t *
             break;
         default:
             l_token = DAP_DUP_SIZE(a_token, a_token_size);
+            if ( !l_token ) {
+                log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_token_add");
+                return -6;
+            }
             break;
     }
 
-    if (update_token == false) {//create new token
-        l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t);
-        snprintf(l_token_item->ticker, sizeof(l_token_item->ticker), "%s", l_token->ticker);
-        pthread_rwlock_init(&l_token_item->token_emissions_rwlock, NULL);
-        pthread_rwlock_init(&l_token_item->token_ts_updated_rwlock, NULL);
-        l_token_item->type = l_token->type;
-        l_token_item->subtype = l_token->subtype;
-        l_token_item->total_supply = l_token->total_supply;
-        l_token_item->current_supply = l_token_item->total_supply;
-        l_token_item->auth_signs_total = l_token->signs_total;
-        l_token_item->auth_signs_valid = l_token->signs_valid;
-        dap_sign_t **l_signs = dap_chain_datum_token_signs_parse(a_token, a_token_size,
-                                                                     &l_token_item->auth_signs_total,
-                                                                     &l_token_item->auth_signs_valid);
-        if (l_token_item->auth_signs_total) {
-            l_token_item->auth_pkeys = DAP_NEW_Z_SIZE(dap_pkey_t*, sizeof(dap_pkey_t*) * l_token_item->auth_signs_total);
-            l_token_item->auth_pkeys_hash = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token_item->auth_signs_total);;
-            for (uint16_t k = 0; k < l_token_item->auth_signs_total; k++) {
-                l_token_item->auth_pkeys[k] = dap_pkey_get_from_sign_deserialization(l_signs[k]);
-                dap_pkey_get_hash(l_token_item->auth_pkeys[k], &l_token_item->auth_pkeys_hash[k]);
+    dap_chain_ledger_token_item_t *l_token_item;
+    pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
+    HASH_FIND_STR(PVT(a_ledger)->tokens, l_token->ticker, l_token_item);
+    pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
+
+    if (l_token_item) {
+        if (l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE) {
+            log_it(L_ERROR, "Duplicate token declaration for ticker '%s'", l_token->ticker);
+            return -3;
+        }
+        if (s_ledger_token_update_check(l_token_item, l_token, l_token_size)) {
+            if (!s_ledger_update_token_add_in_hash_table(l_token_item, l_token, l_token_size)) {
+                log_it(L_ERROR, "Failed to update token with ticker '%s' in ledger", l_token->ticker);
+                return -5;
+            }
+            if (!IS_ZERO_256(l_token->total_supply)) {
+                SUBTRACT_256_256(l_token_item->total_supply, l_token_item->current_supply, &l_token_item->current_supply);
+                SUBTRACT_256_256(l_token->total_supply, l_token_item->current_supply, &l_token_item->current_supply);
+            } else {
+                l_token_item->current_supply = l_token->total_supply;
             }
+            l_token_item->total_supply = l_token->total_supply;
+            DAP_DELETE(l_token_item->datum_token);
+        } else {
+            log_it(L_ERROR, "Token with ticker '%s' update check failed", l_token->ticker);
+            return -2;
         }
+    } else if (l_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE) {
+        log_it(L_WARNING, "Token with ticker '%s' does not yet exist, declare it first", l_token->ticker);
+        return -6;
     }
 
-    l_token_item->datum_token_size = l_token_size;
-    l_token_item->datum_token = DAP_DUP_SIZE(l_token, l_token_size);
-    l_token_item->datum_token->type = l_token_item->type;
+    if (!l_token_item) {
+        size_t l_auth_signs_total, l_auth_signs_valid;
+        dap_sign_t **l_signs = dap_chain_datum_token_signs_parse(l_token, l_token_size, &l_auth_signs_total, &l_auth_signs_valid);
+        if (!l_signs || !l_auth_signs_total) {
+            log_it(L_ERROR, "No auth signs in token '%s' datum!", l_token->ticker);
+            DAP_DELETE(l_token);
+            return -7;
+        }
+        l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t);
+        if ( !l_token_item ) {
+            if (l_token)
+                DAP_DELETE(l_token);
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_token_add");
+            return -8;
+        }
+        *l_token_item = (dap_chain_ledger_token_item_t) {
+                .version        = l_token->version,
+                .type           = l_token->type,
+                .subtype        = l_token->subtype,
+                .total_supply   = l_token->total_supply,
+                .current_supply = l_token->total_supply,
+                .token_emissions_rwlock     = PTHREAD_RWLOCK_INITIALIZER,
+                .token_ts_updated_rwlock    = PTHREAD_RWLOCK_INITIALIZER,
+                .auth_pkeys         = DAP_NEW_Z_SIZE(dap_pkey_t*, sizeof(dap_pkey_t*) * l_token->signs_total),
+                .auth_pkeys_hash    = DAP_NEW_Z_SIZE(dap_chain_hash_fast_t, sizeof(dap_chain_hash_fast_t) * l_token->signs_total),
+                .auth_signs_total   = l_auth_signs_total,
+                .auth_signs_valid   = l_auth_signs_valid
+        };
+        if ( !l_token_item->auth_pkeys ) {
+            if (l_token)
+                DAP_DELETE(l_token);
+            DAP_DELETE(l_token_item);
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_token_add");
+            return -6;
+        };
+        if ( !l_token_item->auth_pkeys ) {
+            if (l_token)
+                DAP_DELETE(l_token);
+            DAP_DEL_Z(l_token_item->auth_pkeys);
+            DAP_DELETE(l_token_item);
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_token_add");
+            return -6;
+        }
+        dap_stpcpy(l_token_item->ticker, l_token->ticker);
+        for (uint16_t k = 0; k < l_token_item->auth_signs_total; k++) {
+            l_token_item->auth_pkeys[k] = dap_pkey_get_from_sign_deserialization(l_signs[k]);
+            dap_pkey_get_hash(l_token_item->auth_pkeys[k], &l_token_item->auth_pkeys_hash[k]);
+        }
+        DAP_DELETE(l_signs);
+    }
+
+
+    l_token_item->datum_token_size  = l_token_size;
+    l_token_item->datum_token       = l_token;
+    l_token_item->datum_token->type = l_token->type;
 
-    if (update_token == false) {
+    if (l_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE) {
         pthread_rwlock_wrlock(&PVT(a_ledger)->tokens_rwlock);
         HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item);
         pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
     }
     int l_res_token_tsd_parse = 0;
 
+    char *l_balance_dbg = s_debug_more ? dap_chain_balance_to_coins(l_token->total_supply) : NULL;
+
+#define CLEAN_UP do { DAP_DELETE(l_token); \
+    DAP_DELETE(l_token_item->auth_pkeys); \
+    DAP_DELETE(l_token_item->auth_pkeys_hash); \
+    DAP_DELETE(l_token_item); \
+    DAP_DELETE(l_balance_dbg); } while (0);
+
     switch (l_token->type) {
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
-            switch (l_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE: {
-                    if (s_debug_more) {
-                        char *l_balance = dap_chain_balance_to_coins(l_token->total_supply);
-                        log_it(L_NOTICE,
-                               "Simple token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu)",
-                               l_token->ticker, l_balance,
-                               l_token->signs_valid, l_token->signs_total);
-                        DAP_DEL_Z(l_balance);
-                    }
-                }
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: {
-                    if (s_debug_more) {
-                        char *l_balance = dap_chain_balance_to_coins(l_token->total_supply);
-                        log_it(L_NOTICE,
-                               "Private token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu)",
-                               l_token->ticker, l_balance,
-                               l_token->signs_valid, l_token->signs_total);
-                        DAP_DEL_Z(l_balance);
-                    }
-                    l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
-                }
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
-                    if (s_debug_more) {
-                        char *l_balance = dap_chain_balance_to_coins(l_token->total_supply);
-                        log_it(L_NOTICE,
-                               "CF20 token %s added (total_supply = %s total_signs_valid=%hu signs_total=%hu)",
-                               l_token->ticker, l_balance,
-                               l_token->signs_valid, l_token->signs_total);
-                        DAP_DELETE(l_balance);
-                    }
-                    l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
-                }
-                    break;
-            }
-        }
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
+        switch (l_token->subtype) {
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
+            debug_if(s_debug_more, L_INFO, "Simple token %s declared, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
+                   l_token->ticker, l_balance_dbg,
+                   l_token->signs_valid, l_token->signs_total);
             break;
-        case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE: {
-            switch (l_token->subtype) {
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE: {
-                    if (s_debug_more) {
-                        char *l_balance = dap_chain_balance_to_coins(l_token->total_supply);
-                        log_it(L_NOTICE,
-                               "Simple token %s update (total_supply = %s total_signs_valid=%hu signs_total=%hu)",
-                               l_token->ticker, l_balance,
-                               l_token->signs_valid, l_token->signs_total);
-                        DAP_DEL_Z(l_balance);
-                    }
-                }
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: {
-                    if (s_debug_more) {
-                        char *l_balance = dap_chain_balance_to_coins(l_token->total_supply);
-                        log_it(L_NOTICE,
-                               "Private token %s updated (total_supply = %s total_signs_valid=%hu signs_total=%hu)",
-                               l_token->ticker, l_balance,
-                               l_token->signs_valid, l_token->signs_total);
-                        DAP_DEL_Z(l_balance);
-                    }
-                    l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
-                    s_tsd_sign_apply(a_ledger, l_token_item, a_token, a_token_size);
-                }
-                    break;
-                case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
-                    if (s_debug_more) {
-                        char *l_balance = dap_chain_balance_to_coins(l_token->total_supply);
-                        log_it(L_NOTICE,
-                               "CF20 token %s updated (total_supply = %s total_signs_valid=%hu signs_total=%hu)",
-                               l_token->ticker, l_balance,
-                               l_token->signs_valid, l_token->signs_total);
-                        DAP_DEL_Z(l_balance);
-                    }
-                    l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
-                    s_tsd_sign_apply(a_ledger, l_token_item, a_token, a_token_size);
-                }
-                    break;
-            }
-        }
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
+            debug_if(s_debug_more, L_INFO, "Private token %s declared, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
+                    l_token->ticker, l_balance_dbg,
+                    l_token->signs_valid, l_token->signs_total);
+            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
+            s_tsd_sign_apply(a_ledger, l_token_item, l_token, l_token_size);
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
+            debug_if(s_debug_more, L_INFO, "CF20 token %s declared, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
+                    l_token->ticker, l_balance_dbg,
+                    l_token->signs_valid, l_token->signs_total);
+            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
+            s_tsd_sign_apply(a_ledger, l_token_item, l_token, l_token_size);
             break;
         default:
-            if (s_debug_more)
-                log_it(L_WARNING, "Unknown token declaration type 0x%04X", l_token->type);
+            /* Bogdanoff, unknown token subtype declaration. What shall we TODO? */
+            debug_if(s_debug_more, L_ERROR, "Unknown token subtype '0x%04X' declaration! Ticker: %s, total_supply: %s, total_signs_valid: %hu, signs_total: %hu"
+                     "Dump it!",
+                   l_token->type, l_token->ticker, l_balance_dbg,
+                   l_token->signs_valid, l_token->signs_total);
+            /* Dump it right now */
+            CLEAN_UP;
+            return -8;
+        } break;
+    case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
+        switch (l_token->subtype) {
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
+            debug_if(s_debug_more, L_INFO, "Simple token %s updated, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
+                   l_token->ticker, l_balance_dbg,
+                   l_token->signs_valid, l_token->signs_total);
+            break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
+            debug_if(s_debug_more, L_INFO, "Private token %s updated, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
+                    l_token->ticker, l_balance_dbg,
+                    l_token->signs_valid, l_token->signs_total);
+            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
+            s_tsd_sign_apply(a_ledger, l_token_item, l_token, l_token_size);
             break;
+        case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
+            debug_if(s_debug_more, L_INFO, "CF20 token %s updated, total_supply: %s, total_signs_valid: %hu, signs_total: %hu",
+                    l_token->ticker, l_balance_dbg,
+                    l_token->signs_valid, l_token->signs_total);
+            l_res_token_tsd_parse = s_token_tsd_parse(a_ledger, l_token_item, l_token, l_token_size);
+            s_tsd_sign_apply(a_ledger, l_token_item, l_token, l_token_size);
+            break;
+        default:
+            /* Bogdanoff, unknown token type update. What shall we TODO? */
+            debug_if(s_debug_more, L_ERROR, "Unknown token subtype '0x%04X' update! Ticker: %s, total_supply: %s, total_signs_valid: %hu, signs_total: %hu"
+                     "Dump it!",
+                   l_token->type, l_token->ticker, l_balance_dbg,
+                   l_token->signs_valid, l_token->signs_total);
+            /* Dump it right now */
+            CLEAN_UP;
+            return -8;
+        } break;
+    default:
+        debug_if(s_debug_more, L_ERROR, "Unknown token type 0x%04X, Dump it!", l_token->type);
+        CLEAN_UP;
+        return -8;
     }
     if (l_res_token_tsd_parse) {
-        if (s_debug_more) {
-            log_it(L_ERROR, "Can't parse tsd section for %s token, code error: %i", l_token->ticker, l_res_token_tsd_parse);
-        }
+        debug_if(s_debug_more, L_ERROR, "Can't parse tsd section for %s token, code error: %i", l_token->ticker, l_res_token_tsd_parse);
+        CLEAN_UP;
         return -1;
     }
-    s_threshold_emissions_proc(a_ledger); //TODO process thresholds only for no-consensus chains
+#undef CLEAN_UP
+    DAP_DELETE(l_balance_dbg);
+    s_threshold_emissions_proc(a_ledger); /* TODO process thresholds only for no-consensus chains */
     if (PVT(a_ledger)->cached)
         s_ledger_token_cache_update(a_ledger, l_token_item);
-    if (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE)
-        DAP_DELETE(l_token);
     return 0;
 }
 
@@ -1299,7 +1325,7 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
 
            // unset flags
             case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:{
-                a_token_item->flags ^= dap_tsd_get_scalar(l_tsd,uint16_t);
+                a_token_item->flags &= ~dap_tsd_get_scalar(l_tsd,uint16_t);
             }break;
 
             // set total supply
@@ -1606,7 +1632,8 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
                         if(s_debug_more)
                             log_it(L_ERROR,"Wrong address checksum in TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD (code %d)",
                                l_add_addr_check);
-                        DAP_DELETE(l_addrs);
+                        if (l_addrs)
+                            DAP_DELETE(l_addrs);
                         return -12;
                     }
                     // Check if its already present
@@ -1617,7 +1644,8 @@ static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_ite
                                 log_it(L_ERROR,"TSD param DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD has address %s thats already present in list",
                                    l_addr_str);
                             DAP_DELETE(l_addr_str);
-                            DAP_DELETE(l_addrs);
+                            if (l_addrs)
+                                DAP_DELETE(l_addrs);
                             return -11;
                         }
                     }
@@ -1761,12 +1789,11 @@ static int s_tsd_sign_apply(dap_ledger_t *a_ledger, dap_chain_ledger_token_item_
 int dap_chain_ledger_token_load(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size)
 {
     if (PVT(a_ledger)->load_mode) {
-        bool l_update_token = (a_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE);
         dap_chain_ledger_token_item_t *l_token_item;
         pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
         HASH_FIND_STR(PVT(a_ledger)->tokens, a_token->ticker, l_token_item);
         pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
-        if (l_token_item && l_update_token == false)
+        if (l_token_item && a_token->type != DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE)
             return 0;
     }
     return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size);
@@ -1966,7 +1993,7 @@ dap_list_t *dap_chain_ledger_token_info(dap_ledger_t *a_ledger)
         const char *l_type_str;
         const char *l_flags_str = s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags);
         switch (l_token_item->type) {
-            case DAP_CHAIN_DATUM_TOKEN_DECL: {
+            case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
                 switch (l_token_item->subtype) {
                     case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE:
                         l_type_str = "SIMPLE"; break;
@@ -2227,6 +2254,10 @@ static void s_load_cache_gdb_loaded_spent_txs_callback(dap_global_db_context_t *
 
     for (size_t i = 0; i < a_values_count; i++) {
         dap_chain_ledger_tx_spent_item_t *l_tx_spent_item = DAP_NEW_Z(dap_chain_ledger_tx_spent_item_t);
+        if ( !l_tx_spent_item ) {
+            log_it(L_ERROR, "Memory allocation error in s_load_cache_gdb_loaded_spent_txs_callback");
+            return;
+        }
         dap_chain_hash_fast_from_str(a_values[i].key, &l_tx_spent_item->tx_hash_fast);
         l_tx_spent_item->cache_data = *(typeof(((dap_chain_ledger_tx_spent_item_t*)0)->cache_data)*)a_values[i].value;
         HASH_ADD(hh, l_ledger_pvt->spent_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_spent_item);
@@ -2258,8 +2289,17 @@ static void s_load_cache_gdb_loaded_txs_callback(dap_global_db_context_t *a_glob
     dap_ledger_private_t * l_ledger_pvt = PVT(l_ledger);
     for (size_t i = 0; i < a_values_count; i++) {
         dap_chain_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
+        if ( !l_tx_item ) {
+            log_it(L_ERROR, "Memory allocation error in s_load_cache_gdb_loaded_txs_callback");
+            return;
+        }
         dap_chain_hash_fast_from_str(a_values[i].key, &l_tx_item->tx_hash_fast);
         l_tx_item->tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, a_values[i].value_len - sizeof(l_tx_item->cache_data));
+        if ( !l_tx_item->tx ) {
+            DAP_DELETE(l_tx_item);
+            log_it(L_ERROR, "Memory allocation error in s_load_cache_gdb_loaded_txs_callback");
+            return;
+        }
         memcpy(&l_tx_item->cache_data, a_values[i].value, sizeof(l_tx_item->cache_data));
         memcpy(l_tx_item->tx, a_values[i].value + sizeof(l_tx_item->cache_data), a_values[i].value_len - sizeof(l_tx_item->cache_data));
         l_tx_item->ts_added = dap_nanotime_now();
@@ -2331,6 +2371,10 @@ static void s_load_cache_gdb_loaded_emissions_callback(dap_global_db_context_t *
             continue;
         }
         dap_chain_ledger_token_emission_item_t *l_emission_item = DAP_NEW_Z(dap_chain_ledger_token_emission_item_t);
+        if ( !l_emission_item ) {
+            log_it(L_ERROR, "Memory allocation error in s_load_cache_gdb_loaded_emissions_callback");
+            return;
+        }
         dap_chain_hash_fast_from_str(a_values[i].key, &l_emission_item->datum_token_emission_hash);
         l_emission_item->tx_used_out = *(dap_hash_fast_t*)a_values[i].value;
         l_emission_item->datum_token_emission = DAP_DUP_SIZE(a_values[i].value + sizeof(dap_hash_fast_t),
@@ -2427,12 +2471,13 @@ void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger)
  * @param a_net_name char * network name, for example "kelvin-testnet"
  * @return dap_ledger_t*
  */
-dap_ledger_t *dap_chain_ledger_create(uint16_t a_flags, char *a_net_name, const char *a_net_native_ticker)
+dap_ledger_t *dap_chain_ledger_create(uint16_t a_flags, char *a_net_name, const char *a_net_native_ticker, dap_list_t *a_poa_certs)
 {
     dap_ledger_t *l_ledger = dap_chain_ledger_handle_new();
     l_ledger->net_name = a_net_name;
     dap_ledger_private_t *l_ledger_pvt = PVT(l_ledger);
     l_ledger_pvt->net_native_ticker = a_net_native_ticker;
+    l_ledger_pvt->poa_certs = a_poa_certs;
     l_ledger_pvt->flags = a_flags;
     l_ledger_pvt->check_ds = a_flags & DAP_CHAIN_LEDGER_CHECK_LOCAL_DS;
     l_ledger_pvt->check_cells_ds = a_flags & DAP_CHAIN_LEDGER_CHECK_CELLS_DS;
@@ -2441,6 +2486,36 @@ dap_ledger_t *dap_chain_ledger_create(uint16_t a_flags, char *a_net_name, const
     pthread_cond_init(&l_ledger_pvt->load_cond, NULL);
     pthread_mutex_init(&l_ledger_pvt->load_mutex, NULL);
 
+    char * l_chains_path = dap_strdup_printf("%s/network/%s", dap_config_path(), a_net_name);
+    DIR * l_chains_dir = opendir(l_chains_path);
+    DAP_DEL_Z(l_chains_path);
+
+    struct dirent * l_dir_entry;
+    uint8_t i = 0;
+    while ( (l_dir_entry = readdir(l_chains_dir) )!= NULL ){
+        if (l_dir_entry->d_name[0] == '\0')
+            continue;
+        char * l_entry_name = dap_strdup(l_dir_entry->d_name);
+        if (strlen(l_entry_name) > 4) {
+            if ( strncmp (l_entry_name + strlen(l_entry_name)-4,".cfg",4) == 0 ) { // its .cfg file
+                l_entry_name [strlen(l_entry_name)-4] = 0;
+                log_it(L_DEBUG,"Open chain config \"%s\"...",l_entry_name);
+                l_chains_path = dap_strdup_printf("network/%s/%s", a_net_name, l_entry_name);
+                dap_config_t * l_cfg = dap_config_open(l_chains_path);
+                uint16_t l_whitelist_size;
+                char **l_whitelist = dap_config_get_array_str(l_cfg, "ledger", "hard_accept_list", &l_whitelist_size);
+                for (uint16_t i = 0; i < l_whitelist_size; ++i) {
+                    dap_ledger_hal_item_t *l_hal_item = DAP_NEW_Z(dap_ledger_hal_item_t);
+                    dap_chain_hash_fast_from_str(l_whitelist[i], &l_hal_item->hash);
+                    HASH_ADD(hh, s_hal_items, hash, sizeof(l_hal_item->hash), l_hal_item);
+                }
+                dap_config_close(l_cfg);
+                log_it(L_DEBUG, "HAL items count for chain %s : %d", l_entry_name, l_whitelist_size);
+            }
+        }
+        DAP_DELETE (l_entry_name);
+    }
+    closedir(l_chains_dir);
 
     log_it(L_DEBUG,"Created ledger \"%s\"",a_net_name);
     l_ledger_pvt->load_mode = true;
@@ -2465,7 +2540,7 @@ void dap_chain_ledger_set_fee(dap_ledger_t *a_ledger, uint256_t a_fee, dap_chain
 int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_chain_hash_fast_t *a_emission_hash)
 {
     if (!a_token_emission || !a_token_emission_size)
-        return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ERROR_EMISSION_NULL_OR_IS_EMISSION_SIZE_ZERO;
+        return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL;
 
     int l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_OK;
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
@@ -2476,13 +2551,12 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_
     HASH_FIND_STR(l_ledger_pvt->tokens, l_token_ticker, l_token_item);
     pthread_rwlock_unlock(&l_ledger_pvt->tokens_rwlock);
 
-    dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
-
     if (!l_token_item) {
-        log_it(L_WARNING, "Ledger_token_emission_add_check. Token ticker %s was not found", l_token_ticker);
+        log_it(L_ERROR, "Check emission: token %s was not found", l_token_ticker);
         return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN;
     }
 
+    dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
     // check if such emission is already present in table
     pthread_rwlock_rdlock(l_token_item ? &l_token_item->token_emissions_rwlock
                                        : &l_ledger_pvt->threshold_emissions_rwlock);
@@ -2505,29 +2579,47 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_
                 log_it(L_ERROR, "Can't add token emission datum of %"DAP_UINT64_FORMAT_U" %s ( %s ): already present in cache",
                     l_token_emission_item->datum_token_emission->hdr.value, l_token_ticker, l_token_hash_str);
         }
-        l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CAN_NOT_ADDED_EMISSION_ALREADY_IN_CACHE;
+        l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED;
     }else if ( (! l_token_item) && ( l_threshold_emissions_count >= s_threshold_emissions_max)) {
         if(s_debug_more)
-            log_it(L_WARNING,"threshold for emissions is overfulled (%zu max)",
-               s_threshold_emissions_max);
-        l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_EMISSION_OVERFULLED;
+            log_it(L_WARNING,"Emissions threshold overflow, max %zu items", s_threshold_emissions_max);
+        l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW;
     }
     if (l_ret || !PVT(a_ledger)->check_token_emission)
         return l_ret;
+
+    if (s_hal_items) {
+        dap_ledger_hal_item_t *l_hash_found = NULL;
+        HASH_FIND(hh, s_hal_items, a_emission_hash, sizeof(*a_emission_hash), l_hash_found);
+        if (l_hash_found) {
+            char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
+            dap_chain_hash_fast_to_str(a_emission_hash, l_hash_str, sizeof(l_hash_str));
+            debug_if(s_debug_more, L_MSG, "Event %s is whitelisted", l_hash_str);
+            return l_ret;
+        }
+    }
+
     // Check emission correctness
     size_t l_emission_size = a_token_emission_size;
     dap_chain_datum_token_emission_t *l_emission = dap_chain_datum_emission_read(a_token_emission, &l_emission_size);
 
+    if (IS_ZERO_256((l_emission->hdr.value_256))) {
+        log_it(L_ERROR, "Emission check: zero %s emission value", l_token_item->ticker);
+        DAP_DELETE(l_emission);
+        return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE;
+    }
+
     // if total_supply > 0 we can check current_supply
     if (!IS_ZERO_256(l_token_item->total_supply)){
         if(compare256(l_token_item->current_supply, l_emission->hdr.value_256) < 0) {
             char *l_balance_cur = dap_chain_balance_print(l_token_item->current_supply);
             char *l_balance_em = dap_chain_balance_print(l_emission->hdr.value_256);
-            log_it(L_WARNING, "Ledger_token_emission_add_check. current_supply %s is lower, then l_emission->hdr.value_256: %s",
+            log_it(L_ERROR, "Emission check: current_supply %s < emission value %s",
                     l_balance_cur, l_balance_em);
             DAP_DELETE(l_balance_cur);
             DAP_DELETE(l_balance_em);
-            return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_MORE_THAN_CURRENT_SUPPLY;
+            DAP_DELETE(l_emission);
+            return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY;
         }
     }
 
@@ -2590,7 +2682,10 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_
                                 l_balance, a_ledger->net_name, l_emission->hdr.ticker, l_aproves, l_aproves_valid);
                         DAP_DELETE(l_balance);
                     }
-                    l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALID_SIGNS_NOT_ENOUGH;
+                    l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS;
+                    char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
+                    dap_chain_hash_fast_to_str(a_emission_hash, l_hash_str, sizeof(l_hash_str));
+                    log_it(L_MSG, "!!! Datum hash for HAL: %s", l_hash_str);
                 }
             }else{
                 if(s_debug_more)
@@ -2707,12 +2802,23 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
 {
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
     dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
+    char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+    dap_chain_hash_fast_to_str(a_emission_hash, l_hash_str, sizeof(l_hash_str));
     int l_ret = dap_chain_ledger_token_emission_add_check(a_ledger, a_token_emission, a_token_emission_size, a_emission_hash);
     if (l_ret) {
         if (l_ret == DAP_CHAIN_CS_VERIFY_CODE_NO_DECREE) { // TODO remove emissions threshold
             if (HASH_COUNT(l_ledger_pvt->threshold_emissions) < s_threshold_emissions_max) {
                 l_token_emission_item = DAP_NEW_Z(dap_chain_ledger_token_emission_item_t);
+                if ( !l_token_emission_item ) {
+                    log_it(L_ERROR, "Memory allocation error in s_token_emission_add");
+                    return DAP_CHAIN_LEDGER_EMISSION_ADD_MEMORY_PROBLEM;
+                }
                 l_token_emission_item->datum_token_emission = DAP_DUP_SIZE(a_token_emission, a_token_emission_size);
+                if ( !l_token_emission_item->datum_token_emission ) {
+                    DAP_DELETE(l_token_emission_item);
+                    log_it(L_ERROR, "Memory allocation error in s_token_emission_add");
+                    return DAP_CHAIN_LEDGER_EMISSION_ADD_MEMORY_PROBLEM;
+                }
                 l_token_emission_item->datum_token_emission_size = a_token_emission_size;
                 dap_hash_fast_t l_emi_hash = {0};
                 dap_hash_fast(a_token_emission, a_token_emission_size, &l_emi_hash);
@@ -2773,13 +2879,14 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
                 } else {
                     char *l_balance = dap_chain_balance_print(l_token_item->current_supply);
                     char *l_value = dap_chain_balance_print(l_emission_value);
-                    log_it(L_WARNING,"Token current supply %s lower, than emission value = %s",
-                                        l_balance, l_value);
+
+                    log_it(L_WARNING,"Token %s current supply %s < emission value %s",
+                                        l_token_item->ticker, l_balance, l_value);
                     DAP_DELETE(l_balance);
                     DAP_DELETE(l_value);
                     DAP_DELETE(l_token_emission_item->datum_token_emission);
                     DAP_DELETE(l_token_emission_item);
-                    return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_MORE_THAN_CURRENT_SUPPLY;
+                    return DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY;
                 }
                 if (PVT(a_ledger)->cached)
                     s_ledger_token_cache_update(a_ledger, l_token_item);
@@ -2828,7 +2935,7 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
             if(s_debug_more)
                 log_it(L_WARNING,"threshold for emissions is overfulled (%zu max), dropping down new data, added nothing",
                    s_threshold_emissions_max);
-            l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_EMISSION_OVERFULLED;
+            l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW;
         }
     } else {
         if (l_token_item) {
@@ -2845,7 +2952,7 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
                             ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.value, c_token_ticker, l_hash_str);
             }
         }
-        l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CAN_NOT_ADDED_EMISSION_ALREADY_IN_CACHE;
+        l_ret = DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED;
     }
     return l_ret;
 }
@@ -2933,27 +3040,10 @@ int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token
     return dap_chain_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size, a_token_emission_hash, false);
 }
 
-char *dap_chain_ledger_token_emission_err_code_to_str(dap_chain_ledger_emission_err_code_t a_code) {
-    switch (a_code) {
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_OK:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_OK");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ERROR_EMISSION_NULL_OR_IS_EMISSION_SIZE_ZERO:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ERROR_EMISSION_NULL_OR_IS_EMISSION_SIZE_ZERO");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CAN_NOT_ADDED_EMISSION_ALREADY_IN_CACHE:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CAN_NOT_ADDED_EMISSION_ALREADY_IN_CACHE");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_EMISSION_OVERFULLED:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_EMISSION_OVERFULLED");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_MORE_THAN_CURRENT_SUPPLY:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_MORE_THAN_CURRENT_SUPPLY");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALID_SIGNS_NOT_ENOUGH:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALID_SIGNS_NOT_ENOUGH");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN");
-        case DAP_CHAIN_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED:
-            return dap_strdup("DAP_CHAIN_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED");
-        default:
-            return dap_strdup_printf("Code emission error: %d - has no string representation.", a_code);
-    }
+char *dap_chain_ledger_token_emission_err_code_to_str(int a_code) {
+    return (a_code >= DAP_CHAIN_LEDGER_EMISSION_ADD_OK && a_code < DAP_CHAIN_LEDGER_EMISSION_ADD_UNKNOWN)
+            ? (char*)s_ledger_emission_add_err_str[(dap_chain_ledger_emission_err_code_t)a_code]
+            : dap_itoa(a_code);
 }
 
 dap_chain_ledger_token_emission_item_t *s_emission_item_find(dap_ledger_t *a_ledger,
@@ -3046,6 +3136,10 @@ void dap_chain_ledger_addr_get_token_ticker_all_depricated(dap_ledger_t *a_ledge
     if(l_tx_item) {
         l_tickers_size = 10;
         l_tickers = DAP_NEW_Z_SIZE(char *, l_tickers_size * sizeof(char*));
+        if ( !l_tickers ) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_addr_get_token_ticker_all_depricated");
+            return;
+        }
         while(l_tx_item) {
             bool l_is_not_in_list = true;
             for(size_t i = 0; i < l_tickers_size; i++) {
@@ -3060,6 +3154,10 @@ void dap_chain_ledger_addr_get_token_ticker_all_depricated(dap_ledger_t *a_ledge
                 if((l_tickers_pos + 1) == l_tickers_size) {
                     l_tickers_size += (l_tickers_size / 2);
                     l_tickers = DAP_REALLOC(l_tickers, l_tickers_size);
+                    if ( !l_tickers ) {
+                        log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_addr_get_token_ticker_all_depricated");
+                        return;
+                    }
                 }
                 l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->cache_data.token_ticker);
                 l_tickers_pos++;
@@ -3070,6 +3168,10 @@ void dap_chain_ledger_addr_get_token_ticker_all_depricated(dap_ledger_t *a_ledge
         }
         l_tickers_size = l_tickers_pos + 1;
         l_tickers = DAP_REALLOC(l_tickers, l_tickers_size * sizeof(char*));
+        if ( !l_tickers ) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_addr_get_token_ticker_all_depricated");
+            return;
+        }
     }
     *a_tickers = l_tickers;
     *a_tickers_size = l_tickers_pos;
@@ -3339,10 +3441,23 @@ bool s_tx_match_sign(dap_chain_datum_token_emission_t *a_datum_emission, dap_cha
     return false;
 }
 
+static int s_callback_sign_compare(const void *a, const void *b)
+{
+    return !dap_pkey_match_sign((dap_pkey_t *)a, (dap_sign_t *)b);
+}
+
+bool dap_chain_ledger_tx_poa_signed(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
+{
+    dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
+    dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
+    return dap_list_find_custom(PVT(a_ledger)->poa_certs, l_sign, s_callback_sign_compare);
+}
+
+
 /**
  * Checking a new transaction before adding to the cache
  *
- * return 1 OK, -1 error
+ * return 0 OK, otherwise error
  */
 // Checking a new transaction before adding to the cache
 int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash,
@@ -3359,7 +3474,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 dap_chain_hash_fast_to_str(a_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str));
                 log_it(L_WARNING, "Transaction %s already present in the cache", l_tx_hash_str);
             }
-            return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_INPUT_DATA;
+            return DAP_CHAIN_LEDGER_TX_ALREADY_CACHED;
         }
     }
 /*
@@ -3381,7 +3496,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
     dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
     if(!a_tx){
         log_it(L_DEBUG, "NULL transaction, check broken");
-        return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_INPUT_DATA;
+        return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NULL_TX;
     }
 
     dap_list_t *l_list_bound_items = NULL;
@@ -3398,12 +3513,12 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
     dap_chain_hash_fast_t *l_emission_hash = NULL;
 
     // check all previous transactions
-    int l_err_num = 0;
+    int l_err_num = DAP_CHAIN_LEDGER_TX_CHECK_OK;
     int l_prev_tx_count = 0;
 
     // 1. Verify signature in current transaction
     if (!a_from_threshold && dap_chain_datum_tx_verify_sign(a_tx) != 1)
-        return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_SIGN_TX;
+        return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_TX_SIGN;
 
     // ----------------------------------------------------------------
     // find all 'in' & conditional 'in' items in current transaction
@@ -3411,7 +3526,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                                                           &l_prev_tx_count);
     if (!l_list_in) {
         log_it(L_WARNING, "Tx check: no valid inputs found");
-        return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND;
+        return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_INPUTS;
     }
     dap_chain_ledger_tx_bound_t *bound_item;
     dap_chain_hash_fast_t l_hash_pkey = {};
@@ -3420,6 +3535,22 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
     dap_list_t *l_list_tmp = l_list_in;
     for (int l_list_tmp_num = 0; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp), l_list_tmp_num++) {
         bound_item = DAP_NEW_Z(dap_chain_ledger_tx_bound_t);
+        if (!bound_item) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_tx_cache_check");
+            if ( l_list_bound_items )
+                dap_list_free_full(l_list_bound_items, NULL);
+            if (l_list_tx_out)  
+                dap_list_free(l_list_tx_out);
+            HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
+                HASH_DEL(l_values_from_prev_tx, l_value_cur);
+                DAP_DELETE(l_value_cur);
+            }
+            HASH_ITER(hh, l_values_from_cur_tx, l_value_cur, l_tmp) {
+                HASH_DEL(l_values_from_cur_tx, l_value_cur);
+                DAP_DELETE(l_value_cur);
+            }
+            return -1;
+        }
         dap_chain_tx_in_t *l_tx_in = NULL;
         dap_chain_addr_t l_tx_in_from={0};
         dap_chain_tx_in_cond_t *l_tx_in_cond = NULL;
@@ -3465,7 +3596,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 // check AUTH token emission
                 if (!dap_hash_fast_is_blank(&l_emission_item->tx_used_out)) {
                     debug_if(s_debug_more, L_WARNING, "Emission for IN_EMS [%s] is already used", l_tx_in_ems->header.ticker);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_IN_EMS_ALREADY_USED;
                     break;
                 }
                 bound_item->item_emission = l_emission_item;
@@ -3481,14 +3612,14 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                             debug_if(s_debug_more, L_WARNING, "stake_lock_emission already present in cache for IN_EMS [%s]", l_token);
                         else
                             debug_if(s_debug_more, L_WARNING, "stake_lock_emission is used out for IN_EMS [%s]", l_token);
-                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND;
+                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_IN_EMS_ALREADY_USED;
                         break;
                     }
                     l_tx_stake_lock = dap_chain_ledger_tx_find_by_hash(a_ledger, l_emission_hash);
                 } else {
                     if (l_girdled_ems_used) {    // Only one allowed item with girdled emission
                         debug_if(s_debug_more, L_WARNING, "stake_lock_emission is used out for IN_EMS [%s]", l_token);
-                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND;
+                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_IN_EMS_ALREADY_USED;
                         break;
                     } else
                         l_girdled_ems_used = true;
@@ -3504,8 +3635,8 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 HASH_FIND_STR(PVT(a_ledger)->tokens, l_token, l_delegated_item);
                 pthread_rwlock_unlock(&PVT(a_ledger)->tokens_rwlock);
                 if (!l_delegated_item) {
-                    debug_if(s_debug_more, L_WARNING, "Token [%s] no found", l_token);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TOKEN;
+                    debug_if(s_debug_more, L_WARNING, "Token [%s] not found", l_token);
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_NOT_FOUND;
                     break;
                 }
                 dap_chain_datum_token_t *l_datum_token = l_delegated_item->datum_token;
@@ -3514,13 +3645,13 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                                                   l_datum_token->header_native_decl.tsd_total_size,
                                                   DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK))) {
                     debug_if(s_debug_more, L_WARNING, "Token [%s] not valid for stake_lock transaction", l_token);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_NOT_VALID_STAKE_LOCK;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_INVALID_TOKEN;
                     break;
                 }
                 dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
                 if (!dap_chain_ledger_token_ticker_check(a_ledger, (char *)l_tsd_section->ticker_token_from)) {
-                    debug_if(s_debug_more, L_WARNING, "Token [%s] no found", l_tsd_section->ticker_token_from);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TOKEN;
+                    debug_if(s_debug_more, L_WARNING, "Token [%s] not found", l_tsd_section->ticker_token_from);
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_NOT_FOUND;
                     break;
                 }
 
@@ -3530,7 +3661,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 dap_chain_tx_out_cond_t *l_tx_stake_lock_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_stake_lock, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, NULL);
                 if (!l_tx_stake_lock_out_cond) {
                     debug_if(s_debug_more, L_WARNING, "No OUT_COND of stake_lock subtype for IN_EMS [%s]", l_tx_in_ems->header.ticker);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_COND_STAKE_LOCK_FROM_IN_EMS;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS;
                     break;
                 }
                 uint256_t l_value_expected ={};
@@ -3543,7 +3674,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                         DAP_DEL_Z(l_emission_rate_str);
                         DAP_DEL_Z(l_locked_value_str);
                     }
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_MULTIPLICATION_OVERFLOW_EMISSION_LOCKED_EMISSION_RATE;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_MULT256_OVERFLOW_EMS_LOCKED_X_RATE;
                     break;
                 }
                 dap_chain_tx_out_ext_t *l_tx_out_ext = NULL;
@@ -3564,7 +3695,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                     dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_OUT, NULL);
                     if (!l_tx_out) {
                         debug_if(true, L_WARNING, "Can't find OUT nor OUT_EXT item for base TX with IN_EMS [%s]", l_tx_in_ems->header.ticker);
-                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_OUT_NOR_OUT_EXT_BASE_TX_IN_EMS;
+                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_NO_OUT_ITEMS_FOR_BASE_TX;
                         break;
                     } else
                         l_stake_lock_ems_value = l_tx_out->header.value;
@@ -3574,36 +3705,36 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                         compare256(l_delegated_item->current_supply, l_stake_lock_ems_value) < 0) {
                     char *l_balance = dap_chain_balance_print(l_delegated_item->current_supply);
                     char *l_value_ch = dap_chain_balance_print(l_stake_lock_ems_value);
-                    log_it(L_WARNING, "Token current supply %s lower, than emission value = %s",
+                    log_it(L_WARNING, "Token current supply %s < emission value %s",
                            l_balance, l_value_ch);
                     DAP_DEL_Z(l_balance);
                     DAP_DEL_Z(l_value_ch);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_CURRENT_SUPPLY_LOWER_EMISSION_VALUE;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY;
                     break;
                 }
                 if (!EQUAL_256(l_value_expected, l_stake_lock_ems_value)) {
                     char *l_value_expected_str = dap_chain_balance_print(l_value_expected);
                     char *l_locked_value_str = dap_chain_balance_print(l_stake_lock_ems_value);
 
-                    debug_if(s_debug_more, L_WARNING, "Value %s not thats expected %s for [%s]",l_locked_value_str, l_value_expected_str,
+                    debug_if(s_debug_more, L_WARNING, "Value %s != %s expected for [%s]",l_locked_value_str, l_value_expected_str,
                              l_tx_in_ems->header.ticker);
 
                     DAP_DEL_Z(l_value_expected_str);
                     DAP_DEL_Z(l_locked_value_str);
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VALUE_NOT_THATS_EXPECTED_IN_EMS;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_UNEXPECTED_VALUE;
                     break;
                 }
                 if (!l_girdled_ems) {
                     // check tiker
                     const char *l_tx_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, l_emission_hash);
                     if (!l_tx_ticker) {
-                        debug_if(s_debug_more, L_WARNING, "No ticker found for sake_lock tx [wait %s]", l_tx_in_ems->header.ticker);
-                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TICKER_FOR_STAKE_LOCK;
+                        debug_if(s_debug_more, L_WARNING, "No ticker found for stake_lock tx [expected '%s']", l_tx_in_ems->header.ticker);
+                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_TICKER_NOT_FOUND;
                         break;
                     }
                     if (strcmp(l_tx_ticker, (char *)l_tsd_section->ticker_token_from)) {
-                        debug_if(s_debug_more, L_WARNING, "Ticker %s in different for expected %s", l_tx_ticker, l_tx_in_ems->header.ticker);
-                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_DIFFERENT_EXPECTED;
+                        debug_if(s_debug_more, L_WARNING, "Ticker '%s' != expected '%s'", l_tx_ticker, l_tx_in_ems->header.ticker);
+                        l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_OTHER_TICKER_EXPECTED;
                         break;
                     }
                 }
@@ -3635,14 +3766,14 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
             // 2. Check if out in previous transaction has spent
             int l_idx = (l_cond_type == TX_ITEM_TYPE_IN) ? l_tx_in->header.tx_out_prev_idx : l_tx_in_cond->header.tx_out_prev_idx;
             if (s_ledger_tx_hash_is_used_out_item(l_item_out, l_idx)) {
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_USED_OUT_ITEM;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_OUT_ITEM_ALREADY_USED;
                 break;
             }
 
             // Get one 'out' item in previous transaction bound with current 'in' item
             l_tx_prev_out = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_idx);
             if(!l_tx_prev_out) {
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_PREV_OUT_TX;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ITEM_NOT_FOUND;
                 break;
             }
             // 3. Compare out in previous transaction with currently used out
@@ -3650,7 +3781,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 dap_chain_ledger_tx_bound_t *l_bound_tmp = it->data;
                 if (l_tx_prev_out == l_bound_tmp->out.tx_prev_out) {
                     debug_if(s_debug_more, L_ERROR, "Previous transaction output already used in current tx");
-                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREVIOUS_TX_OUTPUT_ALREADY_USED_IN_CURRENT_TX;
+                    l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX;
                     break;
                 }
             }
@@ -3682,7 +3813,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 l_token = bound_item->out.tx_prev_out_ext_256->token;
                 break;
             default:
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_PREV_OUT_TX;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ITEM_NOT_FOUND;
                 break;
             }
             if (l_err_num)
@@ -3699,12 +3830,12 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 dap_sign_get_pkey_hash(l_sign, &l_hash_pkey);
             }
             if (!dap_hash_fast_compare(&l_hash_pkey, l_prev_out_addr_key)) {
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_HASH_PKEY_TX_NOT_COMPARE_HASH_PKEY_OUT_ADDR_PREV_TX;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PKEY_HASHES_DONT_MATCH;
                 break;
             }
         } else if(l_cond_type == TX_ITEM_TYPE_IN_COND) { // TX_ITEM_TYPE_IN_COND
             if(*(uint8_t *)l_tx_prev_out != TX_ITEM_TYPE_OUT_COND) {
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_PREV_OUT_TX;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ITEM_NOT_FOUND;
                 break;
             }
             // 5a. Check for condition owner
@@ -3732,13 +3863,13 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
             pthread_rwlock_unlock(&s_verificators_rwlock);
             if (!l_verificator || !l_verificator->callback) {
                 debug_if(s_debug_more, L_ERROR, "No verificator set for conditional output subtype %d", l_sub_tmp);
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_NO_VALIDATOR_COND_OUTPUT;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_VERIFICATOR_SET;
                 break;
             }
             if (l_verificator->callback(a_ledger, l_tx_prev_out_cond, a_tx, l_owner) == false) {
                 debug_if(s_debug_more, L_WARNING, "Verificator check error for conditional output %s",
                                                     dap_chain_tx_out_cond_subtype_to_str(l_sub_tmp));
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_FAIL;
+                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_VERIFICATOR_CHECK_FAILURE;
                 break;
             }
             // calculate sum of values from previous transactions
@@ -3758,7 +3889,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
         }
         if (! l_token || !*l_token ) {
             log_it(L_WARNING, "No token ticker found in previous transaction");
-            l_err_num = DAP_CHAIN_LEDGET_TX_CACHE_CHECK_NO_FOUND_TOKEN_TICKER;
+            l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TICKER_NOT_FOUND;
             break;
         }
         // Get permissions
@@ -3769,7 +3900,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
         if (! l_token_item){
             if(s_debug_more)
                 log_it(L_WARNING, "No token item found for token %s", l_token);
-            l_err_num = DAP_CHAIN_LEDGET_TX_CACHE_CHECK_NO_FOUND_TOKEN_TICKER;
+            l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TOKEN_NOT_FOUND;
             break;
         }
         // Check permissions
@@ -3783,7 +3914,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 if(s_debug_more)
                     log_it(L_WARNING, "No permission for addr %s", l_tmp_tx_in_from?l_tmp_tx_in_from:"(null)");
                 DAP_DELETE(l_tmp_tx_in_from);
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PERMISSION_FAILED;
+                l_err_num = DAP_CHAIN_LEDGER_PERMISSION_CHECK_FAILED;
                 break;
             }
         }
@@ -3795,7 +3926,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 if(s_debug_more)
                     log_it(L_WARNING, "No permission for addr %s", l_tmp_tx_in_from?l_tmp_tx_in_from:"(null)");
                 DAP_DELETE(l_tmp_tx_in_from);
-                l_err_num = DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PERMISSION_FAILED;
+                l_err_num = DAP_CHAIN_LEDGER_PERMISSION_CHECK_FAILED;
                 break;
             }
         }
@@ -3803,6 +3934,16 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
         HASH_FIND_STR(l_values_from_prev_tx, l_token, l_value_cur);
         if (!l_value_cur) {
             l_value_cur = DAP_NEW_Z(dap_chain_ledger_tokenizer_t);
+            if ( !l_value_cur ) {
+                log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_tx_cache_check");
+                if (bound_item)
+                    DAP_DELETE(bound_item);
+                if ( l_list_bound_items )
+                    dap_list_free_full(l_list_bound_items, NULL);
+                if (l_list_tx_out)
+                    dap_list_free(l_list_tx_out);
+                return -1;
+            }
             strcpy(l_value_cur->token_ticker, l_token);
             HASH_ADD_STR(l_values_from_prev_tx, token_ticker, l_value_cur);
         }
@@ -3840,6 +3981,16 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
         }
     } else {
         l_value_cur = DAP_NEW_Z(dap_chain_ledger_tokenizer_t);
+        if ( !l_value_cur ) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_tx_cache_check");
+            if (bound_item)
+                DAP_DELETE(bound_item);
+            if ( l_list_bound_items )
+                dap_list_free_full(l_list_bound_items, NULL);
+            if (l_list_tx_out)
+                dap_list_free(l_list_tx_out);
+            return -1;
+        }
         dap_stpcpy(l_value_cur->token_ticker, l_token);
         if (!l_main_ticker)
             l_main_ticker = l_value_cur->token_ticker;
@@ -3912,6 +4063,16 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
             HASH_FIND_STR(l_values_from_cur_tx, l_token, l_value_cur);
             if (!l_value_cur) {
                 l_value_cur = DAP_NEW_Z(dap_chain_ledger_tokenizer_t);
+                if ( !l_value_cur ) {
+                    log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_tx_cache_check");
+                    if (bound_item)
+                        DAP_DELETE(bound_item);
+                    if ( l_list_bound_items )
+                        dap_list_free_full(l_list_bound_items, NULL);
+                    if (l_list_tx_out)
+                        dap_list_free(l_list_tx_out);
+                    return -1;
+                }
                 strcpy(l_value_cur->token_ticker, l_token);
                 HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur);
             }
@@ -3993,12 +4154,15 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 
     // 7. Check the network fee
     if (l_fee_check && compare256(l_fee_sum, l_ledger_pvt->fee_value) == -1) {
-        char *l_current_fee = dap_chain_balance_to_coins(l_fee_sum);
-        char *l_expected_fee = dap_chain_balance_to_coins(l_ledger_pvt->fee_value);
-        log_it(L_ERROR, "Fee value is invalid, expected %s pointed %s", l_expected_fee, l_current_fee);
-        l_err_num = -55;
-        DAP_DEL_Z(l_current_fee);
-        DAP_DEL_Z(l_expected_fee);
+        // Check for PoA-cert-signed "service" no-tax tx
+        if (!dap_chain_ledger_tx_poa_signed(a_ledger, a_tx)) {
+            char *l_current_fee = dap_chain_balance_to_coins(l_fee_sum);
+            char *l_expected_fee = dap_chain_balance_to_coins(l_ledger_pvt->fee_value);
+            log_it(L_ERROR, "Fee value is invalid, expected %s pointed %s", l_expected_fee, l_current_fee);
+            l_err_num = -55;
+            DAP_DEL_Z(l_current_fee);
+            DAP_DEL_Z(l_expected_fee);
+        }
     }
 
     if (a_main_ticker && !l_err_num)
@@ -4036,29 +4200,27 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 int dap_chain_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)
 {
     if (!a_tx)
-        return DAP_CHAIN_LEDGER_TX_CHECK_ERROR_IS_NULL_TX;
+        return DAP_CHAIN_LEDGER_TX_CHECK_NULL_TX;
 
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
     if (l_tx_size != a_datum_size) {
-        log_it (L_WARNING, "Inconsistent datum TX with data_size=%zu, tx_size=%zu", a_datum_size, l_tx_size);
-        return DAP_CHAIN_LEDGER_TX_CHECK_ERROR_INVALID_SIZE_TX;
+        log_it (L_WARNING, "Inconsistent datum TX: datum size %zu != tx size %zu", a_datum_size, l_tx_size);
+        return DAP_CHAIN_LEDGER_TX_CHECK_INVALID_TX_SIZE;
     }
 
-    int l_ret_check;
-    if( (l_ret_check = dap_chain_ledger_tx_cache_check(a_ledger, a_tx, a_datum_hash, false,
-                                                       NULL, NULL, NULL)) < 0) {
-        char *l_err_str = dap_chain_ledger_tx_check_err_str(l_ret_check);
-        debug_if(s_debug_more, L_DEBUG, "dap_chain_ledger_tx_add_check() tx not passed the check: %s",
-                 l_err_str);
-        DAP_DELETE(l_err_str);
-        return l_ret_check;
-    }
+    int l_ret_check = dap_chain_ledger_tx_cache_check(a_ledger, a_tx, a_datum_hash,
+                                                      false, NULL, NULL, NULL);
     if(s_debug_more) {
         char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
         dap_chain_hash_fast_to_str(a_datum_hash, l_tx_hash_str, sizeof(l_tx_hash_str));
-        log_it ( L_INFO, "dap_chain_ledger_tx_add_check() check passed for tx %s", l_tx_hash_str);
+        if (l_ret_check)
+            log_it(L_NOTICE, "Ledger TX adding check not passed for TX %s: error %s",
+                   l_tx_hash_str, dap_chain_ledger_tx_check_err_str(l_ret_check));
+        else
+            log_it(L_INFO, "Ledger TX adding check passed for TX %s", l_tx_hash_str);
     }
-    return DAP_CHAIN_LEDGER_TX_CHECK_OK;
+
+    return l_ret_check;
 }
 
 /**
@@ -4133,9 +4295,8 @@ void dap_chain_ledger_set_tps_start_time(dap_ledger_t *a_ledger)
  */
 static inline int s_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, bool a_safe_call)
 {
-    if(!a_tx){
-        if(s_debug_more)
-            log_it(L_ERROR, "NULL tx detected");
+    if(!a_tx) {
+        debug_if(s_debug_more, L_ERROR, "NULL tx detected");
         return -1;
     }
     int l_ret = 0;
@@ -4165,7 +4326,7 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
     l_item_tmp = NULL;
     if( (l_ret_check = dap_chain_ledger_tx_cache_check(a_ledger, a_tx, a_tx_hash, a_from_threshold,
                                                        &l_list_bound_items, &l_list_tx_out,
-                                                       &l_main_token_ticker)) < 0) {
+                                                       &l_main_token_ticker))) {
         if (l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS ||
                 l_ret_check == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION) {
             if (!l_from_threshold) {
@@ -4181,8 +4342,17 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
                                        s_threshold_txs_max);
                     } else {
                         l_item_tmp = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
+                        if ( !l_item_tmp ) {
+                            log_it(L_ERROR, "Memory allocation error in s_tx_add");
+                            return -1;
+                        }
                         l_item_tmp->tx_hash_fast = *a_tx_hash;
                         l_item_tmp->tx = DAP_DUP_SIZE(a_tx, dap_chain_datum_tx_get_size(a_tx));
+                        if ( !l_item_tmp->tx ) {
+                            DAP_DELETE(l_item_tmp);
+                            log_it(L_ERROR, "Memory allocation error in s_tx_add");
+                            return -1;
+                        }
                         l_item_tmp->ts_added = dap_nanotime_now();
                         HASH_ADD_BYHASHVALUE(hh, l_ledger_pvt->threshold_txs, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_tmp);
                         if(s_debug_more)
@@ -4192,12 +4362,8 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
                 pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock);
             }
         } else {
-            if(s_debug_more) {
-                char *l_ret_err_str = dap_chain_ledger_tx_check_err_str(l_ret_check);
-                log_it (L_WARNING, "dap_chain_ledger_tx_add() tx %s not passed the check: %s ", l_tx_hash_str,
-                        l_ret_err_str);
-                DAP_DELETE(l_ret_err_str);
-            }
+            debug_if(s_debug_more, L_WARNING, "dap_chain_ledger_tx_add() tx %s not passed the check: %s ", l_tx_hash_str,
+                        dap_chain_ledger_tx_check_err_str(l_ret_check));
         }
         return l_ret_check;
     }
@@ -4210,6 +4376,14 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
     size_t l_outs_used = dap_list_length(l_list_bound_items);
     size_t l_cache_size = sizeof(dap_store_obj_t) * (l_outs_used + 1);
     dap_store_obj_t *l_cache_used_outs = DAP_NEW_Z_SIZE(dap_store_obj_t, l_cache_size);
+    if ( !l_cache_used_outs ) {
+        if (l_item_tmp->tx)
+            DAP_DELETE(l_item_tmp->tx);
+        if (l_item_tmp)
+            DAP_DELETE(l_item_tmp);
+        log_it(L_ERROR, "Memory allocation error in s_tx_add");
+        return -1;
+    }
     char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_LEDGER_TXS_STR);
     const char *l_cur_token_ticker = NULL;
 
@@ -4445,6 +4619,11 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
             s_balance_cache_update(a_ledger, wallet_balance);
         } else {
             wallet_balance = DAP_NEW_Z(dap_ledger_wallet_balance_t);
+            if (!wallet_balance) {
+                log_it(L_ERROR, "Memoru allocation error in s_load_cache_gdb_loaded_txs_callback");
+                l_ret = -1;
+                goto FIN;
+            }
             wallet_balance->key = l_wallet_balance_key;
             strcpy(wallet_balance->token_ticker, l_cur_token_ticker);
             SUM_256_256(wallet_balance->balance, l_value, &wallet_balance->balance);
@@ -4462,6 +4641,11 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
 
     // add transaction to the cache list
     dap_chain_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
+    if ( !l_tx_item ) {
+        log_it(L_ERROR, "Memory allocation error in s_load_cache_gdb_loaded_txs_callback");
+        l_ret = -1;
+        goto FIN;
+    }
     l_tx_item->tx_hash_fast = *a_tx_hash;
     size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
     l_tx_item->tx = DAP_DUP_SIZE(a_tx, l_tx_size);
@@ -4549,7 +4733,7 @@ int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,
         HASH_FIND_BYHASHVALUE(hh, PVT(a_ledger)->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_tx_item);
         if (l_tx_item) {
             pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
-            return 1;
+            return DAP_CHAIN_LEDGER_TX_ALREADY_CACHED;
         }
         HASH_FIND_BYHASHVALUE(hh, PVT(a_ledger)->threshold_txs, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_tx_item);
         if (l_tx_item) {
@@ -4560,7 +4744,7 @@ int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,
         HASH_FIND_BYHASHVALUE(hh, PVT(a_ledger)->spent_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_tx_spent_item);
         pthread_rwlock_unlock(&PVT(a_ledger)->ledger_rwlock);
         if (l_tx_spent_item)
-            return 1;
+            return DAP_CHAIN_LEDGER_TX_CACHE_CHECK_OUT_ITEM_ALREADY_USED;
     }
     return dap_chain_ledger_tx_add(a_ledger, a_tx, a_tx_hash, false);
 }
@@ -4596,6 +4780,15 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_
         HASH_FIND_BYHASHVALUE(hh, l_ledger_pvt->spent_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_used);
         if (!l_item_used) {   // Add it to spent items
             l_item_used = DAP_NEW_Z(dap_chain_ledger_tx_spent_item_t);
+            if ( !l_item_used ) {
+                if (l_item_tmp->tx)
+                    DAP_DELETE(l_item_tmp->tx);
+                if (l_item_tmp)
+                    DAP_DELETE(l_item_tmp);
+                pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
+                log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_tx_remove");
+                return -1;
+            }
             l_item_used->tx_hash_fast = *a_tx_hash;
             l_item_used->cache_data.spent_time = a_spent_time;
             strncpy(l_item_used->cache_data.token_ticker, l_item_tmp->cache_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
@@ -5270,6 +5463,12 @@ dap_list_t *dap_chain_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, c
             // Check whether used 'out' items
             if (!dap_chain_ledger_tx_hash_is_used_out_item (a_ledger, &l_tx_cur_hash, l_out_idx_tmp)) {
                 dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
+                if ( !l_item ) {
+                    if (l_list_used_out)
+                        dap_list_free_full(l_list_used_out, NULL);
+                    dap_list_free(l_list_out_items);
+                    return NULL;
+                }
                 l_item->tx_hash_fast = l_tx_cur_hash;
                 l_item->num_idx_out = l_out_idx_tmp;
                 l_item->value = l_value;
@@ -5296,7 +5495,7 @@ dap_list_t *dap_chain_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, c
     return l_list_used_out;
 }
 
-// Add new verificator callback with associated subtype. Returns 1 if callback replaced, overwise returns 0
+// Add new verificator callback with associated subtype. Returns 1 if callback replaced, -1 error, overwise returns 0
 int dap_chain_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_chain_ledger_verificator_callback_t a_callback, dap_chain_ledger_updater_callback_t a_callback_added)
 {
     dap_chain_ledger_verificator_t *l_new_verificator;
@@ -5309,6 +5508,10 @@ int dap_chain_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype,
         return 1;
     }
     l_new_verificator = DAP_NEW(dap_chain_ledger_verificator_t);
+    if ( !l_new_verificator ) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_ledger_verificator_add");
+        return -1; 
+    }
     l_new_verificator->subtype = (int)a_subtype;
     l_new_verificator->callback = a_callback;
     l_new_verificator->callback_added = a_callback_added;
@@ -5404,6 +5607,12 @@ dap_list_t *dap_chain_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledg
             }
             if (!IS_ZERO_256(l_value)) {
                 dap_chain_tx_used_out_item_t *l_item = DAP_NEW(dap_chain_tx_used_out_item_t);
+                if ( !l_item ) {
+                    if (l_list_used_out)
+                        dap_list_free_full(l_list_used_out, free);
+                    dap_list_free(l_list_out_cond_items);
+                    return NULL;
+                }
                 l_item->tx_hash_fast = l_tx_cur_hash;
                 l_item->num_idx_out = l_out_idx_tmp;
                 l_item->value = l_value;
diff --git a/modules/chain/dap_chain_pvt.c b/modules/chain/dap_chain_pvt.c
index 6c432762c29bc225d4cfc0c4bff5ac4ceced2677..010a4ab8429bd8d24c53e579c82ed657d91b88d9 100644
--- a/modules/chain/dap_chain_pvt.c
+++ b/modules/chain/dap_chain_pvt.c
@@ -37,6 +37,10 @@
 void dap_chain_add_mempool_notify_callback(dap_chain_t *a_chain, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
 {
     dap_chain_gdb_notifier_t *l_notifier = DAP_NEW(dap_chain_gdb_notifier_t);
+    if (!l_notifier) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_add_mempool_notify_callback");
+        return;
+    }
     l_notifier->callback = a_callback;
     l_notifier->cb_arg = a_cb_arg;
     DAP_CHAIN_PVT(a_chain)->mempool_notifires = dap_list_append(DAP_CHAIN_PVT(a_chain)->mempool_notifires, l_notifier);
diff --git a/modules/chain/dap_chain_tx.c b/modules/chain/dap_chain_tx.c
index b5d3441d6d24add54e3c744f70ec604c3f0ae851..78738e78394ec48b109c9288a2d07f2f1f05c9fa 100644
--- a/modules/chain/dap_chain_tx.c
+++ b/modules/chain/dap_chain_tx.c
@@ -36,6 +36,10 @@
 dap_chain_tx_t * dap_chain_tx_wrap_packed(dap_chain_datum_tx_t * a_tx_packed)
 {
     dap_chain_tx_t * l_tx = DAP_NEW_Z(dap_chain_tx_t);
+    if (!l_tx) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_tx_wrap_packed");
+        return NULL;
+    }
     dap_hash_fast(a_tx_packed, dap_chain_datum_tx_get_size(a_tx_packed), &l_tx->hash);
     l_tx->datum_tx = a_tx_packed;
     return l_tx;
diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h
index d2f44e3764bddb58263b9a3d12261086e5ac2b85..fda6fe0e595c9170ece404708127e406104b3b21 100644
--- a/modules/chain/include/dap_chain.h
+++ b/modules/chain/include/dap_chain.h
@@ -100,7 +100,7 @@ typedef dap_time_t (*dap_chain_callback_atom_get_timestamp_t)(dap_chain_atom_ptr
 typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_chain_atom_iter_t * ,dap_chain_hash_fast_t *,size_t*);
 typedef dap_chain_datum_t * (*dap_chain_callback_datum_find_by_hash_t)(dap_chain_t *, dap_chain_hash_fast_t *, dap_chain_hash_fast_t *, int *);
 
-typedef dap_chain_atom_ptr_t (*dap_chain_callback_block_find_by_hash_t)(dap_chain_t * ,dap_chain_hash_fast_t *);
+typedef dap_chain_atom_ptr_t (*dap_chain_callback_block_find_by_hash_t)(dap_chain_t * ,dap_chain_hash_fast_t *, size_t *);
 
 typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_chain_atom_iter_t * ,size_t* ,size_t**);
 typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t );
diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h
index 14297dfd44595f6dabbea39ea0e0f187a0b955bb..77744f24bba8dd230df79333c693ee89c2f799bc 100644
--- a/modules/chain/include/dap_chain_ledger.h
+++ b/modules/chain/include/dap_chain_ledger.h
@@ -47,52 +47,67 @@ typedef struct dap_ledger {
  */
 typedef enum dap_chain_ledger_tx_check{
     DAP_CHAIN_LEDGER_TX_CHECK_OK = 0,
-    DAP_CHAIN_LEDGER_TX_CHECK_ERROR_IS_NULL_TX = -200,
-    DAP_CHAIN_LEDGER_TX_CHECK_ERROR_INVALID_SIZE_TX = -202,
-    //DAP_CHAIN_LEDGER_TX_CACHE_CHECK_OK = 0,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_INPUT_DATA = -1,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_SIGN_TX = -2,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_TNPUTS_FOUND = -22,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TOKEN = -23,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_NOT_VALID_STAKE_LOCK = -31,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_COND_STAKE_LOCK_FROM_IN_EMS = -32,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_MULTIPLICATION_OVERFLOW_EMISSION_LOCKED_EMISSION_RATE = -26,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS = -36,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_OUT_NOR_OUT_EXT_BASE_TX_IN_EMS = -24,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_CURRENT_SUPPLY_LOWER_EMISSION_VALUE = -30,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VALUE_NOT_THATS_EXPECTED_IN_EMS = -34,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FOUND_TICKER_FOR_STAKE_LOCK = -33,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_DIFFERENT_EXPECTED = -35,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_USED_OUT_ITEM = -6,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NOT_FIND_PREV_OUT_TX = -8,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_HASH_PKEY_TX_NOT_COMPARE_HASH_PKEY_OUT_ADDR_PREV_TX = -9,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREVIOUS_TX_OUTPUT_ALREADY_USED_IN_CURRENT_TX = -7,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_NO_VALIDATOR_COND_OUTPUT = -13,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_VERIF_CHECK_FAIL = -14,
-    DAP_CHAIN_LEDGET_TX_CACHE_CHECK_NO_FOUND_TOKEN_TICKER = -15,
-    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PERMISSION_FAILED = -20
-}dap_chain_ledger_tx_check_t;
+    DAP_CHAIN_LEDGER_TX_CHECK_NULL_TX,
+    DAP_CHAIN_LEDGER_TX_CHECK_INVALID_TX_SIZE,
+    DAP_CHAIN_LEDGER_TX_ALREADY_CACHED,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NULL_TX,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_INVALID_TX_SIGN,
+    DAP_CHAIN_LEDGER_TX_CACHE_IN_EMS_ALREADY_USED,
+    DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_IN_EMS_ALREADY_USED,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_EMISSION_NOT_FOUND,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TX_NO_VALID_INPUTS,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TICKER_NOT_FOUND,
+    DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_INVALID_TOKEN,
+    DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_NO_OUT_COND_FOR_IN_EMS,
+    DAP_CHAIN_LEDGER_TX_CACHE_MULT256_OVERFLOW_EMS_LOCKED_X_RATE,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_OUT_EXT_FOR_GIRDLED_IN_EMS,
+    DAP_CHAIN_LEDGER_TX_CACHE_NO_OUT_ITEMS_FOR_BASE_TX,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_TOKEN_EMS_VALUE_EXEEDS_CUR_SUPPLY,
+    DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_UNEXPECTED_VALUE,
+    DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_TICKER_NOT_FOUND,
+    DAP_CHAIN_LEDGER_TX_CACHE_STAKE_LOCK_OTHER_TICKER_EXPECTED,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_OUT_ITEM_ALREADY_USED,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TX_NOT_FOUND,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ITEM_NOT_FOUND,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PKEY_HASHES_DONT_MATCH,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_NO_VERIFICATOR_SET,
+    DAP_CHAIN_LEDGER_TX_CACHE_VERIFICATOR_CHECK_FAILURE,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TICKER_NOT_FOUND,
+    DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TOKEN_NOT_FOUND,
+    DAP_CHAIN_LEDGER_PERMISSION_CHECK_FAILED,
+    /* add custom codes here */
+
+    DAP_CHAIN_LEDGER_TX_CHECK_UNKNOWN /* MAX */
+} dap_chain_ledger_tx_check_t;
 
 typedef enum dap_chain_ledger_emission_err{
     DAP_CHAIN_LEDGER_EMISSION_ADD_OK = 0,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ERROR_EMISSION_NULL_OR_IS_EMISSION_SIZE_ZERO = -100,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CAN_NOT_ADDED_EMISSION_ALREADY_IN_CACHE = -1,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_EMISSION_OVERFULLED = -2,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_MORE_THAN_CURRENT_SUPPLY = -4,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALID_SIGNS_NOT_ENOUGH = -3,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN = -5,
-    DAP_CHAIN_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED = -144
-}dap_chain_ledger_emission_err_code_t;
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_IS_NULL,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_EMS_ALREADY_CACHED,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_THRESHOLD_OVERFLOW,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_VALUE_EXEEDS_CURRENT_SUPPLY,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_NOT_ENOUGH_VALID_SIGNS,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_CANT_FIND_DECLARATION_TOKEN,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_CHECK_ZERO_VALUE,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_TSD_CHECK_FAILED,
+    /* add custom codes here */
+    DAP_CHAIN_LEDGER_EMISSION_ADD_MEMORY_PROBLEM,
+    DAP_CHAIN_LEDGER_EMISSION_ADD_UNKNOWN /* MAX */
+} dap_chain_ledger_emission_err_code_t;
 
 typedef enum dap_chain_ledger_token_decl_add_err{
     DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_OK = 0,
-    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL = -1,
-    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE = -3,
-    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK = -2,
-    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN = -6,
-    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN = -5,
-    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_UNIQUE_SIGNS_LESS_TOTAL_SIGNS = -4
-}dap_chain_ledger_token_decl_add_err_t;
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_LEDGER_IS_NULL,
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_DECL_DUPLICATE,
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_CHECK,
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOKEN_UPDATE_ABSENT_TOKEN,
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_NOT_ENOUGH_VALID_SIGN,
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_ERR_TOTAL_SIGNS_EXCEED_UNIQUE_SIGNS,
+    /* add custom codes here */
+
+    DAP_CHAIN_LEDGER_TOKEN_DECL_ADD_UNKNOWN /* MAX */
+} dap_chain_ledger_token_decl_add_err_t;
 
 typedef bool (*dap_chain_ledger_verificator_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_t *a_tx_out_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner);
 typedef void (*dap_chain_ledger_updater_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_prev_cond);
@@ -115,9 +130,9 @@ typedef struct dap_chain_net dap_chain_net_t;
 #define DAP_CHAIN_LEDGER_CACHE_ENABLED           0x0200
 
 // Error code for no previous transaction (for stay in mempool)
-#define DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS  -1111
+#define DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS  DAP_CHAIN_LEDGER_TX_CACHE_CHECK_PREV_TX_NOT_FOUND
 // Error code for no emission for a transaction (for stay in mempoold)
-#define DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION  -1112
+#define DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION  DAP_CHAIN_LEDGER_TX_CACHE_CHECK_EMISSION_NOT_FOUND
 // Error code for no decree for anchor (for stay in mempool)
 #define DAP_CHAIN_CS_VERIFY_CODE_NO_DECREE       -1113
 
@@ -131,7 +146,7 @@ typedef struct dap_chain_net dap_chain_net_t;
 int dap_chain_ledger_init();
 void dap_chain_ledger_deinit();
 
-dap_ledger_t *dap_chain_ledger_create(uint16_t a_flags, char *a_net_name, const char *a_net_native_ticker);
+dap_ledger_t *dap_chain_ledger_create(uint16_t a_flags, char *a_net_name, const char *a_net_native_ticker, dap_list_t *a_poa_certs);
 
 void dap_chain_ledger_set_fee(dap_ledger_t *a_ledger, uint256_t a_fee, dap_chain_addr_t a_fee_addr);
 
@@ -173,7 +188,7 @@ int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,
 
 int dap_chain_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);
 
-char* dap_chain_ledger_tx_check_err_str(dap_chain_ledger_tx_check_t a_code);
+char* dap_chain_ledger_tx_check_err_str(int a_code);
 
 /**
  * Print list transaction from ledger
@@ -217,7 +232,7 @@ dap_list_t * dap_chain_ledger_token_auth_pkeys_hashes(dap_ledger_t *a_ledger, co
 int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size,
                                         dap_hash_fast_t *a_emission_hash, bool a_from_threshold);
 int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_hash_fast_t *a_token_emission_hash);
-char *dap_chain_ledger_token_emission_err_code_to_str(dap_chain_ledger_emission_err_code_t a_code);
+char *dap_chain_ledger_token_emission_err_code_to_str(int a_code);
 
 // Check if it addable
 int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size, dap_chain_hash_fast_t *a_emission_hash);
@@ -236,6 +251,8 @@ void dap_chain_ledger_addr_get_token_ticker_all_depricated(dap_ledger_t *a_ledge
 void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chain_addr_t * a_addr,
         char *** a_tickers, size_t * a_tickers_size);
 
+bool dap_chain_ledger_tx_poa_signed(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
+
 // Checking a new transaction before adding to the cache
 int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash,
                                     bool a_from_threshold, dap_list_t **a_list_bound_items, dap_list_t **a_list_tx_out, char **a_main_ticker);
diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c
index da64d64ce39b8e4ba83c2f4351374a2481b981f4..609408f87ae3650b825b0a9716aa83d9d30b1944 100644
--- a/modules/chain/tests/dap_chain_ledger_tests.c
+++ b/modules/chain/tests/dap_chain_ledger_tests.c
@@ -369,7 +369,7 @@ void dap_chain_ledger_test_run(void){
     dap_print_module_name("dap_chain_ledger");
     uint16_t l_flags = 0;
     l_flags |= DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION;
-    dap_ledger_t *l_ledger = dap_chain_ledger_create(l_flags, "Snet", s_token_ticker);
+    dap_ledger_t *l_ledger = dap_chain_ledger_create(l_flags, "Snet", s_token_ticker, NULL);
     char *l_seed_ph = "H58i9GJKbn91238937^#$t6cjdf";
     size_t l_seed_ph_size = strlen(l_seed_ph);
     dap_cert_t *l_cert = dap_cert_generate_mem_with_seed("testCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, l_seed_ph, l_seed_ph_size);
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
index a036d7a3a6b4750b2db25bc30f32cfe5ceaecbc3..1e330ae02de8bbcec498f6bd9aa1ff91669bb01c 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c
@@ -30,15 +30,15 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_hash.h"
 #include "rand/dap_rand.h"
 
-#include "dap_chain.h"
-#include "dap_chain_datum_tx.h"
-#include "dap_chain_datum_tx_in.h"
-#include "dap_chain_datum_tx_in_cond.h"
-#include "dap_chain_datum_tx_out.h"
-#include "dap_chain_datum_tx_out_cond.h"
-#include "dap_chain_datum_tx_receipt.h"
-#include "dap_chain_mempool.h"
-#include "dap_common.h"
+//#include "dap_chain.h"
+//#include "dap_chain_datum_tx.h"
+//#include "dap_chain_datum_tx_in.h"
+//#include "dap_chain_datum_tx_in_cond.h"
+//#include "dap_chain_datum_tx_out.h"
+//#include "dap_chain_datum_tx_out_cond.h"
+//#include "dap_chain_datum_tx_receipt.h"
+//#include "dap_chain_mempool.h"
+//#include "dap_common.h"
 
 #include "dap_chain_net_srv.h"
 #include "dap_chain_net_srv_stream_session.h"
@@ -54,6 +54,11 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 
 #define LOG_TAG "dap_stream_ch_chain_net_srv"
 
+typedef struct usages_in_grace{
+    dap_hash_fast_t tx_cond_hash;
+    dap_chain_net_srv_grace_t *grace;
+    UT_hash_handle hh;
+} usages_in_grace_t;
 
 uint8_t dap_stream_ch_chain_net_srv_get_id()
 {
@@ -65,6 +70,62 @@ static void s_stream_ch_delete(dap_stream_ch_t* ch , void* arg);
 static void s_stream_ch_packet_in(dap_stream_ch_t* ch , void* arg);
 static void s_stream_ch_packet_out(dap_stream_ch_t* ch , void* arg);
 
+static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item);
+
+static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size);
+static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace);
+static bool s_grace_period_finish(usages_in_grace_t *a_grace);
+
+static inline void s_grace_error(dap_chain_net_srv_grace_t *a_grace, dap_stream_ch_chain_net_srv_pkt_error_t a_err){
+    dap_stream_ch_t * l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
+    dap_chain_net_srv_stream_session_t *l_srv_session = l_ch && l_ch->stream && l_ch->stream->session ?
+                                        (dap_chain_net_srv_stream_session_t *)l_ch->stream->session->_inheritor : NULL;
+
+        a_grace->usage->is_grace = false;
+    if (a_grace->usage->receipt_next){ // If not first grace-period
+        log_it( L_WARNING, "Next receipt is rejected. Waiting until current limits is over.");
+        DAP_DEL_Z(a_grace->usage->receipt_next);
+        memset(&a_grace->usage->tx_cond_hash, 0, sizeof(a_grace->usage->tx_cond_hash));
+        DAP_DELETE(a_grace->request);
+        DAP_DELETE(a_grace);
+        return;
+    }
+
+    if (a_err.code) {
+        if(l_ch)
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &a_err, sizeof (a_err));
+        if (a_grace->usage->service && a_grace->usage->service->callbacks.response_error)
+            a_grace->usage->service->callbacks.response_error(a_grace->usage->service, 0, NULL, &a_err, sizeof(a_err));
+    }
+
+    if (a_grace->usage) {   // add client pkey hash to banlist
+        a_grace->usage->is_active = false;
+        if (a_grace->usage->service) {
+            dap_chain_net_srv_banlist_item_t *l_item = NULL;
+            pthread_mutex_lock(&a_grace->usage->service->banlist_mutex);
+            HASH_FIND(hh, a_grace->usage->service->ban_list, &a_grace->usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
+            if (l_item)
+                pthread_mutex_unlock(&a_grace->usage->service->banlist_mutex);
+            else {
+                l_item = DAP_NEW_Z(dap_chain_net_srv_banlist_item_t);
+                l_item->client_pkey_hash = a_grace->usage->client_pkey_hash;
+                l_item->ht_mutex = &a_grace->usage->service->banlist_mutex;
+                l_item->ht_head = &a_grace->usage->service->ban_list;
+                HASH_ADD(hh, a_grace->usage->service->ban_list, client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
+                pthread_mutex_unlock(&a_grace->usage->service->banlist_mutex);
+                dap_timerfd_start(a_grace->usage->service->grace_period * 1000, (dap_timerfd_callback_t)s_unban_client, l_item);
+            }
+        }
+
+    } else if (l_srv_session->usage_active)
+        dap_chain_net_srv_usage_delete(l_srv_session);
+    DAP_DELETE(a_grace->request);
+    DAP_DELETE(a_grace);
+}
+
+// TODO: move this to net_srv
+static usages_in_grace_t * s_grace_table = NULL;
+static pthread_mutex_t s_ht_grace_table_mutex;
 /**
  * @brief dap_stream_ch_chain_net_init
  * @return
@@ -73,6 +134,7 @@ int dap_stream_ch_chain_net_srv_init(void)
 {
     log_it(L_NOTICE,"Chain network services channel initialized");
     dap_stream_ch_proc_add(dap_stream_ch_chain_net_srv_get_id(),s_stream_ch_new,s_stream_ch_delete,s_stream_ch_packet_in,s_stream_ch_packet_out);
+    pthread_mutex_init(&s_ht_grace_table_mutex, NULL);
 
     return 0;
 }
@@ -105,7 +167,6 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch , void* arg)
         log_it(L_ERROR, "Session inheritor is already present!");
 
     dap_chain_net_srv_call_opened_all( a_ch);
-
 }
 
 
@@ -120,6 +181,8 @@ void s_stream_ch_delete(dap_stream_ch_t* a_ch , void* a_arg)
     (void) a_arg;
     log_it(L_DEBUG, "Stream ch chain net srv delete");
     dap_chain_net_srv_call_closed_all( a_ch);
+    if (a_ch->stream->session && a_ch->stream->session->_inheritor)
+        dap_chain_net_srv_stream_session_delete( a_ch->stream->session );
     DAP_DEL_Z(a_ch->internal);
 }
 
@@ -132,29 +195,41 @@ static bool s_unban_client(dap_chain_net_srv_banlist_item_t *a_item)
     return false;
 }
 
-static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
+void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx)
 {
-    assert(a_grace);
+    UNUSED(a_ledger);
+    UNUSED(a_arg);
+    // TODO: 1. Get net_srv by srv_uid from tx_cond
+    // 2. Get usages in grace HT from service
+    usages_in_grace_t *l_item = NULL;
+    dap_hash_fast_t tx_cond_hash = {};
+    dap_hash_fast((void*)a_tx, dap_chain_datum_tx_get_size(a_tx), &tx_cond_hash);
+    pthread_mutex_lock(&s_ht_grace_table_mutex);
+    HASH_FIND(hh, s_grace_table, &tx_cond_hash, sizeof(dap_hash_fast_t), l_item);
+    if (l_item){
+        log_it(L_INFO, "Found tx in ledger by notify. Finish grace.");
+        // Stop timer
+        dap_timerfd_delete_mt(l_item->grace->stream_worker->worker, l_item->grace->timer_es_uuid);
+        // finish grace
+        s_grace_period_finish(l_item);
+    }
+    pthread_mutex_unlock(&s_ht_grace_table_mutex);
+}
+
+static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_pkt_request_t * a_request, size_t a_request_size)
+{
+    assert(a_ch);
     dap_stream_ch_chain_net_srv_pkt_error_t l_err;
     memset(&l_err, 0, sizeof(l_err));
     dap_chain_net_srv_t * l_srv = NULL;
-    dap_chain_net_srv_usage_t *l_usage = NULL;
-    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
-
-    if (!l_ch)
-        goto free_exit;
 
-    dap_chain_net_srv_stream_session_t *l_srv_session = l_ch && l_ch->stream && l_ch->stream->session ?
-                                                        (dap_chain_net_srv_stream_session_t *)l_ch->stream->session->_inheritor : NULL;
-    if (!l_srv_session)
-        goto free_exit;
-
-    dap_stream_ch_chain_net_srv_pkt_request_t *l_request = a_grace->request;
-    l_srv = dap_chain_net_srv_get( l_request->hdr.srv_uid );
-    dap_chain_net_t * l_net = dap_chain_net_by_id( l_request->hdr.net_id );
+    dap_chain_net_srv_stream_session_t *l_srv_session = a_ch->stream && a_ch->stream->session ?
+                                                        (dap_chain_net_srv_stream_session_t *)a_ch->stream->session->_inheritor : NULL;
+    l_srv = dap_chain_net_srv_get( a_request->hdr.srv_uid );
+    dap_chain_net_t * l_net = dap_chain_net_by_id( a_request->hdr.net_id );
 
-    l_err.net_id.uint64 = l_request->hdr.net_id.uint64;
-    l_err.srv_uid.uint64 = l_request->hdr.srv_uid.uint64;
+    l_err.net_id.uint64 = a_request->hdr.net_id.uint64;
+    l_err.srv_uid.uint64 = a_request->hdr.srv_uid.uint64;
 
     if ( ! l_net ) // Network not found
         l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND;
@@ -162,83 +237,149 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
     if ( ! l_srv ) // Service not found
         l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND;
 
-    if ( l_err.code ){
-        goto free_exit;
+    if ( l_err.code || !l_srv_session){
+        if(a_ch)
+            dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+        if (l_srv && l_srv->callbacks.response_error)
+            l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err));
+        return;
     }
 
-    dap_ledger_t * l_ledger =l_net->pub.ledger;
+    dap_chain_net_srv_usage_t *l_usage = NULL;
+    l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, l_srv);
+    if ( !l_usage ){ // Usage can't add
+        log_it( L_WARNING, "Can't add usage");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE;
+        if(a_ch)
+            dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+        if (l_srv && l_srv->callbacks.response_error)
+            l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err));
+        return;
+    }
+
+    l_err.usage_id = l_usage->id;
+    // Create one client
+    l_usage->client = DAP_NEW_Z( dap_chain_net_srv_client_remote_t);
+    l_usage->client->stream_worker = a_ch->stream_worker;
+    l_usage->client->ch = a_ch;
+    l_usage->client->session_id = a_ch->stream->session->id;
+    l_usage->client->ts_created = time(NULL);
+    l_usage->tx_cond_hash = a_request->hdr.tx_cond;
+    l_usage->ts_created = time(NULL);
+    l_usage->net = l_net;
+    l_usage->service = l_srv;
+
+
+    dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
+    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, a_request_size);
+    memcpy(l_grace->request, a_request, a_request_size);
+    l_grace->request_size = a_request_size;
+    l_grace->ch_uuid = a_ch->uuid;
+    l_grace->stream_worker = a_ch->stream_worker;
+    l_grace->usage = l_usage;
+
+    if (l_srv->pricelist){
+        // not free service
+        s_grace_period_start(l_grace);
+    } else {
+        // Start service for free
+        log_it( L_INFO, "Service provide for free");
+        l_grace->usage->is_free = true;
+        size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t );
+        dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
+                                                                              l_success_size);
+        l_success->hdr.usage_id = l_usage->id;
+        l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64;
+        l_success->hdr.srv_uid.uint64 = l_usage->service->uid.uint64;
+        dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size);
+        if (l_usage->service->callbacks.response_success)
+            l_usage->service->callbacks.response_success(l_usage->service, l_usage->id,  l_usage->client, NULL, 0);
+        DAP_DELETE(l_success);
+    }
+    return;
+}
+
+static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace)
+{
+    assert(a_grace);
+    dap_stream_ch_chain_net_srv_pkt_error_t l_err;
+    memset(&l_err, 0, sizeof(l_err));
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_grace->stream_worker, a_grace->ch_uuid);
+
+    if (!l_ch){
+        s_grace_error(a_grace, l_err);
+        return;
+    }
+
+    dap_chain_net_t * l_net = a_grace->usage->net;
+
+    l_err.net_id.uint64 = l_net->pub.id.uint64;
+    l_err.srv_uid.uint64 = a_grace->usage->service->uid.uint64;
+
+    dap_ledger_t * l_ledger = l_net->pub.ledger;
     dap_chain_datum_tx_t * l_tx = NULL;
     dap_chain_tx_out_cond_t * l_tx_out_cond = NULL;
-    bool l_grace_start = false;
-    if (l_srv->pricelist ){ // Is present pricelist, not free service
+    dap_chain_net_srv_price_t * l_price = NULL;
+    if ( !l_ledger ){ // No ledger
+        log_it( L_WARNING, "No Ledger");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ;
+        s_grace_error(a_grace, l_err);
+        return;
+    }
 
-        if ( !l_ledger ){ // No ledger
-            log_it( L_WARNING, "No Ledger");
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ;
-            goto free_exit;
-        }
+    l_tx = a_grace->usage->is_waiting_new_tx_cond ? NULL : dap_chain_ledger_tx_find_by_hash(l_ledger, &a_grace->usage->tx_cond_hash);
+    if ( ! l_tx ){ // No tx cond transaction, start grace-period
+        a_grace->usage->is_grace = true;
 
-        l_tx = dap_chain_ledger_tx_find_by_hash( l_ledger,& l_request->hdr.tx_cond );
-        if ( ! l_tx ){ // No tx cond transaction
-            if (a_grace->usage) {   // marker for reentry to function
-                log_it( L_WARNING, "No tx cond transaction");
-                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ;
-                goto free_exit;
-            } else
-                l_grace_start = true;
-        }
-        if (!l_grace_start) {
-            int l_tx_out_cond_size =0;
-            l_tx_out_cond = (dap_chain_tx_out_cond_t *)
-                    dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size );
+        l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
+                        memcpy(l_price, a_grace->usage->service->pricelist, sizeof(*l_price));
 
-            if ( ! l_tx_out_cond ) { // No conditioned output
-                log_it( L_WARNING, "No conditioned output");
-                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
-                goto free_exit;
-            }
+        a_grace->usage->price = l_price;
 
-            // Check cond output if it equesl or not to request
-            if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, l_request->hdr.srv_uid)) {
-                log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X,
-                        l_tx_out_cond->header.srv_uid.uint64 );
-                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID  ;
-                goto free_exit;
-            }
+        if (!a_grace->usage->receipt){
+            a_grace->usage->receipt = dap_chain_net_srv_issue_receipt(a_grace->usage->service, a_grace->usage->price, NULL, 0);
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
+                                       a_grace->usage->receipt, a_grace->usage->receipt->size);
         }
-    }
-    if (!a_grace->usage) {
-        l_usage = dap_chain_net_srv_usage_add(l_srv_session, l_net, l_srv);
-        if ( !l_usage ){ // Usage can't add
-            log_it( L_WARNING, "Can't add usage");
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE;
-            goto free_exit;
+        usages_in_grace_t *l_item = DAP_NEW_Z_SIZE(usages_in_grace_t, sizeof(usages_in_grace_t));
+        l_item->grace = a_grace;
+        l_item->tx_cond_hash = a_grace->usage->tx_cond_hash;
+
+        pthread_mutex_lock(&s_ht_grace_table_mutex);
+        HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_item);
+        pthread_mutex_unlock(&s_ht_grace_table_mutex);
+        a_grace->timer_es_uuid = dap_timerfd_start_on_worker(a_grace->stream_worker->worker, a_grace->usage->service->grace_period * 1000,
+                                                             (dap_timerfd_callback_t)s_grace_period_finish, l_item)->esocket_uuid;
+
+
+    } else { // Start srvice in normal pay mode
+        a_grace->usage->tx_cond = l_tx;
+
+        l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL );
+
+        if ( ! l_tx_out_cond ) { // No conditioned output
+            log_it( L_WARNING, "No conditioned output");
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
+            s_grace_error(a_grace, l_err);
+            return;
         }
 
-        l_err.usage_id = l_usage->id;
+        // Check cond output if it equesl or not to request
+        if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, a_grace->usage->service->uid)) {
+            log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X,
+                    l_tx_out_cond->header.srv_uid.uint64 );
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID  ;
+            s_grace_error(a_grace, l_err);
+            return;
+        }
 
-        // Create one client
-        l_usage->client = DAP_NEW_Z( dap_chain_net_srv_client_remote_t);
-        l_usage->client->stream_worker = l_ch->stream_worker;
-        l_usage->client->ch = l_ch;
-        l_usage->client->session_id = l_ch->stream->session->id;
-        l_usage->client->ts_created = time(NULL);
-        l_usage->tx_cond = l_tx;
-        l_usage->tx_cond_hash = l_request->hdr.tx_cond;
-        l_usage->ts_created = time(NULL);
-    } else {
-        l_usage = a_grace->usage;
-        l_usage->tx_cond = l_tx;
-    }
-    dap_chain_net_srv_price_t * l_price = NULL;
-    const char * l_ticker = NULL;
-    if (l_srv->pricelist && !l_grace_start) {
-        l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_request->hdr.tx_cond );
-        dap_stpcpy(l_usage->token_ticker, l_ticker);
+        const char * l_ticker = NULL;
+        l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &a_grace->usage->tx_cond_hash);
+        dap_stpcpy(a_grace->usage->token_ticker, l_ticker);
 
         dap_chain_net_srv_price_t *l_price_tmp;
-        DL_FOREACH(l_srv->pricelist, l_price_tmp) {
-            if (l_price_tmp->net->pub.id.uint64                 == l_request->hdr.net_id.uint64
+        DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) {
+            if (l_price_tmp && l_price_tmp->net->pub.id.uint64  == a_grace->usage->net->pub.id.uint64
                 && dap_strcmp(l_price_tmp->token, l_ticker)     == 0
                 && l_price_tmp->units_uid.enm                   == l_tx_out_cond->subtype.srv_pay.unit.enm
                 )//&& (l_price_tmp->value_datoshi/l_price_tmp->units)  < l_tx_out_cond->subtype.srv_pay.header.unit_price_max_datoshi)
@@ -251,102 +392,231 @@ static bool s_grace_period_control(dap_chain_net_srv_grace_t *a_grace)
             log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s",
                     l_ticker, l_net->pub.name );
             l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
-            goto free_exit;
+            s_grace_error(a_grace, l_err);
+            return;
+        }
+        a_grace->usage->price = l_price;
+        int ret;
+        if ((ret = a_grace->usage->service->callbacks.requested(a_grace->usage->service, a_grace->usage->id, a_grace->usage->client, a_grace->request, a_grace->request_size)) != 0) {
+            log_it( L_WARNING, "Request canceled by service callback, return code %d", ret);
+            l_err.code = (uint32_t) ret ;
+            s_grace_error(a_grace, l_err);
+            return;
         }
-    }
-    int ret;
-    if ((ret = l_srv->callbacks.requested(l_srv, l_usage->id, l_usage->client, l_request, a_grace->request_size)) != 0) {
-        log_it( L_WARNING, "Request canceled by service callback, return code %d", ret);
-        l_err.code = (uint32_t) ret ;
-        goto free_exit;
-    }
 
-    if ( l_srv->pricelist) {
-        if (l_price || l_grace_start) {
-            if (l_price) {
-                if (a_grace->usage) {
-                    DAP_DELETE(l_usage->price);
-                }
-            } else {
-                l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
-                memcpy(l_price, l_srv->pricelist, sizeof(*l_price));
-                l_price->value_datoshi = uint256_0;
-            }
-            l_usage->price = l_price;
-            if (l_usage->receipt_next){
-                DAP_DEL_Z(l_usage->receipt_next);
-                l_usage->receipt_next = dap_chain_net_srv_issue_receipt(l_usage->service, l_usage->price, NULL, 0);
-            }else{
-                dap_chain_net_srv_price_t l_b_price = *l_usage->price;
-                if (l_grace_start || a_grace->usage){
-                    l_b_price.units *= 2;
-                    MULT_256_256(l_b_price.value_datoshi, GET_256_FROM_64((uint64_t)2), &l_b_price.value_datoshi);
-                }
-                l_usage->receipt = dap_chain_net_srv_issue_receipt(l_usage->service, &l_b_price, NULL, 0);
-                dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
-                                           l_usage->receipt, l_usage->receipt->size);
-            }
+        if (a_grace->usage->receipt_next){
+            DAP_DEL_Z(a_grace->usage->receipt_next);
+            a_grace->usage->receipt_next = dap_chain_net_srv_issue_receipt(a_grace->usage->service, a_grace->usage->price, NULL, 0);
         }else{
-            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_PRICE_NOT_FOUND ;
-            goto free_exit;
+            a_grace->usage->receipt = dap_chain_net_srv_issue_receipt(a_grace->usage->service, a_grace->usage->price, NULL, 0);
+            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_REQUEST,
+                                       a_grace->usage->receipt, a_grace->usage->receipt->size);
         }
-    // If we a here we passed all the checks, wow, now if we're not for free we request the signature.
-    } else{
-        log_it( L_INFO, "Service provide for free");
-        l_usage->is_free = true;
-        size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t );
-        dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
-                                                                              l_success_size);
-        l_success->hdr.usage_id = l_usage->id;
-        l_success->hdr.net_id.uint64 = l_usage->net->pub.id.uint64;
-        l_success->hdr.srv_uid.uint64 = l_usage->service->uid.uint64;
-        dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_SUCCESS, l_success, l_success_size);
-        if (l_usage->service->callbacks.response_success)
-            l_usage->service->callbacks.response_success(l_usage->service, l_usage->id,  l_usage->client, NULL, 0);
-        DAP_DELETE(l_success);
-    }
-    if (l_grace_start) {
-        l_usage->is_grace = true;
-        a_grace->usage = l_usage;
-        dap_timerfd_start_on_worker(a_grace->stream_worker->worker, l_srv->grace_period * 1000,
-                                    (dap_timerfd_callback_t)s_grace_period_control, a_grace);
-        return false;
-    } else {
         DAP_DELETE(a_grace->request);
         DAP_DELETE(a_grace);
-        l_usage->is_grace = false;
+
+    }
+}
+
+static bool s_grace_period_finish(usages_in_grace_t *a_grace_item)
+{
+    assert(a_grace_item);
+    dap_stream_ch_chain_net_srv_pkt_error_t l_err;
+    memset(&l_err, 0, sizeof(l_err));
+    dap_chain_net_srv_grace_t *l_grace = a_grace_item->grace;
+
+    dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(l_grace->stream_worker, l_grace->ch_uuid);
+
+    if (l_grace->usage->price && !l_grace->usage->receipt_next){ // if first grace delete price and set actual
+        DAP_DEL_Z(l_grace->usage->price);
+    }
+
+    if (!l_ch){
+        s_grace_error(l_grace, l_err);
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
         return false;
     }
-free_exit:
-    if (l_err.code) {
-        if(l_ch)
-            dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
-        if (l_srv && l_srv->callbacks.response_error)
-            l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err));
+
+    if (l_grace->usage->is_waiting_new_tx_cond){
+        log_it(L_INFO, "No new tx cond!");
+        s_grace_error(l_grace, l_err);
+        l_grace->usage->is_waiting_new_tx_cond = false;
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
+        return false;
     }
-    if (a_grace->usage) {   // add client pkey hash to banlist
-        a_grace->usage->is_active = false;
-        if (l_srv) {
-            dap_chain_net_srv_banlist_item_t *l_item = NULL;
-            pthread_mutex_lock(&l_srv->banlist_mutex);
-            HASH_FIND(hh, l_srv->ban_list, &a_grace->usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-            if (l_item)
-                pthread_mutex_unlock(&l_srv->banlist_mutex);
-            else {
-                l_item = DAP_NEW_Z(dap_chain_net_srv_banlist_item_t);
-                l_item->client_pkey_hash = a_grace->usage->client_pkey_hash;
-                l_item->ht_mutex = &l_srv->banlist_mutex;
-                l_item->ht_head = &l_srv->ban_list;
-                HASH_ADD(hh, l_srv->ban_list, client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
-                pthread_mutex_unlock(&l_srv->banlist_mutex);
-                dap_timerfd_start(l_srv->grace_period * 1000, (dap_timerfd_callback_t)s_unban_client, l_item);
+
+    dap_chain_net_t * l_net = l_grace->usage->net;
+
+    l_err.net_id.uint64 = l_net->pub.id.uint64;
+    l_err.srv_uid.uint64 = l_grace->usage->service->uid.uint64;
+
+    dap_ledger_t * l_ledger = l_net->pub.ledger;
+    dap_chain_datum_tx_t * l_tx = NULL;
+    dap_chain_tx_out_cond_t * l_tx_out_cond = NULL;
+
+    if ( !l_ledger ){ // No ledger
+        log_it( L_WARNING, "No Ledger");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER ;
+        s_grace_error(l_grace, l_err);
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
+        return false;
+    }
+    log_it(L_INFO, "Grace period is over! Check tx in ledger.");
+    l_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &l_grace->usage->tx_cond_hash);
+    if ( ! l_tx ){ // No tx cond transaction, start grace-period
+        log_it( L_WARNING, "No tx cond transaction");
+        l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND ;
+        s_grace_error(l_grace, l_err);
+        HASH_DEL(s_grace_table, a_grace_item);
+        DAP_DEL_Z(a_grace_item);
+        return false;
+    } else { // Start srvice in normal pay mode
+        log_it(L_INFO, "Tx is found in ledger.");
+        l_grace->usage->tx_cond = l_tx;
+
+        l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL );
+
+        if ( ! l_tx_out_cond ) { // No conditioned output
+            log_it( L_WARNING, "No conditioned output");
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        // Check cond output if it equesl or not to request
+        if (!dap_chain_net_srv_uid_compare(l_tx_out_cond->header.srv_uid, l_grace->usage->service->uid)) {
+            log_it( L_WARNING, "Wrong service uid in request, tx expect to close its output with 0x%016"DAP_UINT64_FORMAT_X,
+                   l_tx_out_cond->header.srv_uid.uint64 );
+            l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_WRONG_SRV_UID  ;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        dap_chain_net_srv_price_t * l_price = NULL;
+        const char * l_ticker = NULL;
+        l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_grace->usage->tx_cond_hash);
+        dap_stpcpy(l_grace->usage->token_ticker, l_ticker);
+
+        dap_chain_net_srv_price_t *l_price_tmp;
+        DL_FOREACH(l_grace->usage->service->pricelist, l_price_tmp) {
+            if (l_price_tmp && l_price_tmp->net->pub.id.uint64                 == l_grace->usage->net->pub.id.uint64
+                && dap_strcmp(l_price_tmp->token, l_ticker)     == 0
+                && l_price_tmp->units_uid.enm                   == l_tx_out_cond->subtype.srv_pay.unit.enm
+                )//&& (l_price_tmp->value_datoshi/l_price_tmp->units)  < l_tx_out_cond->subtype.srv_pay.header.unit_price_max_datoshi)
+            {
+                l_price = l_price_tmp;
+                break;
+            }
+        }
+        if ( !l_price ) {
+            log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s",
+                   l_ticker, l_net->pub.name );
+            l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        l_grace->usage->price = l_price;
+
+        int ret;
+        if ((ret = l_grace->usage->service->callbacks.requested(l_grace->usage->service, l_grace->usage->id, l_grace->usage->client, l_grace->request, l_grace->request_size)) != 0) {
+            log_it( L_WARNING, "Request canceled by service callback, return code %d", ret);
+            l_err.code = (uint32_t) ret ;
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+
+        // make receipt or tx
+        char *l_receipt_hash_str;
+        dap_chain_datum_tx_receipt_t *l_receipt = NULL;
+        if (l_grace->usage->receipt_next){
+            l_receipt = l_grace->usage->receipt_next;
+        } else if (l_grace->usage->receipt){
+            l_receipt = l_grace->usage->receipt;
+        } else {
+            // Send error???
+        }
+        size_t l_receipt_size = l_receipt->size;
+
+        // get a second signature - from the client (first sign in server, second sign in client)
+        dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( l_receipt, l_receipt_size, 1);
+        if ( ! l_receipt_sign ){
+            log_it(L_WARNING, "Tx already in chain, but receipt is not signed by client. Finish grace and wait receipt sign responce.");
+            s_grace_error(l_grace, l_err);
+            HASH_DEL(s_grace_table, a_grace_item);
+            DAP_DEL_Z(a_grace_item);
+            return false;
+        }
+        dap_get_data_hash_str_static(l_receipt, l_receipt_size, l_receipt_hash_str);
+        dap_global_db_set("local.receipts", l_receipt_hash_str, l_receipt, l_receipt_size, false, NULL, NULL);
+            // Form input transaction
+        char *l_hash_str = dap_hash_fast_to_str_new(&l_grace->usage->tx_cond_hash);
+        log_it(L_NOTICE, "Trying create input tx cond from tx %s with active receipt", l_hash_str);
+        DAP_DEL_Z(l_hash_str);
+        dap_chain_addr_t *l_wallet_addr = dap_chain_wallet_get_addr(l_grace->usage->price->wallet, l_grace->usage->net->pub.id);
+        int ret_status = 0;
+        char *l_tx_in_hash_str = dap_chain_mempool_tx_create_cond_input(l_grace->usage->net, &l_grace->usage->tx_cond_hash, l_wallet_addr,
+                                                                        dap_chain_wallet_get_key(l_grace->usage->price->wallet, 0),
+                                                                        l_receipt, "hex", &ret_status);
+        DAP_DEL_Z(l_wallet_addr);
+        if (!ret_status) {
+            dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_grace->usage->tx_cond_hash);
+            log_it(L_NOTICE, "Formed tx %s for input with active receipt", l_tx_in_hash_str);
+            DAP_DELETE(l_tx_in_hash_str);
+
+        }else{
+            if(ret_status == DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH){
+//                memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash));
+//                DAP_DEL_Z(l_grace->usage->receipt_next);
+                log_it(L_ERROR, "Tx cond have not enough funds");
+                dap_chain_net_srv_grace_t* l_grace_new = DAP_NEW_Z(dap_chain_net_srv_grace_t);
+                // Parse the request
+                l_grace_new->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
+                l_grace_new->request->hdr.net_id = a_grace_item->grace->usage->net->pub.id;
+                memcpy(l_grace_new->request->hdr.token, a_grace_item->grace->usage->token_ticker, strlen(a_grace_item->grace->usage->token_ticker));
+                l_grace_new->request->hdr.srv_uid = a_grace_item->grace->usage->service->uid;
+                l_grace_new->request->hdr.tx_cond = a_grace_item->grace->usage->tx_cond_hash;
+                l_grace_new->request_size = sizeof(dap_stream_ch_chain_net_srv_pkt_request_t);
+                l_grace_new->ch_uuid = a_grace_item->grace->usage->client->ch->uuid;
+                l_grace_new->stream_worker = a_grace_item->grace->usage->client->ch->stream_worker;
+                l_grace_new->usage = a_grace_item->grace->usage;
+                l_grace_new->usage->is_waiting_new_tx_cond = true;
+                s_grace_period_start(l_grace_new);
+
+                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH;
+                dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+
+            }else{
+                log_it(L_ERROR, "Can't create input tx cond transaction!");
+                memset(&l_grace->usage->tx_cond_hash, 0, sizeof(l_grace->usage->tx_cond_hash));
+                if (l_grace->usage->receipt_next){
+                    DAP_DEL_Z(l_grace->usage->receipt_next);
+                } else if (l_grace->usage->receipt){
+                    DAP_DEL_Z(l_grace->usage->receipt);
+                }
+                l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND;
+                dap_stream_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
+                if (l_grace->usage->service->callbacks.response_error)
+                    l_grace->usage->service->callbacks.response_error(l_grace->usage->service,l_grace->usage->id, l_grace->usage->client,&l_err,sizeof (l_err));
             }
         }
     }
-    else if (l_usage)
-        dap_chain_net_srv_usage_delete(l_srv_session, l_usage);
-    DAP_DELETE(a_grace->request);
-    DAP_DELETE(a_grace);
+    l_grace->usage->is_grace = false;
+    DAP_DELETE(a_grace_item->grace->request);
+    DAP_DEL_Z(a_grace_item->grace);
+    HASH_DEL(s_grace_table, a_grace_item);
+    DAP_DEL_Z(a_grace_item);
     return false;
 }
 
@@ -434,26 +704,27 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
             log_it( L_WARNING, "Wrong request size, less than minimum");
             break;
         }
-        dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
-        // Parse the request
-        l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.data_size);
-        memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.data_size);
-        l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
-        l_grace->request_size = l_ch_pkt->hdr.data_size;
-        l_grace->ch_uuid = a_ch->uuid;
-        l_grace->stream_worker = a_ch->stream_worker;
-        s_grace_period_control(l_grace);
+        dap_stream_ch_chain_net_srv_pkt_request_t *l_request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.data_size);
+        memcpy(l_request, l_ch_pkt->data, l_ch_pkt->hdr.data_size);
+        l_ch_chain_net_srv->srv_uid.uint64 = l_request->hdr.srv_uid.uint64;
+        s_service_start(a_ch, l_request, l_ch_pkt->hdr.data_size);
     } break; /* DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST */
 
     case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: { // Check receipt sign and make tx if success
-         if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) {
+        dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active;
+        if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) {
             log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.data_size,
                    sizeof(dap_chain_receipt_info_t));
+            if ( l_usage->receipt_next ){ // If we have receipt next
+                DAP_DEL_Z(l_usage->receipt_next);
+            }else if (l_usage->receipt ){ // If we sign first receipt
+                DAP_DEL_Z(l_usage->receipt);
+            }
             break;
         }
         dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data;
         size_t l_receipt_size = l_ch_pkt->hdr.data_size;
-        dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active;
+
         bool l_is_found = false;
         if ( l_usage->receipt_next ){ // If we have receipt next
             if ( memcmp(&l_usage->receipt_next->receipt_info, &l_receipt->receipt_info,sizeof (l_receipt->receipt_info) )==0 ){
@@ -488,9 +759,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                                                                   &l_err, sizeof (l_err) );
                 break;
             }
-            int l_tx_out_cond_size =0;
-            l_tx_out_cond = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_usage->tx_cond, NULL,
-                                                                                   TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size );
+            l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_usage->tx_cond, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL );
             if ( ! l_tx_out_cond ){ // No conditioned output
                 l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT ;
                 dap_stream_ch_pkt_write_unsafe( a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err) );
@@ -519,6 +788,19 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
             HASH_FIND(hh, l_srv->ban_list, &l_usage->client_pkey_hash, sizeof(dap_chain_hash_fast_t), l_item);
             pthread_mutex_unlock(&l_srv->banlist_mutex);
             if (l_item) {   // client banned
+                    log_it(L_INFO, "Client pkey is banned!");
+                    usages_in_grace_t *l_grace_item = NULL;
+                    pthread_mutex_lock(&s_ht_grace_table_mutex);
+                    HASH_FIND(hh, s_grace_table, &l_usage->tx_cond_hash, sizeof(dap_hash_fast_t), l_grace_item);
+                    if (l_grace_item){
+                        // Stop timer
+                        dap_timerfd_delete_mt(l_grace_item->grace->stream_worker->worker, l_grace_item->grace->timer_es_uuid);
+                        // finish grace
+                        HASH_DEL(s_grace_table, l_grace_item);
+                        DAP_DEL_Z(l_grace_item);
+
+                    }
+                    pthread_mutex_unlock(&s_ht_grace_table_mutex);
                     l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_RECEIPT_BANNED_PKEY_HASH ;
                     dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err));
                     if (l_usage->service->callbacks.response_error)
@@ -538,13 +820,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
         // Update actual receipt
         bool l_is_first_sign = false;
         if (! l_usage->receipt_next && l_usage->receipt){
-            DAP_DELETE(l_usage->receipt);
+            DAP_DEL_Z(l_usage->receipt);
             l_usage->receipt = DAP_NEW_SIZE(dap_chain_datum_tx_receipt_t,l_receipt_size);
             l_is_first_sign = true;
             l_usage->is_active = true;
             memcpy( l_usage->receipt, l_receipt, l_receipt_size);
         } else if (l_usage->receipt_next ){
-            DAP_DELETE(l_usage->receipt_next);
+            DAP_DEL_Z(l_usage->receipt_next);
             l_usage->receipt_next = DAP_NEW_SIZE(dap_chain_datum_tx_receipt_t,l_receipt_size);
             l_usage->is_active = true;
             memcpy( l_usage->receipt_next, l_receipt, l_receipt_size);
@@ -579,26 +861,41 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                     l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
                     UNUSED(l_grace);
                     // Parse the request
-//                    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
-//                    l_grace->request->hdr.net_id = l_usage->net->pub.id;
-//                    memcpy(l_grace->request->hdr.token, l_usage->token_ticker, strlen(l_usage->token_ticker));
-//                    l_grace->request->hdr.srv_uid = l_usage->service->uid;
-//                    l_grace->request->hdr.tx_cond = l_usage->tx_cond_hash;
-//                    l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
-//                    l_grace->request_size = l_ch_pkt->hdr.data_size;
-//                    l_grace->ch_uuid = a_ch->uuid;
-//                    l_grace->stream_worker = a_ch->stream_worker;
-//                    s_grace_period_control(l_grace);
+                    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
+                    l_grace->request->hdr.net_id = l_usage->net->pub.id;
+                    memcpy(l_grace->request->hdr.token, l_usage->token_ticker, strlen(l_usage->token_ticker));
+                    l_grace->request->hdr.srv_uid = l_usage->service->uid;
+                    l_grace->request->hdr.tx_cond = l_usage->tx_cond_hash;
+                    l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
+                    l_grace->request_size = l_ch_pkt->hdr.data_size;
+                    l_grace->ch_uuid = a_ch->uuid;
+                    l_grace->stream_worker = a_ch->stream_worker;
+                    l_grace->usage = l_usage;
+                    s_grace_period_start(l_grace);
+                    DAP_DELETE(l_tx_in_hash_str);
                     break;
                 case DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_ENOUGH:
                     // TODO send new tx cond request
-                    memset(&l_usage->tx_cond_hash, 0, sizeof(l_usage->tx_cond_hash));
-                    DAP_DEL_Z(l_usage->receipt_next);
                     log_it(L_ERROR, "Tx cond have not enough funds");
+                    l_usage->is_waiting_new_tx_cond = true;
+                    l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
+                    // Parse the request
+                    l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, sizeof(dap_stream_ch_chain_net_srv_pkt_request_t));
+                    l_grace->request->hdr.net_id = l_usage->net->pub.id;
+                    memcpy(l_grace->request->hdr.token, l_usage->token_ticker, strlen(l_usage->token_ticker));
+                    l_grace->request->hdr.srv_uid = l_usage->service->uid;
+                    l_grace->request->hdr.tx_cond = l_usage->tx_cond_hash;
+                    l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
+                    l_grace->request_size = l_ch_pkt->hdr.data_size;
+                    l_grace->ch_uuid = a_ch->uuid;
+                    l_grace->stream_worker = a_ch->stream_worker;
+                    l_grace->usage = l_usage;
+                    s_grace_period_start(l_grace);
                     l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ENOUGH;
                     dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
-//                    if (l_usage->service->callbacks.response_error)
-//                            l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err));
+                    if (l_usage->service->callbacks.response_error)
+                            l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err));
+                    DAP_DELETE(l_tx_in_hash_str);
                     break;
                 case DAP_CHAIN_MEMPOOL_RET_STATUS_BAD_ARGUMENTS:
                 case DAP_CHAIN_MEMPOOl_RET_STATUS_WRONG_ADDR:
@@ -614,16 +911,17 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
                     dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err));
                     if (l_usage->service->callbacks.response_error)
                             l_usage->service->callbacks.response_error(l_usage->service,l_usage->id, l_usage->client,&l_err,sizeof (l_err));
+                    DAP_DELETE(l_tx_in_hash_str);
                     break;
                 }
-
-
-                break;
+                if (!l_usage->is_grace)
+                    break;
             }
             l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t) + DAP_CHAIN_HASH_FAST_STR_SIZE;//sizeof(dap_chain_hash_fast_t);
         } else {
             l_success_size = sizeof(dap_stream_ch_chain_net_srv_pkt_success_hdr_t);
         }
+
         dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_STACK_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
                                                                               l_success_size);
         memset(&l_success->hdr, 0, sizeof(l_success->hdr));
@@ -634,8 +932,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
 
         if (l_usage->is_grace){
             char *l_hash_str = dap_hash_fast_to_str_new(&l_usage->tx_cond_hash);
-            log_it(L_NOTICE, "Receipt is OK, but transaction %s can't be found. Start the grace period for %d seconds", l_hash_str,
-                   l_srv->grace_period);
+                log_it(L_NOTICE, "Receipt is OK, but tx transaction %s %s. Start the grace period for %d seconds", l_hash_str,
+                       l_usage->is_waiting_new_tx_cond ? "have no enough funds. New tx cond requested": "can't be found",
+                       l_srv->grace_period);
             DAP_DEL_Z(l_hash_str);
         }else {
             char *l_hash_str = dap_hash_fast_to_str_new(&l_usage->tx_cond_hash);
@@ -708,10 +1007,56 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
         dap_chain_net_srv_usage_t * l_usage = NULL;
         l_usage = l_srv_session->usage_active;
         dap_stream_ch_chain_net_srv_pkt_request_t* l_responce = (dap_stream_ch_chain_net_srv_pkt_request_t*)l_ch_pkt->data;
-        l_usage->tx_cond_hash = l_responce->hdr.tx_cond;
-        char *l_tx_in_hash_str = dap_chain_hash_fast_to_str_new(&l_usage->tx_cond_hash);
+
+        char *l_tx_in_hash_str = dap_chain_hash_fast_to_str_new(&l_responce->hdr.tx_cond);
         log_it(L_NOTICE, "Received new tx cond %s", l_tx_in_hash_str);
         DAP_DELETE(l_tx_in_hash_str);
+
+        if(!l_usage->is_waiting_new_tx_cond || !l_usage->is_grace)
+            break;
+
+        l_usage->is_waiting_new_tx_cond = false;
+        dap_stream_ch_chain_net_srv_pkt_error_t l_err = { };
+        usages_in_grace_t *l_curr_grace_item = NULL;
+        pthread_mutex_lock(&s_ht_grace_table_mutex);
+        HASH_FIND(hh, s_grace_table, &l_usage->tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item);
+        pthread_mutex_unlock(&s_ht_grace_table_mutex);
+
+        if (dap_hash_fast_is_blank(&l_responce->hdr.tx_cond)){ //if new tx cond creation failed tx_cond in responce will be blank
+            if (l_curr_grace_item){
+                HASH_DEL(s_grace_table, l_curr_grace_item);
+                dap_timerfd_delete_mt(l_curr_grace_item->grace->stream_worker->worker, l_curr_grace_item->grace->timer_es_uuid);
+                s_grace_error(l_curr_grace_item->grace, l_err);
+                DAP_DEL_Z(l_curr_grace_item);
+            }
+            break;
+        }
+
+        dap_chain_datum_tx_t *l_tx = dap_chain_ledger_tx_find_by_hash(l_usage->net->pub.ledger, &l_responce->hdr.tx_cond);
+        if (l_tx){
+            // Replace
+            if (l_curr_grace_item){
+                log_it(L_INFO, "Found tx in ledger by net tx responce handler. Finish waiting new tx grace period.");
+                // Stop timer
+                dap_timerfd_delete_mt(l_curr_grace_item->grace->stream_worker->worker, l_curr_grace_item->grace->timer_es_uuid);
+                // finish grace
+                l_usage->tx_cond_hash = l_responce->hdr.tx_cond;
+                l_curr_grace_item->grace->request->hdr.tx_cond = l_responce->hdr.tx_cond;
+                s_grace_period_finish(l_curr_grace_item);
+            }
+        }else{
+            if (l_curr_grace_item){
+                l_curr_grace_item->grace->usage->tx_cond_hash = l_responce->hdr.tx_cond;
+                l_curr_grace_item->grace->request->hdr.tx_cond = l_responce->hdr.tx_cond;
+                pthread_mutex_lock(&s_ht_grace_table_mutex);
+                HASH_DEL(s_grace_table, l_curr_grace_item);
+                l_curr_grace_item->tx_cond_hash = l_responce->hdr.tx_cond;
+                HASH_ADD(hh, s_grace_table, tx_cond_hash, sizeof(dap_hash_fast_t), l_curr_grace_item);
+                pthread_mutex_unlock(&s_ht_grace_table_mutex);
+            }
+        }
+
+
         size_t l_success_size = sizeof (dap_stream_ch_chain_net_srv_pkt_success_hdr_t );
         dap_stream_ch_chain_net_srv_pkt_success_t *l_success = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_success_t,
                                                                               l_success_size);
diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
index 53490cc0c59594dc5215bceb4549146935108c6c..649a749c21f00447d3b8d18b9f27801043aa0b1c 100644
--- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
+++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.h
@@ -29,6 +29,16 @@
 #include "dap_stream_ch_pkt.h"
 #include "dap_chain_common.h"
 
+#include "dap_chain.h"
+#include "dap_chain_datum_tx.h"
+#include "dap_chain_datum_tx_in.h"
+#include "dap_chain_datum_tx_in_cond.h"
+#include "dap_chain_datum_tx_out.h"
+#include "dap_chain_datum_tx_out_cond.h"
+#include "dap_chain_datum_tx_receipt.h"
+#include "dap_chain_mempool.h"
+#include "dap_common.h"
+
 typedef struct dap_stream_ch_chain_net_srv dap_stream_ch_chain_net_srv_t;
 
 typedef void (*dap_stream_ch_chain_net_srv_callback_packet_t)(dap_stream_ch_chain_net_srv_t *, uint8_t,
@@ -46,3 +56,5 @@ typedef struct dap_stream_ch_chain_net_srv {
 
 uint8_t dap_stream_ch_chain_net_srv_get_id();
 int dap_stream_ch_chain_net_srv_init(void);
+
+void dap_stream_ch_chain_net_srv_tx_cond_added_cb(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx);
diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c
index 85ba2f81e1866c5072f607ad2e5b7a7a95dd2725..da1d49c44ec4be0d65da832d52821cd1d2f4f178 100644
--- a/modules/channel/chain-net/dap_stream_ch_chain_net.c
+++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c
@@ -173,6 +173,11 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
     HASH_FIND_INT(s_chain_net_data, &a_ch->stream->session->id, l_sdata);
     if(l_sdata == NULL) {
         l_sdata = DAP_NEW_Z(dap_chain_net_session_data_t);
+        if (!l_sdata) {
+            log_it(L_ERROR, "Memory allocation error in s_stream_ch_new");
+            pthread_mutex_unlock(&s_hash_mutex);
+            return;
+        }
         l_sdata->session_id = a_ch->stream->session->id;
         HASH_ADD_INT(s_chain_net_data, session_id, l_sdata);
     }
diff --git a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
index 5077f939c05e85147746d05df1c1b02b64d5f18a..a2b39e60f256b368a51e288693b72af953e88257 100644
--- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
+++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c
@@ -105,6 +105,10 @@ void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_
             l_node_client->client->always_reconnect = true;
 
             l_node_client_item = DAP_NEW_Z(struct voting_node_client_list);
+            if (!l_node_client_item) {
+                log_it(L_ERROR, "Memory allocation error in dap_stream_ch_chain_voting_message_write");
+                return;
+            }
             l_node_client_item->node_addr = *a_remote_node_addr;
             l_node_client_item->node_info = l_node_info;
             l_node_client_item->node_client = l_node_client;
diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c
index 9f1f329765bf1ad6f8d5ac9f2c5dc07b74e12afe..47f8fc81c08ebc55bf1c3e736bf593936384ea8b 100644
--- a/modules/channel/chain/dap_stream_ch_chain.c
+++ b/modules/channel/chain/dap_stream_ch_chain.c
@@ -645,40 +645,6 @@ static void s_gdb_sync_tsd_worker_callback(dap_worker_t *a_worker, void *a_arg)
     DAP_DELETE(l_sync_request);
 }
 
-/**
- * @brief
- *
- * @param net_id
- * @param group_name
- * @return dap_chain_t*
- */
-dap_chain_t *dap_chain_get_chain_from_group_name(dap_chain_net_id_t a_net_id, const char *a_group_name)
-{
-    if (!a_group_name) {
-        log_it(L_ERROR, "GDB group name is NULL ");
-        return NULL;
-    }
-    dap_chain_net_t *l_net = dap_chain_net_by_id(a_net_id);
-    if (!l_net)
-        return NULL;
-    dap_chain_t *l_chain = NULL;
-    DL_FOREACH(l_net->pub.chains, l_chain) {
-        char *l_chain_group_name = dap_chain_net_get_gdb_group_from_chain_new(l_chain);
-        if (!strcmp(a_group_name, l_chain_group_name)) {
-            DAP_DELETE(l_chain_group_name);
-            return l_chain;
-        }
-        DAP_DELETE(l_chain_group_name);
-    }
-    return NULL;
-}
-
-struct gdb_apply_args {
-    dap_store_obj_t *obj;
-    dap_nanotime_t limit_time;
-    struct sync_request *sync_request;
-};
-
 /**
  * @brief s_gdb_in_pkt_proc_callback_get_ts_callback
  * @param a_global_db_context
@@ -691,82 +657,7 @@ struct gdb_apply_args {
  * @param a_is_pinned
  * @param a_arg
  */
-static void s_gdb_in_pkt_proc_callback_apply(dap_global_db_context_t *a_global_db_context, void *a_arg)
-{
-    UNUSED(a_global_db_context);
-    struct gdb_apply_args *l_args = a_arg;
-    dap_store_obj_t *l_obj = l_args->obj;
-    struct sync_request *l_sync_request = l_args->sync_request;
-    // timestamp for exist obj
-    dap_nanotime_t l_timestamp_cur = 0;
-    // Record is pinned or not
-    bool l_is_pinned_cur = false;
-    if (dap_global_db_driver_is(l_obj->group, l_obj->key)) {
-        dap_store_obj_t *l_read_obj = dap_global_db_driver_read(l_obj->group, l_obj->key, NULL);
-        if (l_read_obj) {
-            l_timestamp_cur = l_read_obj->timestamp;
-            l_is_pinned_cur = l_read_obj->flags & RECORD_PINNED;
-            dap_store_obj_free_one(l_read_obj);
-        }
-    }
-    // Do not overwrite pinned records
-    if (l_is_pinned_cur) {
-        debug_if(s_debug_more, L_WARNING, "Can't %s record from group %s key %s - current record is pinned",
-                                l_obj->type != DAP_DB$K_OPTYPE_DEL ? "remove" : "rewrite", l_obj->group, l_obj->key);
-        goto ret;
-    }
-    // Deleted time
-    dap_nanotime_t l_timestamp_del = dap_global_db_get_del_ts_unsafe(a_global_db_context, l_obj->group, l_obj->key);
-    // Limit time
-    dap_nanotime_t l_limit_time = l_args->limit_time;
-    //check whether to apply the received data into the database
-    bool l_apply = false;
-    // check the applied object newer that we have stored or erased
-    if (l_obj->timestamp > (uint64_t)l_timestamp_del &&
-            l_obj->timestamp > (uint64_t)l_timestamp_cur &&
-            (l_obj->type != DAP_DB$K_OPTYPE_DEL || l_obj->timestamp > l_limit_time)) {
-        l_apply = true;
-    }
-    if (s_debug_more){
-        char l_ts_str[50];
-        dap_time_to_str_rfc822(l_ts_str, sizeof(l_ts_str), dap_nanotime_to_sec(l_obj->timestamp));
-        log_it(L_DEBUG, "Unpacked log history: type='%c' (0x%02hhX) group=\"%s\" key=\"%s\""
-                " timestamp=\"%s\" value_len=%" DAP_UINT64_FORMAT_U,
-                (char )l_obj->type, (char)l_obj->type, l_obj->group,
-                l_obj->key, l_ts_str, l_obj->value_len);
-    }
-    if (!l_apply) {
-        if (s_debug_more) {
-            if (l_obj->timestamp <= (uint64_t)l_timestamp_cur)
-                log_it(L_WARNING, "New data not applied, because newly object exists");
-            if (l_obj->timestamp <= (uint64_t)l_timestamp_del)
-                log_it(L_WARNING, "New data not applied, because newly object is deleted");
-            if ((l_obj->type == DAP_DB$K_OPTYPE_DEL && l_obj->timestamp <= l_limit_time))
-                log_it(L_WARNING, "New data not applied, because object is too old");
-        }
-        goto ret;
-    }
-
-    dap_chain_t *l_chain = dap_chain_get_chain_from_group_name(l_sync_request->request_hdr.net_id, l_obj->group);
 
-    if (l_chain && l_chain->callback_add_datums) {
-        log_it(L_WARNING, "New data goes to GDB chain");
-            const void * restrict l_store_obj_value = l_obj->value;
-            l_chain->callback_add_datums(l_chain,
-                    (dap_chain_datum_t** restrict) &l_store_obj_value, 1);
-    } else {
-        // save data to global_db
-        if (dap_global_db_set_raw(l_obj, 1, s_gdb_in_pkt_proc_set_raw_callback, l_sync_request) != 0)
-            log_it(L_ERROR, "Can't send save GlobalDB request");
-        else // do not delete it here
-            l_sync_request = NULL;
-    }
-ret:
-    dap_store_obj_free_one(l_obj);
-    DAP_DEL_Z(l_sync_request);
-    DAP_DELETE(l_args);
-    return;
-}
 /**
  * @brief s_gdb_in_pkt_callback
  * @param a_thread
@@ -815,7 +706,6 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg)
         uint32_t l_time_store_lim_hours = dap_config_get_item_uint32_default(g_config, "global_db", "time_store_limit", 72);
         dap_nanotime_t l_time_now = dap_nanotime_now();
         dap_nanotime_t l_time_alowed = l_time_now + dap_nanotime_from_sec(3600 * 24); // to be sure the timestamp is invalid
-        dap_nanotime_t l_limit_time = l_time_store_lim_hours ? l_time_now - dap_nanotime_from_sec(l_time_store_lim_hours * 3600) : 0;
         for (size_t i = 0; i < l_data_obj_count; i++) {
             // obj to add
             dap_store_obj_t *l_obj = l_store_obj + i;
@@ -857,11 +747,7 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg)
             l_last_group = l_obj->group;
             l_last_type = l_obj->type;
             */
-            struct gdb_apply_args *l_apply_args = DAP_NEW(struct gdb_apply_args);
-            l_apply_args->obj = dap_store_obj_copy(l_obj, 1);
-            l_apply_args->limit_time = l_limit_time;
-            l_apply_args->sync_request = DAP_DUP(l_sync_request);
-            dap_global_db_context_exec(s_gdb_in_pkt_proc_callback_apply, l_apply_args);
+            dap_global_db_remote_apply_obj(l_obj, s_gdb_in_pkt_proc_set_raw_callback, DAP_DUP(l_sync_request));
         }
         if (l_store_obj)
             dap_store_obj_free(l_store_obj, l_data_obj_count);
@@ -899,8 +785,7 @@ static void s_gdb_in_pkt_proc_set_raw_callback(dap_global_db_context_t *a_global
         dap_worker_exec_callback_inter(a_global_db_context->queue_worker_callback_input[l_sync_req->worker->id],
                                     s_gdb_in_pkt_error_worker_callback, l_sync_req);
     }else{
-        if (s_debug_more)
-                            log_it(L_DEBUG, "Added new GLOBAL_DB synchronization record");
+        debug_if(s_debug_more, L_DEBUG, "Added new GLOBAL_DB synchronization record");
         DAP_DELETE(l_sync_req);
     }
 }
@@ -915,6 +800,10 @@ struct sync_request *dap_stream_ch_chain_create_sync_request(dap_stream_ch_chain
 {
     dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch);
     struct sync_request *l_sync_request = DAP_NEW_Z(struct sync_request);
+    if (!l_sync_request) {
+        log_it(L_ERROR, "Memory allocation error in dap_stream_ch_chain_create_sync_request");
+        return NULL;
+    }
     *l_sync_request = (struct sync_request) {
             .worker         = a_ch->stream_worker->worker,
             .ch_uuid        = a_ch->uuid,
@@ -964,6 +853,7 @@ static bool s_chain_timer_callback(void *a_arg)
                                              l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
                                              l_ch_chain->request_hdr.cell_id.uint64, NULL, 0);
         l_ch_chain->sent_breaks = 0;
+        l_ch_chain->timer_shots = 0;
     }
     if (l_ch_chain->state == CHAIN_STATE_SYNC_GLOBAL_DB && l_ch_chain->sent_breaks >= 3 * DAP_SYNC_TICKS_PER_SECOND) {
         debug_if(s_debug_more, L_INFO, "Send one global_db TSD packet (rest=%zu/%zu items)",
@@ -973,6 +863,7 @@ static bool s_chain_timer_callback(void *a_arg)
                                              l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
                                              l_ch_chain->request_hdr.cell_id.uint64, NULL, 0);
         l_ch_chain->sent_breaks = 0;
+        l_ch_chain->timer_shots = 0;
     }
     return true;
 }
@@ -1149,6 +1040,10 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                                       l_hash_item_hashv, l_hash_item);
                 if (!l_hash_item) {
                     l_hash_item = DAP_NEW_Z(dap_stream_ch_chain_hash_item_t);
+                    if (!l_hash_item) {
+                        log_it(L_ERROR, "Memory allocation error in s_stream_ch_packet_in");
+                        return;
+                    }
                     l_hash_item->hash = l_element->hash;
                     l_hash_item->size = l_element->size;
                     HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, hash, sizeof(l_hash_item->hash),
@@ -1360,6 +1255,10 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                                       l_hash_item_hashv, l_hash_item);
                 if( ! l_hash_item ){
                     l_hash_item = DAP_NEW_Z(dap_stream_ch_chain_hash_item_t);
+                    if (!l_hash_item) {
+                        log_it(L_ERROR, "Memory allocation error in s_stream_ch_packet_in");
+                        return;
+                    }
                     l_hash_item->hash = l_element->hash;
                     l_hash_item->size = l_element->size;
                     HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_atoms, hash, sizeof(dap_hash_fast_t),
@@ -1478,7 +1377,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
                             dap_chain_hash_fast_to_str(&l_atom_hash, l_atom_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
                             log_it(L_INFO, "In: CHAIN pkt: atom hash %s (size %zd)", l_atom_hash_str, l_chain_pkt_data_size);
                         }
-                        dap_proc_queue_add_callback_inter(a_ch->stream_worker->worker->proc_queue_input, s_sync_in_chains_callback, l_sync_request);
+                        if (dap_proc_queue_add_callback_inter(a_ch->stream_worker->worker->proc_queue_input, s_sync_in_chains_callback, l_sync_request))
+                            log_it(L_ERROR, "System queue overflow with atom trying atom add. All following atoms will be rejected!");
                     } else {
                         log_it(L_WARNING, "Empty chain packet");
                         s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64,
@@ -1786,11 +1686,15 @@ void s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg)
                     l_skip_count++;
                 } else {
                     l_hash_item = DAP_NEW_Z(dap_stream_ch_chain_hash_item_t);
+                    if (!l_hash_item) {
+                        log_it(L_ERROR, "Memory allocation error in s_stream_ch_packet_out");
+                        return;
+                    }
                     l_hash_item->hash = l_obj->hash;
                     l_hash_item->size = l_obj->pkt->data_size;
                     HASH_ADD_BYHASHVALUE(hh, l_ch_chain->remote_gdbs, hash, sizeof(dap_chain_hash_fast_t),
                                          l_hash_item_hashv, l_hash_item);
-                    l_pkt = dap_store_packet_multiple(l_pkt, l_obj->pkt);
+                    l_pkt = dap_global_db_pkt_pack(l_pkt, l_obj->pkt);
                     l_ch_chain->stats_request_gdb_processed++;
                     l_pkt_size = sizeof(dap_global_db_pkt_t) + l_pkt->data_size;
                 }
@@ -1886,6 +1790,10 @@ void s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg)
                     }*/
                 }else{
                     l_hash_item = DAP_NEW_Z(dap_stream_ch_chain_hash_item_t);
+                    if (!l_hash_item) {
+                        log_it(L_ERROR, "Memory allocation error in s_stream_ch_packet_out");
+                        return;
+                    }
                     l_hash_item->hash = *l_ch_chain->request_atom_iter->cur_hash;
                     if(s_debug_more){
                         char l_atom_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
diff --git a/modules/channel/chain/include/dap_stream_ch_chain.h b/modules/channel/chain/include/dap_stream_ch_chain.h
index 6a0d136033c448499d9ae2cfdc0dfaedf731d834..b0542a834c6a4d7433f062182134795bd45dd8d5 100644
--- a/modules/channel/chain/include/dap_stream_ch_chain.h
+++ b/modules/channel/chain/include/dap_stream_ch_chain.h
@@ -34,7 +34,7 @@
 #include "uthash.h"
 #include "dap_global_db_remote.h"
 
-#define DAP_CHAIN_NODE_SYNC_TIMEOUT 30  // sec
+#define DAP_CHAIN_NODE_SYNC_TIMEOUT 60  // sec
 #define DAP_SYNC_TICKS_PER_SECOND   10
 
 typedef struct dap_stream_ch_chain dap_stream_ch_chain_t;
@@ -94,7 +94,6 @@ int dap_stream_ch_chain_init(void);
 void dap_stream_ch_chain_deinit(void);
 
 inline static uint8_t dap_stream_ch_chain_get_id(void) { return (uint8_t) 'C'; }
-dap_chain_t * dap_chain_get_chain_from_group_name(dap_chain_net_id_t a_net_id, const char *a_group_name);
 void dap_stream_ch_chain_create_sync_request_gdb(dap_stream_ch_chain_t * a_ch_chain, dap_chain_net_t * a_net);
 void dap_stream_ch_chain_timer_start(dap_stream_ch_chain_t *a_ch_chain);
 void dap_stream_ch_chain_reset_unsafe(dap_stream_ch_chain_t *a_ch_chain);
diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index e1ccc2930913f3994f02a57dd3d5d1aa1e182ae5..20fa9b9fc3e3a41ccda24a238caae7d07d3fd1ff 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -296,6 +296,10 @@ uint128_t dap_chain_uint128_from_uint256(uint256_t a_from)
 char *dap_chain_balance_print128(uint128_t a_balance)
 {
     char *l_buf = DAP_NEW_Z_SIZE(char, DATOSHI_POW + 2);
+    if (!l_buf) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_balance_print128");
+        return NULL;
+    }
     int l_pos = 0;
     uint128_t l_value = a_balance;
 #ifdef DAP_GLOBAL_IS_INT128
@@ -626,6 +630,10 @@ uint256_t dap_chain_coins_to_balance256(const char *a_coins)
 
 char *dap_cvt_uint256_to_str(uint256_t a_uint256) {
     char *l_buf = DAP_NEW_Z_SIZE(char, DATOSHI_POW256 + 2); // for decimal dot and trailing zero
+    if (!l_buf) {
+        log_it(L_ERROR, "Memory allocation error in dap_cvt_uint256_to_str");
+        return NULL;
+    }
     int l_pos = 0;
     uint256_t l_value = a_uint256;
     uint256_t uint256_ten = GET_256_FROM_64(10);
diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c
index 945c9d35e86acd461304e6209c5c2eae8c7336a4..fa21942e376fe3541cdb300c51ccf1e83a8897d7 100644
--- a/modules/common/dap_chain_datum.c
+++ b/modules/common/dap_chain_datum.c
@@ -349,8 +349,20 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                                      l_value_str);
             if (((dap_chain_datum_tx_receipt_t*)item)->exts_size == sizeof(dap_sign_t) + sizeof(dap_sign_t)){
                 dap_sign_t *l_provider = DAP_NEW_Z(dap_sign_t);
+                if (!l_provider) {
+                    log_it(L_ERROR, "Memory allocation error in dap_chain_datum_dump_tx");
+                    DAP_DELETE(l_value_str);
+                    DAP_DELETE(l_coins_str);
+                    return false;
+                }
                 memcpy(l_provider, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs, sizeof(dap_sign_t));
                 dap_sign_t *l_client = DAP_NEW_Z(dap_sign_t);
+                if (!l_client) {
+                    log_it(L_ERROR, "Memory allocation error in dap_chain_datum_dump_tx");
+                    DAP_DELETE(l_value_str);
+                    DAP_DELETE(l_coins_str);
+                    return false;
+                }
                 memcpy(l_client,
                        ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs + sizeof(dap_sign_t),
                        sizeof(dap_sign_t));
@@ -361,6 +373,12 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
                 dap_sign_get_information(l_client, a_str_out, a_hash_out_type);
             } else if (((dap_chain_datum_tx_receipt_t*)item)->exts_size == sizeof(dap_sign_t)) {
                 dap_sign_t *l_provider = DAP_NEW_Z(dap_sign_t);
+                if (!l_provider) {
+                    log_it(L_ERROR, "Memory allocation error in dap_chain_datum_dump_tx");
+                    DAP_DELETE(l_value_str);
+                    DAP_DELETE(l_coins_str);
+                    return false;
+                }
                 memcpy(l_provider, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs, sizeof(dap_sign_t));
                 dap_string_append_printf(a_str_out, "Exts:\n"
                                                     "   Provider:\n");
diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c
index 40adfe8121c6761740e0cf694624396766441399..1a9c50e8fe0fd840023e6e21beaad0bd72dbb978 100644
--- a/modules/common/dap_chain_datum_decree.c
+++ b/modules/common/dap_chain_datum_decree.c
@@ -450,6 +450,11 @@ void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree
                 char *l_stake_addr_signing_str = dap_chain_addr_to_str(&l_stake_addr_signing);
                 dap_string_append_printf(a_str_out, "\tSigning addr: %s\n", l_stake_addr_signing_str);
                 dap_chain_hash_fast_t *l_pkey_signing = DAP_NEW(dap_chain_hash_fast_t);
+                if (!l_pkey_signing) {
+                    log_it(L_ERROR, "Memory allocation error in dap_chain_datum_decree_dump");
+                    DAP_DELETE(l_stake_addr_signing_str);
+                    return;
+                }
                 memcpy(l_pkey_signing, l_stake_addr_signing.data.key, sizeof(dap_chain_hash_fast_t));
                 char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex")
                         ? dap_enc_base58_encode_hash_to_str(l_pkey_signing)
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 4b10d01fd1c946098af9ba6885532a88abb98361..b2504b308f5ca1cb4366866980f5e31278335f15 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -66,107 +66,128 @@ const char *c_dap_chain_datum_token_flag_str[] = {
  */
 dap_tsd_t* dap_chain_datum_token_tsd_get(dap_chain_datum_token_t *a_token, size_t a_token_size)
 {
-    // Check if token type could have tsd section
-    size_t l_hdr_size = sizeof(dap_chain_datum_token_t);
-    if (l_hdr_size > a_token_size){
-        log_it(L_WARNING, "Token size smaller then header, corrupted data");
+    if (a_token_size < sizeof(dap_chain_datum_token_t)){
+        log_it(L_WARNING, "Token size %lu < %lu header size, corrupted token datum", a_token_size, sizeof(dap_chain_datum_token_t));
         return NULL;
     }
-    return (dap_tsd_t *)a_token->data_n_tsd;
+    return (dap_tsd_t*)a_token->data_n_tsd;
 }
 
 dap_chain_datum_token_t *dap_chain_datum_token_read(const byte_t *a_token_serial, size_t *a_token_size) {
     dap_chain_datum_token_old_t *l_token_old = (dap_chain_datum_token_old_t*)a_token_serial;
     size_t l_token_data_n_tsd_size = *a_token_size - sizeof(dap_chain_datum_token_old_t);
-    size_t l_token_size     = l_token_data_n_tsd_size + sizeof(dap_chain_datum_token_t);
-    dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
-    memcpy(l_token->ticker, l_token_old->ticker, sizeof(l_token_old->ticker));
-    memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
-//    *a_token_size = l_token_size;
+    size_t l_token_size = l_token_data_n_tsd_size + sizeof(dap_chain_datum_token_t);
     switch (((dap_chain_datum_token_t*)a_token_serial)->type) {
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE: {
-        memcpy(l_token->ticker, l_token_old->ticker, sizeof(l_token_old->ticker));
-//        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, l_token_tsd_size);
+        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+        *l_token = (dap_chain_datum_token_t) {
+                .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
+                .version    = 1,
+                .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE,
+                .signs_valid    = l_token_old->signs_valid,
+                .signs_total    = l_token_old->signs_total,
+                .total_supply   = l_token_old->total_supply,
+                .header_simple.decimals = l_token_old->header_simple.decimals,
+        };
+        dap_stpcpy(l_token->ticker, l_token_old->ticker);
+        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
         *a_token_size = l_token_size;
-        l_token->type           = DAP_CHAIN_DATUM_TOKEN_DECL;
-        l_token->total_supply   = l_token_old->total_supply;
-        l_token->signs_valid    = l_token_old->signs_valid;
-        l_token->signs_total    = l_token_old->signs_total;
-        l_token->header_simple.decimals = l_token_old->header_simple.decimals;
-//        l_token->header_native_decl.tsd_total_size = l_token_tsd_size;
-        l_token->subtype        = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE;
-        l_token->version        = 1;
         return l_token;
     }
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_DECL: {
+        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+        *l_token = (dap_chain_datum_token_t) {
+                .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
+                .version    = 1,
+                .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE,
+                .signs_valid    = l_token_old->signs_valid,
+                .signs_total    = l_token_old->signs_total,
+                .total_supply   = l_token_old->total_supply,
+                .header_private_decl.flags          = l_token_old->header_private_decl.flags,
+                .header_private_decl.tsd_total_size = l_token_old->header_private_decl.tsd_total_size,
+                .header_private_decl.decimals       = l_token_old->header_private_decl.decimals
+        };
+        dap_stpcpy(l_token->ticker, l_token_old->ticker);
+        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
         *a_token_size = l_token_size;
-        l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL;
-        l_token->total_supply   = l_token_old->total_supply;
-        l_token->signs_valid    = l_token_old->signs_valid;
-        l_token->signs_total    = l_token_old->signs_total;
-        l_token->subtype = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE;
-        l_token->header_private_decl.decimals = l_token_old->header_private_decl.decimals;
-        l_token->header_private_decl.tsd_total_size = l_token_old->header_private_decl.tsd_total_size;
-        l_token->header_private_decl.flags = l_token_old->header_private_decl.flags;
-        l_token->version = 1;
         return l_token;
     }
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PRIVATE_UPDATE: {
+        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+        *l_token = (dap_chain_datum_token_t) {
+                .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE,
+                .version    = 1,
+                .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE,
+                .signs_valid    = l_token_old->signs_valid,
+                .signs_total    = l_token_old->signs_total,
+                .total_supply   = l_token_old->total_supply,
+                .header_private_update.flags            = l_token_old->header_private_update.flags,
+                .header_private_update.tsd_total_size   = l_token_old->header_private_update.tsd_total_size,
+                .header_private_update.decimals         = l_token_old->header_private_update.decimals
+        };
+        dap_stpcpy(l_token->ticker, l_token_old->ticker);
+        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
         *a_token_size = l_token_size;
-        l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE;
-        l_token->total_supply   = l_token_old->total_supply;
-        l_token->signs_valid    = l_token_old->signs_valid;
-        l_token->signs_total    = l_token_old->signs_total;
-        l_token->subtype = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE;
-        l_token->header_private_update.decimals = l_token_old->header_private_update.decimals;
-        l_token->header_private_update.tsd_total_size = l_token_old->header_private_update.tsd_total_size;
-        l_token->header_private_update.flags = l_token_old->header_private_update.flags;
-        l_token->version = 1;
         return l_token;
     }
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_DECL: {
+        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+        *l_token = (dap_chain_datum_token_t) {
+                .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
+                .version    = 1,
+                .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE,
+                .signs_valid    = l_token_old->signs_valid,
+                .signs_total    = l_token_old->signs_total,
+                .total_supply   = l_token_old->total_supply,
+                .header_native_decl.flags           = l_token_old->header_native_decl.flags,
+                .header_native_decl.tsd_total_size  = l_token_old->header_native_decl.tsd_total_size,
+                .header_native_decl.decimals        = l_token_old->header_native_decl.decimals
+        };
+        dap_stpcpy(l_token->ticker, l_token_old->ticker);
+        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
         *a_token_size = l_token_size;
-        l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL;
-        l_token->total_supply   = l_token_old->total_supply;
-        l_token->signs_valid    = l_token_old->signs_valid;
-        l_token->signs_total    = l_token_old->signs_total;
-        l_token->subtype = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE;
-        l_token->header_native_decl.decimals = l_token_old->header_native_decl.decimals;
-        l_token->header_native_decl.tsd_total_size = l_token_old->header_native_decl.tsd_total_size;
-        l_token->header_native_decl.flags = l_token_old->header_native_decl.flags;
-        l_token->version = 1;
         return l_token;
     }
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_NATIVE_UPDATE: {
+        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+        *l_token = (dap_chain_datum_token_t) {
+                .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE,
+                .version    = 1,
+                .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE,
+                .signs_valid    = l_token_old->signs_valid,
+                .signs_total    = l_token_old->signs_total,
+                .total_supply   = l_token_old->total_supply,
+                .header_native_update.flags             = l_token_old->header_native_update.flags,
+                .header_native_update.tsd_total_size    = l_token_old->header_native_update.tsd_total_size,
+                .header_native_update.decimals          = l_token_old->header_native_update.decimals
+        };
+        dap_stpcpy(l_token->ticker, l_token_old->ticker);
+        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
         *a_token_size = l_token_size;
-        l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE;
-        l_token->total_supply   = l_token_old->total_supply;
-        l_token->signs_valid    = l_token_old->signs_valid;
-        l_token->signs_total    = l_token_old->signs_total;
-        l_token->subtype = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE;
-        l_token->header_native_update.decimals = l_token_old->header_native_update.decimals;
-        l_token->header_native_update.tsd_total_size = l_token_old->header_native_update.tsd_total_size;
-        l_token->header_native_update.flags = l_token_old->header_native_update.flags;
-        l_token->version = 1;
         return l_token;
     }
     case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_PUBLIC: {
+        dap_chain_datum_token_t *l_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_token_size);
+        *l_token = (dap_chain_datum_token_t) {
+                .type       = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL,
+                .version    = 1,
+                .subtype    = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC,
+                .signs_valid    = l_token_old->signs_valid,
+                .signs_total    = l_token_old->signs_total,
+                .total_supply   = l_token_old->total_supply,
+                .header_public.flags            = l_token_old->header_public.flags,
+                .header_public.premine_supply   = l_token_old->header_public.premine_supply,
+                .header_public.premine_address  = l_token_old->header_public.premine_address
+        };
+        dap_stpcpy(l_token->ticker, l_token_old->ticker);
+        memcpy(l_token->data_n_tsd, l_token_old->data_n_tsd, (uint32_t)l_token_data_n_tsd_size);
         *a_token_size = l_token_size;
-        l_token->type = DAP_CHAIN_DATUM_TOKEN_TYPE_DECL;
-        l_token->total_supply   = l_token_old->total_supply;
-        l_token->signs_valid    = l_token_old->signs_valid;
-        l_token->signs_total    = l_token_old->signs_total;
-        l_token->subtype = DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC;
-        l_token->header_public.flags = l_token_old->header_public.flags;
-        l_token->header_public.premine_address = l_token_old->header_public.premine_address;
-        l_token->header_public.premine_supply = l_token_old->header_public.premine_supply;
-        l_token->version = 1;
         return l_token;
     }
     default:
-        DAP_DELETE(l_token);
+        log_it(L_NOTICE, "Unknown token type '%d' read", ((dap_chain_datum_token_t*)a_token_serial)->type);
         return DAP_DUP_SIZE(a_token_serial, *a_token_size);
-    };
+    }
 }
 
 /**
@@ -250,6 +271,10 @@ dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datu
     assert(a_signs_total);
     assert(a_signs_valid);
     assert(a_datum_token_size >= sizeof(dap_chain_datum_token_old_t));
+    if (!a_datum_token->signs_total) {
+        log_it(L_ERROR, "No signs in datum token with ticker '%s', type %d", a_datum_token->ticker, a_datum_token->type);
+        return NULL;
+    }
     *a_signs_total = 0;
     *a_signs_valid = a_datum_token->signs_valid;
     size_t l_offset = 0;
@@ -325,10 +350,13 @@ dap_sign_t ** dap_chain_datum_token_signs_parse(dap_chain_datum_token_t * a_datu
 dap_chain_datum_token_emission_t *dap_chain_datum_emission_create(uint256_t a_value, const char *a_ticker, dap_chain_addr_t *a_addr)
 {
     dap_chain_datum_token_emission_t *l_emission = DAP_NEW_Z(dap_chain_datum_token_emission_t);
+    if (!l_emission) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_datum_emission_create");
+        return NULL;
+    }
     l_emission->hdr.version = 3;
     l_emission->hdr.value_256 = a_value;
     strncpy(l_emission->hdr.ticker, a_ticker, DAP_CHAIN_TICKER_SIZE_MAX - 1);
-    l_emission->hdr.ticker[DAP_CHAIN_TICKER_SIZE_MAX - 1] = '\0';
     l_emission->hdr.type = DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH;
     l_emission->hdr.address = *a_addr;
     dap_uuid_generate_nonce(&l_emission->hdr.nonce, DAP_CHAIN_DATUM_NONCE_SIZE);
diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c
index 6fdbfb13f137271b4fadb0e3fc7c499210fc1a7f..9480c69043adc17d7ff3e81a872496fcbfb991d5 100644
--- a/modules/common/dap_chain_datum_tx.c
+++ b/modules/common/dap_chain_datum_tx.c
@@ -39,6 +39,10 @@
 dap_chain_datum_tx_t* dap_chain_datum_tx_create(void)
 {
     dap_chain_datum_tx_t *tx = DAP_NEW_Z(dap_chain_datum_tx_t);
+    if (!tx) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_datum_tx_create");
+        return 0;
+    }
     tx->header.ts_created = time(NULL);
     return tx;
 }
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index b22863e40c30d66cac79789bd51778a65d684efd..5ec7c2a87bb068da296692742d95cdc411dc469d 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -235,6 +235,9 @@ dap_chain_tx_in_ems_t *dap_chain_datum_tx_item_in_ems_create(dap_chain_id_t a_id
     if(!a_ticker)
         return NULL;
     dap_chain_tx_in_ems_t *l_item = DAP_NEW_Z(dap_chain_tx_in_ems_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->header.type = TX_ITEM_TYPE_IN_EMS;
     l_item->header.token_emission_chain_id.uint64 = a_id.uint64;
     l_item->header.token_emission_hash = *a_datum_token_hash;;
@@ -266,6 +269,9 @@ dap_chain_tx_in_t* dap_chain_datum_tx_item_in_create(dap_chain_hash_fast_t *a_tx
     if(!a_tx_prev_hash)
         return NULL;
     dap_chain_tx_in_t *l_item = DAP_NEW_Z(dap_chain_tx_in_t);
+        if (!l_item) {
+        return NULL;
+    }
     l_item->header.type = TX_ITEM_TYPE_IN;
     l_item->header.tx_out_prev_idx = a_tx_out_prev_idx;
     l_item->header.tx_prev_hash = *a_tx_prev_hash;
@@ -325,6 +331,9 @@ dap_chain_tx_in_cond_t* dap_chain_datum_tx_item_in_cond_create(dap_chain_hash_fa
     if(!a_tx_prev_hash )
         return NULL;
     dap_chain_tx_in_cond_t *l_item = DAP_NEW_Z(dap_chain_tx_in_cond_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->header.type = TX_ITEM_TYPE_IN_COND;
     l_item->header.receipt_idx = a_receipt_idx;
     l_item->header.tx_out_prev_idx = a_tx_out_prev_idx;
@@ -360,6 +369,9 @@ dap_chain_tx_out_t* dap_chain_datum_tx_item_out_create(const dap_chain_addr_t *a
     if (!a_addr || IS_ZERO_256(a_value))
         return NULL;
     dap_chain_tx_out_t *l_item = DAP_NEW_Z(dap_chain_tx_out_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->addr = *a_addr;
     l_item->header.type = TX_ITEM_TYPE_OUT;
     l_item->header.value = a_value;
@@ -382,6 +394,9 @@ dap_chain_tx_out_ext_t* dap_chain_datum_tx_item_out_ext_create(const dap_chain_a
     if (IS_ZERO_256(a_value))
         return NULL;
     dap_chain_tx_out_ext_t *l_item = DAP_NEW_Z(dap_chain_tx_out_ext_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->header.type = TX_ITEM_TYPE_OUT_EXT;
     l_item->header.value = a_value;
     l_item->addr = *a_addr;
@@ -407,6 +422,9 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee(uint256_t a
     if (IS_ZERO_256(a_value))
         return NULL;
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z(dap_chain_tx_out_cond_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
     l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE;
@@ -544,6 +562,9 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake(dap_c
     if (IS_ZERO_256(a_value))
         return NULL;
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z(dap_chain_tx_out_cond_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
     l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE;
@@ -591,6 +612,9 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
     if (IS_ZERO_256(a_value))
         return NULL;
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z(dap_chain_tx_out_cond_t);
+    if (!l_item) {
+        return NULL;
+    }
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
     l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK;
diff --git a/modules/consensus/block-poa/dap_chain_cs_block_poa.c b/modules/consensus/block-poa/dap_chain_cs_block_poa.c
index 42641314b8300041e05283905e976fd9e551e26b..04f795aebd4b6bab6835b650bf7e033d986c5cd7 100644
--- a/modules/consensus/block-poa/dap_chain_cs_block_poa.c
+++ b/modules/consensus/block-poa/dap_chain_cs_block_poa.c
@@ -176,11 +176,19 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     dap_chain_cs_blocks_new(a_chain, a_chain_cfg);
     dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS( a_chain );
     dap_chain_cs_block_poa_t * l_poa = DAP_NEW_Z ( dap_chain_cs_block_poa_t);
+    if (!l_poa) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return -1;
+    }
     l_blocks->_inheritor = l_poa;
     l_blocks->callback_delete = s_callback_delete;
     l_blocks->callback_block_verify = s_callback_block_verify;
     l_blocks->callback_block_sign = s_callback_block_sign;
     l_poa->_pvt = DAP_NEW_Z(dap_chain_cs_block_poa_pvt_t);
+    if (!l_poa->_pvt) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return -1;
+    }
     dap_chain_cs_block_poa_pvt_t *l_poa_pvt = PVT(l_poa);
 
     if (dap_config_get_item_str(a_chain_cfg,"block-poa","auth_certs_prefix") ) {
@@ -190,6 +198,10 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
         if (l_poa_pvt->auth_certs_count && l_poa_pvt->auth_certs_count_verify ) {
             // Type sizeof's misunderstanding in malloc?
             l_poa_pvt->auth_certs = DAP_NEW_Z_SIZE ( dap_cert_t *, l_poa_pvt->auth_certs_count * sizeof(dap_cert_t*));
+            if (!l_poa_pvt->auth_certs) {
+                log_it(L_ERROR, "Memory allocation error in s_callback_new");
+                return -1;
+            }
             char l_cert_name[512];
             for (size_t i = 0; i < l_poa_pvt->auth_certs_count ; i++ ){
                 snprintf(l_cert_name,sizeof(l_cert_name),"%s.%zu",l_poa_pvt->auth_certs_prefix, i);
diff --git a/modules/consensus/block-pos/dap_chain_cs_block_pos.c b/modules/consensus/block-pos/dap_chain_cs_block_pos.c
index 70195b519698d764e5afac6f3b21cff3f50ab12a..6efe30b407bd14737c681e8017b930a2d9713b86 100644
--- a/modules/consensus/block-pos/dap_chain_cs_block_pos.c
+++ b/modules/consensus/block-pos/dap_chain_cs_block_pos.c
@@ -80,20 +80,26 @@ void dap_chain_cs_block_pos_deinit(void)
 static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
 {
     dap_chain_cs_blocks_new(a_chain, a_chain_cfg);
+    char ** l_tokens_hold = NULL;
+    char ** l_tokens_hold_value_str = NULL;
+    uint16_t l_tokens_hold_size = 0;
+    uint16_t l_tokens_hold_value_size = 0;
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     dap_chain_cs_block_pos_t *l_pos = DAP_NEW_Z(dap_chain_cs_block_pos_t);
+    if (!l_pos) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return -1;
+    }
     l_blocks->_inheritor = l_pos;
     l_blocks->callback_delete = s_callback_delete;
     l_blocks->callback_block_verify = s_callback_block_verify;
     l_blocks->callback_block_sign = s_callback_block_sign;
     l_pos->_pvt = DAP_NEW_Z(dap_chain_cs_block_pos_pvt_t);
-
     dap_chain_cs_block_pos_pvt_t *l_pos_pvt = PVT(l_pos);
-
-    char ** l_tokens_hold = NULL;
-    char ** l_tokens_hold_value_str = NULL;
-    uint16_t l_tokens_hold_size = 0;
-    uint16_t l_tokens_hold_value_size = 0;
+    if (!l_pos->_pvt) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        goto lb_err;
+    }
 
     l_tokens_hold = dap_config_get_array_str(a_chain_cfg, "block-pos", "stake_tokens", &l_tokens_hold_size);
     l_tokens_hold_value_str = dap_config_get_array_str(a_chain_cfg, "block-pos", "stake_tokens_value", &l_tokens_hold_value_size);
@@ -105,8 +111,15 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     l_pos_pvt->confirmations_minimum = dap_config_get_item_uint16_default(a_chain_cfg, "block-pos", "verifications_minimum", 1);
     l_pos_pvt->tokens_hold_size = l_tokens_hold_size;
     l_pos_pvt->tokens_hold = DAP_NEW_Z_SIZE(char *, sizeof(char *) * l_tokens_hold_size);
+    if (!l_pos_pvt->tokens_hold) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        goto lb_err;
+    }
     l_pos_pvt->tokens_hold_value = DAP_NEW_Z_SIZE(uint64_t, l_tokens_hold_value_size * sizeof(uint64_t));
-
+    if (!l_pos_pvt->tokens_hold_value) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        goto lb_err;
+    }
     for (size_t i = 0; i < l_tokens_hold_value_size; i++) {
         l_pos_pvt->tokens_hold[i] = dap_strdup(l_tokens_hold[i]);
         if ((l_pos_pvt->tokens_hold_value[i] =
@@ -122,17 +135,22 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     return 0;
 
 lb_err:
-    for (int i = 0; i < l_tokens_hold_size; i++)
-        DAP_DELETE(l_tokens_hold[i]);
-    DAP_DELETE(l_tokens_hold);
-    DAP_DELETE(l_pos_pvt->tokens_hold_value);
-    DAP_DELETE(l_pos_pvt);
-    DAP_DELETE(l_pos );
+    for (int i = 0; i < l_tokens_hold_size; i++) {
+        if (l_tokens_hold[i])
+            DAP_DELETE(l_tokens_hold[i]);
+    }
+    if (l_tokens_hold)
+        DAP_DELETE(l_tokens_hold);
+    if (l_pos_pvt->tokens_hold_value)
+        DAP_DELETE(l_pos_pvt->tokens_hold_value);
+    if (l_pos_pvt)
+        DAP_DELETE(l_pos_pvt);
+    if (l_pos)
+        DAP_DELETE(l_pos);
     l_blocks->_inheritor = NULL;
     l_blocks->callback_delete = NULL;
     l_blocks->callback_block_verify = NULL;
     return -1;
-
 }
 
 /**
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index ab297ae76f82a9a9ef9a8d66d95a043c4935167e..28876785406260cf4600542ae481ce8a54e05315 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -157,6 +157,10 @@ void dap_chain_cs_dag_poa_presign_callback_set(dap_chain_t *a_chain, dap_chain_c
     dap_chain_cs_dag_poa_pvt_t * l_poa_pvt = PVT(DAP_CHAIN_CS_DAG_POA(l_dag));
     l_poa_pvt->callback_pre_sign =
             (dap_chain_cs_dag_poa_presign_callback_t*)DAP_NEW_Z(dap_chain_cs_dag_poa_presign_callback_t);
+    if (!l_poa_pvt->callback_pre_sign) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_dag_poa_presign_callback_set");
+        return;
+    }
     l_poa_pvt->callback_pre_sign->callback = a_callback;
     l_poa_pvt->callback_pre_sign->arg = a_arg;
 }
@@ -332,12 +336,20 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     dap_chain_cs_dag_new(a_chain,a_chain_cfg);
     dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG ( a_chain );
     dap_chain_cs_dag_poa_t *l_poa = DAP_NEW_Z ( dap_chain_cs_dag_poa_t);
+    if (!l_poa) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return -1;
+    }
     l_dag->_inheritor = l_poa;
     l_dag->callback_delete = s_callback_delete;
     l_dag->callback_cs_verify = s_callback_event_verify;
     l_dag->callback_cs_event_create = s_callback_event_create;
     l_dag->chain->callback_get_poa_certs = dap_chain_cs_dag_poa_get_auth_certs;
     l_poa->_pvt = DAP_NEW_Z ( dap_chain_cs_dag_poa_pvt_t );
+    if (!l_poa->_pvt) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return -1;
+    }
     dap_chain_cs_dag_poa_pvt_t *l_poa_pvt = PVT(l_poa);
     pthread_rwlock_init(&l_poa_pvt->rounds_rwlock, NULL);
     // PoA rounds
@@ -351,6 +363,10 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
         l_poa_pvt->auth_certs_count_verify = dap_config_get_item_uint16_default(a_chain_cfg,"dag-poa","auth_certs_number_verify",0);
         if (l_poa_pvt->auth_certs_count && l_poa_pvt->auth_certs_count_verify) {
             l_poa_pvt->auth_certs = DAP_NEW_Z_SIZE ( dap_cert_t *, l_poa_pvt->auth_certs_count * sizeof(dap_cert_t *));
+            if (!l_poa_pvt->auth_certs) {
+                log_it(L_ERROR, "Memory allocation error in s_callback_new");
+                return -1;
+            }
             char l_cert_name[512];
             for (size_t i = 0; i < l_poa_pvt->auth_certs_count ; i++ ){
                 snprintf(l_cert_name,sizeof(l_cert_name),"%s.%zu",l_poa_pvt->auth_certs_prefix, i);
@@ -591,10 +607,8 @@ static void s_callback_round_event_to_chain_callback_get_round_item(dap_global_d
             DAP_DELETE(l_new_atom);
             char l_datum_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
             dap_chain_hash_fast_to_str(&l_chosen_item->round_info.datum_hash, l_datum_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
-            char *l_err_verify_str = dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum);
             log_it(L_INFO, "Event %s from round %"DAP_UINT64_FORMAT_U" not added into chain, because the inner datum %s doesn't pass verification (%s)",
-                   l_event_hash_hex_str, l_arg->round_id, l_datum_hash_str, l_err_verify_str);
-            DAP_DELETE(l_err_verify_str);
+                   l_event_hash_hex_str, l_arg->round_id, l_datum_hash_str, dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum));
         }
     } else { /* !l_chosen_item */
         log_it(L_WARNING, "No candidates for round id %"DAP_UINT64_FORMAT_U, l_arg->round_id);
@@ -628,6 +642,11 @@ static void s_round_event_cs_done(dap_chain_cs_dag_t * a_dag, uint64_t a_round_i
         return;
     }
     l_callback_arg = DAP_NEW_Z(struct round_timer_arg);
+    if (!l_callback_arg) {
+        log_it(L_ERROR, "Memory allocation error in s_round_event_cs_done");
+        pthread_rwlock_unlock(&l_poa_pvt->rounds_rwlock);
+        return;
+    }
     l_callback_arg->dag = a_dag;
     l_callback_arg->round_id = a_round_id;
     // placement in chain by timer
@@ -865,11 +884,16 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_
         }
         a_event->header.signs_count = l_event_signs_count;
         DAP_DELETE(l_signs);
-        if ( l_ret != 0 ) {
-            return l_ret;
+        if (l_signs_verified_count < l_certs_count_verify) {
+            dap_hash_fast_t l_event_hash;
+            dap_hash_fast(a_event, a_event_size, &l_event_hash);
+            char l_event_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+            dap_hash_fast_to_str(&l_event_hash, l_event_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
+            log_it(L_ERROR, "Corrupted event %s, not enough signs %hu from %hu",
+                            l_event_hash_str, l_signs_verified_count, l_certs_count_verify);
+            return l_ret ? l_ret : -4;
         }
-        return l_signs_verified_count >= l_certs_count_verify ? 0 : -1;
-
+        return 0;
     }
     else if (a_event->header.hash_count == 0){
         dap_chain_hash_fast_t l_event_hash;
diff --git a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
index 75aa18e310d09be01ad7db6cd55b24cd9cb8e6a6..ec07f04253620f6b00e927ba0e39b771dbeba53d 100644
--- a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
+++ b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
@@ -81,13 +81,11 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 {
     dap_chain_cs_dag_new(a_chain,a_chain_cfg);
     dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain );
-    dap_chain_cs_dag_pos_t * l_pos = DAP_NEW_Z ( dap_chain_cs_dag_pos_t);
-    l_dag->_inheritor = l_pos;
-    l_dag->callback_delete = s_callback_delete;
-    l_dag->callback_cs_verify = s_callback_event_verify;
-    l_dag->callback_cs_event_create = s_callback_event_create;
-    l_pos->_pvt = DAP_NEW_Z ( dap_chain_cs_dag_pos_pvt_t );
-
+    dap_chain_cs_dag_pos_t *l_pos = DAP_NEW_Z( dap_chain_cs_dag_pos_t);
+    if (!l_pos) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return -1;
+    }
     dap_chain_cs_dag_pos_pvt_t * l_pos_pvt = PVT ( l_pos );
 
     char ** l_tokens_hold = NULL;
@@ -95,21 +93,37 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     uint16_t l_tokens_hold_size = 0;
     uint16_t l_tokens_hold_value_size = 0;
 
+    l_dag->_inheritor = l_pos;
+    l_dag->callback_delete = s_callback_delete;
+    l_dag->callback_cs_verify = s_callback_event_verify;
+    l_dag->callback_cs_event_create = s_callback_event_create;
+    l_pos->_pvt = DAP_NEW_Z ( dap_chain_cs_dag_pos_pvt_t );
+    if (!l_pos->_pvt) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        goto lb_err;
+    }
+
     l_tokens_hold = dap_config_get_array_str( a_chain_cfg,"dag-pos","tokens_hold",&l_tokens_hold_size);
     l_tokens_hold_value_str = dap_config_get_array_str( a_chain_cfg,"dag-pos","tokens_hold_value",&l_tokens_hold_value_size);
 
     if ( l_tokens_hold_size != l_tokens_hold_value_size ){
-        log_it(L_CRITICAL, "tokens_hold and tokens_hold_value are different size!");
+        log_it(L_CRITICAL, "Entries tokens_hold and tokens_hold_value are different size!");
         goto lb_err;
     }
     l_pos_pvt->confirmations_minimum = dap_config_get_item_uint16_default( a_chain_cfg,"dag-pos","confirmations_minimum",1);
     l_pos_pvt->tokens_hold_size = l_tokens_hold_size;
     l_pos_pvt->tokens_hold = DAP_NEW_Z_SIZE( char*, sizeof(char*) *
                                              l_tokens_hold_size );
-
+    if (!l_pos_pvt->tokens_hold) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        goto lb_err;
+    }
     l_pos_pvt->tokens_hold_value = DAP_NEW_Z_SIZE(uint64_t,
                                                   (l_tokens_hold_value_size +1) *sizeof (uint64_t));
-
+    if (!l_pos_pvt->tokens_hold_value) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        goto lb_err;
+    }
     for (size_t i = 0; i < l_tokens_hold_value_size; i++){
         l_pos_pvt->tokens_hold[i] = dap_strdup( l_tokens_hold[i] );
         if ( ( l_pos_pvt->tokens_hold_value[i] =
@@ -123,12 +137,18 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
     return 0;
 
 lb_err:
-    for (int i = 0; i < l_tokens_hold_size; i++ )
-        DAP_DELETE(l_tokens_hold[i]);
-    DAP_DELETE(l_tokens_hold);
-    DAP_DELETE( l_pos_pvt->tokens_hold_value);
-    DAP_DELETE( l_pos_pvt);
-    DAP_DELETE(l_pos );
+    for (int i = 0; i < l_tokens_hold_size; i++) {
+        if (l_tokens_hold[i])
+            DAP_DELETE(l_tokens_hold[i]);
+    }
+    if (l_tokens_hold)
+        DAP_DELETE(l_tokens_hold);
+    if (l_pos_pvt->tokens_hold_value)
+        DAP_DELETE(l_pos_pvt->tokens_hold_value);
+    if (l_pos_pvt)
+        DAP_DELETE(l_pos_pvt);
+    if (l_pos)
+        DAP_DELETE(l_pos);
     l_dag->_inheritor = NULL;
     l_dag->callback_delete = NULL;
     l_dag->callback_cs_verify = NULL;
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index f9471f2ab185ec72cd31ce275c90de9de71448b1..7633b717a47172897fd426747571bb78d7d12ec5 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -61,6 +61,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
 static uint256_t s_callback_get_minimum_fee(dap_chain_t *a_chain);
 static dap_enc_key_t *s_callback_get_sign_key(dap_chain_t *a_chain);
 static void s_callback_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_new_value);
+static void s_db_change_notifier(dap_global_db_context_t *a_context, dap_store_obj_t *a_obj, void * a_arg);
 
 static int s_cli_esbocs(int argc, char ** argv, char **str_reply);
 
@@ -76,6 +77,7 @@ DAP_STATIC_INLINE const char *s_voting_msg_type_to_str(uint8_t a_type)
     case DAP_CHAIN_ESBOCS_MSG_TYPE_DIRECTIVE: return "DIRECTIVE";
     case DAP_CHAIN_ESBOCS_MSG_TYPE_VOTE_FOR: return "VOTE_FOR";
     case DAP_CHAIN_ESBOCS_MSG_TYPE_VOTE_AGAINST: return "VOTE_AGAINST";
+    case DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB: return "SEND_DB";
     default: return "UNKNOWN";
     }
 }
@@ -131,6 +133,16 @@ typedef struct dap_chain_esbocs_pvt {
 
 #define PVT(a) ((dap_chain_esbocs_pvt_t *)a->_pvt)
 
+struct sync_params {
+    uint64_t attempt;
+    dap_hash_fast_t db_hash;
+} DAP_ALIGN_PACKED;
+
+DAP_STATIC_INLINE uint16_t s_get_round_skip_timeout(dap_chain_esbocs_session_t *a_session)
+{
+    return PVT(a_session->esbocs)->round_attempt_timeout * 6 * PVT(a_session->esbocs)->round_attempts_max;
+}
+
 int dap_chain_cs_esbocs_init()
 {
     dap_stream_ch_chain_voting_init();
@@ -152,7 +164,12 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     dap_chain_cs_blocks_new(a_chain, a_chain_cfg);
 
     dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
+    int l_ret = 0;
     dap_chain_esbocs_t *l_esbocs = DAP_NEW_Z(dap_chain_esbocs_t);
+    if (!l_esbocs) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        return - 5;
+    }
     l_esbocs->blocks = l_blocks;   
     l_blocks->_inheritor = l_esbocs;
     l_blocks->callback_delete = s_callback_delete;
@@ -166,6 +183,11 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
 
     l_esbocs->_pvt = DAP_NEW_Z(dap_chain_esbocs_pvt_t);
     dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs);
+    if (!l_esbocs->_pvt) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_new");
+        l_ret = - 5;
+        goto lb_err;
+    }
     l_esbocs_pvt->debug = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "consensus_debug", false);
     l_esbocs_pvt->poa_mode = dap_config_get_item_bool_default(a_chain_cfg, "esbocs", "poa_mode", false);
     l_esbocs_pvt->round_start_sync_timeout = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_start_sync_timeout", 15);
@@ -173,7 +195,6 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
     l_esbocs_pvt->round_attempts_max = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_attempts_max", 4);
     l_esbocs_pvt->round_attempt_timeout = dap_config_get_item_uint16_default(a_chain_cfg, "esbocs", "round_attempt_timeout", 10);
 
-    int l_ret = 0;
     l_esbocs_pvt->start_validators_min = l_esbocs_pvt->min_validators_count =
             dap_config_get_item_uint16(a_chain_cfg, "esbocs", "min_validators_count");
     if (!l_esbocs_pvt->min_validators_count) {
@@ -210,9 +231,16 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
             l_ret = -4;
             goto lb_err;
         }
-        log_it(L_MSG, "add validator addr:"NODE_ADDR_FP_STR"", NODE_ADDR_FP_ARGS_S(l_signer_node_addr));
+        char *l_signer_addr = dap_chain_addr_to_str(&l_signing_addr);
+        log_it(L_MSG, "add validator addr "NODE_ADDR_FP_STR", signing addr %s", NODE_ADDR_FP_ARGS_S(l_signer_node_addr), l_signer_addr);
+        DAP_DELETE(l_signer_addr);
 
         dap_chain_esbocs_validator_t *l_validator = DAP_NEW_Z(dap_chain_esbocs_validator_t);
+        if (!l_validator) {
+            log_it(L_ERROR, "Memory allocation error in s_callback_new");
+            l_ret = - 5;
+            goto lb_err;
+        }
         l_validator->signing_addr = l_signing_addr;
         l_validator->node_addr = l_signer_node_addr;
         l_validator->weight = uint256_1;
@@ -227,12 +255,15 @@ static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg)
         }
     }
     l_blocks->chain->callback_created = s_callback_created;
+
     return 0;
 
 lb_err:
     dap_list_free_full(l_esbocs_pvt->poa_validators, NULL);
-    DAP_DELETE(l_esbocs_pvt);
-    DAP_DELETE(l_esbocs);
+    if (l_esbocs_pvt)
+        DAP_DELETE(l_esbocs_pvt);
+    if (l_esbocs)
+        DAP_DELETE(l_esbocs);
     l_blocks->_inheritor = NULL;
     l_blocks->callback_delete = NULL;
     l_blocks->callback_block_verify = NULL;
@@ -251,6 +282,67 @@ static void s_new_atom_notifier(void *a_arg, UNUSED_ARG dap_chain_t *a_chain, UN
     pthread_mutex_unlock(&l_session->mutex);
 }
 
+/* *** Temporary added section for over-consensus sync. Remove this after global DB sync refactoring *** */
+
+void s_callback_clean_db_old_records(UNUSED_ARG dap_global_db_context_t *a_global_db_context, void *a_arg)
+{
+    dap_global_db_driver_delete(a_arg, 1);
+    dap_store_obj_free_one(a_arg);
+}
+
+static void s_session_db_serialize(dap_chain_esbocs_session_t *a_session)
+{
+    char *l_sync_group = s_get_penalty_group(a_session->chain->net_id);
+    size_t l_objs_count = 0;
+    dap_global_db_pkt_t *l_pkt = 0;
+    dap_store_obj_t *l_objs = dap_global_db_get_all_raw_sync(l_sync_group, 0, &l_objs_count);
+    for (size_t i = 0; i < l_objs_count; i++) {
+        dap_store_obj_t *it = l_objs + i;
+        it->type = DAP_DB$K_OPTYPE_ADD;
+        dap_global_db_pkt_t *l_pkt_single = dap_global_db_pkt_serialize(it);
+        dap_global_db_pkt_change_id(l_pkt_single, 0);
+        l_pkt = dap_global_db_pkt_pack(l_pkt, l_pkt_single);
+        DAP_DELETE(l_pkt_single);
+    }
+    dap_store_obj_free(l_objs, l_objs_count);
+
+    uint32_t l_time_store_lim_hours = dap_global_db_context_get_default()->instance->store_time_limit;
+    uint64_t l_limit_time = l_time_store_lim_hours ? dap_nanotime_now() - dap_nanotime_from_sec(l_time_store_lim_hours * 3600) : 0;
+    char *l_del_sync_group = dap_strdup_printf("%s.del", l_sync_group);
+    l_objs_count = 0;
+    l_objs = dap_global_db_get_all_raw_sync(l_del_sync_group, 0, &l_objs_count);
+    DAP_DELETE(l_del_sync_group);
+    for (size_t i = 0; i < l_objs_count; i++) {
+        dap_store_obj_t *it = l_objs + i;
+        if (l_limit_time && it->timestamp < l_limit_time) {
+            dap_global_db_context_exec(s_callback_clean_db_old_records, dap_store_obj_copy(it, 1));
+            continue;
+        }
+        it->type = DAP_DB$K_OPTYPE_DEL;
+        DAP_DEL_Z(it->group);
+        it->group = dap_strdup(l_sync_group);
+        dap_global_db_pkt_t *l_pkt_single = dap_global_db_pkt_serialize(it);
+        dap_global_db_pkt_change_id(l_pkt_single, 0);
+        l_pkt = dap_global_db_pkt_pack(l_pkt, l_pkt_single);
+        DAP_DELETE(l_pkt_single);
+    }
+    dap_store_obj_free(l_objs, l_objs_count);
+    DAP_DELETE(l_sync_group);
+    DAP_DEL_Z(a_session->db_serial);
+    a_session->db_serial = l_pkt;
+    if (l_pkt)
+        dap_hash_fast(l_pkt->data, l_pkt->data_size, &a_session->db_hash);
+    else
+        a_session->db_hash = (dap_hash_fast_t){};
+    if (PVT(a_session->esbocs)->debug) {
+        char l_sync_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+        dap_chain_hash_fast_to_str(&a_session->db_hash, l_sync_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
+        log_it(L_MSG, "DB changes applied, new DB resync hash is %s", l_sync_hash_str);
+    }
+}
+
+/* *** End of the temporary added section for over-consensus sync. *** */
+
 static void s_session_load_penaltys(dap_chain_esbocs_session_t *a_session)
 {
     const char *l_penalty_group = s_get_penalty_group(a_session->chain->net_id);
@@ -358,6 +450,10 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
     l_session->my_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net);
     l_session->my_signing_addr = l_my_signing_addr;
     s_session_load_penaltys(l_session);
+    s_session_db_serialize(l_session);
+    dap_global_db_add_notify_group_mask(dap_global_db_context_get_default()->instance,
+                                        DAP_CHAIN_ESBOCS_GDB_GROUPS_PREFIX ".*",
+                                        s_db_change_notifier, l_session);
     pthread_mutexattr_t l_mutex_attr;
     pthread_mutexattr_init(&l_mutex_attr);
     pthread_mutexattr_settype(&l_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
@@ -367,7 +463,7 @@ static int s_callback_created(dap_chain_t *a_chain, dap_config_t *a_chain_net_cf
     dap_chain_add_callback_notify(a_chain, s_new_atom_notifier, l_session);
     s_session_round_new(l_session);
 
-    log_it(L_INFO, "init session for net:%s, chain:%s", a_chain->net_name, a_chain->name);
+    log_it(L_INFO, "Init session for net:%s, chain:%s", a_chain->net_name, a_chain->name);
     DL_APPEND(s_session_items, l_session);
     if (!s_session_cs_timer) {
         s_session_cs_timer = dap_timerfd_start(1000, s_session_timer, NULL);
@@ -429,6 +525,10 @@ static void *s_callback_list_copy(const void *a_validator, UNUSED_ARG void *a_da
 static void *s_callback_list_form(const void *a_srv_validator, UNUSED_ARG void *a_data)
 {
     dap_chain_esbocs_validator_t *l_validator = DAP_NEW_Z(dap_chain_esbocs_validator_t);
+    if (!l_validator) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_list_form");
+        return NULL;
+    }
     l_validator->node_addr = ((dap_chain_net_srv_stake_item_t *)a_srv_validator)->node_addr;
     l_validator->signing_addr = ((dap_chain_net_srv_stake_item_t *)a_srv_validator)->signing_addr;
     l_validator->weight = ((dap_chain_net_srv_stake_item_t *)a_srv_validator)->value;
@@ -462,10 +562,12 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session,
 
     if (!l_esbocs_pvt->poa_mode) {
         dap_list_t *l_validators = dap_chain_net_srv_stake_get_validators(a_session->chain->net_id, true);
+        a_session->cur_round.all_validators = dap_list_copy_deep(l_validators, s_callback_list_form, NULL);
         uint16_t l_total_validators_count = dap_list_length(l_validators);
         if (l_total_validators_count < l_esbocs_pvt->min_validators_count) {
+            l_ret = dap_list_copy_deep(l_esbocs_pvt->poa_validators, s_callback_list_copy, NULL);
             dap_list_free_full(l_validators, NULL);
-            return NULL;
+            return l_ret;
         }
 
         // TODO: make dap_chain_net_srv_stake_get_total_weight() call
@@ -480,8 +582,6 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_session_t *a_session,
             }
         }
 
-        a_session->cur_round.all_validators = dap_list_copy_deep(l_validators, s_callback_list_form, NULL);
-
         size_t l_consensus_optimum = (size_t)l_esbocs_pvt->min_validators_count * 2 - 1;
         size_t l_need_vld_cnt = MIN(l_total_validators_count, l_consensus_optimum);
 
@@ -579,18 +679,21 @@ static void s_session_send_startsync(dap_chain_esbocs_session_t *a_session)
             dap_string_append_printf(l_addr_list, NODE_ADDR_FP_STR"; ",
                                      NODE_ADDR_FP_ARGS_S(((dap_chain_esbocs_validator_t *)it->data)->node_addr));
         }
+        char *l_sync_hash = dap_chain_hash_fast_to_str_new(&a_session->db_hash);
         log_it(L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"."
-                       " Sent START_SYNC pkt, sync attempt %"DAP_UINT64_FORMAT_U" current validators list: %s",
+                       " Sent START_SYNC pkt, sync attempt %"DAP_UINT64_FORMAT_U" current validators list: %s DB sync hash %s",
                             a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id,
-                                a_session->cur_round.sync_attempt, l_addr_list->str);
+                                a_session->cur_round.sync_attempt, l_addr_list->str, l_sync_hash);
         dap_string_free(l_addr_list, true);
+        DAP_DELETE(l_sync_hash);
     }
     dap_list_t *l_inactive_validators = dap_chain_net_srv_stake_get_validators(a_session->chain->net_id, false);
     dap_list_t *l_inactive_sendlist = dap_list_copy_deep(l_inactive_validators, s_callback_list_form, NULL);
     dap_list_free_full(l_inactive_validators, NULL);
     dap_list_t *l_total_sendlist = dap_list_concat(a_session->cur_round.all_validators, l_inactive_sendlist);
+    struct sync_params l_params = { .attempt = a_session->cur_round.sync_attempt, .db_hash = a_session->db_hash };
     s_message_send(a_session, DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC, &l_last_block_hash,
-                   &a_session->cur_round.sync_attempt, sizeof(uint64_t),
+                   &l_params, sizeof(struct sync_params),
                    l_total_sendlist);
     if (l_inactive_sendlist && l_inactive_sendlist->prev) { // List splitting
         l_inactive_sendlist->prev->next = NULL;
@@ -688,41 +791,51 @@ static void s_session_round_new(dap_chain_esbocs_session_t *a_session)
             a_session->cur_round.sync_attempt = 1;
     }
     a_session->cur_round.validators_list = s_get_validators_list(a_session, a_session->cur_round.sync_attempt - 1);
+    if (!a_session->cur_round.validators_list) {
+        log_it(L_WARNING, "Totally no active validators found");
+        a_session->ts_round_sync_start = dap_time_now();
+        return;
+    }
     bool l_round_already_started = a_session->round_fast_forward;
-    if (s_validator_check(&a_session->my_signing_addr, a_session->cur_round.validators_list)) {
-        //I am a current round validator
-        dap_chain_esbocs_sync_item_t *l_item, *l_tmp;
-        HASH_FIND(hh, a_session->sync_items, &a_session->cur_round.last_block_hash, sizeof(dap_hash_fast_t), l_item);
-        if (l_item) {
-            debug_if(PVT(a_session->esbocs)->debug,
-                     L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" already started. Process sync messages",
-                                a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id);
-            l_round_already_started = true;
-            for (dap_list_t *it = l_item->messages; it; it = it->next) {
-                dap_hash_fast_t l_msg_hash;
-                dap_chain_esbocs_message_t *l_msg = it->data;
-                size_t l_msg_size = s_get_esbocs_message_size(l_msg);
-                dap_hash_fast(l_msg, l_msg_size, &l_msg_hash);
-                s_session_packet_in(a_session, NULL, NULL, &l_msg_hash, (uint8_t *)l_msg, l_msg_size);
-            }
-        }
-        HASH_ITER(hh, a_session->sync_items, l_item, l_tmp) {
-            HASH_DEL(a_session->sync_items, l_item);
-            dap_list_free_full(l_item->messages, NULL);
-            DAP_DELETE(l_item);
-        }
-
+    dap_chain_esbocs_sync_item_t *l_item, *l_tmp;
+    HASH_FIND(hh, a_session->sync_items, &a_session->cur_round.last_block_hash, sizeof(dap_hash_fast_t), l_item);
+    if (l_item) {
+        debug_if(PVT(a_session->esbocs)->debug,
+                 L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" already started. Process sync messages",
+                            a_session->chain->net_name, a_session->chain->name, a_session->cur_round.id);
+        l_round_already_started = true;
+        for (dap_list_t *it = l_item->messages; it; it = it->next) {
+            dap_hash_fast_t l_msg_hash;
+            dap_chain_esbocs_message_t *l_msg = it->data;
+            size_t l_msg_size = s_get_esbocs_message_size(l_msg);
+            dap_hash_fast(l_msg, l_msg_size, &l_msg_hash);
+            s_session_packet_in(a_session, NULL, NULL, &l_msg_hash, (uint8_t *)l_msg, l_msg_size);
+        }
+    }
+    HASH_ITER(hh, a_session->sync_items, l_item, l_tmp) {
+        HASH_DEL(a_session->sync_items, l_item);
+        dap_list_free_full(l_item->messages, NULL);
+        DAP_DELETE(l_item);
+    }
+
+    if (!a_session->cur_round.sync_sent) {
+        uint16_t l_sync_send_delay =  a_session->sync_failed ?
+                                            s_get_round_skip_timeout(a_session) :
+                                            PVT(a_session->esbocs)->new_round_delay;
+        if (l_round_already_started)
+            l_sync_send_delay = 0;
         debug_if(PVT(a_session->esbocs)->debug, L_MSG,
                  "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U" start. Syncing validators in %u seconds",
                     a_session->chain->net_name, a_session->chain->name,
-                        a_session->cur_round.id, l_round_already_started ? 0 : PVT(a_session->esbocs)->new_round_delay);
+                        a_session->cur_round.id, l_sync_send_delay);
+        if (l_sync_send_delay)
+            a_session->sync_timer = dap_timerfd_start(l_sync_send_delay * 1000, s_session_send_startsync_on_timer, a_session);
+        else
+            s_session_send_startsync(a_session);
     }
-    if (PVT(a_session->esbocs)->new_round_delay && !l_round_already_started && !a_session->cur_round.sync_sent)
-        a_session->sync_timer = dap_timerfd_start(PVT(a_session->esbocs)->new_round_delay * 1000,
-                                                  s_session_send_startsync_on_timer, a_session);
-    else
-        s_session_send_startsync(a_session);
     a_session->round_fast_forward = false;
+    a_session->sync_failed = false;
+    a_session->listen_ensure = 0;
 }
 
 static void s_session_attempt_new(dap_chain_esbocs_session_t *a_session)
@@ -976,17 +1089,14 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session)
 {
     if (pthread_mutex_trylock(&a_session->mutex) != 0)
         return; // Session is busy
-    static unsigned int l_listen_ensure;
     bool l_cs_debug = PVT(a_session->esbocs)->debug;
     dap_time_t l_time = dap_time_now();
     switch (a_session->state) {
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START: {
-        l_listen_ensure = 1;
-        dap_time_t l_round_timeout = PVT(a_session->esbocs)->round_start_sync_timeout;
+        a_session->listen_ensure = 1;
         bool l_round_skip = !s_validator_check(&a_session->my_signing_addr, a_session->cur_round.validators_list);
-        if (l_round_skip)
-            l_round_timeout += PVT(a_session->esbocs)->round_attempt_timeout * 6 * PVT(a_session->esbocs)->round_attempts_max;
-        if (a_session->ts_round_sync_start && l_time - a_session->ts_round_sync_start >= l_round_timeout) {
+        if (a_session->ts_round_sync_start && l_time - a_session->ts_round_sync_start >=
+                PVT(a_session->esbocs)->round_start_sync_timeout) {
             if (a_session->cur_round.validators_synced_count >= PVT(a_session->esbocs)->min_validators_count && !l_round_skip) {
                 a_session->cur_round.id = s_session_calc_current_round_id(a_session);
                 debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
@@ -1000,13 +1110,14 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session)
                                                 a_session->chain->net_name, a_session->chain->name,
                                                     a_session->cur_round.id, a_session->cur_round.attempt_num,
                                                         l_round_skip ? "skipped" : "can't synchronize minimum number of validators");
+                a_session->sync_failed = true;
                 s_session_round_new(a_session);
             }
         }
     } break;
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC:
-        if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout * l_listen_ensure) {
-            l_listen_ensure += 2;
+        if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout * a_session->listen_ensure) {
+            a_session->listen_ensure += 2;
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                         " Attempt finished by reason: haven't cantidate submitted",
                                             a_session->chain->net_name, a_session->chain->name,
@@ -1015,7 +1126,6 @@ static void s_session_proc_state(dap_chain_esbocs_session_t *a_session)
         }
         break;
     case DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_SIGNS:
-        l_listen_ensure = 1;
         if (l_time - a_session->ts_stage_entry >= PVT(a_session->esbocs)->round_attempt_timeout) {
             dap_chain_esbocs_store_t *l_store;
             HASH_FIND(hh, a_session->cur_round.store_items, &a_session->cur_round.attempt_candidate_hash, sizeof(dap_hash_fast_t), l_store);
@@ -1087,8 +1197,16 @@ static void s_message_chain_add(dap_chain_esbocs_session_t *a_session,
                                 dap_chain_hash_fast_t *a_message_hash,
                                 dap_chain_addr_t *a_signing_addr)
 {
+    if (NULL == a_message) {
+        log_it(L_ERROR, "Argument is NULL for s_message_chain_add");
+        return;
+    }
     dap_chain_esbocs_round_t *l_round = &a_session->cur_round;
     dap_chain_esbocs_message_item_t *l_message_item = DAP_NEW_Z(dap_chain_esbocs_message_item_t);
+    if (!l_message_item) {
+        log_it(L_ERROR, "Memory allocation error in s_message_chain_add");
+        return;
+    }
     if (!a_message_hash) {
         dap_chain_hash_fast_t l_message_hash;
         dap_hash_fast(a_message, a_message_size, &l_message_hash);
@@ -1134,6 +1252,10 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session)
 static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, dap_chain_block_t *a_candidate,
                                        size_t a_candidate_size, dap_hash_fast_t *a_candidate_hash)
 {
+    if (NULL == a_candidate) {
+        log_it(L_ERROR, "Argument is NULL for s_session_candidate_verify");
+        return;
+    }
     // Process early received messages
     for (dap_chain_esbocs_message_item_t *l_item = a_session->cur_round.message_items; l_item; l_item = l_item->hh.next) {
         if (l_item->unprocessed &&
@@ -1177,6 +1299,10 @@ static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, da
 
 static void s_session_candidate_precommit(dap_chain_esbocs_session_t *a_session, dap_chain_esbocs_message_t *a_message)
 {
+    if (NULL == a_message) {
+        log_it(L_ERROR, "Argument is NULL for s_session_candidate_precommit");
+        return;
+    }
     bool l_cs_debug = PVT(a_session->esbocs)->debug;
     uint16_t l_cs_level = PVT(a_session->esbocs)->min_validators_count;
     byte_t *l_message_data = a_message->msg_n_sign;
@@ -1240,6 +1366,10 @@ static void s_session_candidate_precommit(dap_chain_esbocs_session_t *a_session,
 static bool s_session_candidate_to_chain(dap_chain_esbocs_session_t *a_session, dap_chain_hash_fast_t *a_candidate_hash,
                                          dap_chain_block_t *a_candidate, size_t a_candidate_size)
 {
+    if (NULL == a_candidate) {
+        log_it(L_ERROR, "Argument is NULL for s_session_candidate_to_chain");
+        return false;
+    }
     bool res = false;
     dap_chain_block_t *l_candidate = DAP_DUP_SIZE(a_candidate, a_candidate_size);
     dap_chain_atom_verify_res_t l_res = a_session->chain->callback_atom_add(a_session->chain, l_candidate, a_candidate_size);
@@ -1435,7 +1565,15 @@ static void s_session_round_finish(dap_chain_esbocs_session_t *a_session, dap_ch
             l_compare && PVT(a_session->esbocs)->fee_addr) {
 
         fee_serv_param_t *tmp = DAP_NEW(fee_serv_param_t);
+        if (!tmp) {
+            log_it(L_ERROR, "Memory allocation error in s_session_round_finish");
+            return;
+        }
         dap_chain_addr_t * addr = DAP_NEW_Z(dap_chain_addr_t);
+        if (!addr) {
+            log_it(L_ERROR, "Memory allocation error in s_session_round_finish");
+            return;
+        }
         *addr = *PVT(a_session->esbocs)->fee_addr;
         tmp->a_addr_to = addr;
         tmp->block_hash = l_precommit_candidate_hash;
@@ -1454,6 +1592,10 @@ void s_session_sync_queue_add(dap_chain_esbocs_session_t *a_session, dap_chain_e
     HASH_FIND(hh, a_session->sync_items, &a_message->hdr.candidate_hash, sizeof(dap_hash_fast_t), l_sync_item);
     if (!l_sync_item) {
         l_sync_item = DAP_NEW_Z(dap_chain_esbocs_sync_item_t);
+        if (!l_sync_item) {
+            log_it(L_ERROR, "Memory allocation error in s_session_sync_queue_add");
+            return;
+        }
         l_sync_item->last_block_hash = a_message->hdr.candidate_hash;
         HASH_ADD(hh, a_session->sync_items, last_block_hash, sizeof(dap_hash_fast_t), l_sync_item);
     }
@@ -1465,9 +1607,16 @@ void s_session_validator_mark_online(dap_chain_esbocs_session_t *a_session, dap_
     bool l_in_list = false;
     dap_list_t *l_list = s_validator_check(a_signing_addr, a_session->cur_round.all_validators);
     if (l_list) {
+        bool l_was_synced = ((dap_chain_esbocs_validator_t *)l_list->data)->is_synced;
         ((dap_chain_esbocs_validator_t *)l_list->data)->is_synced = true;
-        a_session->cur_round.total_validators_synced++;
+        if (!l_was_synced)
+            a_session->cur_round.total_validators_synced++;
         l_in_list = true;
+        if (PVT(a_session->esbocs)->debug) {
+            const char *l_addr_str = dap_chain_addr_to_str(a_signing_addr);
+            log_it(L_DEBUG, "Mark validator %s as online", l_addr_str);
+            DAP_DELETE(l_addr_str);
+        }
     }
     dap_chain_esbocs_penalty_item_t *l_item = NULL;
     HASH_FIND(hh, a_session->penalty, a_signing_addr, sizeof(*a_signing_addr), l_item);
@@ -1564,7 +1713,6 @@ static void s_session_directive_process(dap_chain_esbocs_session_t *a_session, d
                                             l_directive_hash_str);
         DAP_DELETE(l_directive_hash_str);
     }
-
     a_session->cur_round.directive_hash = *a_directive_hash;
     a_session->cur_round.directive = DAP_DUP_SIZE(a_directive, a_directive->size);
 
@@ -1586,6 +1734,28 @@ static void s_session_directive_process(dap_chain_esbocs_session_t *a_session, d
     s_message_send(a_session, l_type, a_directive_hash, NULL, 0, a_session->cur_round.all_validators);
 }
 
+static void s_db_change_notifier(dap_global_db_context_t *a_context, dap_store_obj_t *a_obj, void *a_arg)
+{
+    dap_chain_addr_t *l_validator_addr = dap_chain_addr_from_str(a_obj->key);
+    if (!l_validator_addr) {
+        log_it(L_WARNING, "Unreadable address in esbocs global DB group");
+        dap_global_db_del_unsafe(a_context, a_obj->group, a_obj->key);
+        return;
+    }
+    if (dap_chain_net_srv_stake_mark_validator_active(l_validator_addr, a_obj->type != DAP_DB$K_OPTYPE_ADD)) {
+        dap_global_db_del_unsafe(a_context, a_obj->group, a_obj->key);
+        return;
+    }
+    dap_chain_esbocs_session_t *l_session = a_arg;
+    dap_global_db_pkt_t *l_pkt = dap_global_db_pkt_serialize(a_obj);
+    dap_hash_fast_t l_blank_hash = {};
+    pthread_mutex_lock(&l_session->mutex);
+    s_message_send(l_session, DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB, &l_blank_hash, l_pkt,
+                   sizeof(*l_pkt) + l_pkt->data_size, l_session->cur_round.all_validators);
+    pthread_mutex_unlock(&l_session->mutex);
+    DAP_DELETE(l_pkt);
+}
+
 static int s_session_directive_apply(dap_chain_esbocs_directive_t *a_directive, dap_hash_fast_t *a_directive_hash)
 {
     if (!a_directive) {
@@ -1609,12 +1779,12 @@ static int s_session_directive_apply(dap_chain_esbocs_directive_t *a_directive,
         const char *l_directive_hash_str = dap_chain_hash_fast_to_str_new(a_directive_hash);
         const char *l_key_hash_str = dap_chain_hash_fast_to_str_new(&l_key_addr->data.hash_fast);
         if (l_status == 1 && a_directive->type == DAP_CHAIN_ESBOCS_DIRECTIVE_KICK) {
-            dap_chain_net_srv_stake_mark_validator_active(l_key_addr, false);
+            // Offline wiil be set in gdb notifier for aim of sync supporting
             dap_global_db_set(l_penalty_group, l_key_str, NULL, 0, false, NULL, 0);
             log_it(L_MSG, "Applied %s directive to exclude validator %s with pkey hash %s from consensus",
                             l_directive_hash_str, l_key_str, l_key_hash_str);
         } else if (l_status == -1 && a_directive->type == DAP_CHAIN_ESBOCS_DIRECTIVE_LIFT) {
-            dap_chain_net_srv_stake_mark_validator_active(l_key_addr, true);
+            // Online wiil be set in gdb notifier for aim of sync supporting
             dap_global_db_del(l_penalty_group, l_key_str, NULL, 0);
             log_it(L_MSG, "Applied %s directive to include validator %s with pkey hash %s in consensus",
                             l_directive_hash_str, l_key_str, l_key_hash_str);
@@ -1659,7 +1829,7 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
     }
 
     size_t l_message_data_size = l_message->hdr.message_size;
-    byte_t *l_message_data = l_message->msg_n_sign;
+    void *l_message_data = l_message->msg_n_sign;
     dap_chain_hash_fast_t *l_candidate_hash = &l_message->hdr.candidate_hash;
     dap_sign_t *l_sign = (dap_sign_t *)(l_message_data + l_message_data_size);
     size_t l_sign_size = l_message->hdr.sign_size;
@@ -1726,6 +1896,15 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
                 s_session_sync_queue_add(l_session, l_message, a_data_size);
                 goto session_unlock;
             }
+        } else if (l_message->hdr.type == DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB) {
+            if (dap_hash_fast_compare(&l_message->hdr.candidate_hash, &l_session->db_hash) &&
+                    !dap_hash_fast_is_blank(&l_session->db_hash)) {
+                debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U"."
+                                            " Send DB message with same DB hash is ignored",
+                                                l_session->chain->net_name, l_session->chain->name,
+                                                    l_session->cur_round.id);
+                goto session_unlock;
+            }
         } else if (l_message->hdr.round_id != l_session->cur_round.id) {
             // round check
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
@@ -1761,7 +1940,8 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
             if (l_same_type && dap_chain_addr_compare(&l_chain_message->signing_addr, &l_signing_addr) &&
                     dap_hash_fast_compare(&l_chain_message->message->hdr.candidate_hash, &l_message->hdr.candidate_hash)) {
                 if (l_message->hdr.type != DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC || // Not sync or same sync attempt
-                        *(uint64_t *)l_message_data == *(uint64_t *)l_chain_message->message->msg_n_sign) {
+                        ((struct sync_params *)l_message_data)->attempt ==
+                        ((struct sync_params *)l_chain_message->message->msg_n_sign)->attempt) {
                     debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
                                                 " Message rejected: duplicate message %s",
                                                     l_session->chain->net_name, l_session->chain->name,
@@ -1781,6 +1961,7 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
     bool l_not_in_list = false;
     switch (l_message->hdr.type) {
     case DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC:
+    case DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB:
         // Add local sync messages, cause a round clear
         if (!a_sender_node_addr)
             s_message_chain_add(l_session, l_message, a_data_size, a_data_hash, &l_signing_addr);
@@ -1810,15 +1991,31 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
 
     switch (l_message->hdr.type) {
     case DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC: {
-        if (l_message_data_size != sizeof(uint64_t)) {
+        if (l_message_data_size != sizeof(struct sync_params)) {
             log_it(L_WARNING, "Invalid START_SYNC message size");
             break;
         }
-        uint64_t l_sync_attempt = *(uint64_t *)l_message_data;
+        uint64_t l_sync_attempt = ((struct sync_params *)l_message_data)->attempt;
         debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U
                                     " Receive START_SYNC: from validator:%s, sync attempt %"DAP_UINT64_FORMAT_U,
                                         l_session->chain->net_name, l_session->chain->name, l_message->hdr.round_id,
                                             l_validator_addr_str, l_sync_attempt);
+        if (!dap_hash_fast_compare(&((struct sync_params *)l_message_data)->db_hash, &l_session->db_hash)) {
+            debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", sync_attempt %"DAP_UINT64_FORMAT_U
+                                        " SYNC message is rejected cause DB hash mismatch",
+                                           l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
+                                               l_session->cur_round.sync_attempt);
+            if (l_session->db_serial) {
+                dap_chain_esbocs_validator_t *l_validator = DAP_NEW_Z(dap_chain_esbocs_validator_t);
+                l_validator->node_addr = *dap_chain_net_srv_stake_key_get_node_addr(&l_signing_addr);
+                l_validator->signing_addr = l_signing_addr;
+                dap_list_t *l_validator_list = dap_list_append(NULL, l_validator);
+                s_message_send(l_session, DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB, &l_session->db_hash, l_session->db_serial,
+                               sizeof(*l_session->db_serial) + l_session->db_serial->data_size, l_validator_list);
+                dap_list_free_full(l_validator_list, NULL);
+            }
+            break;
+        }
         if (l_sync_attempt != l_session->cur_round.sync_attempt) {
             if (l_sync_attempt < l_session->cur_round.sync_attempt) {
                  debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U
@@ -1826,6 +2023,7 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
                                              " is greater than meassage sync attempt %"DAP_UINT64_FORMAT_U,
                                                 l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
                                                     l_session->cur_round.sync_attempt, l_sync_attempt);
+                 break;
             } else {
                 uint64_t l_attempts_miss = l_sync_attempt - l_session->cur_round.sync_attempt;
                 uint32_t l_attempts_miss_max = UINT16_MAX; // TODO calculate it rely on last block aceeption time & min round duration
@@ -1834,6 +2032,7 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
                                                 " SYNC message is rejected - too much sync attempt difference %"DAP_UINT64_FORMAT_U,
                                                    l_session->chain->net_name, l_session->chain->name, l_session->cur_round.id,
                                                        l_attempts_miss);
+                    break;
                 } else {
                     debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U
                                                 " SYNC message sync attempt %"DAP_UINT64_FORMAT_U" is greater than"
@@ -1856,19 +2055,38 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
         if (!l_list)
             break;
         dap_chain_esbocs_validator_t *l_validator = l_list->data;
-        l_validator->is_synced = true;
-        if (++l_session->cur_round.validators_synced_count == dap_list_length(l_session->cur_round.validators_list)) {
-            l_session->cur_round.id = s_session_calc_current_round_id(l_session);
-            debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
-                                        " All validators are synchronized, wait to submit candidate",
-                                            l_session->chain->net_name, l_session->chain->name,
-                                                l_session->cur_round.id, l_message->hdr.attempt_num);
-            s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, dap_time_now());
+        if (!l_validator->is_synced) {
+            l_validator->is_synced = true;
+            if (++l_session->cur_round.validators_synced_count == dap_list_length(l_session->cur_round.validators_list)) {
+                l_session->cur_round.id = s_session_calc_current_round_id(l_session);
+                debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
+                                            " All validators are synchronized, wait to submit candidate",
+                                                l_session->chain->net_name, l_session->chain->name,
+                                                    l_session->cur_round.id, l_message->hdr.attempt_num);
+                s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, dap_time_now());
+            }
+        }
+    } break;
+
+    case DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB: {
+        dap_global_db_pkt_t *l_db_pkt = l_message_data;
+        if (l_db_pkt->data_size + sizeof(*l_db_pkt) != l_message_data_size) {
+            log_it(L_WARNING, "Wrong send_db message size, have %zu bytes, must be %zu bytes",
+                                  l_message_data_size, l_db_pkt->data_size + sizeof(*l_db_pkt));
+            break;
+        }
+        size_t l_data_objs_count = 0;
+        dap_store_obj_t *l_store_objs = dap_global_db_pkt_deserialize(l_db_pkt, &l_data_objs_count);
+        for (size_t i = 0; i < l_data_objs_count; i++)
+            dap_global_db_remote_apply_obj(l_store_objs + i, NULL, NULL);
+        if (l_store_objs) {
+            dap_store_obj_free(l_store_objs, l_data_objs_count);
+            s_session_db_serialize(l_session);
         }
     } break;
 
     case DAP_CHAIN_ESBOCS_MSG_TYPE_SUBMIT: {
-        uint8_t *l_candidate = l_message->msg_n_sign;
+        uint8_t *l_candidate = l_message_data;
         size_t l_candidate_size = l_message_data_size;
         if (!l_candidate_size || dap_hash_fast_is_blank(&l_message->hdr.candidate_hash)) {
             debug_if(l_cs_debug, L_MSG, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
@@ -1910,6 +2128,10 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
 
         // store for new candidate
         l_store = DAP_NEW_Z(dap_chain_esbocs_store_t);
+        if (!l_store) {
+            log_it(L_ERROR, "Memory allocation error in s_session_packet_in");
+            goto session_unlock;
+        }
         l_store->candidate_size = l_candidate_size;
         l_store->candidate_hash = *l_candidate_hash;
         l_store->candidate = DAP_DUP_SIZE(l_candidate, l_candidate_size);
@@ -2045,7 +2267,7 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
             log_it(L_WARNING, "Only one directive can be processed at a time");
             break;
         }
-        dap_chain_esbocs_directive_t *l_directive = (dap_chain_esbocs_directive_t *)l_message->msg_n_sign;
+        dap_chain_esbocs_directive_t *l_directive = l_message_data;
         size_t l_directive_size = l_message_data_size;
         if (l_directive_size < sizeof(dap_chain_esbocs_directive_t) || l_directive_size != l_directive->size) {
             log_it(L_WARNING, "net:%s, chain:%s, round:%"DAP_UINT64_FORMAT_U", attempt:%hhu."
@@ -2110,15 +2332,16 @@ static void s_session_packet_in(void *a_arg, dap_chain_node_addr_t *a_sender_nod
             if (!l_session->cur_round.directive_applied &&
                     ++l_session->cur_round.votes_for_count * 3 >=
                         dap_list_length(l_session->cur_round.all_validators) * 2) {
-                s_session_directive_apply(l_session->cur_round.directive, &l_session->cur_round.directive_hash);
+                int l_res = s_session_directive_apply(l_session->cur_round.directive, &l_session->cur_round.directive_hash);
                 l_session->cur_round.directive_applied = true;
+                if (!l_res)
+                    s_session_db_serialize(l_session);
                 s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_PREVIOUS, dap_time_now());
             }
         } else // l_message->hdr.type == DAP_CHAIN_ESBOCS_MSG_TYPE_VOTE_AGAINST
             if (++l_session->cur_round.votes_against_count * 3 >=
                     dap_list_length(l_session->cur_round.all_validators) * 2)
                 s_session_state_change(l_session, DAP_CHAIN_ESBOCS_SESSION_STATE_PREVIOUS, dap_time_now());
-
     } break;
 
     case DAP_CHAIN_ESBOCS_MSG_TYPE_PRE_COMMIT:
@@ -2165,7 +2388,9 @@ static void s_message_send(dap_chain_esbocs_session_t *a_session, uint8_t a_mess
 
     for (dap_list_t *it = a_validators; it; it = it->next) {
         dap_chain_esbocs_validator_t *l_validator = it->data;
-        if (l_validator->is_synced || a_message_type == DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC) {
+        if (l_validator->is_synced ||
+                a_message_type == DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC ||
+                a_message_type == DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB) {
             debug_if(PVT(a_session->esbocs)->debug, L_MSG, "Send pkt type 0x%x to "NODE_ADDR_FP_STR,
                                                             a_message_type, NODE_ADDR_FP_ARGS_S(l_validator->node_addr));
             l_voting_pkt->hdr.receiver_node_addr = l_validator->node_addr;
@@ -2205,10 +2430,10 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
         return  -7;
     }
 
-    if (a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) {
+    /*if (a_block->hdr.meta_n_datum_n_signs_size != a_block_size - sizeof(a_block->hdr)) {
         log_it(L_WARNING, "Incorrect size with block %p on chain %s", a_block, a_blocks->chain->name);
         return -8;
-    }
+    }*/ // TODO Retunn it after hard-fork with correct block sizes
 
     if (l_esbocs->session && l_esbocs->session->processing_candidate == a_block)
         // It's a block candidate, don't check signs
@@ -2235,6 +2460,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
     uint16_t l_signs_verified_count = 0;
     size_t l_block_excl_sign_size = dap_chain_block_get_sign_offset(a_block, a_block_size) + sizeof(a_block->hdr);
     // Get the header on signing operation time
+    size_t l_block_original = a_block->hdr.meta_n_datum_n_signs_size;
     a_block->hdr.meta_n_datum_n_signs_size = l_block_excl_sign_size - sizeof(a_block->hdr);
     for (size_t i=0; i< l_signs_count; i++) {
         dap_sign_t *l_sign = (dap_sign_t *)l_signs[i];
@@ -2249,7 +2475,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
         if (!l_esbocs_pvt->poa_mode) {
              // Compare signature with delegated keys
             if (!dap_chain_net_srv_stake_key_delegated(&l_signing_addr)) {
-                char *l_bad_addr = dap_chain_addr_to_str(&l_signing_addr);
+                char *l_bad_addr = dap_chain_hash_fast_to_str_new(&l_signing_addr.data.hash_fast);
                 log_it(L_ATT, "Unknown PoS signer %s", l_bad_addr);
                 DAP_DELETE(l_bad_addr);
                 continue;
@@ -2268,14 +2494,16 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
     }
     DAP_DELETE(l_signs);
     // Restore the original header
-    a_block->hdr.meta_n_datum_n_signs_size = a_block_size - sizeof(a_block->hdr);
+    a_block->hdr.meta_n_datum_n_signs_size = l_block_original;
 
-    if ( l_ret != 0 ) {
-        return l_ret;
-    }
     if (l_signs_verified_count < l_esbocs_pvt->min_validators_count) {
-        log_it(L_ERROR, "Corrupted block: not enough authorized signs: %u of %u", l_signs_verified_count, l_esbocs_pvt->min_validators_count);
-        return -1;
+        dap_hash_fast_t l_block_hash;
+        dap_hash_fast(a_block, a_block_size, &l_block_hash);
+        char l_block_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+        dap_hash_fast_to_str(&l_block_hash, l_block_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
+        log_it(L_ERROR, "Corrupted block %s: not enough authorized signs: %u of %u",
+                    l_block_hash_str, l_signs_verified_count, l_esbocs_pvt->min_validators_count);
+        return l_ret ? l_ret : -4;
     }
     return 0;
 }
@@ -2305,12 +2533,21 @@ static dap_chain_datum_decree_t *s_esbocs_decree_set_min_validators_count(dap_ch
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(uint256_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in s_esbocs_decree_set_min_validators_count");
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT;
     l_tsd->size = sizeof(uint256_t);
     *(uint256_t*)(l_tsd->data) = a_value;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
 
     l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size);
+    if (!l_decree) {
+        log_it(L_ERROR, "Memory allocation error in s_esbocs_decree_set_min_validators_count");
+        DAP_DEL_Z(l_tsd);
+        return NULL;
+    }
     l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
@@ -2320,6 +2557,7 @@ static dap_chain_datum_decree_t *s_esbocs_decree_set_min_validators_count(dap_ch
         l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
     if(!l_chain){
         log_it(L_ERROR, "Can't find chain with decree support.");
+        DAP_DEL_Z(l_tsd);
         DAP_DELETE(l_decree);
         return NULL;
     }
@@ -2355,10 +2593,12 @@ static dap_chain_datum_decree_t *s_esbocs_decree_set_min_validators_count(dap_ch
         log_it(L_DEBUG,"<-- Signed with '%s'", a_cert->name);
     }else{
         log_it(L_ERROR, "Decree signing failed");
+        DAP_DEL_Z(l_tsd);
         DAP_DELETE(l_decree);
         return NULL;
     }
-
+    
+    DAP_DEL_Z(l_tsd);
     return l_decree;
 }
 
diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
index 6d99bb1b692a4ab8c2b24cfe6a5fdb78a875d6f2..cdee77d8c20e026e3ca0c01060f6f7ee4eedc2ce 100644
--- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
+++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h
@@ -5,8 +5,9 @@
 #include "dap_chain_block.h"
 #include "dap_chain_cs_blocks.h"
 #include "dap_cert.h"
+#include "dap_global_db_remote.h"
 
-#define DAP_CHAIN_ESBOCS_PROTOCOL_VERSION           6
+#define DAP_CHAIN_ESBOCS_PROTOCOL_VERSION           7
 #define DAP_CHAIN_ESBOCS_GDB_GROUPS_PREFIX          "esbocs"
 
 #define DAP_CHAIN_ESBOCS_MSG_TYPE_SUBMIT            0x04
@@ -18,6 +19,7 @@
 #define DAP_CHAIN_ESBOCS_MSG_TYPE_VOTE_FOR          0x22
 #define DAP_CHAIN_ESBOCS_MSG_TYPE_VOTE_AGAINST      0x24
 #define DAP_CHAIN_ESBOCS_MSG_TYPE_START_SYNC        0x32
+#define DAP_CHAIN_ESBOCS_MSG_TYPE_SEND_DB           0x36
 
 #define DAP_CHAIN_BLOCKS_SESSION_ROUND_ID_SIZE		8
 #define DAP_CHAIN_BLOCKS_SESSION_MESSAGE_ID_SIZE	8
@@ -161,6 +163,8 @@ typedef struct dap_chain_esbocs_session {
     uint8_t old_state; // for previous state return
     dap_chain_esbocs_round_t cur_round;
     bool round_fast_forward;
+    unsigned int listen_ensure;
+    bool sync_failed;
 
     dap_time_t ts_round_sync_start; // time of start sync
     dap_time_t ts_stage_entry; // time of current stage entrance
@@ -171,6 +175,9 @@ typedef struct dap_chain_esbocs_session {
     dap_chain_addr_t my_signing_addr;
 
     dap_chain_esbocs_penalty_item_t *penalty;
+    // Temporary sync-over-consensus params
+    dap_global_db_pkt_t *db_serial;
+    dap_hash_fast_t db_hash;
 
     struct dap_chain_esbocs_session *next;
     struct dap_chain_esbocs_session *prev;
diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c
index 608ea742ffe1cd4c9cc7cc9ece14dc0e1858a2dd..b9d4c4b149cd01286b5e544b5b0875b0c825114e 100644
--- a/modules/consensus/none/dap_chain_cs_none.c
+++ b/modules/consensus/none/dap_chain_cs_none.c
@@ -139,6 +139,7 @@ static void s_history_callback_notify(dap_global_db_context_t *a_context, dap_st
         dap_chain_net_t *l_net = dap_chain_net_by_id( l_gdb->chain->net_id);
         log_it(L_DEBUG,"%s.%s: op_code='%c' group=\"%s\" key=\"%s\" value_size=%zu",l_net->pub.name,
                l_gdb->chain->name, a_obj->type, a_obj->group, a_obj->key, a_obj->value_len);
+        s_chain_callback_atom_add(l_gdb->chain, a_obj->value, a_obj->value_len);
         dap_chain_net_sync_gdb_broadcast(a_context, a_obj, l_net);
     }
 }
@@ -170,7 +171,16 @@ static void s_callback_memepool_notify(dap_global_db_context_t *a_context UNUSED
 int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 {
     dap_chain_gdb_t *l_gdb = DAP_NEW_Z(dap_chain_gdb_t);
+    if (!l_gdb) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_gdb_new");
+        return -1;
+    }
     dap_chain_gdb_private_t *l_gdb_priv = DAP_NEW_Z(dap_chain_gdb_private_t);
+    if (!l_gdb_priv) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_gdb_new");
+        DAP_DELETE(l_gdb);
+        return -1;
+    }
     l_gdb->chain = a_chain;
     l_gdb->_internal = (void*) l_gdb_priv;
     a_chain->_inheritor = l_gdb;
@@ -239,7 +249,8 @@ void dap_chain_gdb_delete(dap_chain_t * a_chain)
     DAP_DELETE(l_gdb_priv->group_datums);
 
     DAP_DELETE(l_gdb);
-    a_chain->_inheritor = NULL;
+    if (a_chain)
+        a_chain->_inheritor = NULL;
 }
 
 /**
@@ -288,9 +299,9 @@ const char* dap_chain_gdb_get_group(dap_chain_t * a_chain)
  * @param a_values
  * @param a_arg
  */
-static void s_ledger_load_callback(dap_global_db_context_t *a_global_db_context,
-                                   int a_rc, const char *a_group,
-                                   const size_t a_values_total, const size_t a_values_count,
+static void s_ledger_load_callback(UNUSED_ARG dap_global_db_context_t *a_global_db_context,
+                                   UNUSED_ARG int a_rc, UNUSED_ARG const char *a_group,
+                                   UNUSED_ARG const size_t a_values_total, const size_t a_values_count,
                                    dap_global_db_obj_t *a_values, void *a_arg)
 {
     assert(a_arg);
@@ -302,7 +313,9 @@ static void s_ledger_load_callback(dap_global_db_context_t *a_global_db_context,
     assert(l_gdb_pvt);
     // make list of datums
     for(size_t i = 0; i < a_values_count; i++) {
-        s_chain_callback_atom_add(l_chain, a_values[i].value, a_values[i].value_len);
+        dap_global_db_obj_t *it = a_values + i;
+        s_chain_callback_atom_add(l_chain, it->value, it->value_len);
+        log_it(L_DEBUG,"Load mode, doesn't save item %s:%s", it->key, l_gdb_pvt->group_datums);
     }
 
     pthread_mutex_lock(&l_gdb_pvt->load_mutex);
@@ -340,12 +353,21 @@ static void s_chain_gdb_ledger_load(dap_chain_t *a_chain)
  * @param a_datums_count object counts in datums array
  * @return size_t
  */
-static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums,
-        size_t a_datums_count)
+static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, size_t a_datums_count)
 {
     for(size_t i = 0; i < a_datums_count; i++) {
-        dap_chain_datum_t * l_datum = a_datums[i];
-        s_chain_callback_atom_add(a_chain, l_datum,dap_chain_datum_size(l_datum) );
+        dap_chain_datum_t *l_datum = a_datums[i];
+        dap_hash_fast_t l_datum_hash;
+        char l_db_key[DAP_CHAIN_HASH_FAST_STR_SIZE];
+        dap_hash_fast(l_datum->data, l_datum->header.data_size, &l_datum_hash);
+        dap_chain_hash_fast_to_str(&l_datum_hash, l_db_key, sizeof(l_db_key));
+        int l_rc = dap_chain_net_verify_datum_for_add(a_chain, l_datum, &l_datum_hash);
+        if (l_rc != 0) {
+            log_it(L_ERROR, "Verified datum %s not passed the check, code %d", l_db_key, l_rc);
+            return i;
+        }
+        dap_global_db_set(PVT(DAP_CHAIN_GDB(a_chain))->group_datums, l_db_key, l_datum,
+                          dap_chain_datum_size(l_datum), false, NULL, NULL);
     }
     return a_datums_count;
 }
@@ -360,6 +382,10 @@ static size_t s_chain_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain
  */
 static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size)
 {
+    if (NULL == a_chain) {
+        log_it(L_WARNING, "Arguments is NULL for s_chain_callback_atom_add");
+        return ATOM_REJECT;
+    }
     dap_chain_gdb_t * l_gdb = DAP_CHAIN_GDB(a_chain);
     dap_chain_gdb_private_t *l_gdb_priv = PVT(l_gdb);
     dap_chain_datum_t *l_datum = (dap_chain_datum_t*) a_atom;
@@ -369,13 +395,13 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
         return ATOM_REJECT;
 
     dap_chain_gdb_datum_hash_item_t * l_hash_item = DAP_NEW_Z(dap_chain_gdb_datum_hash_item_t);
+    if (!l_hash_item) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_add");
+        return ATOM_REJECT;
+    }
     size_t l_datum_size = dap_chain_datum_size(l_datum);
     dap_hash_fast(l_datum->data,l_datum->header.data_size,&l_hash_item->datum_data_hash );
     dap_chain_hash_fast_to_str(&l_hash_item->datum_data_hash, l_hash_item->key, sizeof(l_hash_item->key));
-    if (!l_gdb_priv->is_load_mode) {
-        dap_global_db_set(l_gdb_priv->group_datums, l_hash_item->key, l_datum, l_datum_size, false, NULL, NULL);
-    } else
-        log_it(L_DEBUG,"Load mode, doesn't save item %s:%s", l_hash_item->key, l_gdb_priv->group_datums);
     DL_APPEND(l_gdb_priv->hash_items, l_hash_item);
     if (!l_gdb_priv->is_load_mode && a_chain->atom_notifiers) {
         for(dap_list_t *l_iter = a_chain->atom_notifiers; l_iter; l_iter = dap_list_next(l_iter)) {
@@ -425,6 +451,10 @@ static size_t s_chain_callback_atom_get_static_hdr_size()
 static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold)
 {
     dap_chain_atom_iter_t * l_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    if (!l_iter) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_iter_create");
+        return NULL;
+    }
     l_iter->chain = a_chain;
     l_iter->cell_id = a_cell_id;
     l_iter->with_treshold = a_with_treshold;
@@ -443,6 +473,10 @@ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t
         dap_chain_atom_ptr_t a_atom, size_t a_atom_size)
 {
     dap_chain_atom_iter_t * l_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    if (!l_iter) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_iter_create");
+        return NULL;
+    }
     l_iter->chain = a_chain;
     l_iter->cur = a_atom;
     l_iter->cur_size = a_atom_size;
@@ -608,6 +642,10 @@ static dap_chain_datum_t **s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t
         dap_chain_datum_t *l_datum = (dap_chain_datum_t *)a_atom;
         if (l_datum){
             dap_chain_datum_t **l_datums = DAP_NEW(dap_chain_datum_t *);
+            if (!l_datums) {
+                log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_get_datum");
+                return NULL;
+            }
             if (a_datums_count)
                 *a_datums_count = 1;
             l_datums[0] = l_datum;
diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c
index 562dbc76647670e61e86811e890870384605f6aa..be5d6ae3db2d0a7c1d165c7a33d6120c57bfb3c2 100644
--- a/modules/mempool/dap_chain_mempool.c
+++ b/modules/mempool/dap_chain_mempool.c
@@ -533,6 +533,12 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a
                 }
                 if ( memcmp(&l_out->addr, a_addr_from, sizeof (*a_addr_from))==0 ){
                     dap_chain_tx_used_out_item_t *l_item_back = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
+                    if (!l_item_back) {
+                        log_it(L_ERROR, "Memory allocation error in dap_chain_mempool_tx_create_massive");
+                        DAP_DELETE(l_objs);
+                        dap_list_free( l_list_out_items);
+                        return -6;
+                    }
                     l_item_back->tx_hash_fast = l_tx_new_hash;
                     l_item_back->num_idx_out = l_out_idx_tmp;
                     l_item_back->value = l_value_back;
@@ -828,21 +834,22 @@ char *dap_chain_mempool_tx_create_cond(dap_chain_net_t *a_net,
 
 char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_emission_hash,
                                        dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker,
-                                       dap_enc_key_t *a_key_from, dap_chain_addr_t *a_addr_to, dap_cert_t **a_certs, size_t a_certs_count,
+                                       dap_chain_addr_t *a_addr_to, dap_enc_key_t *a_private_key,
                                        const char *a_hash_out_type, uint256_t a_value_fee)
 {
     uint256_t l_net_fee = {};
     uint256_t l_total_fee = a_value_fee;
     uint256_t l_value_need = a_emission_value;
     uint256_t l_value_transfer = {};
-    dap_chain_addr_t l_addr_fee = {};
-    dap_chain_addr_t* l_addr_from = NULL;
+    dap_chain_addr_t l_addr_to_fee = {};
+    dap_chain_addr_t l_addr_from_fee = {};
     dap_list_t *l_list_used_out;
     const char *l_native_ticker = dap_chain_net_by_id(a_chain->net_id)->pub.native_ticker;
     bool not_native = dap_strcmp(a_ticker, l_native_ticker);
-    bool l_net_fee_used = dap_chain_net_tx_get_fee(a_chain->net_id, &l_net_fee, &l_addr_fee);
-    if(l_net_fee_used)
-        SUM_256_256(l_total_fee,l_net_fee,&l_total_fee);
+    bool l_net_fee_used = IS_ZERO_256(a_value_fee) ? false :
+                                                     dap_chain_net_tx_get_fee(a_chain->net_id, &l_net_fee, &l_addr_to_fee);
+    if (l_net_fee_used)
+        SUM_256_256(l_total_fee, l_net_fee, &l_total_fee);
 
     dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
     l_tx->header.ts_created = time(NULL);
@@ -855,21 +862,18 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
         dap_chain_datum_tx_delete(l_tx);
         return NULL;
     }
-    if (not_native)
+    if (not_native && !IS_ZERO_256(l_total_fee))
     {
-        l_addr_from = DAP_NEW_Z(dap_chain_addr_t);
-        dap_chain_addr_fill_from_key(l_addr_from, a_key_from, a_chain->net_id);
-        if(!l_addr_from){
+        if (dap_chain_addr_fill_from_key(&l_addr_from_fee, a_private_key, a_chain->net_id) != 0 ) {
             log_it(L_WARNING,"Can't fill address from transfer");
             dap_chain_datum_tx_delete(l_tx);
             return NULL;
         }
-            // list of transaction with 'out' items
+        // list of transaction with 'out' items
         l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(a_chain->ledger, l_native_ticker,
-                                                                                 l_addr_from, l_total_fee, &l_value_transfer);
+                                                                     &l_addr_from_fee, l_total_fee, &l_value_transfer);
         if (!l_list_used_out) {
             log_it(L_WARNING,"Not enough funds to transfer");
-            DAP_DEL_Z(l_addr_from);
             dap_chain_datum_tx_delete(l_tx);
             return NULL;
         }
@@ -881,72 +885,54 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
         }
          //add out
         uint256_t l_value_back = l_value_transfer; // how much datoshi add to 'out' items
-         // Network fee
-        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_fee, l_net_fee, l_native_ticker)){
-            dap_chain_datum_tx_delete(l_tx);
-            DAP_DEL_Z(l_addr_from);
-            return NULL;
+        // Network fee
+        if (l_net_fee_used) {
+            SUBTRACT_256_256(l_value_back, l_net_fee, &l_value_back);
+            if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_to_fee, l_net_fee, l_native_ticker)){
+                dap_chain_datum_tx_delete(l_tx);
+                return NULL;
+            }
         }
-        SUBTRACT_256_256(l_value_back, l_net_fee, &l_value_back);
-        if (!IS_ZERO_256(a_value_fee))
+        if (!IS_ZERO_256(a_value_fee)) {
             SUBTRACT_256_256(l_value_back, a_value_fee, &l_value_back);
+            if (!dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee)){
+                dap_chain_datum_tx_delete(l_tx);
+                return NULL;
+            }
+        }
         // coin back
-        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_native_ticker)){
+        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_from_fee, l_value_back, l_native_ticker)) {
             dap_chain_datum_tx_delete(l_tx);
-            DAP_DEL_Z(l_addr_from);
             return NULL;
         }
-        DAP_DEL_Z(l_addr_from);
-
-        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, l_value_need, a_ticker)){
+        if (!dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, l_value_need, a_ticker)) {
             dap_chain_datum_tx_delete(l_tx);
             return NULL;
         }
     } else { //native ticker
-        if (!IS_ZERO_256(a_value_fee))
+        if (!IS_ZERO_256(a_value_fee)) {
             SUBTRACT_256_256(l_value_need, a_value_fee, &l_value_need);
-        if(l_net_fee_used){
+            if (!dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee)){
+                dap_chain_datum_tx_delete(l_tx);
+                return NULL;
+            }
+        }
+        if (l_net_fee_used) {
             SUBTRACT_256_256(l_value_need, l_net_fee, &l_value_need);
-            if (!dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee)){
+            if (!dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_to_fee, l_net_fee)) {
                 dap_chain_datum_tx_delete(l_tx);
                 return NULL;
             }
         }
-        if (!dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, l_value_need)){
+        if (!dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, l_value_need)) {
             dap_chain_datum_tx_delete(l_tx);
             return NULL;
         }        
     }
-    if (!IS_ZERO_256(a_value_fee)){
-        if (!dap_chain_datum_tx_add_fee_item(&l_tx, a_value_fee)){
-            dap_chain_datum_tx_delete(l_tx);
-            return NULL;
-        }
-    }
     //sign item
-    if (not_native)
-    {
-        if(a_key_from)
-            if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) < 0) {
-                log_it(L_WARNING, "No private key for sign");
-                return NULL;
-            }
-    }
-    else{
-        if (a_certs) {
-            for(size_t i = 0; i < a_certs_count; i++) {
-                if(dap_chain_datum_tx_add_sign_item(&l_tx, a_certs[i]->enc_key) < 0) {
-                    log_it(L_WARNING, "No private key for certificate '%s'", a_certs[i]->name);
-                    return NULL;
-                }
-            }
-        }
-        else
-            if(a_key_from)
-                if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key_from) < 0) {
-                    log_it(L_WARNING, "No private key for sign");
-                    return NULL;
-                }
+    if(dap_chain_datum_tx_add_sign_item(&l_tx, a_private_key) < 0) {
+        log_it(L_WARNING, "No private key for sign");
+        return NULL;
     }
 
     size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
@@ -1054,6 +1040,10 @@ dap_datum_mempool_t * dap_datum_mempool_deserialize(uint8_t *a_datum_mempool_ser
     //uint8_t *a_datum_mempool_ser = DAP_NEW_Z_SIZE(uint8_t, datum_mempool_size / 2 + 1);
     //datum_mempool_size = hex2bin(a_datum_mempool_ser, datum_mempool_str_in, datum_mempool_size) / 2;
     dap_datum_mempool_t *datum_mempool = DAP_NEW_Z(dap_datum_mempool_t);
+    if (!datum_mempool) {
+        log_it(L_ERROR, "Memory allocation error in dap_datum_mempool_deserialize");
+        return NULL;
+    }
     datum_mempool->version = *(uint16_t*)(a_datum_mempool_ser + shift_size);
     shift_size += sizeof(uint16_t);
     datum_mempool->datum_count = *(uint16_t*)(a_datum_mempool_ser + shift_size);
diff --git a/modules/mempool/include/dap_chain_mempool.h b/modules/mempool/include/dap_chain_mempool.h
index f14bdce4ebae2ee3249b48147e618ab0b787a0e9..97a3042c191e27cf21c386cb799deadf115e269e 100644
--- a/modules/mempool/include/dap_chain_mempool.h
+++ b/modules/mempool/include/dap_chain_mempool.h
@@ -83,9 +83,23 @@ int dap_chain_mempool_tx_create_massive(dap_chain_t * a_chain, dap_enc_key_t *a_
         const char a_token_ticker[DAP_CHAIN_TICKER_SIZE_MAX],
         uint256_t a_value, uint256_t a_value_fee, size_t a_tx_num);
 
+/**
+ * @brief dap_chain_mempool_base_tx_create
+ * @param a_chain
+ * @param a_emission_hash
+ * @param a_emission_chain_id
+ * @param a_emission_value
+ * @param a_ticker
+ * @param a_addr_to
+ * @param a_private_key For a basic transaction not in a native token, use the key obtained from the wallet. For the
+ * basic transaction in the native token, use the key obtained from the certificate.
+ * @param a_hash_out_type
+ * @param a_value_fee
+ * @return
+ */
 char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_emission_hash,
                                        dap_chain_id_t a_emission_chain_id, uint256_t a_emission_value, const char *a_ticker,
-                                       dap_enc_key_t *a_key_from, dap_chain_addr_t *a_addr_to, dap_cert_t **a_certs, size_t a_certs_count,
+                                       dap_chain_addr_t *a_addr_to, dap_enc_key_t *a_private_key,
                                        const char *a_hash_out_type, uint256_t a_value_fee);
 
 dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_chain, const char *a_emission_hash_str);
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 81229ae1a2313b649130d8ceacddf5d5e5516058..c642c468154ca296e1c12fe133e3ab39b42d5339 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -115,8 +115,8 @@
 #include "dap_chain_node_dns_client.h"
 #include "dap_module.h"
 
-#include "json-c/json.h"
-#include "json-c/json_object.h"
+#include "json.h"
+#include "json_object.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_chain_net_srv_xchange.h"
 
@@ -329,7 +329,9 @@ int dap_chain_net_init()
         "net -net <chain net name> ca del -hash <cert hash> [-H {hex | base58(default)}]\n"
             "\tDelete certificate from list of authority cetificates in GDB group by it's hash\n"
         "net -net <chain net name> ledger reload\n"
-            "\tPurge the cache of chain net ledger and recalculate it from chain file\n");
+            "\tPurge the cache of chain net ledger and recalculate it from chain file\n"
+        "net -net <chain net name> poa_cets list\n"
+            "\tPrint list of PoA cerificates for this network\n");
     s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false);
     s_debug_more = dap_config_get_item_bool_default(g_config,"chain_net","debug_more",false);
 
@@ -443,6 +445,10 @@ dap_chain_net_state_t dap_chain_net_get_target_state(dap_chain_net_t *a_net)
 void dap_chain_net_add_gdb_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
 {
     dap_chain_gdb_notifier_t *l_notifier = DAP_NEW(dap_chain_gdb_notifier_t);
+    if (!l_notifier) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_add_gdb_notify_callback");
+        return;
+    }
     l_notifier->callback = a_callback;
     l_notifier->cb_arg = a_cb_arg;
     PVT(a_net)->gdb_notifiers = dap_list_append(PVT(a_net)->gdb_notifiers, l_notifier);
@@ -463,6 +469,11 @@ int dap_chain_net_add_downlink(dap_chain_net_t *a_net, dap_stream_worker_t *a_wo
         return -2;
     }
     l_downlink = DAP_NEW_Z(struct downlink);
+    if (!l_downlink) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_add_downlink");
+        pthread_rwlock_unlock(&l_net_pvt->downlinks_lock);
+        return -1;
+    }
     l_downlink->worker = a_worker;
     l_downlink->ch_uuid = a_ch_uuid;
     l_downlink->esocket_uuid = a_esocket_uuid;
@@ -489,12 +500,7 @@ void dap_chain_net_sync_gdb_broadcast(dap_global_db_context_t *a_context, dap_st
         return;
 
     dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
-    dap_chain_t *l_chain = NULL;
-    if (a_obj->type == DAP_DB$K_OPTYPE_ADD)
-        l_chain = dap_chain_get_chain_from_group_name(l_net->pub.id, a_obj->group);
-    dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t) {};
-    dap_chain_cell_id_t l_cell_id = l_chain ? l_chain->cells->id : (dap_chain_cell_id_t){};
-    dap_global_db_pkt_t *l_data_out = dap_store_packet_single(a_obj);
+    dap_global_db_pkt_t *l_data_out = dap_global_db_pkt_serialize(a_obj);
     struct downlink *l_link, *l_tmp;
     pthread_rwlock_rdlock(&PVT(l_net)->downlinks_lock);
     HASH_ITER(hh, PVT(l_net)->downlinks, l_link, l_tmp) {
@@ -507,7 +513,7 @@ void dap_chain_net_sync_gdb_broadcast(dap_global_db_context_t *a_context, dap_st
         if (!dap_stream_ch_chain_pkt_write_inter(a_context->queue_worker_ch_io_input[l_link->worker->worker->id],
                                              l_link->ch_uuid,
                                              DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, l_net->pub.id.uint64,
-                                             l_chain_id.uint64, l_cell_id.uint64, l_data_out,
+                                             0, 0, l_data_out,
                                              sizeof(dap_global_db_pkt_t) + l_data_out->data_size))
             debug_if(g_debug_reactor, L_ERROR, "Can't send pkt to worker (%d) for writing", l_link->worker->worker->id);
     }
@@ -556,8 +562,10 @@ static bool s_net_send_atoms(dap_proc_thread_t *a_thread, void *a_arg)
  */
 static void s_chain_callback_notify(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void* a_atom, size_t a_atom_size)
 {
-    if (!a_arg)
+    if (!a_arg || !a_chain) {
+        log_it(L_ERROR, "Argument is NULL for s_chain_callback_notify");
         return;
+    }
     dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
     if (!HASH_COUNT(PVT(l_net)->downlinks))
         return;
@@ -567,6 +575,10 @@ static void s_chain_callback_notify(void *a_arg, dap_chain_t *a_chain, dap_chain
         return;
 
     struct net_broadcast_atoms_args *l_args = DAP_NEW(struct net_broadcast_atoms_args);
+    if (!l_args) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_notify");
+        return;
+    }
     l_args->net = l_net;
     l_args->atom = DAP_DUP_SIZE(a_atom, a_atom_size);
     l_args->atom_size = a_atom_size;
@@ -691,6 +703,11 @@ static int s_net_link_add(dap_chain_net_t *a_net, dap_chain_node_info_t *a_link_
         return -3;
     }
     l_new_link = DAP_NEW_Z(struct net_link);
+    if (!l_new_link) {
+        log_it(L_ERROR, "Memory allocation error in s_net_link_add");
+        pthread_mutex_unlock(&PVT(a_net)->uplinks_mutex);
+        return -4;
+    }
     l_new_link->link_info = DAP_DUP(a_link_node_info);
     l_new_link->uplink_ip = a_link_node_info->hdr.ext_addr_v4.s_addr;
     HASH_ADD(hh, l_pvt_net->net_links, uplink_ip, sizeof(l_new_link->uplink_ip), l_new_link);
@@ -1139,6 +1156,10 @@ static bool s_new_balancer_link_request(dap_chain_net_t *a_net, int a_link_repla
     inet_ntop(AF_INET, &l_link_node_info->hdr.ext_addr_v4, l_node_addr_str, INET_ADDRSTRLEN);
     log_it(L_DEBUG, "Start balancer %s request to %s", PVT(a_net)->balancer_http ? "HTTP" : "DNS", l_node_addr_str);
     struct balancer_link_request *l_balancer_request = DAP_NEW_Z(struct balancer_link_request);
+    if (!l_balancer_request) {
+        log_it(L_ERROR, "Memory allocation error in s_new_balancer_link_request");
+        return false;
+    }
     l_balancer_request->net = a_net;
     l_balancer_request->link_info = l_link_node_info;
     l_balancer_request->worker = dap_events_worker_get_auto();
@@ -1296,6 +1317,11 @@ static bool s_net_states_proc(dap_proc_thread_t *a_thread, void *a_arg)
                 if (i >= l_net_pvt->gdb_sync_nodes_addrs_count)
                     break;
                 dap_chain_node_info_t *l_link_node_info = DAP_NEW_Z(dap_chain_node_info_t);
+                if (!l_link_node_info) {
+                    log_it(L_ERROR, "Memory allocation error in s_net_states_proc");
+                    pthread_rwlock_unlock(&l_net_pvt->states_lock);
+                    return false;
+                }
                 l_link_node_info->hdr.address.uint64 = l_net_pvt->gdb_sync_nodes_addrs[i].uint64;
                 l_link_node_info->hdr.ext_addr_v4.s_addr = l_net_pvt->gdb_sync_nodes_links_ips[i];
                 l_link_node_info->hdr.ext_port = l_net_pvt->gdb_sync_nodes_links_ports[i];
@@ -1453,6 +1479,10 @@ static dap_chain_net_t *s_net_new(const char *a_id, const char *a_name,
     if (!a_id || !a_name || !a_native_ticker || !a_node_role)
         return NULL;
     dap_chain_net_t *ret = DAP_NEW_Z_SIZE( dap_chain_net_t, sizeof(ret->pub) + sizeof(dap_chain_net_pvt_t) );
+    if (!ret) {
+        log_it(L_ERROR, "Memory allocation error in s_net_new");
+        return NULL;
+    }
     ret->pub.name = strdup( a_name );
     ret->pub.native_ticker = strdup( a_native_ticker );
     pthread_mutexattr_t l_mutex_attr;
@@ -1791,6 +1821,7 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply)
         const char *l_stats_str = NULL;
         const char *l_ca_str = NULL;
         const char *l_ledger_str = NULL;
+        const char *l_list_str = NULL;
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "sync", &l_sync_str);
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "link", &l_links_str);
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "go", &l_go_str);
@@ -1798,6 +1829,7 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply)
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "stats", &l_stats_str);
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "ca", &l_ca_str);
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "ledger", &l_ledger_str);
+        dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "poa_certs", &l_list_str);
 
         const char * l_sync_mode_str = "updates";
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-mode", &l_sync_mode_str);
@@ -2121,6 +2153,31 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply)
             s_chain_net_ledger_cache_reload(l_net);
             if (l_return_state)
                 dap_chain_net_start(l_net);
+        } else if (l_list_str && !strcmp(l_list_str, "list")) {
+            dap_list_t *l_net_keys = NULL;
+            for (dap_chain_t *l_chain = l_net->pub.chains; l_chain; l_chain = l_chain->next) {
+                if (!l_chain->callback_get_poa_certs)
+                    continue;
+                l_net_keys = l_chain->callback_get_poa_certs(l_chain, NULL, NULL);
+                if (l_net_keys)
+                    break;
+            }
+            if (!l_net_keys) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "No PoA certs found for this network");
+                return -11;
+            }
+            dap_string_t *l_str_out = dap_string_new("List of network PoA certificates:\n");
+            int i = 0;
+            for (dap_list_t *it = l_net_keys; it; it = it->next) {
+                dap_hash_fast_t l_pkey_hash;
+                char l_pkey_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+                dap_pkey_get_hash(it->data, &l_pkey_hash);
+                dap_chain_hash_fast_to_str(&l_pkey_hash, l_pkey_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
+                dap_string_append_printf(l_str_out, "%d) %s\n", i++, l_pkey_hash_str);
+            }
+            *a_str_reply = l_str_out->str;
+            dap_string_free(l_str_out, false);
+
         } else {
             dap_cli_server_cmd_set_reply_text(a_str_reply,
                                               "Command 'net' requires one of subcomands: sync, link, go, get, stats, ca, ledger");
@@ -2203,365 +2260,475 @@ int s_net_init(const char * a_net_name, uint16_t a_acl_idx)
         log_it(L_ERROR,"Can't open default network config");
         dap_string_free(l_cfg_path,true);
         return -1;
-    } else {
-        dap_string_free(l_cfg_path,true);
-        dap_chain_net_t * l_net = s_net_new(
-                                            dap_config_get_item_str(l_cfg , "general" , "id" ),
-                                            dap_config_get_item_str(l_cfg , "general" , "name" ),
-                                            dap_config_get_item_str(l_cfg , "general" , "native_ticker"),
-                                            dap_config_get_item_str(l_cfg , "general" , "node-role" )
-                                           );
-        if(!l_net) {
-            log_it(L_ERROR,"Can't create l_net");
+    }
+    dap_string_free(l_cfg_path,true);
+    dap_chain_net_t * l_net = s_net_new(
+                                        dap_config_get_item_str(l_cfg , "general" , "id" ),
+                                        dap_config_get_item_str(l_cfg , "general" , "name" ),
+                                        dap_config_get_item_str(l_cfg , "general" , "native_ticker"),
+                                        dap_config_get_item_str(l_cfg , "general" , "node-role" )
+                                       );
+    if(!l_net) {
+        log_it(L_ERROR,"Can't create l_net");
+        return -1;
+    }
+    dap_chain_net_pvt_t * l_net_pvt = PVT(l_net);
+    l_net_pvt->load_mode = true;
+    l_net_pvt->acl_idx = a_acl_idx;
+    l_net->pub.gdb_groups_prefix = dap_strdup (
+                dap_config_get_item_str_default(l_cfg , "general" , "gdb_groups_prefix",
+                                                dap_config_get_item_str(l_cfg , "general" , "name" ) ) );
+    dap_global_db_add_sync_group(l_net->pub.name, "global", s_gbd_history_callback_notify, l_net);
+    dap_global_db_add_sync_group(l_net->pub.name, l_net->pub.gdb_groups_prefix, s_gbd_history_callback_notify, l_net);
+
+    l_net->pub.gdb_nodes = dap_strdup_printf("%s.nodes",l_net->pub.gdb_groups_prefix);
+    l_net->pub.gdb_nodes_aliases = dap_strdup_printf("%s.nodes.aliases",l_net->pub.gdb_groups_prefix);
+
+    // nodes for special sync
+    char **l_gdb_sync_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "gdb_sync_nodes_addrs",
+            &l_net_pvt->gdb_sync_nodes_addrs_count);
+    if(l_gdb_sync_nodes_addrs && l_net_pvt->gdb_sync_nodes_addrs_count > 0) {
+        l_net_pvt->gdb_sync_nodes_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
+                sizeof(dap_chain_node_addr_t)*l_net_pvt->gdb_sync_nodes_addrs_count);
+        if (!l_net_pvt->gdb_sync_nodes_addrs) {
+            log_it(L_ERROR, "Memory allocation error in s_net_init");
+            dap_config_close(l_cfg);
             return -1;
         }
-        dap_chain_net_pvt_t * l_net_pvt = PVT(l_net);
-        l_net_pvt->load_mode = true;
-        l_net_pvt->acl_idx = a_acl_idx;
-        l_net->pub.gdb_groups_prefix = dap_strdup (
-                    dap_config_get_item_str_default(l_cfg , "general" , "gdb_groups_prefix",
-                                                    dap_config_get_item_str(l_cfg , "general" , "name" ) ) );
-        dap_global_db_add_sync_group(l_net->pub.name, "global", s_gbd_history_callback_notify, l_net);
-        dap_global_db_add_sync_group(l_net->pub.name, l_net->pub.gdb_groups_prefix, s_gbd_history_callback_notify, l_net);
-
-        l_net->pub.gdb_nodes = dap_strdup_printf("%s.nodes",l_net->pub.gdb_groups_prefix);
-        l_net->pub.gdb_nodes_aliases = dap_strdup_printf("%s.nodes.aliases",l_net->pub.gdb_groups_prefix);
-
-        // nodes for special sync
-        char **l_gdb_sync_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "gdb_sync_nodes_addrs",
-                &l_net_pvt->gdb_sync_nodes_addrs_count);
-        if(l_gdb_sync_nodes_addrs && l_net_pvt->gdb_sync_nodes_addrs_count > 0) {
-            l_net_pvt->gdb_sync_nodes_addrs = DAP_NEW_Z_SIZE(dap_chain_node_addr_t,
-                    sizeof(dap_chain_node_addr_t)*l_net_pvt->gdb_sync_nodes_addrs_count);
-            for(uint16_t i = 0; i < l_net_pvt->gdb_sync_nodes_addrs_count; i++) {
-                dap_chain_node_addr_from_str(l_net_pvt->gdb_sync_nodes_addrs + i, l_gdb_sync_nodes_addrs[i]);
-            }
+        for(uint16_t i = 0; i < l_net_pvt->gdb_sync_nodes_addrs_count; i++) {
+            dap_chain_node_addr_from_str(l_net_pvt->gdb_sync_nodes_addrs + i, l_gdb_sync_nodes_addrs[i]);
         }
-        // links for special sync
-        uint16_t l_gdb_links_count = 0;
-        PVT(l_net)->gdb_sync_nodes_links_count = 0;
-        char **l_gdb_sync_nodes_links = dap_config_get_array_str(l_cfg, "general", "gdb_sync_nodes_links", &l_gdb_links_count);
-        if (l_gdb_sync_nodes_links && l_gdb_links_count > 0) {
-            l_net_pvt->gdb_sync_nodes_links_ips = DAP_NEW_Z_SIZE(uint32_t, l_gdb_links_count * sizeof(uint32_t));
-            l_net_pvt->gdb_sync_nodes_links_ports = DAP_NEW_SIZE(uint16_t, l_gdb_links_count * sizeof(uint16_t));
-            for(uint16_t i = 0; i < l_gdb_links_count; i++) {
-                char *l_gdb_link_port_str = strchr(l_gdb_sync_nodes_links[i], ':');
-                if (!l_gdb_link_port_str) {
-                    continue;
-                }
-                uint16_t l_gdb_link_port = atoi(l_gdb_link_port_str + 1);
-                if (!l_gdb_link_port) {
-                    continue;
-                }
-                int l_gdb_link_len = l_gdb_link_port_str - l_gdb_sync_nodes_links[i];
-                char l_gdb_link_ip_str[l_gdb_link_len + 1];
-                memcpy(l_gdb_link_ip_str, l_gdb_sync_nodes_links[i], l_gdb_link_len);
-                l_gdb_link_ip_str[l_gdb_link_len] = '\0';
-                struct in_addr l_in_addr;
-                if (inet_pton(AF_INET, (const char *)l_gdb_link_ip_str, &l_in_addr) > 0) {
-                    PVT(l_net)->gdb_sync_nodes_links_ips[PVT(l_net)->gdb_sync_nodes_links_count] = l_in_addr.s_addr;
-                    PVT(l_net)->gdb_sync_nodes_links_ports[PVT(l_net)->gdb_sync_nodes_links_count] = l_gdb_link_port;
-                    PVT(l_net)->gdb_sync_nodes_links_count++;
-                }
-            }
+    }
+    // links for special sync
+    uint16_t l_gdb_links_count = 0;
+    PVT(l_net)->gdb_sync_nodes_links_count = 0;
+    char **l_gdb_sync_nodes_links = dap_config_get_array_str(l_cfg, "general", "gdb_sync_nodes_links", &l_gdb_links_count);
+    if (l_gdb_sync_nodes_links && l_gdb_links_count > 0) {
+        l_net_pvt->gdb_sync_nodes_links_ips = DAP_NEW_Z_SIZE(uint32_t, l_gdb_links_count * sizeof(uint32_t));
+        if (!l_net_pvt->gdb_sync_nodes_links_ips) {
+            log_it(L_ERROR, "Memory allocation error in s_net_init");
+            dap_config_close(l_cfg);
+            return -1;
         }
-        // groups for special sync
-        uint16_t l_gdb_sync_groups_count;
-        char **l_gdb_sync_groups = dap_config_get_array_str(l_cfg, "general", "gdb_sync_groups", &l_gdb_sync_groups_count);
-        if (l_gdb_sync_groups && l_gdb_sync_groups_count > 0) {
-            for(uint16_t i = 0; i < l_gdb_sync_groups_count; i++) {
-                // add group to special sync
-                dap_global_db_add_sync_extra_group(l_net->pub.name, l_gdb_sync_groups[i], s_gbd_history_callback_notify, l_net);
-            }
+        l_net_pvt->gdb_sync_nodes_links_ports = DAP_NEW_SIZE(uint16_t, l_gdb_links_count * sizeof(uint16_t));
+        if (!l_net_pvt->gdb_sync_nodes_links_ports) {
+            log_it(L_ERROR, "Memory allocation error in s_net_init");
+            DAP_DEL_Z(l_net_pvt->gdb_sync_nodes_links_ips);
+            dap_config_close(l_cfg);
+            return -1;
         }
-
-        // Add network to the list
-        dap_chain_net_item_t * l_net_item = DAP_NEW_Z( dap_chain_net_item_t);
-        snprintf(l_net_item->name,sizeof (l_net_item->name),"%s"
-                     ,dap_config_get_item_str(l_cfg , "general" , "name" ));
-        l_net_item->chain_net = l_net;
-        l_net_item->net_id.uint64 = l_net->pub.id.uint64;
-        pthread_rwlock_wrlock(&s_net_items_rwlock);
-        HASH_ADD_STR(s_net_items,name,l_net_item);
-        HASH_ADD(hh2, s_net_ids, net_id, sizeof(l_net_item->net_id), l_net_item);
-        pthread_rwlock_unlock(&s_net_items_rwlock);
-
-        // LEDGER model
-        uint16_t l_ledger_flags = 0;
-        switch ( PVT( l_net )->node_role.enums ) {
-        case NODE_ROLE_LIGHT:
-            break;
-        case NODE_ROLE_FULL:
-            l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_LOCAL_DS | DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION;
-            if (dap_config_get_item_bool_default(g_config, "ledger", "cache_enabled", true))
-                l_ledger_flags |= DAP_CHAIN_LEDGER_CACHE_ENABLED;
-        default:
-            l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_CELLS_DS;
+        for(uint16_t i = 0; i < l_gdb_links_count; i++) {
+            char *l_gdb_link_port_str = strchr(l_gdb_sync_nodes_links[i], ':');
+            if (!l_gdb_link_port_str) {
+                continue;
+            }
+            uint16_t l_gdb_link_port = atoi(l_gdb_link_port_str + 1);
+            if (!l_gdb_link_port)
+                continue;
+            int l_gdb_link_len = l_gdb_link_port_str - l_gdb_sync_nodes_links[i];
+            char l_gdb_link_ip_str[l_gdb_link_len + 1];
+            memcpy(l_gdb_link_ip_str, l_gdb_sync_nodes_links[i], l_gdb_link_len);
+            l_gdb_link_ip_str[l_gdb_link_len] = '\0';
+            struct in_addr l_in_addr;
+            if (inet_pton(AF_INET, (const char *)l_gdb_link_ip_str, &l_in_addr) > 0) {
+                PVT(l_net)->gdb_sync_nodes_links_ips[PVT(l_net)->gdb_sync_nodes_links_count] = l_in_addr.s_addr;
+                PVT(l_net)->gdb_sync_nodes_links_ports[PVT(l_net)->gdb_sync_nodes_links_count] = l_gdb_link_port;
+                PVT(l_net)->gdb_sync_nodes_links_count++;
+            }
         }
-        // init LEDGER model
-        l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags, l_net->pub.name, l_net->pub.native_ticker);
-        // Check if seed nodes are present in local db alias
-        char **l_seed_aliases = dap_config_get_array_str(l_cfg, "general", "seed_nodes_aliases",
-                                                         &l_net_pvt->seed_aliases_count);
-        if (l_net_pvt->seed_aliases_count)
-            l_net_pvt->seed_aliases = DAP_NEW_Z_SIZE(char*, sizeof(char*) * l_net_pvt->seed_aliases_count);
-        for(size_t i = 0; i < l_net_pvt->seed_aliases_count; i++)
-            l_net_pvt->seed_aliases[i] = dap_strdup(l_seed_aliases[i]);
-        // randomize seed nodes list
-        for (int j = l_net_pvt->seed_aliases_count - 1; j > 0; j--) {
-            int n = rand() % j;
-            char *tmp = l_net_pvt->seed_aliases[n];
-            l_net_pvt->seed_aliases[n] = l_net_pvt->seed_aliases[j];
-            l_net_pvt->seed_aliases[j] = tmp;
+    }
+    // groups for special sync
+    uint16_t l_gdb_sync_groups_count;
+    char **l_gdb_sync_groups = dap_config_get_array_str(l_cfg, "general", "gdb_sync_groups", &l_gdb_sync_groups_count);
+    if (l_gdb_sync_groups && l_gdb_sync_groups_count > 0) {
+        for(uint16_t i = 0; i < l_gdb_sync_groups_count; i++) {
+            // add group to special sync
+            dap_global_db_add_sync_extra_group(l_net->pub.name, l_gdb_sync_groups[i], s_gbd_history_callback_notify, l_net);
         }
+    }
 
-        uint16_t l_seed_nodes_addrs_len =0;
-        char ** l_seed_nodes_addrs = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_addrs"
-                                                             ,&l_seed_nodes_addrs_len);
-
-        uint16_t l_seed_nodes_ipv4_len =0;
-        char ** l_seed_nodes_ipv4 = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_ipv4"
-                                                             ,&l_seed_nodes_ipv4_len);
-
-        uint16_t l_seed_nodes_ipv6_len =0;
-        char ** l_seed_nodes_ipv6 = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_ipv6"
-                                                             ,&l_seed_nodes_ipv6_len);
-
-        uint16_t l_seed_nodes_hostnames_len =0;
-        char ** l_seed_nodes_hostnames = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_hostnames"
-                                                             ,&l_seed_nodes_hostnames_len);
-
-        uint16_t l_seed_nodes_port_len =0;
-        char ** l_seed_nodes_port = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_port"
-                                                                     ,&l_seed_nodes_port_len);
-        uint16_t l_bootstrap_nodes_len = 0;
-        char **l_bootstrap_nodes = dap_config_get_array_str(l_cfg, "general", "bootstrap_hostnames", &l_bootstrap_nodes_len);
-
-        // maximum number of prepared connections to other nodes
-        l_net_pvt->max_links_count = dap_config_get_item_int16_default(l_cfg, "general", "max_links", 5);
-        // required number of active connections to other nodes
-        l_net_pvt->required_links_count = dap_config_get_item_int16_default(l_cfg, "general", "require_links", 3);
-        // wait time before reconnect attempt with same link
-        l_net_pvt->reconnect_delay = dap_config_get_item_int16_default(l_cfg, "general", "reconnect_delay", 10);
-
-        const char * l_node_addr_type = dap_config_get_item_str_default(l_cfg , "general" ,"node_addr_type","auto");
-
-        const char * l_node_addr_str = NULL;
-        const char * l_node_alias_str = NULL;
-
-        // use unique addr from pub key
-        if(!dap_strcmp(l_node_addr_type, "auto")) {
-            size_t l_pub_key_data_size = 0;
-            uint8_t *l_pub_key_data = NULL;
-
-            // read pub key
-            char *l_addr_key = dap_strdup_printf("node-addr-%s", l_net->pub.name);
-            l_pub_key_data = dap_global_db_get_sync(GROUP_LOCAL_NODE_ADDR, l_addr_key, &l_pub_key_data_size, NULL, NULL);
-            // generate a new pub key if it doesn't exist
-            if(!l_pub_key_data || !l_pub_key_data_size){
-
-                const char * l_certs_name_str = l_addr_key;
-                dap_cert_t ** l_certs = NULL;
-                size_t l_certs_size = 0;
-                dap_cert_t * l_cert = NULL;
-                // Load certs or create if not found
-                if(!dap_cert_parse_str_list(l_certs_name_str, &l_certs, &l_certs_size)) { // Load certs
-                    const char *l_cert_folder = dap_cert_get_folder(0);
-                    // create new cert
-                    if(l_cert_folder) {
-                        char *l_cert_path = dap_strdup_printf("%s/%s.dcert", l_cert_folder, l_certs_name_str);
-                        l_cert = dap_cert_generate(l_certs_name_str, l_cert_path, DAP_ENC_KEY_TYPE_SIG_DILITHIUM);
-                        DAP_DELETE(l_cert_path);
-                    }
-                }
-                if(l_certs_size > 0)
-                    l_cert = l_certs[0];
-                if(l_cert) {
-                    l_pub_key_data = dap_enc_key_serialize_pub_key(l_cert->enc_key, &l_pub_key_data_size);
-                    // save pub key
-                    if(l_pub_key_data && l_pub_key_data_size > 0)
-                        dap_global_db_set(GROUP_LOCAL_NODE_ADDR, l_addr_key, l_pub_key_data, l_pub_key_data_size, false,
-                                            NULL, NULL);
+    // Add network to the list
+    dap_chain_net_item_t * l_net_item = DAP_NEW_Z( dap_chain_net_item_t);
+    if (!l_net_item) {
+        log_it(L_ERROR, "Memory allocation error in s_net_init");
+        dap_config_close(l_cfg);
+        return -1;
+    }
+    snprintf(l_net_item->name,sizeof (l_net_item->name),"%s"
+                 ,dap_config_get_item_str(l_cfg , "general" , "name" ));
+    l_net_item->chain_net = l_net;
+    l_net_item->net_id.uint64 = l_net->pub.id.uint64;
+    pthread_rwlock_wrlock(&s_net_items_rwlock);
+    HASH_ADD_STR(s_net_items,name,l_net_item);
+    HASH_ADD(hh2, s_net_ids, net_id, sizeof(l_net_item->net_id), l_net_item);
+    pthread_rwlock_unlock(&s_net_items_rwlock);
+
+    // Check if seed nodes are present in local db alias
+    char **l_seed_aliases = dap_config_get_array_str(l_cfg, "general", "seed_nodes_aliases",
+                                                     &l_net_pvt->seed_aliases_count);
+    if (l_net_pvt->seed_aliases_count)
+        l_net_pvt->seed_aliases = DAP_NEW_Z_SIZE(char*, sizeof(char*) * l_net_pvt->seed_aliases_count);
+    for(size_t i = 0; i < l_net_pvt->seed_aliases_count; i++)
+        l_net_pvt->seed_aliases[i] = dap_strdup(l_seed_aliases[i]);
+    // randomize seed nodes list
+    for (int j = l_net_pvt->seed_aliases_count - 1; j > 0; j--) {
+        int n = rand() % j;
+        char *tmp = l_net_pvt->seed_aliases[n];
+        l_net_pvt->seed_aliases[n] = l_net_pvt->seed_aliases[j];
+        l_net_pvt->seed_aliases[j] = tmp;
+    }
+
+    uint16_t l_seed_nodes_addrs_len =0;
+    char ** l_seed_nodes_addrs = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_addrs"
+                                                         ,&l_seed_nodes_addrs_len);
+
+    uint16_t l_seed_nodes_ipv4_len =0;
+    char ** l_seed_nodes_ipv4 = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_ipv4"
+                                                         ,&l_seed_nodes_ipv4_len);
+
+    uint16_t l_seed_nodes_ipv6_len =0;
+    char ** l_seed_nodes_ipv6 = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_ipv6"
+                                                         ,&l_seed_nodes_ipv6_len);
+
+    uint16_t l_seed_nodes_hostnames_len =0;
+    char ** l_seed_nodes_hostnames = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_hostnames"
+                                                         ,&l_seed_nodes_hostnames_len);
+
+    uint16_t l_seed_nodes_port_len =0;
+    char ** l_seed_nodes_port = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_port"
+                                                                 ,&l_seed_nodes_port_len);
+    uint16_t l_bootstrap_nodes_len = 0;
+    char **l_bootstrap_nodes = dap_config_get_array_str(l_cfg, "general", "bootstrap_hostnames", &l_bootstrap_nodes_len);
+
+    // maximum number of prepared connections to other nodes
+    l_net_pvt->max_links_count = dap_config_get_item_int16_default(l_cfg, "general", "max_links", 5);
+    // required number of active connections to other nodes
+    l_net_pvt->required_links_count = dap_config_get_item_int16_default(l_cfg, "general", "require_links", 3);
+    // wait time before reconnect attempt with same link
+    l_net_pvt->reconnect_delay = dap_config_get_item_int16_default(l_cfg, "general", "reconnect_delay", 10);
+
+    const char * l_node_addr_type = dap_config_get_item_str_default(l_cfg , "general" ,"node_addr_type","auto");
+
+    const char * l_node_addr_str = NULL;
+    const char * l_node_alias_str = NULL;
+
+    // use unique addr from pub key
+    if(!dap_strcmp(l_node_addr_type, "auto")) {
+        size_t l_pub_key_data_size = 0;
+        uint8_t *l_pub_key_data = NULL;
+
+        // read pub key
+        char *l_addr_key = dap_strdup_printf("node-addr-%s", l_net->pub.name);
+        l_pub_key_data = dap_global_db_get_sync(GROUP_LOCAL_NODE_ADDR, l_addr_key, &l_pub_key_data_size, NULL, NULL);
+        // generate a new pub key if it doesn't exist
+        if(!l_pub_key_data || !l_pub_key_data_size){
+
+            const char * l_certs_name_str = l_addr_key;
+            dap_cert_t ** l_certs = NULL;
+            size_t l_certs_size = 0;
+            dap_cert_t * l_cert = NULL;
+            // Load certs or create if not found
+            if(!dap_cert_parse_str_list(l_certs_name_str, &l_certs, &l_certs_size)) { // Load certs
+                const char *l_cert_folder = dap_cert_get_folder(0);
+                // create new cert
+                if(l_cert_folder) {
+                    char *l_cert_path = dap_strdup_printf("%s/%s.dcert", l_cert_folder, l_certs_name_str);
+                    l_cert = dap_cert_generate(l_certs_name_str, l_cert_path, DAP_ENC_KEY_TYPE_SIG_DILITHIUM);
+                    DAP_DELETE(l_cert_path);
                 }
             }
-            // generate addr from pub_key
-            dap_chain_hash_fast_t l_hash;
-            if(l_pub_key_data_size > 0 && dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash) == 1) {
-                l_node_addr_str = dap_strdup_printf("%04X::%04X::%04X::%04X",
-                        (uint16_t) *(uint16_t*) (l_hash.raw),
-                        (uint16_t) *(uint16_t*) (l_hash.raw + 2),
-                        (uint16_t) *(uint16_t*) (l_hash.raw + DAP_CHAIN_HASH_FAST_SIZE - 4),
-                        (uint16_t) *(uint16_t*) (l_hash.raw + DAP_CHAIN_HASH_FAST_SIZE - 2));
+            if(l_certs_size > 0)
+                l_cert = l_certs[0];
+            if(l_cert) {
+                l_pub_key_data = dap_enc_key_serialize_pub_key(l_cert->enc_key, &l_pub_key_data_size);
+                // save pub key
+                if(l_pub_key_data && l_pub_key_data_size > 0)
+                    dap_global_db_set(GROUP_LOCAL_NODE_ADDR, l_addr_key, l_pub_key_data, l_pub_key_data_size, false,
+                                        NULL, NULL);
             }
-            DAP_DELETE(l_addr_key);
-            DAP_DELETE(l_pub_key_data);
         }
-        // use static addr from setting
-        else if(!dap_strcmp(l_node_addr_type, "static")) {
-            //const char * l_node_ipv4_str = dap_config_get_item_str(l_cfg , "general" ,"node-ipv4");
-            l_node_addr_str = dap_strdup(dap_config_get_item_str(l_cfg, "general", "node-addr"));
-            l_node_alias_str = dap_config_get_item_str(l_cfg, "general", "node-alias");
+        // generate addr from pub_key
+        dap_chain_hash_fast_t l_hash;
+        if(l_pub_key_data_size > 0 && dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash) == 1) {
+            l_node_addr_str = dap_strdup_printf("%04X::%04X::%04X::%04X",
+                    (uint16_t) *(uint16_t*) (l_hash.raw),
+                    (uint16_t) *(uint16_t*) (l_hash.raw + 2),
+                    (uint16_t) *(uint16_t*) (l_hash.raw + DAP_CHAIN_HASH_FAST_SIZE - 4),
+                    (uint16_t) *(uint16_t*) (l_hash.raw + DAP_CHAIN_HASH_FAST_SIZE - 2));
         }
-
-        log_it (L_DEBUG, "Read %u aliases, %u address and %u ipv4 addresses, check them",
-                l_net_pvt->seed_aliases_count,l_seed_nodes_addrs_len, l_seed_nodes_ipv4_len );
-        PVT(l_net)->seed_nodes_addrs_v4 = DAP_NEW_SIZE(struct in_addr, l_net_pvt->seed_aliases_count * sizeof(struct in_addr));
-        // save new nodes from cfg file to db
-        for ( size_t i = 0; i < PVT(l_net)->seed_aliases_count &&
-                            i < l_seed_nodes_addrs_len &&
-                            (
-                                ( l_seed_nodes_ipv4_len  && i < l_seed_nodes_ipv4_len  ) ||
-                                ( l_seed_nodes_ipv6_len  && i < l_seed_nodes_ipv6_len  ) ||
-                                ( l_seed_nodes_hostnames_len  && i < l_seed_nodes_hostnames_len  )
-                            ); i++) {
-            dap_chain_node_addr_t l_seed_node_addr  = { 0 }, *l_seed_node_addr_gdb  = NULL;
-            dap_chain_node_info_t l_node_info       = { 0 }, *l_node_info_gdb       = NULL;
-
-            log_it(L_NOTICE, "Check alias %s in db", l_net_pvt->seed_aliases[i]);
-            snprintf(l_node_info.hdr.alias,sizeof (l_node_info.hdr.alias),"%s", PVT(l_net)->seed_aliases[i]);
-            if (dap_chain_node_addr_from_str(&l_seed_node_addr, l_seed_nodes_addrs[i])) {
-                log_it(L_ERROR,"Wrong address format, must be 0123::4567::89AB::CDEF");
-                continue;
-            }
-            if (l_seed_nodes_ipv4_len)
-                inet_pton(AF_INET, l_seed_nodes_ipv4[i], &l_node_info.hdr.ext_addr_v4);
-            if (l_seed_nodes_ipv6_len)
-                inet_pton(AF_INET6, l_seed_nodes_ipv6[i], &l_node_info.hdr.ext_addr_v6);
-            l_node_info.hdr.ext_port = l_seed_nodes_port_len && l_seed_nodes_port_len >= i ?
-                strtoul(l_seed_nodes_port[i], NULL, 10) : 8079;
-
-            if (l_seed_nodes_hostnames_len) {
-                struct sockaddr l_sa = {};
-                log_it(L_DEBUG, "Resolve %s addr", l_seed_nodes_hostnames[i]);
-                int l_ret_code = dap_net_resolve_host(l_seed_nodes_hostnames[i], AF_INET, &l_sa);
-                if (l_ret_code == 0) {
-                    struct in_addr *l_res = (struct in_addr *)&l_sa;
-                    log_it(L_NOTICE, "Resolved %s to %s (ipv4)", l_seed_nodes_hostnames[i], inet_ntoa(*l_res));
-                    l_node_info.hdr.ext_addr_v4.s_addr = l_res->s_addr;
-                    l_net_pvt->seed_nodes_addrs_v4[i].s_addr = l_res->s_addr;
-                } else {
-                    log_it(L_ERROR, "%s", gai_strerror(l_ret_code));
-                }
+        DAP_DELETE(l_addr_key);
+        DAP_DELETE(l_pub_key_data);
+    }
+    // use static addr from setting
+    else if(!dap_strcmp(l_node_addr_type, "static")) {
+        //const char * l_node_ipv4_str = dap_config_get_item_str(l_cfg , "general" ,"node-ipv4");
+        l_node_addr_str = dap_strdup(dap_config_get_item_str(l_cfg, "general", "node-addr"));
+        l_node_alias_str = dap_config_get_item_str(l_cfg, "general", "node-alias");
+    }
+
+    log_it (L_DEBUG, "Read %u aliases, %u address and %u ipv4 addresses, check them",
+            l_net_pvt->seed_aliases_count,l_seed_nodes_addrs_len, l_seed_nodes_ipv4_len );
+    PVT(l_net)->seed_nodes_addrs_v4 = DAP_NEW_SIZE(struct in_addr, l_net_pvt->seed_aliases_count * sizeof(struct in_addr));
+    // save new nodes from cfg file to db
+    for ( size_t i = 0; i < PVT(l_net)->seed_aliases_count &&
+                        i < l_seed_nodes_addrs_len &&
+                        (
+                            ( l_seed_nodes_ipv4_len  && i < l_seed_nodes_ipv4_len  ) ||
+                            ( l_seed_nodes_ipv6_len  && i < l_seed_nodes_ipv6_len  ) ||
+                            ( l_seed_nodes_hostnames_len  && i < l_seed_nodes_hostnames_len  )
+                        ); i++) {
+        dap_chain_node_addr_t l_seed_node_addr  = { 0 }, *l_seed_node_addr_gdb  = NULL;
+        dap_chain_node_info_t l_node_info       = { 0 }, *l_node_info_gdb       = NULL;
+
+        log_it(L_NOTICE, "Check alias %s in db", l_net_pvt->seed_aliases[i]);
+        snprintf(l_node_info.hdr.alias,sizeof (l_node_info.hdr.alias),"%s", PVT(l_net)->seed_aliases[i]);
+        if (dap_chain_node_addr_from_str(&l_seed_node_addr, l_seed_nodes_addrs[i])) {
+            log_it(L_ERROR,"Wrong address format, must be 0123::4567::89AB::CDEF");
+            continue;
+        }
+        if (l_seed_nodes_ipv4_len)
+            inet_pton(AF_INET, l_seed_nodes_ipv4[i], &l_node_info.hdr.ext_addr_v4);
+        if (l_seed_nodes_ipv6_len)
+            inet_pton(AF_INET6, l_seed_nodes_ipv6[i], &l_node_info.hdr.ext_addr_v6);
+        l_node_info.hdr.ext_port = l_seed_nodes_port_len && l_seed_nodes_port_len >= i ?
+            strtoul(l_seed_nodes_port[i], NULL, 10) : 8079;
+
+        if (l_seed_nodes_hostnames_len) {
+            struct sockaddr l_sa = {};
+            log_it(L_DEBUG, "Resolve %s addr", l_seed_nodes_hostnames[i]);
+            int l_ret_code = dap_net_resolve_host(l_seed_nodes_hostnames[i], AF_INET, &l_sa);
+            if (l_ret_code == 0) {
+                struct in_addr *l_res = (struct in_addr *)&l_sa;
+                log_it(L_NOTICE, "Resolved %s to %s (ipv4)", l_seed_nodes_hostnames[i], inet_ntoa(*l_res));
+                l_node_info.hdr.ext_addr_v4.s_addr = l_res->s_addr;
+                l_net_pvt->seed_nodes_addrs_v4[i].s_addr = l_res->s_addr;
+            } else {
+                log_it(L_ERROR, "%s", gai_strerror(l_ret_code));
             }
+        }
 
-            l_seed_node_addr_gdb    = dap_chain_node_alias_find(l_net, l_net_pvt->seed_aliases[i]);
-            l_node_info_gdb         = l_seed_node_addr_gdb ? dap_chain_node_info_read(l_net, l_seed_node_addr_gdb) : NULL;
+        l_seed_node_addr_gdb    = dap_chain_node_alias_find(l_net, l_net_pvt->seed_aliases[i]);
+        l_node_info_gdb         = l_seed_node_addr_gdb ? dap_chain_node_info_read(l_net, l_seed_node_addr_gdb) : NULL;
 
-            l_node_info.hdr.address = l_seed_node_addr;
-            if (l_node_info.hdr.ext_addr_v4.s_addr ||
+        l_node_info.hdr.address = l_seed_node_addr;
+        if (l_node_info.hdr.ext_addr_v4.s_addr ||
 #ifdef DAP_OS_BSD
-                l_node_info.hdr.ext_addr_v6.__u6_addr.__u6_addr32[0]
+            l_node_info.hdr.ext_addr_v6.__u6_addr.__u6_addr32[0]
 #else
-                l_node_info.hdr.ext_addr_v6.s6_addr32[0]
+            l_node_info.hdr.ext_addr_v6.s6_addr32[0]
 #endif
-            ) {
-                /* Let's check if config was altered */
-                int l_ret = l_node_info_gdb ? memcmp(&l_node_info, l_node_info_gdb, sizeof(dap_chain_node_info_t)) : 1;
+        ) {
+            /* Let's check if config was altered */
+            int l_ret = l_node_info_gdb ? memcmp(&l_node_info, l_node_info_gdb, sizeof(dap_chain_node_info_t)) : 1;
+            if (!l_ret) {
+                log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" already in list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
+            } else {
+                /* Either not yet added or must be altered */
+                l_ret = dap_chain_node_info_save(l_net, &l_node_info);
                 if (!l_ret) {
-                    log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" already in list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
+                    if (dap_chain_node_alias_register(l_net,l_net_pvt->seed_aliases[i], &l_seed_node_addr))
+                        log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" added to the curent list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
+                    else
+                        log_it(L_WARNING,"Cant register alias %s for address "NODE_ADDR_FP_STR, l_net_pvt->seed_aliases[i], NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
                 } else {
-                    /* Either not yet added or must be altered */
-                    l_ret = dap_chain_node_info_save(l_net, &l_node_info);
-                    if (!l_ret) {
-                        if (dap_chain_node_alias_register(l_net,l_net_pvt->seed_aliases[i], &l_seed_node_addr))
-                            log_it(L_NOTICE,"Seed node "NODE_ADDR_FP_STR" added to the curent list", NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
-                        else
-                            log_it(L_WARNING,"Cant register alias %s for address "NODE_ADDR_FP_STR, l_net_pvt->seed_aliases[i], NODE_ADDR_FP_ARGS_S(l_seed_node_addr));
-                    } else {
-                        log_it(L_WARNING,"Cant save node info for address "NODE_ADDR_FP_STR" return code %d", NODE_ADDR_FP_ARGS_S(l_seed_node_addr), l_ret);
-                    }
+                    log_it(L_WARNING,"Cant save node info for address "NODE_ADDR_FP_STR" return code %d", NODE_ADDR_FP_ARGS_S(l_seed_node_addr), l_ret);
                 }
-            } else
-                log_it(L_WARNING,"No address for seed node, can't populate global_db with it");
-            DAP_DEL_Z(l_seed_node_addr_gdb);
-            DAP_DEL_Z(l_node_info_gdb);
-        }
-
-        PVT(l_net)->bootstrap_nodes_count = 0;
-        PVT(l_net)->bootstrap_nodes_addrs = DAP_NEW_SIZE(struct in_addr, l_bootstrap_nodes_len * sizeof(struct in_addr));
-        PVT(l_net)->bootstrap_nodes_ports = DAP_NEW_SIZE(uint16_t, l_bootstrap_nodes_len * sizeof(uint16_t));
-        for (int i = 0; i < l_bootstrap_nodes_len; i++) {
-            char *l_bootstrap_port_str = strchr(l_bootstrap_nodes[i], ':');
-            if (!l_bootstrap_port_str) {
-                continue;
-            }
-            uint16_t l_bootstrap_port = atoi(l_bootstrap_port_str + 1);
-            if (!l_bootstrap_port) {
-                continue;
             }
-            int l_bootstrap_name_len = l_bootstrap_port_str - l_bootstrap_nodes[i];
-            char *l_bootstrap_name = DAP_NEW_SIZE(char, l_bootstrap_name_len + 1);
-            strncpy(l_bootstrap_name, l_bootstrap_nodes[i], l_bootstrap_name_len);
-            struct in_addr l_bootstrap_addr;
-            if (dap_net_resolve_host(l_bootstrap_name, AF_INET, (struct sockaddr* )&l_bootstrap_addr) == 0) {
-                PVT(l_net)->bootstrap_nodes_addrs[PVT(l_net)->bootstrap_nodes_count] = l_bootstrap_addr;
-                PVT(l_net)->bootstrap_nodes_ports[PVT(l_net)->bootstrap_nodes_count] = l_bootstrap_port;
-                PVT(l_net)->bootstrap_nodes_count++;
-            }
-            DAP_DELETE(l_bootstrap_name);
+        } else
+            log_it(L_WARNING,"No address for seed node, can't populate global_db with it");
+        DAP_DEL_Z(l_seed_node_addr_gdb);
+        DAP_DEL_Z(l_node_info_gdb);
+    }
+
+    PVT(l_net)->bootstrap_nodes_count = 0;
+    PVT(l_net)->bootstrap_nodes_addrs = DAP_NEW_SIZE(struct in_addr, l_bootstrap_nodes_len * sizeof(struct in_addr));
+    PVT(l_net)->bootstrap_nodes_ports = DAP_NEW_SIZE(uint16_t, l_bootstrap_nodes_len * sizeof(uint16_t));
+    for (int i = 0; i < l_bootstrap_nodes_len; i++) {
+        char *l_bootstrap_port_str = strchr(l_bootstrap_nodes[i], ':');
+        if (!l_bootstrap_port_str) {
+            continue;
         }
-        if ( l_node_addr_str || l_node_alias_str ){
-            dap_chain_node_addr_t * l_node_addr;
-            if ( l_node_addr_str == NULL)
-                l_node_addr = dap_chain_node_alias_find(l_net, l_node_alias_str);
-            else {
-                l_node_addr = DAP_NEW_Z(dap_chain_node_addr_t);
-                if (dap_chain_node_addr_from_str(l_node_addr, l_node_addr_str) == 0)
-                    log_it(L_NOTICE, "Parse node addr "NODE_ADDR_FP_STR" successfully", NODE_ADDR_FP_ARGS(l_node_addr));
-                else
-                    DAP_DEL_Z(l_node_addr);
-                l_net_pvt->node_addr = l_node_addr;
-            }
-            if ( l_node_addr ) {
-                char *l_addr_hash_str = dap_chain_node_addr_to_hash_str(l_node_addr);
-                // save current node address
-                dap_db_set_cur_node_addr(l_node_addr->uint64, l_net->pub.name);
-                if(!l_addr_hash_str){
-                    log_it(L_ERROR,"Can't get hash string for node address!");
-                } else {
-                    l_net_pvt->node_info = dap_chain_node_info_read (l_net, l_node_addr);
-                    if ( !l_net_pvt->node_info ) { // If not present - create it
-                        l_net_pvt->node_info = DAP_NEW_Z(dap_chain_node_info_t);
-                        l_net_pvt->node_info->hdr.address = *l_node_addr;
-                        if (dap_config_get_item_bool_default(g_config,"server","enabled",false) ){
-                            const char * l_ext_addr_v4 = dap_config_get_item_str_default(g_config,"server","ext_address",NULL);
-                            const char * l_ext_addr_v6 = dap_config_get_item_str_default(g_config,"server","ext_address6",NULL);
-                            uint16_t l_ext_port = dap_config_get_item_uint16_default(g_config,"server","ext_port_tcp",0);
-                            uint16_t l_node_info_port = l_ext_port ? l_ext_port :
-                                                    dap_config_get_item_uint16_default(g_config,"server","listen_port_tcp",8089);
-                            if (l_ext_addr_v4)
-                                inet_pton(AF_INET,l_ext_addr_v4,&l_net_pvt->node_info->hdr.ext_addr_v4 );
-                            if (l_ext_addr_v6)
-                                inet_pton(AF_INET6,l_ext_addr_v6,&l_net_pvt->node_info->hdr.ext_addr_v6 );
-                            l_net_pvt->node_info->hdr.ext_port =l_node_info_port;
-                            log_it(L_INFO,"Server is enabled on %s:%u",l_ext_addr_v4?l_ext_addr_v4:"<none>",
-                                   l_node_info_port);
-                        }else
-                            log_it(L_INFO,"Server is disabled, add only node address in nodelist");
-                        if (l_net_pvt->node_info->hdr.ext_port &&
-                                (l_net_pvt->node_info->hdr.ext_addr_v4.s_addr != INADDR_ANY ||
-                                 memcmp(&l_net_pvt->node_info->hdr.ext_addr_v6, &in6addr_any, sizeof(struct in6_addr))))
-                            // Save only info with non null address & port!
-                            dap_chain_node_info_save(l_net,l_net_pvt->node_info);
-                    }
-                    log_it(L_NOTICE,"GDB Info: node_addr: " NODE_ADDR_FP_STR"  links: %u cell_id: 0x%016"DAP_UINT64_FORMAT_X,
-                           NODE_ADDR_FP_ARGS(l_node_addr),
-                           l_net_pvt->node_info->hdr.links_number,
-                           l_net_pvt->node_info->hdr.cell_id.uint64);
+        uint16_t l_bootstrap_port = atoi(l_bootstrap_port_str + 1);
+        if (!l_bootstrap_port) {
+            continue;
+        }
+        int l_bootstrap_name_len = l_bootstrap_port_str - l_bootstrap_nodes[i];
+        char *l_bootstrap_name = DAP_NEW_SIZE(char, l_bootstrap_name_len + 1);
+        strncpy(l_bootstrap_name, l_bootstrap_nodes[i], l_bootstrap_name_len);
+        struct in_addr l_bootstrap_addr;
+        if (dap_net_resolve_host(l_bootstrap_name, AF_INET, (struct sockaddr* )&l_bootstrap_addr) == 0) {
+            PVT(l_net)->bootstrap_nodes_addrs[PVT(l_net)->bootstrap_nodes_count] = l_bootstrap_addr;
+            PVT(l_net)->bootstrap_nodes_ports[PVT(l_net)->bootstrap_nodes_count] = l_bootstrap_port;
+            PVT(l_net)->bootstrap_nodes_count++;
+        }
+        DAP_DELETE(l_bootstrap_name);
+    }
+    if ( l_node_addr_str || l_node_alias_str ){
+        dap_chain_node_addr_t * l_node_addr;
+        if ( l_node_addr_str == NULL)
+            l_node_addr = dap_chain_node_alias_find(l_net, l_node_alias_str);
+        else {
+            l_node_addr = DAP_NEW_Z(dap_chain_node_addr_t);
+            if (dap_chain_node_addr_from_str(l_node_addr, l_node_addr_str) == 0)
+                log_it(L_NOTICE, "Parse node addr "NODE_ADDR_FP_STR" successfully", NODE_ADDR_FP_ARGS(l_node_addr));
+            else
+                DAP_DEL_Z(l_node_addr);
+            l_net_pvt->node_addr = l_node_addr;
+        }
+        if ( l_node_addr ) {
+            char *l_addr_hash_str = dap_chain_node_addr_to_hash_str(l_node_addr);
+            // save current node address
+            dap_db_set_cur_node_addr(l_node_addr->uint64, l_net->pub.name);
+            if(!l_addr_hash_str){
+                log_it(L_ERROR,"Can't get hash string for node address!");
+            } else {
+                l_net_pvt->node_info = dap_chain_node_info_read (l_net, l_node_addr);
+                if ( !l_net_pvt->node_info ) { // If not present - create it
+                    l_net_pvt->node_info = DAP_NEW_Z(dap_chain_node_info_t);
+                    l_net_pvt->node_info->hdr.address = *l_node_addr;
+                    if (dap_config_get_item_bool_default(g_config,"server","enabled",false) ){
+                        const char * l_ext_addr_v4 = dap_config_get_item_str_default(g_config,"server","ext_address",NULL);
+                        const char * l_ext_addr_v6 = dap_config_get_item_str_default(g_config,"server","ext_address6",NULL);
+                        uint16_t l_ext_port = dap_config_get_item_uint16_default(g_config,"server","ext_port_tcp",0);
+                        uint16_t l_node_info_port = l_ext_port ? l_ext_port :
+                                                dap_config_get_item_uint16_default(g_config,"server","listen_port_tcp",8089);
+                        if (l_ext_addr_v4)
+                            inet_pton(AF_INET,l_ext_addr_v4,&l_net_pvt->node_info->hdr.ext_addr_v4 );
+                        if (l_ext_addr_v6)
+                            inet_pton(AF_INET6,l_ext_addr_v6,&l_net_pvt->node_info->hdr.ext_addr_v6 );
+                        l_net_pvt->node_info->hdr.ext_port =l_node_info_port;
+                        log_it(L_INFO,"Server is enabled on %s:%u",l_ext_addr_v4?l_ext_addr_v4:"<none>",
+                               l_node_info_port);
+                    }else
+                        log_it(L_INFO,"Server is disabled, add only node address in nodelist");
+                    if (l_net_pvt->node_info->hdr.ext_port &&
+                            (l_net_pvt->node_info->hdr.ext_addr_v4.s_addr != INADDR_ANY ||
+                             memcmp(&l_net_pvt->node_info->hdr.ext_addr_v6, &in6addr_any, sizeof(struct in6_addr))))
+                        // Save only info with non null address & port!
+                        dap_chain_node_info_save(l_net,l_net_pvt->node_info);
                 }
-                DAP_DELETE(l_addr_hash_str);
-            }
-            else{
-                log_it(L_WARNING, "Not present our own address %s in database", (l_node_alias_str) ? l_node_alias_str: "");
+                log_it(L_NOTICE,"GDB Info: node_addr: " NODE_ADDR_FP_STR"  links: %u cell_id: 0x%016"DAP_UINT64_FORMAT_X,
+                       NODE_ADDR_FP_ARGS(l_node_addr),
+                       l_net_pvt->node_info->hdr.links_number,
+                       l_net_pvt->node_info->hdr.cell_id.uint64);
             }
+            DAP_DELETE(l_addr_hash_str);
         }
+        else{
+            log_it(L_WARNING, "Not present our own address %s in database", (l_node_alias_str) ? l_node_alias_str: "");
+        }
+    }
 
+    /* *** Chaiins init by configs *** */
+    char * l_chains_path = dap_strdup_printf("%s/network/%s", dap_config_path(), l_net->pub.name);
+    DIR * l_chains_dir = opendir(l_chains_path);
+    DAP_DEL_Z(l_chains_path);
+    if (!l_chains_dir) {
+        log_it(L_ERROR, "Can't find any chains for network %s", l_net->pub.name);
+        l_net_pvt->load_mode = false;
+        return -2;
+    }
+    // for sequential loading chains
+    dap_list_t *l_prior_list = NULL;
 
+    struct dirent * l_dir_entry;
+    while ( (l_dir_entry = readdir(l_chains_dir) )!= NULL ){
+        if (l_dir_entry->d_name[0]=='\0')
+            continue;
+        char * l_entry_name = strdup(l_dir_entry->d_name);
+        if (strlen (l_entry_name) > 4 ){ // It has non zero name excluding file extension
+            if ( strncmp (l_entry_name+ strlen(l_entry_name)-4,".cfg",4) == 0 ) { // its .cfg file
+                l_entry_name [strlen(l_entry_name)-4] = 0;
+                log_it(L_DEBUG,"Open chain config \"%s\"...",l_entry_name);
+                l_chains_path = dap_strdup_printf("network/%s/%s",l_net->pub.name,l_entry_name);
+                dap_config_t * l_cfg = dap_config_open(l_chains_path);
+                if(l_cfg) {
+                    list_priority *l_chain_prior = DAP_NEW_Z(list_priority);
+                    if (!l_chain_prior) {
+                        log_it(L_ERROR, "Memory allocation error in s_net_init");
+                        DAP_DELETE (l_entry_name);
+                        closedir(l_chains_dir);
+                        dap_config_close(l_cfg);
+                        return -1;
+                    }
+                    l_chain_prior->prior = dap_config_get_item_uint16_default(l_cfg, "chain", "load_priority", 100);
+                    l_chain_prior->chains_path = l_chains_path;
+                    // add chain to load list;
+                    l_prior_list = dap_list_append(l_prior_list, l_chain_prior);
+                    dap_config_close(l_cfg);
+                }
+            }
+        }
+        DAP_DELETE (l_entry_name);
+    }
+    closedir(l_chains_dir);
 
+    // sort list with chains names by priority
+    l_prior_list = dap_list_sort(l_prior_list, callback_compare_prioritity_list);
 
-        DAP_DELETE(l_node_addr_str);
-        dap_config_close(l_cfg);
+    // create and load chains params by priority
+    dap_chain_t *l_chain;
+    dap_list_t *l_list = l_prior_list;
+    while(l_list){
+        list_priority *l_chain_prior = l_list->data;
+        // Create chain object
+        l_chain = dap_chain_load_from_cfg(l_net->pub.ledger, l_net->pub.name,
+                                          l_net->pub.id, l_chain_prior->chains_path);
+        if(l_chain)
+            DL_APPEND(l_net->pub.chains, l_chain);
+        else
+            log_it(L_WARNING, "Can't process chain from config %s", l_chain_prior->chains_path);
+        DAP_DELETE (l_chain_prior->chains_path);
+        l_list = dap_list_next(l_list);
+    }
+    dap_list_free_full(l_prior_list, NULL);
+    dap_chain_t *l_chain02;
+    DL_FOREACH(l_net->pub.chains, l_chain){
+        DL_FOREACH(l_net->pub.chains, l_chain02){
+            if (l_chain != l_chain02){
+                if (l_chain->id.uint64 == l_chain02->id.uint64) {
+                    log_it(L_ERROR, "Your network %s has chains with duplicate ids: 0x%"DAP_UINT64_FORMAT_U", chain01: %s, chain02: %s", l_chain->net_name,
+                                    l_chain->id.uint64, l_chain->name,l_chain02->name);
+                    log_it(L_ERROR, "Please, fix your configs and restart node");
+                    return -2;
+                }
+                if (!dap_strcmp(l_chain->name, l_chain02->name)) {
+                    log_it(L_ERROR, "Your network %s has chains with duplicate names %s: chain01 id = 0x%"DAP_UINT64_FORMAT_U", chain02 id = 0x%"DAP_UINT64_FORMAT_U"",l_chain->net_name,
+                           l_chain->name, l_chain->id.uint64, l_chain02->id.uint64);
+                    log_it(L_ERROR, "Please, fix your configs and restart node");
+                    return -2;
+                }
+                remove_duplicates_in_chain_by_priority(l_chain, l_chain02);
+            }
+        }
     }
+    // LEDGER model
+    uint16_t l_ledger_flags = 0;
+    switch ( PVT( l_net )->node_role.enums ) {
+    case NODE_ROLE_LIGHT:
+        break;
+    case NODE_ROLE_FULL:
+        l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_LOCAL_DS;
+        if (dap_config_get_item_bool_default(g_config, "ledger", "cache_enabled", true))
+            l_ledger_flags |= DAP_CHAIN_LEDGER_CACHE_ENABLED;
+    default:
+        l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_CELLS_DS | DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION;
+    }
+    dap_list_t *l_net_keys = NULL;
+    for (dap_chain_t *l_chain = l_net->pub.chains; l_chain; l_chain = l_chain->next) {
+        if (!l_chain->callback_get_poa_certs)
+            continue;
+        l_net_keys = l_chain->callback_get_poa_certs(l_chain, NULL, NULL);
+        if (l_net_keys)
+            break;
+    }
+    if (!l_net_keys)
+        log_it(L_WARNING,"PoA certificates for net %s not found.", l_net->pub.name);
+    // init LEDGER model
+    l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags, l_net->pub.name, l_net->pub.native_ticker, l_net_keys);
+
+    DAP_DELETE(l_node_addr_str);
+    dap_config_close(l_cfg);
     return 0;
 }
 
@@ -2580,128 +2747,47 @@ int s_net_load(dap_chain_net_t *a_net)
     }
 
     dap_chain_net_pvt_t * l_net_pvt = PVT(l_net);
-    char * l_chains_path = dap_strdup_printf("%s/network/%s", dap_config_path(), l_net->pub.name);
-    DIR * l_chains_dir = opendir(l_chains_path);
-    DAP_DEL_Z(l_chains_path);
-    if ( l_chains_dir ){
-        // for sequential loading chains
-        dap_list_t *l_prior_list = NULL;
-
-        struct dirent * l_dir_entry;
-        while ( (l_dir_entry = readdir(l_chains_dir) )!= NULL ){
-            if (l_dir_entry->d_name[0]=='\0')
-                continue;
-            char * l_entry_name = strdup(l_dir_entry->d_name);
-            if (strlen (l_entry_name) > 4 ){ // It has non zero name excluding file extension
-                if ( strncmp (l_entry_name+ strlen(l_entry_name)-4,".cfg",4) == 0 ) { // its .cfg file
-                    l_entry_name [strlen(l_entry_name)-4] = 0;
-                    log_it(L_DEBUG,"Open chain config \"%s\"...",l_entry_name);
-                    l_chains_path = dap_strdup_printf("network/%s/%s",l_net->pub.name,l_entry_name);
-                    dap_config_t * l_cfg = dap_config_open(l_chains_path);
-                    if(l_cfg) {
-                        list_priority *l_chain_prior = DAP_NEW_Z(list_priority);
-                        l_chain_prior->prior = dap_config_get_item_uint16_default(l_cfg, "chain", "load_priority", 100);
-                        l_chain_prior->chains_path = l_chains_path;
-                        // add chain to load list;
-                        l_prior_list = dap_list_append(l_prior_list, l_chain_prior);
-                        dap_config_close(l_cfg);
-                    }
-                }
-            }
-            DAP_DELETE (l_entry_name);
-        }
-        closedir(l_chains_dir);
-
-        // reload ledger cache at once
-        if (s_chain_net_reload_ledger_cache_once(l_net)) {
-            log_it(L_WARNING,"Start one time ledger cache reloading");
-            dap_chain_ledger_purge(l_net->pub.ledger, false);
-            dap_chain_net_srv_stake_purge(l_net);
-        } else
-            dap_chain_net_srv_stake_load_cache(l_net);
-
-        // sort list with chains names by priority
-        l_prior_list = dap_list_sort(l_prior_list, callback_compare_prioritity_list);
-
-        // create and load chains params by priority
-        dap_chain_t *l_chain;
-        dap_list_t *l_list = l_prior_list;
-        while(l_list){
-            list_priority *l_chain_prior = l_list->data;
-            // Create chain object
-            l_chain = dap_chain_load_from_cfg(l_net->pub.ledger, l_net->pub.name,
-                                              l_net->pub.id, l_chain_prior->chains_path);
 
-            if(l_chain) {
-                DL_APPEND(l_net->pub.chains, l_chain);
-
-                // add a callback to monitor changes in the chain
-                dap_chain_add_callback_notify(l_chain, s_chain_callback_notify, l_net);
-            }
-            DAP_DELETE (l_chain_prior->chains_path);
-            l_list = dap_list_next(l_list);
+    // reload ledger cache at once
+    if (s_chain_net_reload_ledger_cache_once(l_net)) {
+        log_it(L_WARNING,"Start one time ledger cache reloading");
+        dap_chain_ledger_purge(l_net->pub.ledger, false);
+        dap_chain_net_srv_stake_purge(l_net);
+    } else
+        dap_chain_net_srv_stake_load_cache(l_net);
+
+    //load decree
+    dap_chain_net_decree_init(l_net);
+    // load chains
+    dap_chain_t *l_chain = l_net->pub.chains;
+    while(l_chain){
+        l_chain->ledger = l_net->pub.ledger;
+        dap_chain_ledger_set_fee(l_net->pub.ledger, uint256_0, c_dap_chain_addr_blank);
+        if (dap_chain_load_all(l_chain) == 0)
+            log_it (L_NOTICE, "Loaded chain files");
+        else {
+            dap_chain_save_all( l_chain );
+            log_it (L_NOTICE, "Initialized chain files");
         }
-        dap_list_free_full(l_prior_list, NULL);
-
-        //load decree
-        dap_chain_net_decree_init(l_net);
-        // load chains
-        l_chain = l_net->pub.chains;
-        while(l_chain){
-            dap_chain_ledger_set_fee(l_net->pub.ledger, uint256_0, c_dap_chain_addr_blank);
-            if (dap_chain_load_all(l_chain) == 0)
-                log_it (L_NOTICE, "Loaded chain files");
-            else {
-                dap_chain_save_all( l_chain );
-                log_it (L_NOTICE, "Initialized chain files");
-            }
 
-            if(l_chain->callback_created)
-                l_chain->callback_created(l_chain, l_cfg);
+        if(l_chain->callback_created)
+            l_chain->callback_created(l_chain, l_cfg);
 
-            l_chain = l_chain->next;
-        }
-
-        dap_chain_t *l_chain02;
-        DL_FOREACH(l_net->pub.chains, l_chain){
-            DL_FOREACH(l_net->pub.chains, l_chain02){
-                if (l_chain != l_chain02){
-                    if (l_chain->id.uint64 == l_chain02->id.uint64)
-                    {
-                        log_it(L_ERROR, "Your network %s has chains with duplicate ids: 0x%"DAP_UINT64_FORMAT_U", chain01: %s, chain02: %s", l_chain->net_name,
-                                        l_chain->id.uint64, l_chain->name,l_chain02->name);
-                        log_it(L_ERROR, "Please, fix your configs and restart node");
-                        return -2;
-                    }
-                    if (!dap_strcmp(l_chain->name, l_chain02->name))
-                    {
-                        log_it(L_ERROR, "Your network %s has chains with duplicate names %s: chain01 id = 0x%"DAP_UINT64_FORMAT_U", chain02 id = 0x%"DAP_UINT64_FORMAT_U"",l_chain->net_name,
-                               l_chain->name, l_chain->id.uint64, l_chain02->id.uint64);
-                        log_it(L_ERROR, "Please, fix your configs and restart node");
-                        return -2;
-                    }
-                    remove_duplicates_in_chain_by_priority(l_chain, l_chain02);
+        l_chain = l_chain->next;
+    }
+    // Process thresholds if any
+    bool l_processed;
+    do {
+        l_processed = false;
+        DL_FOREACH(l_net->pub.chains, l_chain) {
+            if (l_chain->callback_atom_add_from_treshold) {
+                while (l_chain->callback_atom_add_from_treshold(l_chain, NULL)) {
+                    log_it(L_DEBUG, "Added atom from treshold");
+                    l_processed = true;
                 }
             }
         }
-
-        bool l_processed;
-        do {
-            l_processed = false;
-            DL_FOREACH(l_net->pub.chains, l_chain) {
-                if (l_chain->callback_atom_add_from_treshold) {
-                    while (l_chain->callback_atom_add_from_treshold(l_chain, NULL)) {
-                        log_it(L_DEBUG, "Added atom from treshold");
-                        l_processed = true;
-                    }
-                }
-            }
-        } while (l_processed);
-    } else {
-        log_it(L_ERROR, "Can't find any chains for network %s", l_net->pub.name);
-        l_net_pvt->load_mode = false;
-        return -2;
-    }
+    } while (l_processed);
 
     // Do specific role actions post-chain created
     l_net_pvt->state_target = NET_STATE_OFFLINE;
@@ -2711,7 +2797,8 @@ int s_net_load(dap_chain_net_t *a_net)
         case NODE_ROLE_ROOT_MASTER:{
             // Set to process everything in datum pool
             dap_chain_t * l_chain = NULL;
-            DL_FOREACH(l_net->pub.chains, l_chain ) l_chain->is_datum_pool_proc = true;
+            DL_FOREACH(l_net->pub.chains, l_chain)
+                l_chain->is_datum_pool_proc = true;
             log_it(L_INFO,"Root master node role established");
         } // Master root includes root
         case NODE_ROLE_ROOT:{
@@ -2765,8 +2852,9 @@ int s_net_load(dap_chain_net_t *a_net)
     l_net_pvt->balancer_http = !dap_config_get_item_bool_default(l_cfg, "general", "use_dns_links", false);
 
     dap_chain_net_add_gdb_notify_callback(l_net, dap_chain_net_sync_gdb_broadcast, l_net);
-    if (l_target_state != l_net_pvt->state_target)
-        dap_chain_net_state_go_to(l_net, l_target_state);
+    DL_FOREACH(l_net->pub.chains, l_chain)
+        // add a callback to monitor changes in the chain
+        dap_chain_add_callback_notify(l_chain, s_chain_callback_notify, l_net);
 
     uint32_t l_timeout = dap_config_get_item_uint32_default(g_config, "node_client", "timer_update_states", 600);
     PVT(l_net)->main_timer = dap_interval_timer_create(l_timeout * 1000, s_main_timer_callback, l_net);
@@ -2775,6 +2863,9 @@ int s_net_load(dap_chain_net_t *a_net)
 
     dap_config_close(l_cfg);
 
+    if (l_target_state != l_net_pvt->state_target)
+        dap_chain_net_state_go_to(l_net, l_target_state);
+
     return 0;
 }
 
@@ -2803,6 +2894,11 @@ dap_chain_net_t **dap_chain_net_list(uint16_t *a_size)
     *a_size = HASH_COUNT(s_net_items);
     if(*a_size){
         dap_chain_net_t **l_net_list = DAP_NEW_SIZE(dap_chain_net_t *, (*a_size) * sizeof(dap_chain_net_t *));
+        if (!l_net_list) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_list");
+            pthread_rwlock_unlock(&s_net_items_rwlock);
+            return NULL;
+        }
         dap_chain_net_item_t *l_current_item, *l_tmp;
         int i = 0;
         HASH_ITER(hh, s_net_items, l_current_item, l_tmp) {
@@ -2810,8 +2906,8 @@ dap_chain_net_t **dap_chain_net_list(uint16_t *a_size)
             if(i > *a_size)
                 break;
         }
-        return l_net_list;
         pthread_rwlock_unlock(&s_net_items_rwlock);
+        return l_net_list;
     } else {
         pthread_rwlock_unlock(&s_net_items_rwlock);
         return NULL;
@@ -3067,10 +3163,15 @@ dap_list_t* dap_chain_net_get_link_node_list(dap_chain_net_t * l_net, bool a_is_
                 dap_chain_node_info_t *l_remote_node_info = dap_chain_node_info_read(l_net, l_remote_address);
                 if(!l_remote_node_info || l_remote_node_info->hdr.cell_id.uint64 != l_cur_node_info->hdr.cell_id.uint64)
                     l_is_add = false;
-                DAP_DELETE(l_remote_node_info);
+                if (l_remote_node_info)    
+                    DAP_DELETE(l_remote_node_info);
             }
             if(l_is_add) {
                 dap_chain_node_addr_t *l_address = DAP_NEW(dap_chain_node_addr_t);
+                if (!l_address) {
+                    log_it(L_ERROR, "Memory allocation error in dap_chain_net_get_link_node_list");
+                    return NULL;
+                }
                 l_address->uint64 = l_cur_node_info->links[i].uint64;
                 l_node_list = dap_list_append(l_node_list, l_address);
             }
@@ -3105,6 +3206,10 @@ dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net)
     for(size_t i = 0; i < l_nodes_count; i++) {
         dap_chain_node_info_t *l_node_info = (dap_chain_node_info_t *) l_objs[i].value;
         dap_chain_node_addr_t *l_address = DAP_NEW(dap_chain_node_addr_t);
+        if (!l_address) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_get_node_list");
+            return NULL;
+        }
         l_address->uint64 = l_node_info->hdr.address.uint64;
         l_node_list = dap_list_append(l_node_list, l_address);
     }
@@ -3213,18 +3318,15 @@ int dap_chain_net_verify_datum_for_add(dap_chain_t *a_chain, dap_chain_datum_t *
 
 char *dap_chain_net_verify_datum_err_code_to_str(dap_chain_datum_t *a_datum, int a_code){
     switch (a_datum->header.type_id) {
-        case DAP_CHAIN_DATUM_TX:
-            return dap_chain_ledger_tx_check_err_str(a_code);
-        case DAP_CHAIN_DATUM_TOKEN_DECL:
-            return dap_chain_ledger_token_decl_add_err_code_to_str(a_code);
-        case DAP_CHAIN_DATUM_TOKEN_EMISSION:
-            return dap_chain_ledger_token_emission_err_code_to_str(a_code);
-        default:
-            if (a_code == 0) {
-                return dap_strdup("DAP_CHAIN_DATUM_VERIFY_OK");
-            } else {
-                return dap_strdup_printf("Error code: %d", a_code);
-            }
+    case DAP_CHAIN_DATUM_TX:
+        return dap_chain_ledger_tx_check_err_str(a_code);
+    case DAP_CHAIN_DATUM_TOKEN_DECL:
+        return dap_chain_ledger_token_decl_add_err_code_to_str(a_code);
+    case DAP_CHAIN_DATUM_TOKEN_EMISSION:
+        return dap_chain_ledger_token_emission_err_code_to_str(a_code);
+    default:
+        return !a_code ? "DAP_CHAIN_DATUM_VERIFY_OK" : dap_itoa(a_code);
+
     }
 }
 
@@ -3240,8 +3342,7 @@ static bool s_net_check_acl(dap_chain_net_t *a_net, dap_chain_hash_fast_t *a_pke
 {
     const char l_path[] = "network/";
     char l_cfg_path[strlen(a_net->pub.name) + strlen(l_path) + 1];
-    strcpy(l_cfg_path, l_path);
-    strcat(l_cfg_path, a_net->pub.name);
+    dap_snprintf(l_cfg_path, sizeof(l_cfg_path), "%s%s", l_path, a_net->pub.name);
     dap_config_t *l_cfg = dap_config_open(l_cfg_path);
     const char *l_auth_type = dap_config_get_item_str(l_cfg, "auth", "type");
     bool l_authorized = true;
@@ -3308,6 +3409,11 @@ static uint8_t *s_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash)
     dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count);
     if (l_net_count && l_net_list) {
         uint8_t *l_ret = DAP_NEW_SIZE(uint8_t, l_net_count);
+        if (!l_ret) {
+            log_it(L_ERROR, "Memory allocation error in s_net_set_acl");
+            DAP_DELETE(l_net_list);
+            return NULL;
+        }
         for (uint16_t i = 0; i < l_net_count; i++) {
             l_ret[i] = s_net_check_acl(l_net_list[i], a_pkey_hash);
         }
@@ -3358,7 +3464,12 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d
                     */
                     l_sz = sizeof(dap_chain_datum_t) + l_datum->header.data_size + 16;
                     l_datum2 = DAP_NEW_Z_SIZE(dap_chain_datum_t, l_sz);
-                    assert ( l_datum2 );
+                    if (!l_datum2) {
+                        log_it(L_ERROR, "Memory allocation in dap_chain_datum_list");
+                        DAP_DEL_Z(l_datums);
+                        dap_list_free(l_list);
+                        return NULL;
+                    }
                     memcpy(l_datum2, l_datum, l_sz);
 
                     /* Add new entry into the list */
diff --git a/modules/net/dap_chain_net_balancer.c b/modules/net/dap_chain_net_balancer.c
index b21a20d888ac507973645740b8642c05545fa5d4..50aefc9b428a99a76569ef8f66299112c3a3d381 100644
--- a/modules/net/dap_chain_net_balancer.c
+++ b/modules/net/dap_chain_net_balancer.c
@@ -81,6 +81,11 @@ dap_chain_node_info_t *dap_chain_net_balancer_get_node(const char *a_net_name)
         l_node_num = rand() % l_nodes_count;
         l_node_candidate = (dap_chain_node_info_t *)dap_list_nth_data(l_objs_list,l_node_num);
         dap_chain_node_info_t *l_node_info = DAP_NEW_Z(dap_chain_node_info_t);
+        if (!l_node_info) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_balancer_get_node");
+            dap_list_free(l_objs_list);
+            return NULL;
+        }
         memcpy(l_node_info, l_node_candidate, sizeof(dap_chain_node_info_t));
         dap_list_free(l_objs_list);
         return l_node_info;
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index a334887a54080d69e104c230cd89a922880f2d64..5ffef5faec7836da640164d993588a70278f5808 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -265,11 +265,15 @@ int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_d
             return -110;
         }
         if (l_decree_hh->is_applied) {
-            log_it(L_WARNING,"Decree already applyed");
+            log_it(L_WARNING,"Decree already applied");
             return -111;
         }
     } else {
         l_decree_hh = DAP_NEW_Z(struct decree_hh);
+        if (!l_decree_hh) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_decree_apply");
+            return -1;
+        }
         l_decree_hh->decree = DAP_DUP_SIZE(a_decree, dap_chain_datum_decree_get_size(a_decree));
         l_decree_hh->key = *a_decree_hash;
         HASH_ADD(hh, s_decree_hh, key, sizeof(dap_hash_fast_t), l_decree_hh);
@@ -386,6 +390,10 @@ static int s_common_decree_handler(dap_chain_datum_decree_t * a_decree, dap_chai
                     }
                 } else{
                     dap_chain_addr_t *l_decree_addr = DAP_NEW_Z_SIZE(dap_chain_addr_t, sizeof(dap_chain_addr_t));
+                    if (!l_decree_addr) {
+                        log_it(L_ERROR, "Memory allocation error in s_common_decree_handler");
+                        return -1;
+                    }
                     memcpy(l_decree_addr, &l_addr, sizeof(dap_chain_addr_t));
                     l_net->pub.decree->fee_addr = l_decree_addr;
                 }
diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index a3e7548543344b46b2066a04b520a9258aa5e748..40973efac8d31a1213bf8335ee351f625781cb3d 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -45,6 +45,10 @@ dap_chain_datum_tx_spends_items_t * dap_chain_net_get_tx_cond_all_with_spends_by
 {
     dap_ledger_t * l_ledger = a_net->pub.ledger;
     dap_chain_datum_tx_spends_items_t * l_ret = DAP_NEW_Z(dap_chain_datum_tx_spends_items_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid");
+        return NULL;
+    }
 
     switch (a_search_type) {
         case TX_SEARCH_TYPE_NET:
@@ -113,6 +117,11 @@ dap_chain_datum_tx_spends_items_t * dap_chain_net_get_tx_cond_all_with_spends_by
 
                                             if (l_tx_prev_out_item){ // we found previous out_cond with target srv_uid
                                                 dap_chain_datum_tx_spends_item_t *l_item_in = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t);
+                                                if (!l_item_in) {
+                                                    log_it(L_ERROR, "Memory allocation error in dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid");
+                                                    DAP_DEL_Z(l_datums);
+                                                    return NULL;
+                                                }
                                                 size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
                                                 dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size);
                                                 dap_hash_fast(l_tx_dup,l_tx_size, &l_item_in->tx_hash);
@@ -130,6 +139,11 @@ dap_chain_datum_tx_spends_items_t * dap_chain_net_get_tx_cond_all_with_spends_by
                                             dap_chain_tx_out_cond_t * l_tx_out_cond = (dap_chain_tx_out_cond_t *)l_item;
                                             if(l_tx_out_cond->header.srv_uid.uint64 == a_srv_uid.uint64){
                                                 dap_chain_datum_tx_spends_item_t * l_item = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t);
+                                                if (!l_item) {
+                                                    log_it(L_ERROR, "Memory allocation error in dap_chain_net_get_tx_cond_all_with_spends_by_srv_uid");
+                                                    DAP_DEL_Z(l_datums);
+                                                    return NULL;
+                                                }
                                                 size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
                                                 dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size);
                                                 dap_hash_fast(l_tx,l_tx_size, &l_item->tx_hash);
@@ -316,6 +330,10 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum
 dap_list_t * dap_chain_net_get_tx_cond_chain(dap_chain_net_t * a_net, dap_hash_fast_t * a_tx_hash, dap_chain_net_srv_uid_t a_srv_uid)
 {
     struct get_tx_cond_all_from_tx * l_args = DAP_NEW_Z(struct get_tx_cond_all_from_tx);
+    if (!l_args) {
+        log_it (L_ERROR, "Memory allocation error in dap_chain_net_get_tx_cond_all_for_addr");
+        return NULL;
+    }
     l_args->tx_begin_hash = a_tx_hash;
     l_args->srv_uid = a_srv_uid;
     dap_chain_net_get_tx_all(a_net,TX_SEARCH_TYPE_NET,s_get_tx_cond_chain_callback, l_args);
@@ -430,6 +448,10 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai
 dap_list_t * dap_chain_net_get_tx_cond_all_for_addr(dap_chain_net_t * a_net, dap_chain_addr_t * a_addr, dap_chain_net_srv_uid_t a_srv_uid)
 {
     struct get_tx_cond_all_for_addr * l_args = DAP_NEW_Z(struct get_tx_cond_all_for_addr);
+    if (!l_args) {
+        log_it (L_ERROR, "Memory allocation error in dap_chain_net_get_tx_cond_all_for_addr");
+        return NULL;
+    }
     l_args->addr = a_addr;
     l_args->srv_uid = a_srv_uid;
     dap_chain_net_get_tx_all(a_net,TX_SEARCH_TYPE_NET,s_get_tx_cond_all_for_addr_callback, l_args);
diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c
index b7eabde8dc274e538785639794edc1f723b85291..b646c2bf116cf3f8f940ac2884e78566ca6c0055 100644
--- a/modules/net/dap_chain_node.c
+++ b/modules/net/dap_chain_node.c
@@ -55,6 +55,10 @@
 dap_chain_node_addr_t* dap_chain_node_gen_addr(dap_chain_net_id_t a_net_id)
 {
     dap_chain_node_addr_t *l_addr = DAP_NEW_Z(dap_chain_node_addr_t);
+    if (!l_addr) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_node_gen_addr");
+        return NULL;
+    }
     dap_chain_hash_fast_t l_hash;
     dap_hash_fast(&a_net_id, sizeof(dap_chain_net_id_t), &l_hash);
     // first 4 bytes is last 4 bytes of shard id hash
@@ -257,19 +261,25 @@ void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force)
                 if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX &&
                         a_chain->callback_get_minimum_fee){
                     uint256_t l_tx_fee = {};
-                    if (dap_chain_datum_tx_get_fee_value ((dap_chain_datum_tx_t*)l_datum->data, &l_tx_fee)) {
-                        log_it(L_WARNING, "Can't get fee value from tx");
-                        continue;
-                    }
-                    uint256_t l_min_fee = a_chain->callback_get_minimum_fee(a_chain);
-                    if (compare256(l_tx_fee, l_min_fee) < 0) {
-                        char *l_tx_fee_str = dap_chain_balance_to_coins(l_tx_fee);
-                        char *l_min_fee_str = dap_chain_balance_to_coins(l_min_fee);
-                        log_it(L_WARNING, "Fee %s is lower than minimum fee %s for tx %s",
-                               l_tx_fee_str, l_min_fee_str, l_objs[i].key);
-                        DAP_DELETE(l_tx_fee_str);
-                        DAP_DELETE(l_min_fee_str);
-                        continue;
+                    dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
+                    if (dap_chain_datum_tx_get_fee_value (l_tx, &l_tx_fee) ||
+                            IS_ZERO_256(l_tx_fee)) {
+                        if (!dap_chain_ledger_tx_poa_signed(l_net->pub.ledger, l_tx)) {
+                            log_it(L_WARNING, "Can't get fee value from tx %s", l_objs[i].key);
+                            continue;
+                        } else
+                            log_it(L_DEBUG, "Process service tx without fee");
+                    } else {
+                        uint256_t l_min_fee = a_chain->callback_get_minimum_fee(a_chain);
+                        if (compare256(l_tx_fee, l_min_fee) < 0) {
+                            char *l_tx_fee_str = dap_chain_balance_to_coins(l_tx_fee);
+                            char *l_min_fee_str = dap_chain_balance_to_coins(l_min_fee);
+                            log_it(L_WARNING, "Fee %s is lower than minimum fee %s for tx %s",
+                                   l_tx_fee_str, l_min_fee_str, l_objs[i].key);
+                            DAP_DELETE(l_tx_fee_str);
+                            DAP_DELETE(l_min_fee_str);
+                            continue;
+                        }
                     }
                 }
 
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 314bd2dcedd970e0103ee1c936d7da709ba74af7..401368f0ef9f664e157490eaa195098ff62314f9 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -87,6 +87,9 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
             "global_db write -group <group_name> -key <key_name> -value <value>"
             "global_db read -group <group_name> -key <key_name>"
             "global_db delete -group <group_name> -key <key_name>"
+            "global_db drop_table -group <group_name>\n"
+            "global_db get_keys -group <group name>"
+
 //                    "global_db wallet_info set -addr <wallet address> -cell <cell id> \n\n"
             );
     dap_cli_server_cmd_add("mempool", com_signer, "Sign operations",
@@ -123,7 +126,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                                         );
     dap_cli_server_cmd_add ("wallet", com_tx_wallet, "Wallet operations",
                             "wallet list\n"
-                            "wallet new -w <wallet_name> [-sign <sign_type>] [-restore <hex_value>] [-net <net_name>] [-force] [-password <password>] [-restore <hash>]\n"
+                            "wallet new -w <wallet_name> [-sign <sign_type>] [-restore <hex_value> | -restore_legacy <restore_string>] [-net <net_name>] [-force] [-password <password>]\n"
                             "wallet info {-addr <addr> | -w <wallet_name>} -net <net_name>\n"
                             "wallet activate -w <wallet_name> -password <password> [-ttl <password_ttl_in_minutes>]\n"
                             "wallet deactivate -w <wallet_name> -password <password>\n"
@@ -273,7 +276,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
     // Transaction commands
     dap_cli_server_cmd_add ("tx_create", com_tx_create, "Make transaction",
             "tx_create -net <net_name> -chain <chain_name> -value <value> -token <token_ticker> -to_addr <addr>"
-            "{-from_wallet <wallet_name> | -from_emission <emission_hash> {-certs <cert list> | -wallet_fee <wallet_name>}} -fee <value>\n");
+            "{-from_wallet <wallet_name> | -from_emission <emission_hash> {-cert <cert_name> | -wallet_fee <wallet_name>}} -fee <value>\n");
     dap_cli_server_cmd_add ("tx_create_json", com_tx_create_json, "Make transaction",
                 "tx_create_json -net <net_name> -chain <chain_name> -json <json_file_path>\n" );
     dap_cli_server_cmd_add ("tx_cond_create", com_tx_cond_create, "Make cond transaction",
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index a8e1cb47ec395a0294dd945b0959ba2623b09ba7..f6668b1cf5984cde97583233b0aa600051d08fd8 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -187,6 +187,10 @@ static dap_chain_node_addr_t* s_node_info_get_addr(dap_chain_net_t * a_net, dap_
     }
     if(a_addr->uint64) {
         l_address = DAP_NEW(dap_chain_node_addr_t);
+        if (!l_address) {
+            log_it(L_ERROR, "Memory allocation error in s_node_info_get_addr");
+            return NULL;
+        }
         l_address->uint64 = a_addr->uint64;
     }
     return l_address;
@@ -536,19 +540,20 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
         dap_chain_node_addr_t *l_addr = NULL;
         if(a_addr && a_addr->uint64) {
             l_addr = DAP_NEW(dap_chain_node_addr_t);
+            if(!l_addr) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "addr not valid");
+                dap_string_free(l_string_reply, true);
+                return -1;
+            }
             l_addr->uint64 = a_addr->uint64;
         } else if(a_alias) {
             l_addr = dap_chain_node_alias_find(a_net, a_alias);
         }
-        if(!l_addr) {
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "addr not valid");
-            dap_string_free(l_string_reply, true);
-            return -1;
-        }
+
         // read node
         dap_chain_node_info_t *node_info_read = node_info_read_and_reply(a_net, l_addr, a_str_reply);
         if(!node_info_read) {
-            DAP_DELETE(l_addr);
+            DAP_DEL_Z(l_addr);
             dap_string_free(l_string_reply, true);
             return -2;
         }
@@ -730,7 +735,7 @@ static int node_info_dump_with_reply(dap_chain_net_t * a_net, dap_chain_node_add
 int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
 {
     enum {
-        CMD_NONE, CMD_NAME_CELL, CMD_ADD, CMD_FLUSH, CMD_RECORD, CMD_WRITE, CMD_READ, CMD_DELETE
+        CMD_NONE, CMD_NAME_CELL, CMD_ADD, CMD_FLUSH, CMD_RECORD, CMD_WRITE, CMD_READ, CMD_DELETE, CMD_DROP, CMD_GET_KEYS
     };
     int arg_index = 1;
     int cmd_name = CMD_NONE;
@@ -747,6 +752,11 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
                 cmd_name = CMD_READ;
     else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, MIN(a_argc, arg_index + 1), "delete", NULL))
                 cmd_name = CMD_DELETE;
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "drop_table", NULL))
+                cmd_name = CMD_DROP;
+    else if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, min(a_argc, arg_index + 1), "get_keys", NULL))
+            cmd_name = CMD_GET_KEYS;
+
     switch (cmd_name) {
     case CMD_NAME_CELL:
     {
@@ -930,100 +940,164 @@ int com_global_db(int a_argc, char ** a_argv, char **a_str_reply)
         return l_ret;
     }
     case CMD_WRITE:
-        {
-            const char *l_group_str = NULL;
-            const char *l_key_str = NULL;
-            const char *l_value_str = NULL;
+    {
+        const char *l_group_str = NULL;
+        const char *l_key_str = NULL;
+        const char *l_value_str = NULL;
 
-            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
-            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-key", &l_key_str);
-            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-value", &l_value_str);
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-key", &l_key_str);
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-value", &l_value_str);
 
-            if(!l_group_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
-                return -120;
-            }
+        if(!l_group_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
+            return -120;
+        }
 
-            if(!l_key_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'key' to be valid", a_argv[0]);
-                return -121;
-            }
+        if(!l_key_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'key' to be valid", a_argv[0]);
+            return -121;
+        }
 
-            if(!l_value_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'value' to be valid", a_argv[0]);
-                return -122;
-            }
+        if(!l_value_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'value' to be valid", a_argv[0]);
+            return -122;
+        }
 
-            if (dap_global_db_set(l_group_str, l_key_str, l_value_str, strlen(l_value_str), false, NULL, NULL)) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Data has been successfully written to the database");
-                return 0;
-            } else {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Data writing is failed");
-                return -124;
-            }
+        if (!dap_global_db_set_sync(l_group_str, l_key_str, l_value_str, strlen(l_value_str) +1 , false)) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Data has been successfully written to the database");
+            return 0;
+        } else {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Data writing is failed");
+            return -124;
+        }
+
+    }
+    case CMD_READ:
+    {
+        const char *l_group_str = NULL;
+        const char *l_key_str = NULL;
 
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-key", &l_key_str);
+
+        if(!l_group_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
+            return -120;
+        }
+
+        if(!l_key_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'key' to be valid", a_argv[0]);
+            return -122;
         }
-        case CMD_READ:
+
+        size_t l_out_len = 0;
+        uint8_t *l_value_out = dap_global_db_get_sync(l_group_str, l_key_str, &l_out_len, NULL, NULL);
+
+        if (!l_value_out || !l_out_len)
         {
-            const char *l_group_str = NULL;
-            const char *l_key_str = NULL;
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Record with key %s in group %s not found", l_key_str, l_group_str);
+            return -121;
+        }
 
-            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
-            dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-key", &l_key_str);
+        dap_cli_server_cmd_set_reply_text(a_str_reply, "Group %s, key %s, data:\n %s", l_group_str, l_key_str, (char*)l_value_out);
+        return 0;
+    }
+    case CMD_DELETE:
+    {
+        const char *l_group_str = NULL;
+        const char *l_key_str = NULL;
 
-            if(!l_group_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
-                return -120;
-            }
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-key", &l_key_str);
 
-            if(!l_key_str) {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'key' to be valid", a_argv[0]);
-                return -122;
-            }
+        if(!l_group_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
+            return -120;
+        }
 
-            size_t l_out_len = 0;
-            uint8_t *l_value_out = dap_global_db_get_sync(l_group_str, l_key_str, &l_out_len, NULL, NULL);
+        if(!l_key_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "No key provided, entire table %s will be altered", l_group_str);
+            size_t l_objs_count = 0;
+            dap_global_db_obj_t* l_obj = dap_global_db_get_all_sync(l_group_str, &l_objs_count);
 
-            if (!l_value_out || !l_out_len)
+            if (!l_obj || !l_objs_count)
             {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Record with key %s in group %s not found", l_key_str, l_group_str);
-                return -121;
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "No data in group %s.", l_group_str);
+                return -124;
+            }
+            size_t i, j = 0;
+            for (i = 0; i < l_objs_count; ++i) {
+                if (!l_obj[i].key)
+                    continue;
+                if (!dap_global_db_del_sync(l_group_str, l_obj[i].key)) {
+                    ++j;
+                }
             }
+            dap_global_db_objs_delete(l_obj, l_objs_count);
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Removed %lu of %lu records in table %s", j, i, l_group_str);
+            return 0;
+        }
 
-            dap_cli_server_cmd_set_reply_text(a_str_reply, "Group %s, key %s, data:\n %s", l_group_str, l_key_str, (char*)l_value_out);
+        if (dap_global_db_del(l_group_str, l_key_str, NULL, NULL)) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Record with key %s in group %s was deleted successfuly", l_key_str, l_group_str);
             return 0;
+        } else {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Record with key %s in group %s deleting failed", l_group_str, l_key_str);
+            return -122;
         }
-        case CMD_DELETE:
-            {
-                const char *l_group_str = NULL;
-                const char *l_key_str = NULL;
+    }
+    case CMD_DROP:
+    {
+        const char *l_group_str = NULL;
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
 
-                dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
-                dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-key", &l_key_str);
+        if(!l_group_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
+            return -120;
+        }
 
-                if(!l_group_str) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
-                    return -120;
-                }
+        if (!dap_global_db_del_sync(l_group_str, NULL))
+        {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Dropped table %s", l_group_str);
+            return 0;
+        } else {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "Failed to drop table %s", l_group_str);
+            return -122;
+        }
+    }
+    case CMD_GET_KEYS:
+    {
+        const char *l_group_str = NULL;
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-group", &l_group_str);
 
-                if(!l_key_str) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'key' to be valid", a_argv[0]);
-                    return -121;
-                }
+        if(!l_group_str) {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "%s requires parameter 'group' to be valid", a_argv[0]);
+            return -120;
+        }
 
-                if (dap_global_db_del(l_group_str, l_key_str, NULL, NULL)) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Record with key %s in group %s was deleted successfuly", l_key_str, l_group_str);
-                    return 0;
-                } else {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Record with key %s in group %s deleting failed", l_group_str, l_key_str);
-                    return -122;
-                }
-            }
+        size_t l_objs_count = 0;
+        dap_global_db_obj_t* l_obj = dap_global_db_get_all_sync(l_group_str, &l_objs_count);
+
+        if (!l_obj || !l_objs_count)
+        {
+            dap_cli_server_cmd_set_reply_text(a_str_reply, "No data in group %s.", l_group_str);
+            return -124;
+        }
+
+        dap_string_t *l_ret_str = dap_string_new(NULL);
+        for(size_t i = 0; i < l_objs_count; i++){
+            dap_string_append_printf(l_ret_str, "%s\n", l_obj[i].key);
+        }
+
+        dap_cli_server_cmd_set_reply_text(a_str_reply, "Keys list for group %s:\n%s\n", l_group_str, l_ret_str->str);
+        dap_string_free(l_ret_str, true);
+        return 0;
+    }
     default:
         dap_cli_server_cmd_set_reply_text(a_str_reply, "parameters are not valid");
         return -1;
     }
-    return  -555;
 }
 
 /**
@@ -1924,7 +1998,10 @@ char    l_buf[1024];
         case CMD_WALLET_NEW: {
             dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-password", &l_pass_str);
             dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-sign", &l_sign_type_str);
-            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-restore", &l_restore_str);
+            int l_restore_opt = dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-restore", &l_restore_str);
+            int l_restore_legacy_opt = 0;
+            if (!l_restore_str)
+                l_restore_legacy_opt = dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-restore_legacy", &l_restore_str);
             // rewrite existing wallet
             int l_is_force = dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-force", NULL);
 
@@ -1969,9 +2046,26 @@ char    l_buf[1024];
             if (l_sign_type.type == SIG_TYPE_TESLA)
                 return  dap_cli_server_cmd_set_reply_text(a_str_reply, "Tesla algorithm is no longer supported, please, use another variant"), -1;
 
+            uint8_t *l_seed = NULL;
+            size_t l_seed_size = 0, l_restore_str_size = dap_strlen(l_restore_str);
+
+            if(l_restore_opt || l_restore_legacy_opt) {
+                if (l_restore_str_size > 3 && !dap_strncmp(l_restore_str, "0x", 2) && (!dap_is_hex_string(l_restore_str + 2, l_restore_str_size - 2) || l_restore_legacy_opt)) {
+                    l_seed_size = (l_restore_str_size - 2) / 2;
+                    l_seed = DAP_NEW_SIZE(uint8_t, l_seed_size);
+                    dap_hex2bin(l_seed, l_restore_str + 2, l_restore_str_size - 2);
+                    if (l_restore_legacy_opt) {
+                        dap_string_append_printf(l_l_string_ret, "CAUTION!!! CAUTION!!! CAUTION!!!\nYour wallet has a low level of protection. Please create a new wallet again with the option -restore\n");
+                    }
+                } else {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Restored hash is invalid or too short, wallet is not created. Please use -restore 0x<hex_value> or -restore_legacy 0x<restore_string>");
+                    return -1;
+                }
+            }
+
             // Creates new wallet
             dap_chain_wallet_t *l_wallet = dap_chain_wallet_create_with_seed(l_wallet_name, c_wallets_path, l_sign_type,
-                    l_restore_str, dap_strlen(l_restore_str), l_pass_str);
+                    l_seed, l_seed_size, l_pass_str);
 
             if (!l_wallet)
                 return  dap_cli_server_cmd_set_reply_text(a_str_reply, "Wallet is not created because of internal error"), -1;
@@ -2937,37 +3031,62 @@ int com_mempool_check(int a_argc, char **a_argv, char ** a_str_reply)
                 l_datum_hash_hex_str = dap_enc_base58_to_hex_str_from_str(l_datum_hash_str);
             } else
                 l_datum_hash_hex_str = dap_strdup(l_datum_hash_str);
-            if (l_chain) {
-                dap_chain_datum_t *l_datum = s_com_mempool_check_datum_in_chain(l_chain, l_datum_hash_hex_str);
-                DAP_DELETE(l_datum_hash_hex_str);
-                if (l_datum) {
-                    dap_string_t *l_str_reply = dap_string_new("");
-                    dap_string_append_printf(l_str_reply, "Datum %s is present in mempool\n", l_datum_hash_str);
-                    dap_chain_datum_dump(l_str_reply, l_datum, l_hash_out_type);
-                    DAP_DELETE(l_datum);
-                    *a_str_reply = l_str_reply->str;
-                    dap_string_free(l_str_reply, false);
-                    return 0;
-                } else {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s in %s.%s", l_datum_hash_str, l_net->pub.name, l_chain->name);
+            dap_chain_datum_t *l_datum = NULL;
+            char *l_chain_name = l_chain ? l_chain->name : NULL;
+            bool l_found_in_chains = false;
+            int l_ret_code = 0;
+            dap_hash_fast_t l_atom_hash = {};
+            if (l_chain)
+                l_datum = s_com_mempool_check_datum_in_chain(l_chain, l_datum_hash_hex_str);
+            else {
+                dap_chain_t *it = NULL;
+                DL_FOREACH(l_net->pub.chains, it) {
+                    l_datum = s_com_mempool_check_datum_in_chain(it, l_datum_hash_hex_str);
+                    if (l_datum) {
+                        l_chain_name = it->name;
+                        break;
+                    }
+                }
+            }
+            if (!l_datum) {
+                l_found_in_chains = true;
+                dap_hash_fast_t l_datum_hash;
+                if (dap_chain_hash_fast_from_hex_str(l_datum_hash_hex_str, &l_datum_hash)) {
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect hash string %s", l_datum_hash_str);
                     return -4;
                 }
-            } else {
-                DL_FOREACH(l_net->pub.chains, l_chain) {
-                    dap_chain_datum_t *l_datum = s_com_mempool_check_datum_in_chain(l_chain, l_datum_hash_hex_str);
-                    if (l_datum) {
-                        DAP_DELETE(l_datum_hash_hex_str);
-                        dap_string_t *l_str_reply = dap_string_new("");
-                        dap_string_append_printf(l_str_reply, "Datum %s is present in mempool\n", l_datum_hash_str);
-                        dap_chain_datum_dump(l_str_reply, l_datum, l_hash_out_type);
-                        DAP_DELETE(l_datum);
-                        *a_str_reply = l_str_reply->str;
-                        dap_string_free(l_str_reply, false);
-                        return 0;
+                if (l_chain)
+                    l_datum = l_chain->callback_datum_find_by_hash(l_chain, &l_datum_hash, &l_atom_hash, &l_ret_code);
+                else {
+                    dap_chain_t *it = NULL;
+                    DL_FOREACH(l_net->pub.chains, it) {
+                        l_datum = it->callback_datum_find_by_hash(it, &l_datum_hash, &l_atom_hash, &l_ret_code);
+                        if (l_datum) {
+                            l_chain_name = it->name;
+                            break;
+                        }
                     }
                 }
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s in net %s", l_datum_hash_str, l_net->pub.name);
-                DAP_DEL_Z(l_datum_hash_hex_str);
+            }
+            DAP_DELETE(l_datum_hash_hex_str);
+            if (l_datum) {
+                dap_string_t *l_str_reply = dap_string_new("");
+                dap_string_append_printf(l_str_reply, "Datum %s is present in %s.%s\n", l_datum_hash_str,
+                                                        l_found_in_chains ? "chains" : "mempool", l_chain_name);
+                if (l_found_in_chains) {
+                    char l_atom_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
+                    dap_chain_hash_fast_to_str(&l_atom_hash, l_atom_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
+                    dap_string_append_printf(l_str_reply, "Atom hash is %s return code is %d (%s)\n",
+                                                            l_atom_hash_str, l_ret_code, dap_chain_ledger_tx_check_err_str(l_ret_code));
+                }
+                dap_chain_datum_dump(l_str_reply, l_datum, l_hash_out_type);
+                if (!l_found_in_chains)
+                    DAP_DELETE(l_datum);
+                *a_str_reply = l_str_reply->str;
+                dap_string_free(l_str_reply, false);
+                return 0;
+            } else {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find datum %s in %s.%s", l_datum_hash_str, l_net->pub.name, l_chain ? l_chain->name : "");
                 return -4;
             }
         } else {
@@ -3067,10 +3186,8 @@ int com_mempool_proc(int a_argc, char **a_argv, char **a_str_reply)
             dap_ctime_r(&l_ts_create, buf), l_datum->header.data_size);
     int l_verify_datum = dap_chain_net_verify_datum_for_add(l_chain, l_datum, &l_datum_hash) ;
     if (l_verify_datum != 0){
-        char *l_err_verify_datum_str = dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum);
         dap_string_append_printf(l_str_tmp, "Error! Datum doesn't pass verifications (%s) examine node log files",
-                                 l_err_verify_datum_str);
-        DAP_DELETE(l_err_verify_datum_str);
+                                 dap_chain_net_verify_datum_err_code_to_str(l_datum, l_verify_datum));
         ret = -9;
     } else {
         if (l_chain->callback_add_datums) {
@@ -5112,9 +5229,9 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     const char * l_emission_chain_name = NULL;
     const char * l_tx_num_str = NULL;
     const char *l_emission_hash_str = NULL;
-    const char *l_certs_str = NULL;
-    dap_cert_t **l_certs = NULL;
-    size_t l_certs_count = 0;
+    const char *l_cert_str = NULL;
+    dap_cert_t *l_cert = NULL;
+    dap_enc_key_t *l_priv_key = NULL;
     dap_chain_hash_fast_t l_emission_hash = {};
     size_t l_tx_num = 0;
     dap_chain_wallet_t * l_wallet_fee = NULL;
@@ -5139,7 +5256,7 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-net", &l_net_name);
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-chain", &l_chain_name);
     dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-tx_num", &l_tx_num_str);
-    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-certs", &l_certs_str);
+    dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-cert", &l_cert_str);
 
     if(l_tx_num_str)
         l_tx_num = strtoul(l_tx_num_str, NULL, 10);
@@ -5152,9 +5269,9 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     }
 
     // Validator's fee
-    if(dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-fee", &str_tmp))
+    if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-fee", &str_tmp))
         l_value_fee = dap_chain_balance_scan(str_tmp);
-    if (IS_ZERO_256(l_value_fee)) {
+    if (IS_ZERO_256(l_value_fee) && (!l_emission_hash_str || (str_tmp && strcmp(str_tmp, "0")))) {
         dap_cli_server_cmd_set_reply_text(a_str_reply,
                 "tx_create requires parameter '-fee' to be valid uint256");
         return -5;
@@ -5211,36 +5328,24 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
             return -9;
         }
 
-        const char *l_native_ticker = l_net->pub.native_ticker;
-        bool not_native = dap_strcmp(l_token_ticker, l_native_ticker);
-
-        if (not_native) {
-            if (l_wallet_fee_name){
-                l_wallet_fee = dap_chain_wallet_open(l_wallet_fee_name, c_wallets_path);
-                if (!l_wallet_fee) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply, "wallet %s does not exist", l_wallet_fee_name);
-                    return -12;
-                }
-            } else {
-                dap_cli_server_cmd_set_reply_text(a_str_reply, "To create a basic transaction with a "
-                                                               "non-native ticker, you must specify the '-wallet_fee' "
-                                                               "parameter. It is required to pay a commission for the "
-                                                               "transaction.");
-                return -11;
+        if (l_wallet_fee_name){
+            l_wallet_fee = dap_chain_wallet_open(l_wallet_fee_name, c_wallets_path);
+            if (!l_wallet_fee) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Wallet %s does not exist", l_wallet_fee_name);
+                return -12;
             }
-        } else {
-            if (l_certs_str) {
-                dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_count);
-                if (!l_certs_count) {
-                    dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                                      "tx_create requires at least one valid certificate to sign the basic transaction of emission");
-                    return -5;
-                }
-            } else {
-                dap_cli_server_cmd_set_reply_text(a_str_reply,
-                                                  "tx_create requires parameter '-certs' for create base tx for emission in native token");
-                return -10;
+            l_priv_key = dap_chain_wallet_get_key(l_wallet_fee, 0);
+        } else if (l_cert_str) {
+            l_cert = dap_cert_find_by_name(l_cert_str);
+            if (!l_cert) {
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Certificate %s is invalid", l_cert_str);
+                return -5;
             }
+            l_priv_key = l_cert->enc_key;
+        } else {
+            dap_cli_server_cmd_set_reply_text(a_str_reply,
+                                              "tx_create requires parameter '-cert' or '-wallet' for create base tx for emission");
+            return -10;
         }
     }
 
@@ -5266,17 +5371,15 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
     dap_string_t *l_string_ret = dap_string_new(NULL);
     int res = 0;
     if (l_emission_hash_str) {
-        bool not_native = dap_strcmp(l_token_ticker, l_net->pub.native_ticker);
         char *l_tx_hash_str = NULL;
-        if (not_native) {
-            l_tx_hash_str = dap_chain_mempool_base_tx_create(l_chain, &l_emission_hash, l_emission_chain->id,
-                                             l_value, l_token_ticker,dap_chain_wallet_get_key(l_wallet_fee, 0), l_addr_to, NULL,
-                                             0, l_hash_out_type,l_value_fee);
-        } else {
-            l_tx_hash_str = dap_chain_mempool_base_tx_create(l_chain, &l_emission_hash, l_emission_chain->id,
-                                             l_value, l_token_ticker,NULL, l_addr_to, l_certs,
-                                             l_certs_count, l_hash_out_type,l_value_fee);
-        }
+        if (!l_priv_key) {
+            dap_string_append_printf(l_string_ret, "No private key defined for creating the underlying "
+                                                   "transaction no '-wallet_fee' or ' -cert' parameter specified.");
+            res = -10;
+        }
+        l_tx_hash_str = dap_chain_mempool_base_tx_create(l_chain, &l_emission_hash, l_emission_chain->id,
+                                                         l_value, l_token_ticker, l_addr_to, l_priv_key,
+                                                         l_hash_out_type, l_value_fee);
         if (l_tx_hash_str) {
             dap_string_append_printf(l_string_ret, "\nDatum %s with 256bit TX is placed in datum pool\n", l_tx_hash_str);
             DAP_DELETE(l_tx_hash_str);
@@ -5288,6 +5391,7 @@ int com_tx_create(int a_argc, char **a_argv, char **a_str_reply)
         dap_string_free(l_string_ret, true);
         DAP_DELETE(l_addr_to);
         dap_chain_wallet_close(l_wallet_fee);
+        DAP_DEL_Z(l_cert);
         return res;        
     }
 
@@ -5957,6 +6061,11 @@ int cmd_remove(int a_argc, char **a_argv, char ** a_str_reply)
         for (uint16_t i = 0; i < l_net_count; i++) {
             size_t l_aliases_count = 0;
             _pvt_net_aliases_list_t *l_gdb_groups = DAP_NEW(_pvt_net_aliases_list_t);
+            if (!l_gdb_groups) {
+                log_it(L_ERROR, "Memory allocation error in cmd_remove");
+                dap_list_free(l_net_returns);
+                return -1;
+            }
             l_gdb_groups->net = l_net_list[i];
             l_gdb_groups->group_aliases = dap_global_db_get_all_sync(l_gdb_groups->net->pub.gdb_nodes_aliases, &l_gdb_groups->count_aliases);
             l_gdb_groups->group_nodes = dap_global_db_get_all_sync(l_gdb_groups->net->pub.gdb_nodes, &l_gdb_groups->count_nodes);
@@ -6311,6 +6420,11 @@ static char **s_parse_items(const char *a_str, char a_delimiter, int *a_count, c
     }
 
     char **lines = DAP_CALLOC(l_count_temp, sizeof (void *));
+    if (!lines) {
+        log_it(L_ERROR, "Memoru allocation error in s_parse_items");
+        DAP_FREE(l_temp_str);
+        return NULL;
+    }
     for (int i = 0; i < l_count_temp; i++) {
         while (*s == 0) s++;
         lines[i] = strdup(s);
@@ -6556,7 +6670,10 @@ static byte_t *s_concat_meta (dap_list_t *a_meta, size_t *a_fullsize)
         if (l_counter >= l_part_power) {
             l_part_power = l_part * l_power++;
             l_buf = (byte_t *) DAP_REALLOC(l_buf, l_part_power);
-
+            if (!l_buf) {
+                log_it(L_ERROR, "Memory allocation error in s_concat_meta");
+                return NULL;
+            }
         }
         memcpy (&l_buf[l_index], l_tsd->data, strlen((char *)l_tsd->data));
     }
@@ -6576,6 +6693,10 @@ static uint8_t *s_concat_hash_and_mimetypes (dap_chain_hash_fast_t *a_chain_hash
     size_t l_len_meta_buf = *a_fullsize;
     *a_fullsize += sizeof (a_chain_hash->raw) + 1;
     uint8_t *l_fullbuf = DAP_CALLOC(*a_fullsize, 1);
+    if (!l_fullbuf) {
+        log_it(L_ERROR, "Memory allocation error in s_concat_hash_and_mimetypes");
+        return NULL;
+    }
     uint8_t *l_s = l_fullbuf;
 
     memcpy(l_s, a_chain_hash->raw, sizeof(a_chain_hash->raw));
@@ -6590,6 +6711,10 @@ static uint8_t *s_concat_hash_and_mimetypes (dap_chain_hash_fast_t *a_chain_hash
 static char *s_strdup_by_index (const char *a_file, const int a_index)
 {
     char *l_buf = DAP_CALLOC(a_index + 1, 1);
+    if (!l_buf) {
+        log_it(L_ERROR, "Memory allocation error in s_strdup_by_index");
+        return NULL;
+    }
     strncpy (l_buf, a_file, a_index);
     return l_buf;
 }
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 96a764ff535fc83fa9d7487b09acac6f313c1df3..e2c9cf73700c544bbff0f203ab6c5a741677c009 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -170,6 +170,10 @@ static void s_tx_header_print(dap_string_t *a_str_out, dap_chain_tx_hash_process
         l_declined = true;
     else {
         l_tx_data = DAP_NEW_Z(dap_chain_tx_hash_processed_ht_t);
+        if (!l_tx_data) {
+            log_it(L_ERROR, "Memory allocation error in s_tx_header_print");
+            return;
+        }
         l_tx_data->hash = *a_tx_hash;
         HASH_ADD(hh, *a_tx_data_ht, hash, sizeof(*a_tx_hash), l_tx_data);
         const char *l_token_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_ledger, a_tx_hash);
@@ -550,6 +554,10 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger
                         break;
                     }
                     l_sht = DAP_NEW_Z(dap_chain_tx_hash_processed_ht_t);
+                    if (!l_sht) {
+                        log_it(L_ERROR, "Memory allocation error in dap_db_history_filter");
+                        return NULL;
+                    }
                     l_sht->hash = l_tx_hash;
                     HASH_ADD(hh, a_tx_hash_processed, hash, sizeof(dap_chain_hash_fast_t), l_sht);
                     l_tx_num++;
@@ -676,6 +684,11 @@ int com_ledger(int a_argc, char ** a_argv, char **a_str_reply)
                     dap_chain_addr_t *l_addr_tmp = (dap_chain_addr_t *) dap_chain_wallet_get_addr(l_wallet,
                             l_net->pub.id);
                     l_addr = DAP_NEW_SIZE(dap_chain_addr_t, sizeof(dap_chain_addr_t));
+                    if (!l_addr) {
+                        dap_cli_server_cmd_set_reply_text(a_str_reply, "Out of memory!");
+                        log_it(L_ERROR, "Memory allocation error in com_ledger");
+                        return -1;
+                    }
                     memcpy(l_addr, l_addr_tmp, sizeof(dap_chain_addr_t));
                     dap_chain_wallet_close(l_wallet);
                 }
@@ -1326,6 +1339,11 @@ int cmd_decree(int a_argc, char **a_argv, char ** a_str_reply)
                 }else{
                     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_chain_addr_t);
                     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+                    if (!l_tsd) {
+                        log_it(L_ERROR, "Memory allocation error in cmd_decree");
+                        dap_list_free_full(l_tsd_list, NULL);
+                        return -1;
+                    }
                     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET;
                     l_tsd->size = sizeof(dap_chain_addr_t);
                     dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_param_addr_str);
@@ -1335,6 +1353,11 @@ int cmd_decree(int a_argc, char **a_argv, char ** a_str_reply)
 
                 l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(uint256_t);
                 l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+                if (!l_tsd) {
+                    log_it(L_ERROR, "Memory allocation error in cmd_decree");
+                    dap_list_free_full(l_tsd_list, NULL);
+                    return -1;
+                }
                 l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE;
                 l_tsd->size = sizeof(uint256_t);
                 *(uint256_t*)(l_tsd->data) = dap_cvt_str_to_uint256(l_param_value_str);
@@ -1387,6 +1410,11 @@ int cmd_decree(int a_argc, char **a_argv, char ** a_str_reply)
 
                 l_total_tsd_size = sizeof(dap_tsd_t) + sizeof(uint256_t);
                 l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+                if (!l_tsd) {
+                    log_it(L_ERROR, "Memory allocation error in cmd_decree");
+                    dap_list_free_full(l_tsd_list, NULL);
+                    return -1;
+                }
                 l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER;
                 l_tsd->size = sizeof(uint256_t);
                 *(uint256_t*)(l_tsd->data) = l_new_num_of_owners;
diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c
index e96fdc788f6509a88c6c7a491807cd0c719de003..3b2a56925986f93f236bed3509048e5a87449394 100644
--- a/modules/net/dap_chain_node_client.c
+++ b/modules/net/dap_chain_node_client.c
@@ -685,6 +685,10 @@ dap_chain_node_client_t *dap_chain_node_client_create(dap_chain_net_t *a_net,
         return NULL;
     }
     dap_chain_node_client_t *l_node_client = DAP_NEW_Z(dap_chain_node_client_t);
+    if (!l_node_client) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_node_client_create");
+        return NULL;
+    }
 
     l_node_client->state = NODE_CLIENT_STATE_DISCONNECTED;
     l_node_client->callbacks_arg = a_callback_arg;
diff --git a/modules/net/dap_chain_node_dns_client.c b/modules/net/dap_chain_node_dns_client.c
index 3b8ed6a71547e60a53d1a653daacc1576b92be76..641f11bedc5e2b3af54703a923c9e8c41a6dafa0 100644
--- a/modules/net/dap_chain_node_dns_client.c
+++ b/modules/net/dap_chain_node_dns_client.c
@@ -171,6 +171,10 @@ static void s_dns_client_esocket_worker_assign_callback(dap_events_socket_t * a_
     dap_events_socket_write_unsafe(a_esocket,l_dns_client->dns_request.data, l_dns_client->dns_request.size );
 
     dap_events_socket_uuid_t * l_es_uuid_ptr = DAP_NEW_Z(dap_events_socket_uuid_t);
+    if (!l_es_uuid_ptr) {
+        log_it(L_ERROR, "Memory allocation error in s_dns_client_esocket_worker_assign_callback");
+        return;
+    }
     *l_es_uuid_ptr = a_esocket->uuid;
     dap_timerfd_start_on_worker(a_worker, dap_config_get_item_uint64_default(g_config,"dns_client","request_timeout",10)*1000,
                                  s_dns_client_esocket_timeout_callback,l_es_uuid_ptr);
diff --git a/modules/net/dap_chain_node_dns_server.c b/modules/net/dap_chain_node_dns_server.c
index 7ed8fea2822e41a1262efc404947b15571961a7f..da023392eccdd15a656232dce62bb6bb550802b4 100644
--- a/modules/net/dap_chain_node_dns_server.c
+++ b/modules/net/dap_chain_node_dns_server.c
@@ -53,6 +53,10 @@ int dap_dns_zone_register(char *zone, dap_dns_zone_callback_t callback) {
     HASH_FIND_STR(s_dns_server->hash_table, zone, new_zone);
     if (new_zone == NULL) {      // zone is not present
       new_zone = DAP_NEW(dap_dns_zone_hash_t);
+      if (!new_zone) {
+        log_it(L_ERROR, "Memory allocation error in dap_dns_zone_register");
+        return DNS_ERROR_FAILURE;
+      }
       new_zone->zone = dap_strdup(zone);
       HASH_ADD_KEYPTR(hh, s_dns_server->hash_table, new_zone->zone, strlen(new_zone->zone), new_zone);
     }                           // if zone present, just reassign callback
@@ -112,8 +116,20 @@ void dap_dns_client_read(dap_events_socket_t *a_es, void *a_arg) {
         return;
     }
     dap_dns_buf_t *dns_message = DAP_NEW(dap_dns_buf_t);
+    if (!dns_message) {
+        log_it(L_ERROR, "Memory allocation error in dap_dns_client_read");
+        return;
+    }
     dap_dns_buf_t *dns_reply = DAP_NEW(dap_dns_buf_t);
+    if (!dns_reply) {
+        log_it(L_ERROR, "Memory allocation error in dap_dns_client_read");
+        return;
+    }
     dns_message->data = DAP_NEW_SIZE(char, a_es->buf_in_size + 1);
+    if (!dns_message->data) {
+        log_it(L_ERROR, "Memory allocation error in dap_dns_client_read");
+        return;
+    }
     dns_message->data[a_es->buf_in_size] = 0;
     dap_events_socket_pop_from_buf_in(a_es, dns_message->data, a_es->buf_in_size);
     dns_message->size = 0;
@@ -121,6 +137,10 @@ void dap_dns_client_read(dap_events_socket_t *a_es, void *a_arg) {
     // Parse incoming DNS message
     int block_len = DNS_HEADER_SIZE;
     dns_reply->data = DAP_NEW_SIZE(char, block_len);
+    if (!dns_reply->data) {
+        log_it(L_ERROR, "Memory allocation error in dap_dns_client_read");
+        return;
+    }
     dns_reply->size = 0;
     uint16_t val = dap_dns_buf_get_uint16(dns_message); // ID
     dap_dns_buf_put_uint16(dns_reply, val);
@@ -260,6 +280,10 @@ cleanup:
 void dap_dns_server_start( uint16_t a_port)
 {
     s_dns_server = DAP_NEW_Z(dap_dns_server_t);
+    if (!s_dns_server) {
+        log_it(L_ERROR, "Memory allocation error in dap_dns_server_start");
+        return;
+    }
     dap_events_socket_callbacks_t l_cb = {};
     l_cb.read_callback = dap_dns_client_read;
     s_dns_server->instance = dap_server_new( NULL, a_port, SERVER_UDP, &l_cb);
diff --git a/modules/net/dap_chain_node_ping.c b/modules/net/dap_chain_node_ping.c
index f40d10edec1a5ee7b21b8b0f15555a323fa6f837..10d65ae03abab2465e77f3af56dc2539077def3a 100644
--- a/modules/net/dap_chain_node_ping.c
+++ b/modules/net/dap_chain_node_ping.c
@@ -87,6 +87,10 @@ static void* node_ping_proc(void *a_arg)
     DAP_DELETE(a_arg);
 
     char *host4 = DAP_NEW_SIZE(char, INET_ADDRSTRLEN);
+    if (!host4) {
+        log_it(L_ERROR, "Memory allocation error in node_ping_proc");
+        return NULL;
+    }
     struct sockaddr_in sa4 = { .sin_family = AF_INET, .sin_addr = l_addr };
     const char* str_ip4 = inet_ntop(AF_INET, &(((struct sockaddr_in *) &sa4)->sin_addr), host4, INET_ADDRSTRLEN);
     if(!str_ip4){
@@ -156,6 +160,10 @@ static void* node_ping_proc(void *a_arg)
 int start_node_ping(pthread_t *a_thread, struct in_addr a_addr, int a_port, int a_count)
 {
     uint8_t *l_data = DAP_NEW_Z_SIZE(uint8_t, sizeof(struct in_addr) + 2 * sizeof(int));
+    if (!l_data) {
+        log_it(L_ERROR, "Memory allocation error in start_node_ping");
+        return -1;
+    }
     memcpy(l_data, &a_count, sizeof(int));
     memcpy(l_data + sizeof(int), &a_port, sizeof(int));
     memcpy(l_data + 2 * sizeof(int), &a_addr, sizeof(struct in_addr));
@@ -265,6 +273,12 @@ static void* node_ping_background_proc(void *a_arg)
     // allocate memory for best node addresses
     dap_chain_node_addr_t *l_node_addr_tmp;
     l_node_addr_tmp = DAP_NEW(dap_chain_node_addr_t);
+    if (!l_node_addr_tmp) {
+        log_it(L_ERROR, "Memory allocation error in node_ping_background_proc");
+        dap_list_free_full(l_node_list0, NULL);
+        DAP_DEL_Z(s_node_addr_ping);
+        return 0;
+    }
     memcpy(l_node_addr_tmp, s_node_addr_tr, sizeof(dap_chain_node_addr_t));
     DAP_DELETE(s_node_addr_tr);
     s_node_addr_tr = l_node_addr_tmp;
@@ -292,12 +306,22 @@ int dap_chain_node_ping_background_start(dap_chain_net_t *a_net, dap_list_t *a_n
     dap_list_t *l_node_list_tmp = a_node_list;
     while(l_node_list_tmp) {
         dap_chain_node_addr_t *l_addr = DAP_NEW(dap_chain_node_addr_t);
+        if (!l_addr) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_node_ping_background_start");
+            dap_list_free_full(l_node_list, NULL);
+            return -1;
+        }
         memcpy(l_addr, l_node_list_tmp->data, sizeof(dap_chain_node_addr_t));
         l_node_list = dap_list_append(l_node_list, l_addr);
         l_node_list_tmp = dap_list_next(l_node_list_tmp);
     }
     // start searching for better nodes
     uint8_t *l_arg = DAP_NEW_SIZE(uint8_t, sizeof(dap_chain_net_t*) + sizeof(dap_list_t*));
+    if (!l_arg) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_node_ping_background_start");
+        dap_list_free_full(l_node_list, NULL);
+        return -1;
+    }
     memcpy(l_arg, &a_net, sizeof(dap_chain_net_t*));
     memcpy(l_arg + sizeof(dap_chain_net_t*), &l_node_list, sizeof(dap_list_t*));
     pthread_create(&s_thread, NULL, node_ping_background_proc, l_arg);
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index d5ad5708f222ddc953507b2cfd76efb42fa6fbac..5c4843ada1f5e2e450b29fc1875c9bec5eb6ce19 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -247,14 +247,14 @@ static int s_cli_net_srv( int argc, char **argv, char **a_str_reply)
 
         const char* l_region_str = NULL;
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-region", &l_region_str);
+
         const char* l_continent_str = NULL;
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-continent", &l_continent_str);
+        int8_t l_continent_num = dap_chain_net_srv_order_continent_to_num(l_continent_str);
 
         const char *l_units_str = NULL;
         dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "-units", &l_units_str);
 
-        int8_t l_continent_num = dap_chain_net_srv_order_continent_to_num(l_continent_str);
-
         char *l_order_hash_hex_str;
         char *l_order_hash_base58_str;
         // datum hash may be in hex or base58 format
@@ -651,10 +651,12 @@ static bool s_fee_verificator_callback(dap_ledger_t *a_ledger, UNUSED_ARG dap_ch
             return false;
         if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash))
             return false;
-        const dap_chain_block_cache_t *l_block_cache = l_chain->callback_block_find_by_tx_hash(l_chain, &l_tx_in_cond->header.tx_prev_hash);
-        if (!l_block_cache)
+        size_t l_block_size = 0;
+        dap_chain_block_t *l_block = (dap_chain_block_t *)l_chain->callback_block_find_by_tx_hash(
+                                                    l_chain, &l_tx_in_cond->header.tx_prev_hash, &l_block_size);
+        if (!l_block)
             continue;
-        dap_sign_t *l_sign_block = dap_chain_block_sign_get(l_block_cache->block, l_block_cache->block_size, 0);
+        dap_sign_t *l_sign_block = dap_chain_block_sign_get(l_block, l_block_size, 0);
         if (!l_sign_block)
             return false;
 
@@ -808,6 +810,10 @@ int dap_chain_net_srv_parse_pricelist(dap_chain_net_srv_t *a_srv, const char *a_
     char **l_pricelist = dap_config_get_array_str(g_config, a_config_section, "pricelist", &l_pricelist_count);
     for (uint16_t i = 0; i < l_pricelist_count; i++) {
         dap_chain_net_srv_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_price_t);
+        if (!l_price) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_parse_pricelist");
+            return ret;
+        }
         short l_iter = 0;
         char *l_ctx;
         for (char *l_price_token = strtok_r(l_pricelist[i], ":", &l_ctx); l_price_token || l_iter == 6; l_price_token = strtok_r(NULL, ":", &l_ctx), ++l_iter) {
@@ -903,16 +909,30 @@ dap_chain_net_srv_t* dap_chain_net_srv_add(dap_chain_net_srv_uid_t a_uid,
     HASH_FIND(hh, s_srv_list, &l_uid, sizeof(l_uid), l_sdata);
     if(l_sdata == NULL) {
         l_srv = DAP_NEW_Z(dap_chain_net_srv_t);
+        if (!l_srv) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_add");
+            pthread_mutex_unlock(&s_srv_list_mutex);
+            return NULL;
+        }
         l_srv->uid.uint64 = a_uid.uint64;
         if (a_callbacks)
             l_srv->callbacks = *a_callbacks;
         pthread_mutex_init(&l_srv->banlist_mutex, NULL);
         l_sdata = DAP_NEW_Z(service_list_t);
+        if (!l_sdata) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_add");
+            DAP_DEL_Z(l_srv);
+            pthread_mutex_unlock(&s_srv_list_mutex);
+            return NULL;
+        }
         l_sdata->uid = l_uid;
         strncpy(l_sdata->name, a_config_section, sizeof(l_sdata->name) - 1);
         l_sdata->srv = l_srv;
         dap_chain_net_srv_price_apply_from_my_order(l_srv, a_config_section);
+//        dap_chain_net_srv_parse_pricelist(l_srv, a_config_section);
         HASH_ADD(hh, s_srv_list, uid, sizeof(l_srv->uid), l_sdata);
+        if (l_srv->pricelist)
+            dap_chain_ledger_tx_add_notify(l_srv->pricelist->net->pub.ledger, dap_stream_ch_chain_net_srv_tx_cond_added_cb, NULL);
     }else{
         log_it(L_ERROR, "Already present service with 0x%016"DAP_UINT64_FORMAT_X, a_uid.uint64);
     }
diff --git a/modules/net/srv/dap_chain_net_srv_client.c b/modules/net/srv/dap_chain_net_srv_client.c
index 90259de8c283a9acb95c40e29b25ef05e653c6ad..16f080dc106747ed390e4bfe98f73303e4f9510e 100644
--- a/modules/net/srv/dap_chain_net_srv_client.c
+++ b/modules/net/srv/dap_chain_net_srv_client.c
@@ -41,6 +41,10 @@ dap_chain_net_srv_client_t *dap_chain_net_srv_client_create_n_connect(dap_chain_
                                                                       void *a_callbacks_arg)
 {
     dap_chain_net_srv_client_t *l_ret = DAP_NEW_Z(dap_chain_net_srv_client_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_client_create_n_connect");
+        return NULL;
+    }
     if (a_callbacks)
         l_ret->callbacks = *a_callbacks;
     l_ret->callbacks_arg = a_callbacks_arg;
@@ -50,6 +54,11 @@ dap_chain_net_srv_client_t *dap_chain_net_srv_client_create_n_connect(dap_chain_
         .delete = s_srv_client_callback_deleted
     };
     dap_chain_node_info_t *l_info = DAP_NEW_Z(dap_chain_node_info_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_client_create_n_connect");
+        DAP_DEL_Z(l_ret);
+        return NULL;
+    }
     inet_pton(AF_INET, a_addr, &l_info->hdr.ext_addr_v4);
     l_info->hdr.ext_port = a_port;
     const char l_channels[] = {dap_stream_ch_chain_net_srv_get_id(), '\0'};
diff --git a/modules/net/srv/dap_chain_net_srv_geoip.c b/modules/net/srv/dap_chain_net_srv_geoip.c
index 84bc1c133e7be6705740c11b850df59fdd6bc92f..ad6fa6542588cd5c59a7e64fd0ba39c837535fdf 100644
--- a/modules/net/srv/dap_chain_net_srv_geoip.c
+++ b/modules/net/srv/dap_chain_net_srv_geoip.c
@@ -175,17 +175,21 @@ geoip_info_t *chain_net_geoip_get_ip_info_by_local_db(const char *a_ip_str, cons
     //char *l_file_db_name = dap_strdup_printf("%s/share/geoip/GeoLite2-City.mmdb", g_sys_dir_path);
     if(!dap_file_test(s_geoip_db_file_path)) {
         //DAP_DELETE(l_file_db_name);
-        return NULL ;
+        return NULL;
     }
     MMDB_s mmdb;
     int l_status = MMDB_open(s_geoip_db_file_path, MMDB_MODE_MMAP, &mmdb);
     if(MMDB_SUCCESS != l_status) {
         log_it(L_WARNING, "geoip file %s opened with errcode=%d", s_geoip_db_file_path, l_status);
-        return NULL ;
+        return NULL;
     }
     //DAP_DELETE(l_file_db_name);
 
 	geoip_info_t *l_ret = DAP_NEW_Z(geoip_info_t);
+	if (!l_ret) {
+		log_it(L_ERROR, "Memory allocation error in chain_net_geoip_get_ip_info_by_local_db");
+		return NULL;
+	}
 
 	int gai_error, mmdb_error;
 	MMDB_lookup_result_s result = MMDB_lookup_string(&mmdb, a_ip_str, &gai_error, &mmdb_error);
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index 00c9494de16aabfefbe9ce322f1352c7bf3fae44..eacda3cf4f9bff2b54853fee217ff30c6bd3f312 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -67,11 +67,11 @@ static dap_list_t *s_order_notify_callbacks = NULL;
 static void s_srv_order_callback_notify(dap_global_db_context_t *a_context, dap_store_obj_t *a_obj, void *a_arg);
 
 static dap_timerfd_t *s_timer_order_check_decree_sign = NULL;
-static void s_srv_order_check_decree_sign_timer(){
+static void s_srv_order_check_decree_sign_timer() {
     uint32_t l_unverified_orders_lifetime = dap_config_get_item_uint32_default(g_config, "srv", "unverified_orders_lifetime", 21600);
     dap_time_t l_time_cut_off = dap_time_now();
     l_time_cut_off -= l_unverified_orders_lifetime; // 6 Hours;
-    size_t l_net_count = 0;
+    uint16_t l_net_count = 0;
     dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count);
     for (uint16_t i = 0; i < l_net_count; i++) {
         if (dap_chain_net_get_role(l_net_list[i]).enums == NODE_ROLE_MASTER) {
@@ -217,6 +217,10 @@ bool dap_chain_net_srv_order_get_continent_region(dap_chain_net_srv_order_t *a_o
         size_t l_size = a_order_static->ext_size - sizeof(uint8_t) - 1;
         if(l_size > 0) {
             *a_region = DAP_NEW_SIZE(char, l_size);
+            if (!a_region) {
+                log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_order_get_continent_region");
+                return false;
+            }
             memcpy(*a_region, a_order_static->ext_n_sign + 1 + sizeof(uint8_t), l_size);
         }
         else
@@ -348,11 +352,19 @@ dap_chain_net_srv_order_t *dap_chain_net_srv_order_compose(dap_chain_net_t *a_ne
     dap_chain_net_srv_order_t *l_order;
     if (a_ext_size) {
         l_order = (dap_chain_net_srv_order_t *)DAP_NEW_Z_SIZE(void, sizeof(dap_chain_net_srv_order_t) + a_ext_size);
+        if (!l_order) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_order_compose");
+            return NULL;
+        }
         memcpy(l_order->ext_n_sign, a_ext, a_ext_size);
         l_order->ext_size = a_ext_size;
     }
     else {
         l_order = DAP_NEW_Z(dap_chain_net_srv_order_t);
+        if (!l_order) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_order_compose");
+            return NULL;
+        }
         dap_chain_net_srv_order_set_continent_region(&l_order, a_continent_num, a_region);
     }
 
@@ -407,6 +419,10 @@ char *dap_chain_net_srv_order_save(dap_chain_net_t *a_net, dap_chain_net_srv_ord
 
 dap_chain_net_srv_order_t *dap_chain_net_srv_order_read(byte_t *a_order, size_t a_order_size)
 {
+    if (NULL == a_order) {
+        log_it(L_ERROR, "Argumets are NULL for dap_chain_net_srv_order_read");
+        return NULL;
+    }
     dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_order;
     size_t l_order_size = dap_chain_net_srv_order_get_size((dap_chain_net_srv_order_t *)a_order);
     if (l_order->version > 3 || l_order->direction > SERV_DIR_SELL || l_order_size != a_order_size)
@@ -615,12 +631,12 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d
         }
         else
             dap_string_append_printf(a_str_out, "  ext:              0x0\n");
-        dap_string_append_printf(a_str_out, "  units:            %zu\n", a_order->units);
         dap_sign_t *l_sign = (dap_sign_t*)((byte_t*)a_order->ext_n_sign + a_order->ext_size);
         dap_hash_fast_t l_sign_pkey = {0};
         dap_sign_get_pkey_hash(l_sign, &l_sign_pkey);
         char *l_sign_pkey_hash_str = dap_hash_fast_to_str_new(&l_sign_pkey);
         dap_string_append_printf(a_str_out, "  pkey:             %s\n", l_sign_pkey_hash_str);
+        dap_string_append_printf(a_str_out, "  units:            %zu\n", a_order->units);
         DAP_DELETE(l_sign_pkey_hash_str);
         // order state
 /*        {
@@ -660,7 +676,6 @@ static void s_srv_order_callback_notify(dap_global_db_context_t *a_context, dap_
             }
         }
         bool l_allow_unsigned_orders = dap_config_get_item_bool_default(g_config, "srv", "allow_unsigned_orders", false);
-//        bool l_allow_unverified_orders = dap_config_get_item_bool_default(g_config, "srv", "allow_unverified_orders", false);
         if (a_obj->value && a_obj->type == DAP_DB$K_OPTYPE_ADD) {
             dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_obj->value;
             if (l_order->version != 3) {
@@ -688,6 +703,10 @@ static void s_srv_order_callback_notify(dap_global_db_context_t *a_context, dap_
 void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_store_obj_callback_notify_t a_callback, void *a_cb_arg)
 {
     struct dap_order_notify *l_notifier = DAP_NEW(struct dap_order_notify);
+    if (!l_notifier) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_order_add_notify_callback");
+        return;
+    }
     l_notifier->net = a_net;
     l_notifier->callback = a_callback;
     l_notifier->cb_arg = a_cb_arg;
diff --git a/modules/net/srv/dap_chain_net_srv_stream_session.c b/modules/net/srv/dap_chain_net_srv_stream_session.c
index 34128a0d38f0abfb4c01c3c734d90449b470ae0d..445a8eddb854fef906454c15ffeca7fe88738487 100644
--- a/modules/net/srv/dap_chain_net_srv_stream_session.c
+++ b/modules/net/srv/dap_chain_net_srv_stream_session.c
@@ -41,12 +41,32 @@ dap_chain_net_srv_stream_session_t * dap_chain_net_srv_stream_session_create( da
         return NULL;
     }
     dap_chain_net_srv_stream_session_t * l_session_srv= DAP_NEW_Z(dap_chain_net_srv_stream_session_t);
+    if (!l_session_srv) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stream_session_create");
+        return NULL;
+    }
     a_session->_inheritor = l_session_srv;
     l_session_srv->parent = a_session;
     log_it(L_NOTICE, "created service session");
     return  l_session_srv;
 }
 
+/**
+ * @brief dap_chain_net_srv_stream_session_create
+ * @param a_session
+ * @return
+ */
+void dap_chain_net_srv_stream_session_delete( dap_stream_session_t * a_session)
+{
+    if (!a_session){
+        log_it (L_ERROR, "Session is NULL!");
+        return;
+    }
+    dap_chain_net_srv_stream_session_t * l_session_srv = a_session->_inheritor;
+    dap_chain_net_srv_usage_delete(l_session_srv);
+}
+
+
 /**
  * @brief dap_chain_net_srv_usage_add
  * @param a_srv_session
@@ -59,6 +79,10 @@ dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream
 {
     if ( a_srv_session && a_net && a_srv ){
         dap_chain_net_srv_usage_t * l_ret = DAP_NEW_Z(dap_chain_net_srv_usage_t);
+        if (!l_ret) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_usage_add");
+            return NULL;
+        }
         randombytes(&l_ret->id, sizeof(l_ret->id));
         l_ret->net = a_net;
         l_ret->service = a_srv;
@@ -78,21 +102,23 @@ dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream
  * @param a_usage
  * @return
  */
-void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session,
-                                                                               dap_chain_net_srv_usage_t* a_usage)
+void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session)
 {
-    if ( a_usage->receipt )
-        DAP_DELETE( a_usage->receipt );
-    if ( a_usage->client ){
-        for (dap_chain_net_srv_client_remote_t * l_srv_client = a_usage->client, * tmp = NULL; l_srv_client; ){
+    if (!a_srv_session || !a_srv_session->usage_active)
+        return;
+
+    if ( a_srv_session->usage_active->receipt )
+        DAP_DEL_Z( a_srv_session->usage_active->receipt );
+    if ( a_srv_session->usage_active->receipt_next )
+        DAP_DEL_Z( a_srv_session->usage_active->receipt_next);
+    if ( a_srv_session->usage_active->client ){
+        for (dap_chain_net_srv_client_remote_t * l_srv_client = a_srv_session->usage_active->client, * tmp = NULL; l_srv_client; ){
             tmp = l_srv_client;
             l_srv_client = l_srv_client->next;
             DAP_DELETE( tmp);
         }
-
-
     }
-    DAP_DELETE( a_usage );
+    DAP_DEL_Z(a_srv_session->usage_active);
 }
 
 /**
diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h
index 05e1644b3e6198759dba4ad2887e5963e9b52e0c..6756d30a9e1b79867cefcb83298c953588c2a645 100755
--- a/modules/net/srv/include/dap_chain_net_srv.h
+++ b/modules/net/srv/include/dap_chain_net_srv.h
@@ -186,6 +186,7 @@ typedef struct dap_chain_net_srv_grace {
     dap_stream_worker_t *stream_worker;
     dap_stream_ch_uuid_t ch_uuid;
     dap_chain_net_srv_usage_t *usage;
+    dap_events_socket_uuid_t timer_es_uuid;
     dap_stream_ch_chain_net_srv_pkt_request_t *request;
     size_t request_size;
 } dap_chain_net_srv_grace_t;
@@ -303,7 +304,8 @@ dap_chain_datum_tx_receipt_t * dap_chain_net_srv_issue_receipt(dap_chain_net_srv
                                                                const void * a_ext, size_t a_ext_size);
 uint8_t dap_stream_ch_chain_net_srv_get_id();
 
-//int dap_chain_net_srv_parse_pricelist(dap_chain_net_srv_t *a_srv, const char *a_config_section);
+int dap_chain_net_srv_parse_pricelist(dap_chain_net_srv_t *a_srv, const char *a_config_section);
+
 int dap_chain_net_srv_price_apply_from_my_order(dap_chain_net_srv_t *a_srv, const char *a_config_section);
 
 DAP_STATIC_INLINE const char * dap_chain_net_srv_price_unit_uid_to_str( dap_chain_net_srv_price_unit_uid_t a_uid )
diff --git a/modules/net/srv/include/dap_chain_net_srv_stream_session.h b/modules/net/srv/include/dap_chain_net_srv_stream_session.h
index 6f7a7b0dda5c930ca9557af4378dab2a708c8756..af8bb938713a95f508ce0d14c06441e5276c0d37 100644
--- a/modules/net/srv/include/dap_chain_net_srv_stream_session.h
+++ b/modules/net/srv/include/dap_chain_net_srv_stream_session.h
@@ -55,6 +55,7 @@ typedef struct dap_chain_net_srv_usage{
     bool is_active;
     bool is_free;
     bool is_grace;
+    bool is_waiting_new_tx_cond;
 //    UT_hash_handle hh; //
 } dap_chain_net_srv_usage_t;
 
@@ -91,9 +92,9 @@ typedef struct dap_chain_net_srv_stream_session {
 #define DAP_CHAIN_NET_SRV_STREAM_SESSION(a) ((dap_chain_net_srv_stream_session_t *) (a)->_inheritor )
 
 dap_chain_net_srv_stream_session_t * dap_chain_net_srv_stream_session_create( dap_stream_session_t * a_session);
+void dap_chain_net_srv_stream_session_delete( dap_stream_session_t * a_session);
 dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_add (dap_chain_net_srv_stream_session_t * a_srv_session,
                                                                             dap_chain_net_t * a_net, dap_chain_net_srv_t * a_srv);
-void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session,
-                                                                               dap_chain_net_srv_usage_t* a_usage);
+void dap_chain_net_srv_usage_delete (dap_chain_net_srv_stream_session_t * a_srv_session);
 dap_chain_net_srv_usage_t* dap_chain_net_srv_usage_find_unsafe (dap_chain_net_srv_stream_session_t * a_srv_session,
                                                                              uint32_t a_usage_id);
diff --git a/modules/service/datum/dap_chain_net_srv_datum.c b/modules/service/datum/dap_chain_net_srv_datum.c
index 971586fe17c915642433bcc96a7e79e80ac88138..ed5776f87e777b5bd1b2663f672b0a0f4f892167 100644
--- a/modules/service/datum/dap_chain_net_srv_datum.c
+++ b/modules/service/datum/dap_chain_net_srv_datum.c
@@ -46,6 +46,10 @@ int dap_chain_net_srv_datum_init()
         "srv_datum -net <net_name> -chain <chain_name> datum load -datum <datum_hash>\n"
             "\tLoad datum custum from file to mempool.\n\n");
     s_srv_datum = DAP_NEW_Z(dap_chain_net_srv_t);
+    if (!s_srv_datum) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_datum_init");
+        return -1;
+    }
     s_srv_datum->uid.uint64 = DAP_CHAIN_NET_SRV_DATUM_ID;
     dap_chain_net_srv_price_apply_from_my_order(s_srv_datum, "srv_datum");
     dap_chain_net_srv_price_t *l_price;
diff --git a/modules/service/stake/dap_chain_net_srv_stake_lock.c b/modules/service/stake/dap_chain_net_srv_stake_lock.c
index 077330a82c0dcaa13db289006a6a40d2666898a3..a31b7db25426ea1aefccd296785e1f9dc263bcba 100644
--- a/modules/service/stake/dap_chain_net_srv_stake_lock.c
+++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c
@@ -931,6 +931,15 @@ static bool s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_
             if (dap_hash_fast_is_blank(&l_burning_tx_hash))
                 return false;
             l_burning_tx = dap_chain_ledger_tx_find_by_hash(a_ledger, &l_burning_tx_hash);
+            if (!l_burning_tx) {
+                char l_burning_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
+                dap_hash_fast_to_str(&l_burning_tx_hash, l_burning_tx_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
+                char *l_take_tx_hash_str;
+                dap_get_data_hash_str_static(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in), l_take_tx_hash_str);
+                log_it(L_ERROR, "[Legacy] Can't find burning tx with hash %s, obtained from the receipt of take tx %s",
+                       l_burning_tx_hash_str, l_take_tx_hash_str);
+                return false;
+            }
         } else
             l_burning_tx = a_tx_in;
 
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 5a8d9b359436f45579ad2c2e775c1325282b0c71..b09e976a838d742deafaf717216e63736a551fb1 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
@@ -93,6 +93,10 @@ int dap_chain_net_srv_stake_pos_delegate_init()
     );
 
     s_srv_stake = DAP_NEW_Z(dap_chain_net_srv_stake_t);
+    if (!s_srv_stake) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_pos_delegate_init");
+        return -1;
+    }
     s_srv_stake->delegate_allowed_min = dap_chain_coins_to_balance("1.0");
 
     return 0;
@@ -251,6 +255,19 @@ dap_list_t *dap_chain_net_srv_stake_get_validators(dap_chain_net_id_t a_net_id,
     return l_ret;
 }
 
+dap_chain_node_addr_t *dap_chain_net_srv_stake_key_get_node_addr(dap_chain_addr_t *a_signing_addr)
+{
+    assert(s_srv_stake);
+    if (!a_signing_addr)
+        NULL;
+
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    HASH_FIND(hh, s_srv_stake->itemlist, a_signing_addr, sizeof(dap_chain_addr_t), l_stake);
+    if (l_stake) // public key delegated for this network
+        return &l_stake->node_addr;
+    return NULL;
+}
+
 int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_addr, bool a_on_off)
 {
     assert(s_srv_stake);
@@ -327,6 +344,10 @@ int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net)
         dap_chain_net_srv_stake_cache_data_t *l_cache_data =
                 (dap_chain_net_srv_stake_cache_data_t *)l_store_obj[i].value;
         dap_chain_net_srv_stake_cache_item_t *l_cache = DAP_NEW_Z(dap_chain_net_srv_stake_cache_item_t);
+        if (!l_cache) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_load_cache");
+            return -1;
+        }
         l_cache->signing_addr   = l_cache_data->signing_addr;
         l_cache->tx_hash        = l_cache_data->tx_hash;
         HASH_ADD(hh, s_srv_stake->cache, tx_hash, sizeof(dap_hash_fast_t), l_cache);
@@ -518,6 +539,10 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_hash_fast_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_decree_approve");
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_TX_HASH;
     l_tsd->size = sizeof(dap_hash_fast_t);
     *(dap_hash_fast_t*)(l_tsd->data) = *a_stake_tx_hash;
@@ -525,6 +550,11 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(uint256_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_decree_approve");
+        dap_list_free_full(l_tsd_list, NULL);
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE;
     l_tsd->size = sizeof(uint256_t);
     *(uint256_t*)(l_tsd->data) = l_tx_out_cond->header.value;
@@ -532,6 +562,11 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_chain_addr_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_decree_approve");
+        dap_list_free_full(l_tsd_list, NULL);
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR;
     l_tsd->size = sizeof(dap_chain_addr_t);
     *(dap_chain_addr_t*)(l_tsd->data) = l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr;
@@ -539,12 +574,22 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_chain_node_addr_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_decree_approve");
+        dap_list_free_full(l_tsd_list, NULL);
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNER_NODE_ADDR;
     l_tsd->size = sizeof(dap_chain_node_addr_t);
     *(dap_chain_node_addr_t*)(l_tsd->data) = l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
 
     l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size);
+    if (!l_decree) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_stake_decree_approve");
+        dap_list_free_full(l_tsd_list, NULL);
+        return NULL;
+    }
     l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
@@ -740,12 +785,21 @@ static dap_chain_datum_decree_t *s_stake_decree_invalidate(dap_chain_net_t *a_ne
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_chain_addr_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in s_stake_decree_invalidate");
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR;
     l_tsd->size = sizeof(dap_chain_addr_t);
     *(dap_chain_addr_t*)(l_tsd->data) = l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
 
     l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size);
+    if (!l_decree) {
+        log_it(L_ERROR, "Memory allocation error in s_stake_decree_set_min_stake");
+        dap_list_free_full(l_tsd_list, NULL);
+        return NULL;
+    }
     l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
@@ -755,6 +809,7 @@ static dap_chain_datum_decree_t *s_stake_decree_invalidate(dap_chain_net_t *a_ne
         l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
     if (!l_chain) {
         log_it(L_ERROR, "No chain supported anchor datum type");
+        dap_list_free_full(l_tsd_list, NULL);
         return NULL;
     }
     l_decree->header.common_decree_params.chain_id = l_chain->id;
@@ -805,12 +860,21 @@ static dap_chain_datum_decree_t *s_stake_decree_set_min_stake(dap_chain_net_t *a
 
     l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(uint256_t);
     l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size);
+    if (!l_tsd) {
+        log_it(L_ERROR, "Memory allocation error in s_stake_decree_set_min_stake");
+        return NULL;
+    }
     l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE;
     l_tsd->size = sizeof(uint256_t);
     *(uint256_t*)(l_tsd->data) = a_value;
     l_tsd_list = dap_list_append(l_tsd_list, l_tsd);
 
     l_decree = DAP_NEW_Z_SIZE(dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + l_total_tsd_size);
+    if (!l_decree) {
+        log_it(L_ERROR, "Memory allocation error in s_stake_decree_set_min_stake");
+        dap_list_free_full(l_tsd_list, NULL);
+        return NULL;
+    }
     l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION;
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
@@ -820,6 +884,7 @@ static dap_chain_datum_decree_t *s_stake_decree_set_min_stake(dap_chain_net_t *a
         l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
     if (!l_chain) {
         log_it(L_ERROR, "No chain supported anchor datum type");
+        dap_list_free_full(l_tsd_list, NULL);
         return NULL;
     }
     l_decree->header.common_decree_params.chain_id = l_chain->id;
@@ -1141,8 +1206,11 @@ static void s_srv_stake_print(dap_chain_net_srv_stake_item_t *a_stake, dap_strin
     dap_string_append_printf(a_string, "Pkey hash: %s\n"
                                         "\tStake value: %s\n"
                                         "\tTx hash: %s\n"
-                                        "\tNode addr: "NODE_ADDR_FP_STR"\n\n",
-                             l_pkey_hash_str, l_balance, l_tx_hash_str, NODE_ADDR_FP_ARGS_S(a_stake->node_addr));
+                                        "\tNode addr: "NODE_ADDR_FP_STR"\n"
+                                        "\tActive: %s\n"
+                                        "\n",
+                             l_pkey_hash_str, l_balance, l_tx_hash_str, NODE_ADDR_FP_ARGS_S(a_stake->node_addr),
+                             a_stake->is_active ? "true" : "false");
     DAP_DELETE(l_balance);
 }
 
@@ -1562,7 +1630,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply)
                     dap_cli_server_cmd_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
                     return -4;
                 }
-                dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp;
+                dap_chain_net_srv_stake_item_t *l_stake = NULL;
                 dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-cert", &l_cert_str);
                 if (l_cert_str) {
                     dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str);
@@ -1582,18 +1650,27 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply)
                     }
                 }
                 dap_string_t *l_reply_str = dap_string_new("");
+                size_t l_inactive_count = 0, l_total_count = 0;
                 if (l_stake)
                     s_srv_stake_print(l_stake, l_reply_str);
                 else
-                    HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) {
-                        if (l_stake->net->pub.id.uint64 != l_net->pub.id.uint64) {
+                    for (l_stake = s_srv_stake->itemlist; l_stake; l_stake = l_stake->hh.next) {
+                        if (l_stake->net->pub.id.uint64 != l_net->pub.id.uint64)
                             continue;
-                        }
+                        l_total_count++;
+                        if (!l_stake->is_active)
+                            l_inactive_count++;
                         s_srv_stake_print(l_stake, l_reply_str);
                     }
                 if (!HASH_CNT(hh, s_srv_stake->itemlist)) {
                     dap_string_append(l_reply_str, "No keys found\n");
+                } else {
+                    dap_string_append_printf(l_reply_str, "Total keys count: %zu\n", l_total_count);
+                    dap_string_append_printf(l_reply_str, "Inactive keys count: %zu\n", l_inactive_count);
                 }
+
+
+
                 char *l_delegate_min_str = dap_chain_balance_to_coins(s_srv_stake->delegate_allowed_min);
                 char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
                 dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_net->pub.native_ticker);
@@ -1615,6 +1692,11 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply)
                     return -4;
                 }
                 struct get_tx_cond_pos_del_from_tx * l_args = DAP_NEW_Z(struct get_tx_cond_pos_del_from_tx);
+                if(!l_args) {
+                    log_it(L_ERROR, "Memory allocation error in s_cli_srv_stake");
+                    dap_cli_server_cmd_set_reply_text(a_str_reply, "Out of memory");
+                    return -1;
+                }
                 dap_string_t * l_str_tmp = dap_string_new(NULL);
                 dap_hash_fast_t l_datum_hash;
                 dap_chain_datum_tx_t *l_datum_tx = NULL;
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 820ad2a8caba1908bffeb51bb78cbbb7ab95bb77..418e7aaa7c58f614387e44c9d3c52b641a2874df 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
@@ -73,6 +73,7 @@ uint256_t dap_chain_net_srv_stake_get_allowed_min_value();
 int dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_addr);
 int dap_chain_net_srv_stake_verify_key_and_node(dap_chain_addr_t* a_signing_addr, dap_chain_node_addr_t* a_node_addr);
 dap_list_t *dap_chain_net_srv_stake_get_validators(dap_chain_net_id_t a_net_id, bool a_is_active);
+dap_chain_node_addr_t *dap_chain_net_srv_stake_key_get_node_addr(dap_chain_addr_t *a_signing_addr);
 
 bool dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net,
                                                 uint256_t *a_max_fee, uint256_t *a_average_fee, uint256_t *a_min_fee);
diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c
index 05683727900ab216fb5522df9842d7ff5f38d032..a50285aa9e9c427dc4d660605d86ec01cb0e225c 100644
--- a/modules/service/vpn/dap_chain_net_srv_vpn.c
+++ b/modules/service/vpn/dap_chain_net_srv_vpn.c
@@ -319,6 +319,10 @@ static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * l_ch_vpn_in
     } else {
         /* Shift it to other worker context */
         tun_socket_msg_t* l_msg = DAP_NEW_Z(tun_socket_msg_t);
+        if (!l_msg) {
+            log_it(L_ERROR, "Memory allocation error in s_tun_client_send_data");
+            return false;
+        }
         l_msg->type             = TUN_SOCKET_MSG_CH_VPN_SEND;
         l_msg->ch_vpn           = l_ch_vpn_info->ch_vpn;
         l_msg->esocket          = l_ch_vpn_info->esocket;
@@ -394,6 +398,11 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
                 log_it(L_WARNING, "Already assigned address %s on tun sock #%u", l_addrbuf, l_tun_sock->worker_id);
             }else{
                 l_new_info                      = DAP_NEW_Z(dap_chain_net_srv_ch_vpn_info_t);
+                if (!l_new_info) {
+                    log_it (L_ERROR, "Memory allocation error in s_tun_recv_msg_callback");
+                    DAP_DELETE(l_msg);
+                    return;
+                }
                 l_new_info->ch_vpn              = l_msg->ch_vpn;
                 l_new_info->addr_ipv4           = l_msg->ip_assigment.addr;
                 l_new_info->queue_msg           = s_tun_sockets_queue_msg[l_msg->ip_assigment.worker_id];
@@ -467,6 +476,10 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void
 static void s_tun_send_msg_ip_assigned(uint32_t a_worker_own_id, uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr )
 {
     struct tun_socket_msg * l_msg = DAP_NEW_Z(struct tun_socket_msg);
+    if (!l_msg) {
+        log_it (L_ERROR, "Memory allocation error in s_tun_send_msg_ip_assigned");
+        return;
+    }
     l_msg->type = TUN_SOCKET_MSG_IP_ASSIGNED;
     l_msg->ch_vpn = a_ch_vpn;
     l_msg->esocket = a_ch_vpn->ch->stream->esocket;
@@ -504,6 +517,10 @@ static void s_tun_send_msg_ip_assigned_all(uint32_t a_worker_own_id, dap_chain_n
 static void s_tun_send_msg_ip_unassigned(uint32_t a_worker_own_id, uint32_t a_worker_id, dap_chain_net_srv_ch_vpn_t * a_ch_vpn, struct in_addr a_addr)
 {
     struct tun_socket_msg * l_msg = DAP_NEW_Z(struct tun_socket_msg);
+    if (!l_msg) {
+        log_it (L_ERROR, "Memory allocation error in s_tun_send_msg_ip_unassigned");
+        return;
+    }
     l_msg->type = TUN_SOCKET_MSG_IP_UNASSIGNED;
     l_msg->ch_vpn = a_ch_vpn;
     l_msg->ip_unassigment.addr = a_addr;
@@ -549,6 +566,10 @@ static void s_tun_send_msg_esocket_reassigned_inter(uint32_t a_worker_own_id, da
                                                    dap_events_socket_uuid_t a_esocket_uuid, struct in_addr a_addr)
 {
     struct tun_socket_msg * l_msg = DAP_NEW_Z(struct tun_socket_msg);
+    if (!l_msg) {
+        log_it (L_ERROR, "Memory allocation error in s_tun_send_msg_esocket_reassigned_inter");
+        return;
+    }
     l_msg->type = TUN_SOCKET_MSG_ESOCKET_REASSIGNED ;
     l_msg->ch_vpn = a_ch_vpn;
     l_msg->esocket_reassigment.addr = a_addr;
@@ -801,6 +822,10 @@ lb_err:
 static int s_vpn_tun_init()
 {
     s_raw_server=DAP_NEW_Z(vpn_local_network_t);
+    if (!s_raw_server) {
+        log_it(L_ERROR, "Memory allocation error in s_vpn_tun_init");
+        return -1;
+    }
     pthread_rwlock_init(&s_raw_server->rwlock, NULL);
     pthread_mutex_init(&s_raw_server->pkt_out_mutex,NULL);
     pthread_mutex_init(&s_tun_sockets_mutex_started, NULL);
@@ -826,6 +851,10 @@ static int s_vpn_service_create(dap_config_t * g_config)
     dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "srv_vpn", &l_srv_callbacks);
 
     dap_chain_net_srv_vpn_t* l_srv_vpn  = DAP_NEW_Z( dap_chain_net_srv_vpn_t);
+    if(!l_srv_vpn) {
+        log_it(L_ERROR, "Memory allocation error in s_vpn_service_create");
+        return -1;
+    }
     l_srv->_internal = l_srv_vpn;
     l_srv_vpn->parent = l_srv;
 
@@ -915,8 +944,17 @@ static int s_callback_response_success(dap_chain_net_srv_t * a_srv, uint32_t a_u
     usage_client_t * l_usage_client = NULL;
 
     l_usage_client = DAP_NEW_Z(usage_client_t);
+    if (!l_usage_client) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_response_success");
+        return -1;
+    }
     l_usage_client->usage_id = a_usage_id;
     l_usage_client->receipt = DAP_NEW_SIZE(dap_chain_datum_tx_receipt_t,l_receipt_size);
+    if (!l_usage_client->receipt) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_response_success");
+        DAP_DEL_Z(l_usage_client);
+        return -1;
+    }
 
     memcpy(l_usage_client->receipt, l_receipt, l_receipt_size);
 
@@ -1076,7 +1114,7 @@ void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg)
 
     dap_chain_net_srv_stream_session_t * l_srv_session = (dap_chain_net_srv_stream_session_t *) a_ch->stream->session->_inheritor;
 
-    l_srv_vpn->usage_id = l_srv_session->usage_active?  l_srv_session->usage_active->id : 0;
+    l_srv_vpn->usage_id = l_srv_session->usage_active ?  l_srv_session->usage_active->id : 0;
 
     if( l_srv_vpn->usage_id) {
         // So complicated to update usage client to be sure that nothing breaks it
@@ -1088,7 +1126,6 @@ void s_ch_vpn_new(dap_stream_ch_t* a_ch, void* a_arg)
         }
         pthread_rwlock_unlock(&s_clients_rwlock);
     }
-
 }
 
 
@@ -1131,6 +1168,11 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg)
     if ( l_is_unleased ){ // If unleased
         log_it(L_DEBUG, "Unlease address %s and store in treshold", inet_ntoa(l_ch_vpn->addr_ipv4));
         dap_chain_net_srv_vpn_item_ipv4_t * l_item_unleased = DAP_NEW_Z(dap_chain_net_srv_vpn_item_ipv4_t);
+        if (!l_is_unleased) {
+            log_it(L_ERROR, "Memory allocation error in s_ch_vpn_delete");
+            pthread_rwlock_unlock(&s_clients_rwlock);
+            return;
+        }
         l_item_unleased->addr.s_addr = l_ch_vpn->addr_ipv4.s_addr;
         l_item_unleased->next = l_srv_vpn->ipv4_unleased;
         l_srv_vpn->ipv4_unleased = l_item_unleased;
@@ -1146,6 +1188,7 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg)
     l_ch_vpn->ch = NULL;
     l_ch_vpn->net_srv = NULL;
     l_ch_vpn->is_allowed =false;
+    DAP_DEL_Z(a_ch->internal);
 }
 
 /**
@@ -1162,21 +1205,20 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
     bool l_issue_new_receipt = false;
     // Check if there are time limits
 
-    if (a_usage->is_free)
+    if (a_usage->is_free || !a_usage->receipt || !a_usage->is_active)
         return;
 
     if (a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_DAY ||
         a_usage->receipt->receipt_info.units_type.enm == SERV_UNIT_SEC){
         time_t l_current_limit_ts = 0;
-        if ( a_usage->receipt){
-            switch( a_usage->receipt->receipt_info.units_type.enm){
+
+        switch( a_usage->receipt->receipt_info.units_type.enm){
             case SERV_UNIT_DAY:{
                 l_current_limit_ts = (time_t)a_usage->receipt->receipt_info.units*24*3600;
             } break;
             case SERV_UNIT_SEC:{
                 l_current_limit_ts = (time_t)a_usage->receipt->receipt_info.units;
             }
-            }
         }
 
         a_srv_session->limits_ts -= time(NULL) - a_srv_session->last_update_ts;
@@ -1189,7 +1231,7 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
 
         if( a_srv_session->limits_ts <= 0 && !a_usage->is_grace){
             log_it(L_INFO, "Limits by timestamp are over. Switch to the next receipt");
-            DAP_DELETE(a_usage->receipt);
+            DAP_DEL_Z(a_usage->receipt);
             a_usage->receipt = a_usage->receipt_next;
             a_usage->receipt_next = NULL;
             if ( a_usage->receipt){ // If there is next receipt add the time and request the next receipt
@@ -1246,7 +1288,7 @@ static void s_update_limits(dap_stream_ch_t * a_ch ,
 
         if (a_srv_session->limits_bytes <= 0  && !a_usage->is_grace){
             log_it(L_INFO, "Limits by traffic is over. Switch to the next receipt");
-            DAP_DELETE(a_usage->receipt);
+            DAP_DEL_Z(a_usage->receipt);
             a_usage->receipt = a_usage->receipt_next;
             a_usage->receipt_next = NULL;
             if ( a_usage->receipt){ // If there is next receipt add the time and request the next receipt
@@ -1299,6 +1341,10 @@ static void send_pong_pkt(dap_stream_ch_t* a_ch)
 {
 //    log_it(L_DEBUG,"---------------------------------- PONG!");
     ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header));
+    if (!pkt_out) {
+        log_it(L_ERROR, "Memory allocation error in send_pong_pkt");
+        return;
+    }
     pkt_out->header.op_code = VPN_PACKET_OP_CODE_PONG;
 
     dap_stream_ch_pkt_write_unsafe(a_ch, 'd', pkt_out,
@@ -1323,6 +1369,10 @@ static void s_ch_packet_in_vpn_address_request(dap_stream_ch_t* a_ch, dap_chain_
     if ( l_ch_vpn->addr_ipv4.s_addr ) {
         log_it(L_WARNING, "IP address is already leased");
         ch_vpn_pkt_t* pkt_out           = DAP_NEW_STACK_SIZE(ch_vpn_pkt_t, sizeof(pkt_out->header));
+        if (!pkt_out) {
+            log_it(L_ERROR, "Memory allocation error in send_pong_pkt");
+            return;
+        }
         pkt_out->header.op_code         = VPN_PACKET_OP_CODE_PROBLEM;
         pkt_out->header.sock_id         = s_raw_server->tun_fd;
         pkt_out->header.usage_id        = a_usage->id;
diff --git a/modules/service/vpn/dap_chain_net_vpn_client.c b/modules/service/vpn/dap_chain_net_vpn_client.c
index 9366297ade46dc374ce44f514ba391a4495fe0e1..b7b3337c677db8a39b1220354160d3abf74201c3 100644
--- a/modules/service/vpn/dap_chain_net_vpn_client.c
+++ b/modules/service/vpn/dap_chain_net_vpn_client.c
@@ -181,6 +181,10 @@ static int s_callback_client_success(dap_chain_net_srv_t * a_srv, uint32_t a_usa
     if(l_ch) { // Is present in hash table such destination address
         size_t l_ipv4_str_len = 0; //dap_strlen(a_ipv4_str);
         ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header) + l_ipv4_str_len);
+        if (!pkt_out) {
+            log_it(L_ERROR, "Memory allocation error in s_callback_client_success");
+            return -1;
+        }
 
         pkt_out->header.op_code = VPN_PACKET_OP_CODE_VPN_ADDR_REQUEST;
         //pkt_out->header.sock_id = l_stream->stream->events_socket->socket;
diff --git a/modules/service/vpn/dap_chain_net_vpn_client_tun.c b/modules/service/vpn/dap_chain_net_vpn_client_tun.c
index 801422a282b49dca80c6d51f57f8927bb0e0714b..6f77ec4eed63eb8a3b5e39f7db0505461520c873 100644
--- a/modules/service/vpn/dap_chain_net_vpn_client_tun.c
+++ b/modules/service/vpn/dap_chain_net_vpn_client_tun.c
@@ -638,7 +638,7 @@ static void ch_sf_pkt_send(dap_stream_ch_t * a_ch, void * a_data, size_t a_data_
     //       ,inet_ntoa(in_daddr), read_ret);
     if(!a_ch) {
         log_it(L_ERROR, "Try to send to NULL channel");
-//        return;
+       return;
     }
     l_pkt_out = DAP_NEW_SIZE(ch_vpn_pkt_t, l_pkt_out_size);
     memset(&l_pkt_out->header,0,sizeof(l_pkt_out->header));
@@ -685,6 +685,14 @@ void ch_sf_tun_client_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data,
         log_it(L_ERROR, "write() returned error %d : '%s'", ret, strerror(errno));
         //log_it(ERROR,"raw socket ring buffer overflowed");
         ch_vpn_pkt_t *pkt_out = (ch_vpn_pkt_t*) calloc(1, sizeof(pkt_out->header));
+        if (!pkt_out) {
+            log_it(L_ERROR, "Memory allocation error in ch_sf_tun_client_send");
+            if(in_daddr_str)
+                free(in_daddr_str);
+            if(in_saddr_str)
+                free(in_saddr_str);
+            return;
+        }
         pkt_out->header.op_code = VPN_PACKET_OP_CODE_PROBLEM;
         pkt_out->header.op_problem.code = VPN_PROBLEM_CODE_PACKET_LOST;
         pkt_out->header.sock_id = s_fd_tun;
@@ -697,9 +705,9 @@ void ch_sf_tun_client_send(dap_chain_net_srv_ch_vpn_t * ch_sf, void * pkt_data,
     }
 
     if(in_daddr_str)
-    free(in_daddr_str);
+        free(in_daddr_str);
     if(in_saddr_str)
-    free(in_saddr_str);
+        free(in_saddr_str);
 }
 
 /**
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 47b9fcaf51a361f43d5c50f14e4edd85d5f13120..c7173809ebf11fb40fea3d62509f168b0492ed92 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -130,6 +130,10 @@ int dap_chain_net_srv_xchange_init()
 
     dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, "srv_xchange", &l_srv_callbacks);
     s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t);
+    if (!s_srv_xchange) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_net_srv_xchange_init");
+        return -1;
+    }
     l_srv->_internal = s_srv_xchange;
     s_srv_xchange->parent = l_srv;
     s_srv_xchange->enabled = false;
@@ -329,6 +333,10 @@ static dap_chain_datum_tx_receipt_t *s_xchange_receipt_create(dap_chain_net_srv_
 {
     uint32_t l_ext_size = sizeof(uint256_t) + DAP_CHAIN_TICKER_SIZE_MAX;
     uint8_t *l_ext = DAP_NEW_STACK_SIZE(uint8_t, l_ext_size);
+    if (!l_ext) {
+        log_it(L_ERROR, "Memory allocation error in s_xchange_receipt_create");
+        return NULL;
+    }
     memcpy(l_ext, &a_datoshi_buy, sizeof(uint256_t));
     strcpy((char *)&l_ext[sizeof(uint256_t)], a_price->token_buy);
     dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED};
@@ -915,6 +923,10 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
 dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_net_srv_order_t *a_order,  bool a_ret_is_invalid)
 {
     dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t);
+    if (!l_price) {
+        log_it(L_ERROR, "Memory allocation error in s_xchange_price_from_order");
+        return NULL;
+    }
     dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)a_order->ext_n_sign;
     strcpy(l_price->token_buy, l_ext->token_buy);
     l_price->datoshi_buy = l_ext->datoshi_buy;
@@ -1071,6 +1083,12 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c
             }
             // Create the price
             dap_chain_net_srv_xchange_price_t *l_price = DAP_NEW_Z(dap_chain_net_srv_xchange_price_t);
+            if (!l_price) {
+                log_it(L_ERROR, "Memory allocation error in s_cli_srv_xchange_order");
+                dap_cli_server_cmd_set_reply_text(a_str_reply, "Out of memory");
+                dap_chain_wallet_close(l_wallet);
+                return -1;
+            }
             l_price->wallet_str = dap_strdup(l_wallet_str);
             dap_stpcpy(l_price->token_sell, l_token_sell_str);
             l_price->net = l_net;
diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c
index 15083cccb2d62f0e7feb2bc1294fa10f95899ebf..8c7379149acbb66d04189d3252e96bfe3115b44c 100644
--- a/modules/type/blocks/dap_chain_block.c
+++ b/modules/type/blocks/dap_chain_block.c
@@ -460,6 +460,10 @@ dap_chain_block_meta_t** dap_chain_block_get_meta(dap_chain_block_t * a_block, s
     size_t l_offset = 0;
     dap_chain_block_meta_t * l_meta=NULL;
     dap_chain_block_meta_t ** l_ret = DAP_NEW_Z_SIZE(dap_chain_block_meta_t *,sizeof (dap_chain_block_meta_t *)* a_block->hdr.meta_count );
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_block_get_meta");
+        return NULL;
+    }
     for( size_t i = 0; i< a_block->hdr.meta_count &&
                        l_offset < (a_block_size-sizeof (a_block->hdr)) &&
                        sizeof (l_meta->hdr) <=  (a_block_size-sizeof (a_block->hdr)) - l_offset ; i++){
diff --git a/modules/type/blocks/dap_chain_block_cache.c b/modules/type/blocks/dap_chain_block_cache.c
index b374fc923cd6158b03e6c671f56cd43854d146a6..1182d280d8ede50973d10f586062b3db49255736 100644
--- a/modules/type/blocks/dap_chain_block_cache.c
+++ b/modules/type/blocks/dap_chain_block_cache.c
@@ -61,6 +61,10 @@ dap_chain_block_cache_t *dap_chain_block_cache_new(dap_chain_cs_blocks_t *a_bloc
         return NULL;
 
     dap_chain_block_cache_t * l_block_cache = DAP_NEW_Z(dap_chain_block_cache_t);
+    if (!l_block_cache) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_block_cache_new");
+        return NULL;
+    }
     l_block_cache->block = a_block;
     l_block_cache->block_size= a_block_size;
     l_block_cache->_inheritor = a_blocks;
@@ -83,6 +87,10 @@ dap_chain_block_cache_t *dap_chain_block_cache_new(dap_chain_cs_blocks_t *a_bloc
 dap_chain_block_cache_t * dap_chain_block_cache_dup(dap_chain_block_cache_t * a_block)
 {
     dap_chain_block_cache_t * l_ret = DAP_NEW_Z(dap_chain_block_cache_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_block_cache_dup");
+        return NULL;
+    }
     memcpy(l_ret,a_block, sizeof (*a_block));
     memset(&l_ret->hh,0, sizeof (l_ret->hh)); // Drop hash handle to prevent its usage
     return l_ret;
@@ -172,6 +180,12 @@ dap_list_t * dap_chain_block_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledg
         dap_hash_fast_t *l_tx_hash = a_block_cache->datum_hash + i;
         if (!dap_chain_ledger_tx_hash_is_used_out_item (a_ledger, l_tx_hash, l_out_idx_tmp)) {
             dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
+            if (!l_item) {
+                log_it(L_ERROR, "Memory allocation error in dap_chain_block_get_list_tx_cond_outs_with_val");
+                if (l_list_used_out)
+                    dap_list_free_full(l_list_used_out, NULL);
+                return NULL;
+            }
             l_item->tx_hash_fast = *l_tx_hash;
             l_item->num_idx_out = l_out_idx_tmp;
             l_item->value = l_tx_out_cond->header.value;
diff --git a/modules/type/blocks/dap_chain_block_chunk.c b/modules/type/blocks/dap_chain_block_chunk.c
index 4aeef8db3858af8afa04f3741d109510ffa79892..c8b15c24ba44cfce927bd031b2acb4f8760c5926 100644
--- a/modules/type/blocks/dap_chain_block_chunk.c
+++ b/modules/type/blocks/dap_chain_block_chunk.c
@@ -37,6 +37,10 @@ dap_chain_block_chunks_t * dap_chain_block_chunks_create(dap_chain_cs_blocks_t *
     assert(a_blocks);
     assert(a_blocks->chain);
     dap_chain_block_chunks_t * l_ret = DAP_NEW_Z(dap_chain_block_chunks_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_block_chunks_create");
+        return NULL;
+    }
     l_ret->blocks = a_blocks;
     l_ret->gdb_group = dap_strdup_printf("local.%s.%s.block.chunks",a_blocks->chain->net_name, a_blocks->chain->name );
 
@@ -106,6 +110,10 @@ void dap_chain_block_chunks_add(dap_chain_block_chunks_t * a_chunks,dap_chain_bl
         if(dap_hash_fast_compare(&l_chunk->block_cache_top->block_hash, &a_block_cache->prev_hash ) ){
             // Init cache-hash object
             l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t);
+            if (!l_chunk_cache_hash) {
+                log_it(L_ERROR, "Memory allocation error in dap_chain_block_chunks_add");
+                return;
+            }
             l_chunk_cache_hash->block_cache=a_block_cache;
             l_chunk_cache_hash->ts_created = time(NULL);
             l_chunk_cache_hash->block_hash = a_block_cache->block_hash;
@@ -128,6 +136,10 @@ void dap_chain_block_chunks_add(dap_chain_block_chunks_t * a_chunks,dap_chain_bl
 
         // Init cache-hash object
         l_chunk_cache_hash = DAP_NEW_Z(dap_chain_block_cache_hash_t);
+        if (!l_chunk_cache_hash) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_block_chunks_add");
+            return;
+        }
         l_chunk_cache_hash->block_cache=a_block_cache;
         l_chunk_cache_hash->ts_created = time(NULL);
         l_chunk_cache_hash->block_hash = a_block_cache->block_hash;
@@ -156,6 +168,10 @@ void dap_chain_block_chunks_add(dap_chain_block_chunks_t * a_chunks,dap_chain_bl
 dap_chain_block_chunk_t * dap_chain_block_chunk_create(dap_chain_block_chunks_t * a_chunks)
 {
     dap_chain_block_chunk_t * l_chunk = DAP_NEW_Z(dap_chain_block_chunk_t);
+    if (!l_chunk) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_block_chunk_create ");
+        return NULL;
+    }
     // Add in tail
     l_chunk->prev = a_chunks->chunks_first;
     if (a_chunks->chunks_first){
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index 04dcbcd786eadb01f9e6bec9af14ca7d6e4d7945..36a723f9e35034c6f741b7e2624591f95c417e80 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -47,6 +47,11 @@ typedef struct dap_chain_block_datum_index {
     UT_hash_handle hh;
 } dap_chain_block_datum_index_t;
 
+struct cs_blocks_hal_item {
+    dap_chain_hash_fast_t hash;
+    UT_hash_handle hh;
+};
+
 typedef struct dap_chain_cs_blocks_pvt
 {
     pthread_rwlock_t rwlock;
@@ -78,6 +83,7 @@ typedef struct dap_chain_cs_blocks_pvt
     pthread_rwlock_t datums_lock;
     uint64_t fill_timeout;
 
+    struct cs_blocks_hal_item *hal;
 } dap_chain_cs_blocks_pvt_t;
 
 #define PVT(a) ((dap_chain_cs_blocks_pvt_t *)(a)->_pvt )
@@ -107,7 +113,7 @@ static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_ite
 static dap_chain_datum_t *s_callback_datum_find_by_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_datum_hash,
                                                         dap_chain_hash_fast_t *a_block_hash, int *a_ret_code);
 
-static dap_chain_atom_ptr_t s_callback_block_find_by_tx_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_tx_hash);
+static dap_chain_atom_ptr_t s_callback_block_find_by_tx_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_tx_hash, size_t *a_block_size);
 
 static dap_chain_datum_t** s_callback_atom_get_datums(dap_chain_atom_ptr_t a_atom, size_t a_atom_size, size_t * a_datums_count);
 static dap_time_t s_chain_callback_atom_get_timestamp(dap_chain_atom_ptr_t a_atom) { return ((dap_chain_block_t *)a_atom)->hdr.ts_created; }
@@ -202,6 +208,10 @@ void dap_chain_cs_blocks_deinit()
 int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config)
 {
     dap_chain_cs_blocks_t * l_cs_blocks = DAP_NEW_Z(dap_chain_cs_blocks_t);
+    if (!l_cs_blocks) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_blocks_new");
+        return -1;
+    }
     a_chain->_inheritor = l_cs_blocks;
     l_cs_blocks->chain = a_chain;
 
@@ -244,6 +254,10 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config
     l_cs_blocks->callback_new_block_move = s_new_block_move;
 
     dap_chain_cs_blocks_pvt_t *l_cs_blocks_pvt = DAP_NEW_Z(dap_chain_cs_blocks_pvt_t);
+    if (!l_cs_blocks_pvt) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_blocks_new");
+        return -1;
+    }
     l_cs_blocks->_pvt = l_cs_blocks_pvt;
     pthread_rwlock_init(&l_cs_blocks_pvt->rwlock,NULL);
     pthread_rwlock_init(&l_cs_blocks_pvt->datums_lock, NULL);
@@ -268,6 +282,21 @@ int dap_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_config
     l_cs_blocks_pvt->fill_timeout = dap_config_get_item_uint64_default(a_chain_config, "blocks", "fill_timeout", 60) * 1000; // 1 min
     l_cs_blocks_pvt->blocks_count = 0;
 
+    uint16_t l_list_len = 0;
+    char **l_hard_accept_list = dap_config_get_array_str(a_chain_config, "blocks", "hard_accept_list", &l_list_len);
+    log_it(L_MSG, "HAL for blocks contains %d whitelisted events", l_list_len);
+    for (uint16_t i = 0; i < l_list_len; i++) {
+        struct cs_blocks_hal_item *l_hal_item = DAP_NEW_Z(struct cs_blocks_hal_item);
+        if (!l_hal_item){
+            log_it(L_ERROR, "Memory allocation error in dap_chain_cs_dag_new");
+            DAP_DEL_Z(l_cs_blocks_pvt);
+            DAP_DELETE(l_cs_blocks);
+            return -10;
+        }
+        dap_chain_hash_fast_from_str(l_hard_accept_list[i], &l_hal_item->hash);
+        HASH_ADD(hh, l_cs_blocks_pvt->hal, hash, sizeof(l_hal_item->hash), l_hal_item);
+    }
+
     return 0;
 }
 
@@ -460,6 +489,11 @@ static int s_cli_blocks(int a_argc, char ** a_argv, char **a_str_reply)
             char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain);
             dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*,
                                                            sizeof(dap_chain_datum_t*)*l_datums_count);
+            if (!l_datums) {
+                log_it(L_ERROR, "Memory allocation error in s_cli_blocks");
+                dap_cli_server_cmd_set_reply_text(a_str_reply,"Out of memory in s_cli_blocks");
+                return -1;
+            }
             size_t l_datum_size = 0;
 
             dap_chain_datum_t * l_datum = (dap_chain_datum_t*) dap_global_db_get_sync(l_gdb_group_mempool, l_subcmd_str_arg ,
@@ -891,6 +925,10 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca
         l_ret++;
         // Save datum hash -> block_hash link in hash table
         dap_chain_block_datum_index_t *l_datum_index = DAP_NEW_Z(dap_chain_block_datum_index_t);
+        if (!l_datum_index) {
+            log_it(L_ERROR, "Memory allocation error in s_add_atom_datums");
+            return 1;
+        }
         l_datum_index->ts_added = time(NULL);
         l_datum_index->block_cache = a_block_cache;
         l_datum_index->datum_hash = *l_datum_hash;
@@ -1034,8 +1072,10 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da
     // verify hashes and consensus
     dap_chain_atom_verify_res_t ret = s_callback_atom_verify (a_chain, a_atom, a_atom_size);
 
-    if (ret == ATOM_MOVE_TO_THRESHOLD)
+    if (ret == ATOM_MOVE_TO_THRESHOLD) {
+        //log_it(L_ATT, "Booo!");
         ret = ATOM_REJECT; // TODO remove it when threshold will work
+    }
 
     if( ret == ATOM_ACCEPT){
         int l_consensus_check = s_add_atom_to_blocks(l_blocks, l_block_cache);
@@ -1082,11 +1122,23 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain,
     dap_chain_cs_blocks_pvt_t * l_blocks_pvt = PVT(l_blocks);
     assert(l_blocks_pvt);
     dap_chain_block_t * l_block = (dap_chain_block_t *) a_atom;
+    dap_chain_hash_fast_t l_block_hash;
 
     if(sizeof (l_block->hdr) >= a_atom_size){
         log_it(L_WARNING,"Size of block is %zd that is equal or less then block's header size %zd",a_atom_size,sizeof (l_block->hdr));
         return  ATOM_REJECT;
     }
+
+    // Hard accept list
+    if (l_blocks_pvt->hal) {
+        dap_hash_fast(l_block, a_atom_size, &l_block_hash);
+        struct cs_blocks_hal_item *l_hash_found = NULL;
+        HASH_FIND(hh, l_blocks_pvt->hal, &l_block_hash, sizeof(l_block_hash), l_hash_found);
+        if (l_hash_found) {
+            return ATOM_ACCEPT;
+        }
+    }
+
     size_t l_meta_count = 0;
     dap_chain_block_meta_t ** l_meta=  dap_chain_block_get_meta(l_block, a_atom_size, & l_meta_count);
     // Parse metadata
@@ -1095,7 +1147,6 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain,
     dap_chain_hash_fast_t l_block_anchor_hash = {0};
     uint64_t l_nonce = 0;
     uint64_t l_nonce2 = 0;
-    dap_chain_hash_fast_t l_block_hash;
 
     dap_chain_block_meta_extract(l_meta, l_meta_count,
                                         &l_block_prev_hash,
@@ -1124,7 +1175,9 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain,
                     &&!dap_hash_fast_is_blank(&l_block_hash))
                 log_it(L_NOTICE, "Accepting static genesis block");
             else{
-                log_it(L_WARNING,"Cant accept genesis block: seed mode not enabled or hash mismatch with static genesis block in configuration");
+                char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
+                dap_hash_fast_to_str(&l_block_hash, l_hash_str, sizeof(l_hash_str));
+                log_it(L_WARNING,"Cant accept genesis block: seed mode not enabled or hash mismatch with static genesis block %s in configuration", l_hash_str);
                 return ATOM_REJECT;
             }
         } else {
@@ -1154,6 +1207,10 @@ static size_t s_callback_atom_get_static_hdr_size(void)
 static dap_chain_atom_iter_t *s_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold)
 {
     dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    if (!l_atom_iter) {
+        log_it(L_ERROR, "Memory allocation error in s_callback_atom_iter_create");
+        return NULL;
+    }
     l_atom_iter->chain = a_chain;
     l_atom_iter->cell_id = a_cell_id;
     l_atom_iter->with_treshold = a_with_treshold;
@@ -1246,7 +1303,7 @@ static dap_chain_datum_t *s_callback_datum_find_by_hash(dap_chain_t *a_chain, da
  * @param a_tx_hash
  * @return atom_ptr
  */
-static dap_chain_atom_ptr_t s_callback_block_find_by_tx_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_tx_hash)
+static dap_chain_atom_ptr_t s_callback_block_find_by_tx_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_tx_hash, size_t *a_block_size)
 {
     dap_chain_cs_blocks_t * l_cs_blocks = DAP_CHAIN_CS_BLOCKS(a_chain);
     dap_chain_block_datum_index_t *l_datum_index = NULL;
@@ -1255,7 +1312,9 @@ static dap_chain_atom_ptr_t s_callback_block_find_by_tx_hash(dap_chain_t * a_cha
     pthread_rwlock_unlock(&PVT(l_cs_blocks)->datums_rwlock);
     if (!l_datum_index)
         return NULL;
-    return l_datum_index->block_cache;
+    if (a_block_size)
+        *a_block_size = l_datum_index->block_cache->block_size;
+    return l_datum_index->block_cache->block;
 }
 
 /**
@@ -1377,9 +1436,21 @@ static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter
             *a_links_size = 1;
         if (a_lasts_size_ptr) {
             *a_lasts_size_ptr = DAP_NEW_Z(size_t);
+            if (!a_lasts_size_ptr) {
+                log_it(L_ERROR, "Memory allocation error in s_callback_atom_iter_get_lasts");
+                return NULL;
+            }
             (*a_lasts_size_ptr)[0] = l_block_cache_last->block_size;
         }
         dap_chain_atom_ptr_t *l_ret = DAP_NEW_Z(dap_chain_atom_ptr_t);
+        if (!l_ret) {
+                log_it(L_ERROR, "Memory allocation error in s_callback_atom_iter_get_lasts");
+                return NULL;
+            }
+        if (!l_ret) {
+            log_it(L_ERROR, "Memory allocation error in s_callback_atom_iter_get_lasts");
+            return NULL;
+        }
         l_ret[0] = l_block_cache_last->block;
         return l_ret;
     }
@@ -1408,6 +1479,10 @@ static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter)
 static dap_chain_datum_iter_t *s_chain_callback_datum_iter_create(dap_chain_t *a_chain)
 {
     dap_chain_datum_iter_t *l_ret = DAP_NEW_Z(dap_chain_datum_iter_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_datum_iter_create");
+        return NULL;
+    }
     l_ret->chain = a_chain;
     return l_ret;
 }
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index dffba69ad8fdccfdca9b5aaf69a36d5d0bb050be..f113ca6fa37658a60fa9ce8103bfb915bf2bf374 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -226,7 +226,16 @@ static void s_timer_process_callback(void *a_arg)
 int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
 {
     dap_chain_cs_dag_t * l_dag = DAP_NEW_Z(dap_chain_cs_dag_t);
+    if (!l_dag){
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_dag_new");
+        return -1;
+    }
     l_dag->_pvt = DAP_NEW_Z(dap_chain_cs_dag_pvt_t);
+    if (!l_dag->_pvt){
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_dag_new");
+        DAP_DELETE(l_dag);
+        return -1;
+    }
     l_dag->chain = a_chain;
 
     pthread_mutexattr_t l_mutex_attr;
@@ -288,9 +297,16 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
         }
     }
     uint16_t l_list_len = 0;
-    char **l_hard_accept_list = dap_config_get_array_str(a_chain_cfg, "dag", "hard_accept_list", &l_list_len);
+    char **l_hard_accept_list = dap_config_get_array_str(a_chain_cfg, "dag-poa", "hard_accept_list", &l_list_len);
+    log_it(L_MSG, "HAL contains %d whitelisted events", l_list_len);
     for (uint16_t i = 0; i < l_list_len; i++) {
         dap_chain_cs_dag_hal_item_t *l_hal_item = DAP_NEW_Z(dap_chain_cs_dag_hal_item_t);
+        if (!l_hal_item){
+            log_it(L_ERROR, "Memory allocation error in dap_chain_cs_dag_new");
+            DAP_DEL_Z(l_dag->_pvt);
+            DAP_DELETE(l_dag);
+            return -1;
+        }
         dap_chain_hash_fast_from_str(l_hard_accept_list[i], &l_hal_item->hash);
         HASH_ADD(hh, l_dag->hal, hash, sizeof(l_hal_item->hash), l_hal_item);
     }
@@ -335,6 +351,11 @@ static void s_dap_chain_cs_dag_threshold_free(dap_chain_cs_dag_t *a_dag) {
     HASH_ITER(hh, l_pvt->events_treshold, l_current, l_tmp) {
         if (l_current->ts_added < l_time_cut_off) {
             dap_chain_cs_dag_blocked_t *l_el = DAP_NEW(dap_chain_cs_dag_blocked_t);
+            if (!l_el) {
+                log_it(L_ERROR, "Memory allocation error in s_dap_chain_cs_dag_threshold_free");
+                pthread_mutex_unlock(&l_pvt->events_mutex);
+                return;
+            }
             l_el->hash = l_current->hash;
             HASH_ADD(hh, l_pvt->removed_events_from_treshold, hash, sizeof(dap_chain_hash_fast_t), l_el);
             char *l_hash_dag = dap_hash_fast_to_str_new(&l_current->hash);
@@ -477,6 +498,10 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
     dap_chain_cs_dag_event_t * l_event = (dap_chain_cs_dag_event_t *) a_atom;
 
     dap_chain_cs_dag_event_item_t * l_event_item = DAP_NEW_Z(dap_chain_cs_dag_event_item_t);
+    if (!l_event_item) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_add");
+        return ATOM_REJECT;
+    }
     pthread_mutex_t *l_events_mutex = &PVT(l_dag)->events_mutex;
     l_event_item->event = l_event;
     l_event_item->event_size = a_atom_size;
@@ -486,10 +511,10 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
     dap_chain_cs_dag_event_calc_hash(l_event, a_atom_size, &l_event_hash);
     l_event_item->hash = l_event_hash;
 
-    char * l_event_hash_str = NULL;
     if(s_debug_more) {
-        l_event_hash_str = dap_chain_hash_fast_to_str_new(&l_event_item->hash);
-        log_it(L_DEBUG, "Processing event: %s... (size %zd)", l_event_hash_str,a_atom_size);
+        char l_event_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' };
+        dap_chain_hash_fast_to_str(&l_event_item->hash, l_event_hash_str, sizeof(l_event_hash_str));
+        log_it(L_DEBUG, "Processing event: %s ... (size %zd)", l_event_hash_str,a_atom_size);
     }
 
     pthread_mutex_lock(l_events_mutex);
@@ -511,7 +536,6 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
     case ATOM_PASS:
         if(s_debug_more) {
             log_it(L_DEBUG, "Atom already present");
-            DAP_DELETE(l_event_hash_str);
         }
         DAP_DELETE(l_event_item);
         return ret;
@@ -573,8 +597,6 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha
         DAP_DELETE(l_event_item); // Neither added, nor freed
         break;
     }
-    if(s_debug_more)
-        DAP_DELETE(l_event_hash_str);
     return ret;
 }
 
@@ -616,8 +638,10 @@ static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_
 }
 
 static bool s_chain_callback_datums_pool_proc(dap_chain_t *a_chain, dap_chain_datum_t *a_datum) {
-    if (!a_datum || !a_chain)
-        log_it(L_ERROR, "Datum or chain in mempool processing comes NULL");
+    if (!a_datum || !a_chain){
+        log_it(L_ERROR, "Datum or chain in mempool processing comes NULL in s_chain_callback_datums_pool_proc");
+        return false;
+    }
 
     dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_chain);
     /* If datum passes thru rounds, let's check if it wasn't added before */
@@ -785,11 +809,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_
             log_it(L_WARNING, "Event from another chain, possible corrupted event");
         return ATOM_REJECT;
     }
-    if (!s_event_verify_size(l_event, a_atom_size)) {
-        if (s_debug_more)
-            log_it(L_WARNING,"Event size not equal to expected");
-        return  ATOM_REJECT;
-    }
+
     // Hard accept list
     if (l_dag->hal) {
         dap_chain_hash_fast_t l_event_hash = { };
@@ -802,6 +822,12 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_
             return ATOM_ACCEPT;
         }
     }
+    if (!s_event_verify_size(l_event, a_atom_size)) {
+        if (s_debug_more)
+            log_it(L_WARNING,"Event size not equal to expected");
+        return  ATOM_REJECT;
+    }
+
     // genesis or seed mode
     if (l_event->header.hash_count == 0){
         if(s_seed_mode && !PVT(l_dag)->events){
@@ -896,6 +922,10 @@ void s_dag_events_lasts_process_new_last_event(dap_chain_cs_dag_t * a_dag, dap_c
 
     //add self
     dap_chain_cs_dag_event_item_t * l_event_last= DAP_NEW_Z(dap_chain_cs_dag_event_item_t);
+    if (!l_event_last) {
+        log_it(L_ERROR, "Memory allocation error in s_dag_events_lasts_process_new_last_event");
+        return;
+    }
     l_event_last->ts_added = a_event_item->ts_added;
     l_event_last->event = a_event_item->event;
     l_event_last->event_size = a_event_item->event_size;
@@ -1012,6 +1042,10 @@ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t
                                                                      dap_chain_atom_ptr_t a_atom, size_t a_atom_size)
 {
     dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    if (!l_atom_iter) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_iter_create_from");
+        return NULL;
+    }
     l_atom_iter->chain = a_chain;
     l_atom_iter->cur = a_atom;
     l_atom_iter->cur_size = a_atom_size;
@@ -1037,6 +1071,10 @@ static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t
 static dap_chain_atom_iter_t *s_chain_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold)
 {
     dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t);
+    if (!l_atom_iter) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_iter_create");
+        return NULL;
+    }
     l_atom_iter->chain = a_chain;
     l_atom_iter->cell_id = a_cell_id;
     l_atom_iter->with_treshold = a_with_treshold;
@@ -1063,6 +1101,10 @@ static dap_chain_datum_t **s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t
         return NULL;
 
     dap_chain_datum_t **l_datums = DAP_NEW_Z(dap_chain_datum_t*);
+    if (!l_datums) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_get_datum");
+        return NULL;
+    }
     if (a_datums_count)
         *a_datums_count = 1;
     l_datums[0] = l_datum;
@@ -1174,9 +1216,18 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_ato
         if ( l_event->header.hash_count > 0){
             dap_chain_atom_ptr_t * l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t,
                                                sizeof (dap_chain_atom_ptr_t) * l_event->header.hash_count );
+            if (!l_ret) {
+                log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_iter_get_links");
+                return NULL;
+            }
             if( a_links_size)
                 *a_links_size = l_event->header.hash_count;
             *a_links_size_array = DAP_NEW_Z_SIZE(size_t, l_event->header.hash_count*sizeof (size_t));
+            if (!a_links_size_array) {
+                log_it(L_ERROR, "Memory allocation error in s_chain_callback_atom_iter_get_links");
+                DAP_DEL_Z(l_ret);
+                return NULL;
+            }
             for (uint16_t i = 0; i < l_event->header.hash_count; i++){
                 dap_chain_cs_dag_event_item_t * l_link_item = NULL;
                 dap_chain_hash_fast_t * l_link_hash = (dap_chain_hash_fast_t *)
@@ -1319,6 +1370,10 @@ static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_ite
 static dap_chain_datum_iter_t *s_chain_callback_datum_iter_create(dap_chain_t *a_chain)
 {
     dap_chain_datum_iter_t *l_ret = DAP_NEW_Z(dap_chain_datum_iter_t);
+    if (!l_ret) {
+        log_it(L_ERROR, "Memory allocation error in s_chain_callback_datum_iter_create");
+        return NULL;
+    }
     l_ret->chain = a_chain;
     return l_ret;
 }
diff --git a/modules/type/dag/dap_chain_cs_dag_event.c b/modules/type/dag/dap_chain_cs_dag_event.c
index c1600428d4bf37a469bbe5f7c8f6f1c7b2231f7b..9e5360fd37dbf253ca8154402cce791df6ec4326 100644
--- a/modules/type/dag/dap_chain_cs_dag_event.c
+++ b/modules/type/dag/dap_chain_cs_dag_event.c
@@ -230,6 +230,10 @@ static bool s_event_broadcast_send(dap_chain_cs_dag_event_round_broadcast_t *a_a
 void dap_chain_cs_dag_event_broadcast(dap_chain_cs_dag_t *a_dag, dap_store_obj_t *a_obj, dap_global_db_context_t *a_context)
 {
     dap_chain_cs_dag_event_round_broadcast_t *l_arg = DAP_NEW(dap_chain_cs_dag_event_round_broadcast_t);
+    if (!l_arg) {
+        log_it(L_ERROR, "Memory allocation error in dap_chain_cs_dag_event_broadcast");
+        return;
+    }
     l_arg->dag = a_dag;
     l_arg->obj = dap_store_obj_copy(a_obj, 1);
     l_arg->context = a_context;
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index b3dbc6749120c8137ac7ca2153619e306bddb20d..d23c3681dec9fc86d859b7dc1e78f80bff1c716b 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -125,6 +125,10 @@ char *c_wallets_path;
     if ( !l_prec )
     {
         l_prec  = DAP_NEW_Z(dap_chain_wallet_n_pass_t);                 /* Get memory for new record */
+        if (!l_prec) {
+            log_it(L_ERROR, "Memory allocation error in dap_chain_wallet_activate");
+            return -EINVAL;
+        }
         *l_prec = l_rec;                                                /* Fill it by data */
         HASH_ADD_STR(s_wallet_n_pass, name, l_prec);                    /* Add into the hash-table */
     }