diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index a08b3ea2fa7c5663611cb533585757186f934437..8d0752cedb0d16ef83628af8aed8a714abf564a6 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -93,6 +93,12 @@ typedef struct dap_chain_ledger_tx_item {
     UT_hash_handle hh;
 } dap_chain_ledger_tx_item_t;
 
+typedef struct dap_chain_ledger_tokenizer {
+    char token_ticker[10];
+    uint64_t sum;
+    UT_hash_handle hh;
+} dap_chain_ledger_tokenizer_t;
+
 typedef struct dap_chain_ledger_tx_bound {
     dap_chain_hash_fast_t tx_prev_hash_fast;
     dap_chain_datum_tx_t *tx_prev;
@@ -590,6 +596,28 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_hash(dap_ledger_t *a_ledger, d
     return s_find_datum_tx_by_hash(a_ledger, a_tx_hash, NULL);
 }
 
+/**
+ * Check whether used 'out' items (local function)
+ */
+static bool dap_chain_ledger_item_is_used_out(dap_chain_ledger_tx_item_t *a_item, int a_idx_out)
+{
+    bool l_used_out = false;
+    if(!a_item) {
+        //log_it(L_DEBUG, "list_cached_item is NULL");
+        return false;
+    }
+    if(a_idx_out >= MAX_OUT_ITEMS) {
+        log_it(L_ERROR, "Too big index(%d) of 'out'items (max=%d)", a_idx_out, MAX_OUT_ITEMS);
+    }
+    assert(a_idx_out < MAX_OUT_ITEMS);
+    // if there are used 'out' items
+    if(a_item->n_outs_used > 0) {
+        if(!dap_hash_fast_is_blank(&(a_item->tx_hash_spent_fast[a_idx_out])))
+            l_used_out = true;
+    }
+    return l_used_out;
+}
+
 /**
  * Checking a new transaction before adding to the cache
  *
@@ -601,15 +629,15 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 {
     /*
      Steps of checking for current transaction tx2 and every previous transaction tx1:
-     1. valid(tx2.dap_chain_datum_tx_sig.pkey )
+     1. valid(tx2.dap_chain_datum_tx_sig.pkey ) && valid (tx1.dap_chain_datum_tx_sig.pkey)
      &&
-     2. valid (tx1.dap_chain_datum_tx_sig.pkey)
+     2. !is_used_out(tx1.dap_chain_datum_tx_out)
      &&
      3. hash(tx1) == tx2.dap_chain_datump_tx_in.tx_prev_hash
      &&
      4. tx1.dap_chain_datum_tx_out.addr.data.key == tx2.dap_chain_datum_tx_sig.pkey
      &&
-     5. sum(  find (tx2.input.tx_prev_hash).output[tx2.input_tx_prev_idx].value )  ==  sum (tx2.outputs.value)
+     5. sum(  find (tx2.input.tx_prev_hash).output[tx2.input_tx_prev_idx].value )  ==  sum (tx2.outputs.value) per token
      */
 
     dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
@@ -622,8 +650,9 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 
     bool l_is_first_transaction = false;
     // sum of values in 'out' items from the previous transactions
-    uint64_t l_values_from_prev_tx = 0;
-
+    dap_chain_ledger_tokenizer_t *l_values_from_prev_tx = NULL, *l_values_from_cur_tx = NULL,
+                                 *l_value_cur = NULL, *l_tmp = NULL, *l_res = NULL;
+    char *token;
     // 1. Verify signature in current transaction
     if(dap_chain_datum_tx_verify_sign(a_tx) != 1)
         return -2;
@@ -633,7 +662,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
     dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash);
 
     // check all previous transactions
-    bool l_is_err = false;
+    int l_err_num = 0;
     int l_prev_tx_count = 0;
 
     // ----------------------------------------------------------------
@@ -667,7 +696,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
         if(l_is_blank || l_is_first_transaction) {
             // if at least one blank hash is present, then all the hashes should be blank
             if((!l_is_first_transaction && l_list_tmp_num > 1) || !l_is_blank) {
-                l_is_err = true;
+                l_err_num = -3;
                 DAP_DELETE(bound_item);
                 break;
             }
@@ -690,16 +719,23 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 
             bound_item->tx_prev = l_tx_prev;
 
-            // 2. Verify signature in previous transaction
+            // 1. Verify signature in previous transaction
             int l_res_sign = dap_chain_datum_tx_verify_sign(l_tx_prev);
 
+            // 2. Check if out in previous transaction has spent
+            if (dap_chain_ledger_item_is_used_out(l_item_out, l_tx_in->header.tx_out_prev_idx)) {
+                l_err_num = -4;
+                DAP_DELETE(bound_item);
+                break;
+            }
+
+            // 3. Compare hash in previous transaction with hash inside 'in' item
             // calculate hash of previous transaction anew
             dap_chain_hash_fast_t *l_hash_prev = dap_chain_node_datum_tx_calc_hash(l_tx_prev);
-            // 3. Compare hash in previous transaction with hash inside 'in' item
             int l_res_hash = dap_hash_fast_compare(l_hash_prev, &l_tx_prev_hash);
 
             if(l_res_sign != 1 || l_res_hash != 1) {
-                l_is_err = true;
+                l_err_num = -5;
                 DAP_DELETE(bound_item);
                 break;
             }
@@ -710,7 +746,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
             // Get one 'out' item in previous transaction bound with current 'in' item
             dap_chain_tx_out_t *l_tx_prev_out = dap_list_nth_data(l_list_prev_out, l_tx_in->header.tx_out_prev_idx);
             if(!l_tx_prev_out) {
-                l_is_err = true;
+                l_err_num = -6;
                 DAP_DELETE(bound_item);
                 break;
             }
@@ -736,13 +772,20 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
 
             // 4. compare public key hashes in the signature of the current transaction and in the 'out' item of the previous transaction
             if(memcmp(&l_hash_pkey, l_prev_out_addr_key, sizeof(dap_chain_hash_fast_t))) {
-                l_is_err = true;
+                l_err_num = -7;
                 DAP_DELETE(bound_item);
                 break;
             }
-
-            // calculate sum of values from previous transactions
-            l_values_from_prev_tx += l_tx_prev_out->header.value;
+            token = l_item_out->token_tiker;
+            HASH_FIND_STR(l_values_from_prev_tx, token, l_value_cur);
+            if (!l_value_cur) {
+                l_value_cur = DAP_NEW_Z(dap_chain_ledger_tokenizer_t);
+                strcpy(l_value_cur->token_ticker, token);
+                HASH_ADD_STR(l_values_from_prev_tx, token_ticker, l_value_cur);
+            }
+            // calculate sum of values from previous transactions per each token
+            l_value_cur->sum += l_tx_prev_out->header.value;
+            l_value_cur = NULL;
 
             l_list_bound_items = dap_list_append(l_list_bound_items, bound_item);
 
@@ -754,101 +797,108 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
     if (l_list_in)
         dap_list_free(l_list_in);
 
-    if(l_is_err) {
+    if (l_err_num) {
         if ( l_list_bound_items )
             dap_list_free_full(l_list_bound_items, free);
-        return -3;
+        HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
+            DAP_DELETE(l_value_cur);
+        }
+        return l_err_num;
     }
 
+    // 5. Compare sum of values in 'out' items in the current transaction and in the previous transactions
     // Calculate the sum of values in 'out' items from the current transaction
+    l_value_cur = DAP_NEW_Z(dap_chain_ledger_tokenizer_t);
+    strcpy(l_values_from_cur_tx->token_ticker, token);
+    HASH_ADD_STR(l_values_from_cur_tx, token_ticker, l_value_cur);
     dap_list_t *l_list_tx_out = NULL;
-    uint64_t l_values_from_cur_tx = 0;
     bool emission_flag = !l_is_first_transaction || (l_is_first_transaction && l_ledger_priv->check_token_emission);
     // find 'out' items
     dap_list_t *l_list_out = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_OUT, NULL);
-    dap_list_t *l_list_out_cond = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_OUT_COND, NULL);
-    // accumalate value ​from all  'out' transactions
-    l_list_tmp = l_list_out;
-    while(l_list_tmp) {
-        dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*) l_list_tmp->data;
-        if (emission_flag) {
-            l_values_from_cur_tx += l_tx_out->header.value;
-        }
-        l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out);
-        l_list_tmp = dap_list_next(l_list_tmp);
+    l_list_tmp = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_OUT_COND, NULL);
+    // accumalate value ​from all 'out' & 'out_cond' transactions
+    if (l_list_tmp) {
+        l_list_out = dap_list_append(l_list_out, l_list_tmp);
     }
-    // accumalate value ​from all  'ut_cond' transactions
-    l_list_tmp = l_list_out_cond;
-    while(l_list_tmp) {
-        dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t*) l_list_tmp->data;
-        if (emission_flag) {
-            l_values_from_cur_tx += l_tx_out->header.value;
+    for (l_list_tmp = l_list_out; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp)) {
+        if (*(uint8_t *)l_list_tmp->data == TX_ITEM_TYPE_OUT) {
+            dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*) l_list_tmp->data;
+            if (emission_flag) {
+                l_value_cur->sum += l_tx_out->header.value;
+            }
+            l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out);
+        } else {
+            dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t*) l_list_tmp->data;
+            if (emission_flag) {
+                l_value_cur->sum += l_tx_out->header.value;
+            }
+            l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out);
         }
-        l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out);
-        l_list_tmp = dap_list_next(l_list_tmp);
     }
     if ( l_list_out )
         dap_list_free(l_list_out);
-    if ( l_list_out_cond)
-        dap_list_free(l_list_out_cond);
+    l_value_cur = NULL;
 
     // Additional check whether the transaction is first
-    if(l_is_first_transaction)
-    {
-        // Get sign item
+    while (l_is_first_transaction) {
+    // Get sign item
         size_t l_tx_token_size;
         dap_chain_tx_token_t * l_tx_token;
-        if(!(l_tx_token = (dap_chain_tx_token_t*) dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL))) {
-            if ( l_list_bound_items )
-                dap_list_free_full(l_list_bound_items, free);
-            if (l_list_tx_out)
-                dap_list_free(l_list_tx_out);
-            return -4;
+        if (!(l_tx_token = (dap_chain_tx_token_t*) dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL))) {
+            l_err_num = -8;
+            break;
         }
         l_tx_token_size = dap_chain_datum_item_tx_get_size((uint8_t*) l_tx_token);
 
-        if(l_ledger_priv->check_token_emission) { // Check the token emission
+        if (l_ledger_priv->check_token_emission) { // Check the token emission
             dap_chain_datum_token_emission_t * l_token_emission =
                     dap_chain_ledger_token_emission_find(a_ledger, l_tx_token->header.ticker,
                             &l_tx_token->header.token_emission_hash);
-            if(l_token_emission) {
-                if(l_token_emission->hdr.value != l_values_from_cur_tx) {
-                    if ( l_list_bound_items )
-                        dap_list_free_full(l_list_bound_items, free);
-                    if (l_list_tx_out)
-                        dap_list_free(l_list_tx_out);
-                    return -5;
+            if (l_token_emission) {
+                HASH_FIND_STR(l_values_from_cur_tx, l_tx_token->header.ticker, l_value_cur);
+                if (!l_value_cur || l_token_emission->hdr.value != l_value_cur->sum) {
+                    l_err_num = -9;
                 }
+                l_value_cur = NULL;
             } else {
-                if ( l_list_bound_items )
-                    dap_list_free_full(l_list_bound_items, free);
-                if (l_list_tx_out)
-                    dap_list_free(l_list_tx_out);
                 log_it(L_ERROR, "Emission for tx_token wasn't found");
-                return -6;
+                l_err_num = -9;
             }
         }
+        break;
+    }
 
-    } else if(l_values_from_cur_tx != l_values_from_prev_tx) { // 5. Compare sum of values in 'out' items in
-                                                               // the current transaction and in the previous transactions
-        log_it(L_ERROR, "Sum of values in out items of current tx (%llu) is not equal outs from previous tx (%llu)",
-               l_values_from_cur_tx, l_values_from_prev_tx);
-        if ( l_list_bound_items )
-            dap_list_free_full(l_list_bound_items, free);
-        if (l_list_tx_out)
-            dap_list_free(l_list_tx_out);
-        return -7;
+    while (!l_is_first_transaction) {
+        HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
+            HASH_FIND_STR(l_values_from_cur_tx, l_value_cur->token_ticker, l_res);
+            if (!l_res || l_res->sum != l_value_cur->sum) {
+                log_it(L_ERROR, "Sum of values in out items of current tx (%llu) is not equal outs from previous tx (%llu) for token %s",
+                       l_values_from_cur_tx, l_values_from_prev_tx, l_value_cur->token_ticker);
+                l_err_num = -10;
+                break;
+            }
+        }
+        break;
     }
 
-    if(a_list_bound_items)
-        *a_list_bound_items = l_list_bound_items;
-    else if ( l_list_bound_items )
+    HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) {
+        DAP_DELETE(l_value_cur);
+    }
+    HASH_ITER(hh, l_values_from_cur_tx, l_value_cur, l_tmp) {
+        DAP_DELETE(l_value_cur);
+    }
+    if (!a_list_bound_items || l_err_num) {
         dap_list_free_full(l_list_bound_items, free);
-    if (a_list_tx_out)
-        *a_list_tx_out = l_list_tx_out;
-    else if (l_list_tx_out)
+    } else {
+        *a_list_bound_items = l_list_bound_items;
+    }
+    if (!a_list_tx_out || l_err_num) {
         dap_list_free(l_list_tx_out);
-    return 0;
+    } else {
+        *a_list_tx_out = l_list_tx_out;
+    }
+
+    return l_err_num;
 }
 
 /**
@@ -1202,28 +1252,6 @@ uint64_t dap_chain_ledger_count_from_to(dap_ledger_t * a_ledger, time_t a_ts_fro
     return l_ret;
 }
 
-/**
- * Check whether used 'out' items (local function)
- */
-static bool dap_chain_ledger_item_is_used_out(dap_chain_ledger_tx_item_t *a_item, int a_idx_out)
-{
-    bool l_used_out = false;
-    if(!a_item) {
-        //log_it(L_DEBUG, "list_cached_item is NULL");
-        return false;
-    }
-    if(a_idx_out >= MAX_OUT_ITEMS) {
-        log_it(L_ERROR, "Too big index(%d) of 'out'items (max=%d)", a_idx_out, MAX_OUT_ITEMS);
-    }
-    assert(a_idx_out < MAX_OUT_ITEMS);
-    // if there are used 'out' items
-    if(a_item->n_outs_used > 0) {
-        if(!dap_hash_fast_is_blank(&(a_item->tx_hash_spent_fast[a_idx_out])))
-            l_used_out = true;
-    }
-    return l_used_out;
-}
-
 /**
  * Check whether used 'out' items
  */