diff --git a/dap-sdk b/dap-sdk
index a7b6da64ee24a3aba64dcbbd5f3f356069d853ad..ff8478aa04fa94540016fee0038db4b63965d0d1 160000
--- a/dap-sdk
+++ b/dap-sdk
@@ -1 +1 @@
-Subproject commit a7b6da64ee24a3aba64dcbbd5f3f356069d853ad
+Subproject commit ff8478aa04fa94540016fee0038db4b63965d0d1
diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c
index 6a31319fb60d1ca52080ae5d5ee4d98351f0f6dd..3981dd2b116ddc8b109e97ae8730915bbe8191d4 100644
--- a/modules/chain/dap_chain.c
+++ b/modules/chain/dap_chain.c
@@ -982,4 +982,4 @@ const char *dap_chain_type_to_str(const dap_chain_type_t a_default_chain_type)
         default:
             return "unknown";
     }
-}
+}
\ No newline at end of file
diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c
new file mode 100644
index 0000000000000000000000000000000000000000..2b6e06c41c0b9d65cef64779d6c62e798e16941a
--- /dev/null
+++ b/modules/chain/dap_chain_policy.c
@@ -0,0 +1,375 @@
+/*
+* Authors:
+* Pavel Uhanov <pavel.uhanov@demlabs.net>
+* Cellframe       https://cellframe.net
+* DeM Labs Inc.   https://demlabs.net
+* Copyright  (c) 2017-2025
+* All rights reserved.
+
+This file is part of CellFrame SDK the open source project
+
+CellFrame SDK is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+CellFrame SDK is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "dap_chain_policy.h"
+#include "dap_chain_datum_decree.h"
+#include "dap_list.h"
+#include "uthash.h"
+
+#define LOG_TAG "dap_chain_policy"
+
+typedef struct dap_chain_net dap_chain_net_t;
+
+struct net_policy_item {
+    uint64_t net_id;
+    uint32_t last_num_policy;
+    dap_list_t *exception_list;
+    dap_list_t *policies;
+    UT_hash_handle hh;
+};
+
+static struct net_policy_item *s_net_policy_items = NULL;
+
+/**
+ * @brief search net element in list by id
+ * @param a_net_id
+ * @return pointer if find, NULL if not
+ */
+DAP_STATIC_INLINE struct net_policy_item *s_net_item_find(uint64_t a_net_id)
+{
+    struct net_policy_item *l_item = NULL;
+    HASH_FIND_BYHASHVALUE(hh, s_net_policy_items, &a_net_id, sizeof(a_net_id), a_net_id, l_item);
+    return l_item;
+}
+
+DAP_STATIC_INLINE int s_policy_num_compare(dap_list_t  *a_list1, dap_list_t  *a_list2)
+{
+    dap_chain_policy_t
+        *l_policy1 = a_list1->data,
+        *l_policy2 = a_list2->data;
+    if (l_policy1->type != DAP_CHAIN_POLICY_ACTIVATE || l_policy2->type != DAP_CHAIN_POLICY_ACTIVATE) {
+        log_it(L_WARNING, "Compare wrong policy type");
+        return 0;
+    }
+    return ((dap_chain_policy_activate_t *)(l_policy1->data))->num == ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 0 :
+        ((dap_chain_policy_activate_t *)(l_policy1->data))->num > ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 1 : -1;
+}
+
+DAP_STATIC_INLINE bool s_policy_is_cond(dap_chain_policy_t *a_policy)
+{
+    return a_policy->type == DAP_CHAIN_POLICY_ACTIVATE &&
+        (DAP_FLAG_CHECK(a_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS) ||
+        DAP_FLAG_CHECK(a_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM));
+}
+
+static bool s_policy_cond_activated(dap_chain_policy_activate_t *a_policy_activate, uint64_t a_flags)
+{
+    bool l_ret = false;
+    if (DAP_FLAG_CHECK(a_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) {
+        time_t l_current_time = dap_time_now();
+        l_ret |= l_current_time >= a_policy_activate->ts_start;
+    }
+    if (DAP_FLAG_CHECK(a_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) {
+        if (!a_policy_activate->chain_union.chain) {
+            log_it(L_ERROR, "Chain is null in policy item with upped DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM flag");
+            return l_ret;
+        }
+        l_ret |= a_policy_activate->chain_union.chain->atom_num_last >= a_policy_activate->block_start;
+    }
+    return l_ret;
+}
+
+/**
+ * @brief init policy commands
+ * @return 0 if pass, other if error
+ */
+int dap_chain_policy_init()
+{
+    return 0;
+}
+
+/**
+ * @brief deinit policy commands
+ */
+void dap_chain_policy_deinit()
+{
+    struct net_policy_item
+        *l_temp = NULL,
+        *l_current = NULL;
+    HASH_ITER(hh, s_net_policy_items, l_current, l_temp) {
+        HASH_DEL(s_net_policy_items, l_current);
+        dap_list_free_full(l_current->policies, NULL);
+        dap_list_free(l_current->exception_list);
+        DAP_DELETE(l_current);
+    }
+}
+
+/**
+ * @brief add new net to policies list
+ * @param a_net_id
+ * @return 0 if pass, other if error
+ */
+int dap_chain_policy_net_add(uint64_t a_net_id)
+{
+    dap_return_val_if_pass(!a_net_id, -1);
+    if(s_net_item_find(a_net_id)) {
+        log_it(L_ERROR, "Net with id %"DAP_UINT64_FORMAT_X" already added", a_net_id);
+        return -2;
+    }
+    struct net_policy_item *l_new_item = DAP_NEW_Z_RET_VAL_IF_FAIL(struct net_policy_item, -3);
+    l_new_item->net_id = a_net_id;
+    HASH_ADD_BYHASHVALUE(hh, s_net_policy_items, net_id, sizeof(l_new_item->net_id), l_new_item->net_id, l_new_item);
+    return 0;
+}
+
+/**
+ * @brief remove net from policies list
+ * @param a_net_id
+ * @return 0 if pass, other if error
+ */
+int dap_chain_policy_net_remove(uint64_t a_net_id)
+{
+    dap_return_val_if_pass(!a_net_id, -1);
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    if (!l_net_item) {
+        log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id);
+        return -2;
+    }
+    HASH_DEL(s_net_policy_items, l_net_item);
+    dap_list_free_full(l_net_item->policies, NULL);
+    dap_list_free(l_net_item->exception_list);
+    DAP_DELETE(l_net_item);
+    return 0;
+}
+
+/**
+ * @brief add new policy
+ * @param a_policy_num
+ * @param a_net_id net id
+ * @return 0 if pass, other if error
+ */
+int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id)
+{
+    dap_return_val_if_pass(!a_policy, -1);
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    if (!l_net_item) {
+        log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id);
+        return -2;
+    }
+    switch (a_policy->type) {
+        case DAP_CHAIN_POLICY_ACTIVATE:
+            if (dap_list_find(l_net_item->policies, a_policy, s_policy_num_compare)) {
+                log_it(L_ERROR, "CN-%u already added to net %"DAP_UINT64_FORMAT_X, ((dap_chain_policy_activate_t *)(a_policy->data))->num, a_net_id);
+                return -3;
+            }
+            l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare);
+            if (!s_policy_is_cond(a_policy))
+                l_net_item->last_num_policy = dap_max(((dap_chain_policy_activate_t *)(a_policy->data))->num, l_net_item->last_num_policy);
+            break;
+        case DAP_CHAIN_POLICY_DEACTIVATE:
+            for (size_t i = 0; i < ((dap_chain_policy_deactivate_t *)(a_policy->data))->count; ++i) {
+                uint32_t l_policy_num = ((dap_chain_policy_deactivate_t *)(a_policy->data))->nums[i];
+                if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_num, NULL)) {
+                    log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, l_policy_num, a_net_id);
+                    continue;
+                }
+                l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)l_policy_num);
+            }
+            break;
+        default:
+            log_it(L_ERROR, "Unknow policy type %u", a_policy->type);
+            break;
+    }
+    return 0;
+}
+
+/**
+ * @brief add policy num to exception list
+ * @param a_policy_num
+ * @param a_net_id net id
+ * @return 0 if pass, other if error
+ */
+int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net_id)
+{
+    dap_return_val_if_pass(!a_policy_num, -1);
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    if (!l_net_item) {
+        log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id);
+        return -2;
+    }
+    if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL)) {
+        log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id);
+        return -3;
+    }
+    l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)a_policy_num);
+    return 0;
+}
+
+/**
+ * @brief check policy activation
+ * @param a_policy_num
+ * @param a_net_id net id
+ * @return true if yes, false if no
+ */
+bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id)
+{
+    const bool l_ret_false = false;
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    dap_return_val_if_pass(!l_net_item, l_ret_false);
+    // exception list check
+    if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL))
+        return l_ret_false;
+    // seach politics to condition check
+    dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
+    l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
+    ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num;
+    dap_list_t *l_list_item = dap_list_find(l_net_item->policies, l_to_search, s_policy_num_compare);
+    DAP_DELETE(l_to_search);
+    if (l_list_item && s_policy_is_cond((dap_chain_policy_t *)l_list_item->data)) {
+        dap_chain_policy_activate_t *l_activate = (dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_list_item->data))->data;
+        bool l_ret = s_policy_cond_activated(l_activate, ((dap_chain_policy_t *)l_list_item->data)->flags);
+        if (l_ret)
+            l_net_item->last_num_policy = dap_max(l_activate->num, l_net_item->last_num_policy);
+        return l_ret;
+    }
+    // cumulative return
+    return a_policy_num <= l_net_item->last_num_policy;
+}
+
+/**
+ * @brief find policy
+ * @param a_policy_num
+ * @param a_net_id net id
+ * @return true if yes, false if no
+ */
+dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_id)
+{
+    dap_return_val_if_pass(!a_policy_num, NULL);
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    dap_return_val_if_pass(!l_net_item, NULL);
+
+    dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false);
+    l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE;
+    ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num;
+    dap_list_t *l_find = dap_list_find(l_net_item->policies, l_to_search, s_policy_num_compare);
+    DAP_DELETE(l_to_search);
+    if (!l_find) {
+        log_it(L_DEBUG, "Can't find CN-%u in net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id);
+        return NULL;
+    }
+    return (dap_chain_policy_t *)l_find->data;
+}
+
+/**
+ * @brief return last policy num in enet
+ * @param a_net_id net id to search
+ * @return last num
+ */
+DAP_INLINE uint32_t dap_chain_policy_get_last_num(uint64_t a_net_id)
+{
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    dap_return_val_if_pass(!l_net_item, 0);
+    return l_net_item->last_num_policy;
+}
+
+
+json_object *dap_chain_policy_list(uint64_t a_net_id)
+{
+    struct net_policy_item *l_net_item = s_net_item_find(a_net_id);
+    dap_return_val_if_pass(!l_net_item, NULL);
+    json_object *l_ret = json_object_new_object();
+
+    dap_string_t *l_active_str = dap_string_new("");
+    dap_string_t *l_inactive_str = dap_string_new("");
+    if (l_net_item->last_num_policy)
+        dap_string_append_printf(l_active_str, "%s CN-%u ", dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_net_item->last_num_policy, NULL) ? "<" : "<=", l_net_item->last_num_policy);
+    json_object_object_add(l_ret, "cumulative active", json_object_new_string(l_active_str->str));
+    dap_string_erase(l_active_str, 0, -1);
+    for (dap_list_t *l_iter = dap_list_first(l_net_item->policies); l_iter; l_iter = l_iter->next) {
+        dap_chain_policy_activate_t *l_policy_activate =  (dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_iter->data))->data;
+        if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_activate->num, NULL))
+            continue;
+        if (s_policy_is_cond((dap_chain_policy_t *)(l_iter->data))) {
+            if (s_policy_cond_activated(l_policy_activate, ((dap_chain_policy_t *)(l_iter->data))->flags))
+                dap_string_append_printf(l_active_str, "CN-%u ", l_policy_activate->num);
+            else
+                dap_string_append_printf(l_inactive_str, "CN-%u ", l_policy_activate->num);
+        }
+    }
+    json_object_object_add(l_ret, "conditional active", json_object_new_string(l_active_str->str));
+    json_object_object_add(l_ret, "conditional inactive", json_object_new_string(l_inactive_str->str));
+    
+    dap_string_free(l_active_str, true);
+    dap_string_erase(l_inactive_str, 0, -1);
+    for (dap_list_t *l_iter = dap_list_first(l_net_item->exception_list); l_iter; l_iter = l_iter->next) {
+        dap_string_append_printf(l_inactive_str, "CN-%u ", (uint32_t)(uintptr_t)l_iter->data);
+    }
+    json_object_object_add(l_ret, "exception list", json_object_new_string(l_inactive_str->str));
+    dap_string_free(l_inactive_str, true);
+    return l_ret;
+}
+
+json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy)
+{
+    dap_return_val_if_pass(!a_policy, NULL);
+    json_object *l_ret = json_object_new_object();
+
+    json_object_object_add(l_ret, "version", json_object_new_uint64(a_policy->version));
+    json_object_object_add(l_ret, "type", json_object_new_string(dap_chain_policy_to_str(a_policy)));
+    switch (a_policy->type) {
+        case DAP_CHAIN_POLICY_ACTIVATE: {
+            dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)a_policy->data;
+            json_object_object_add(l_ret, "num", json_object_new_uint64(l_policy_activate->num));
+            if (l_policy_activate->ts_start) {
+                char l_time[DAP_TIME_STR_SIZE] = {};
+                dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, l_policy_activate->ts_start);
+                json_object_object_add(l_ret, "ts_start", json_object_new_string(l_time));
+            } else {
+                json_object_object_add(l_ret, "ts_start", json_object_new_int(0));
+            }
+            json_object_object_add(l_ret, "block_start", json_object_new_uint64(l_policy_activate->block_start));
+            if (l_policy_activate->block_start) {
+                if (!l_policy_activate->chain_union.chain) {
+                    json_object_object_add(l_ret, "chain", json_object_new_string("ERROR pointer chain is NULL"));
+                } else {
+                    char l_chain_id[32] = { };
+                    snprintf(l_chain_id, sizeof(l_chain_id) - 1, "0x%016"DAP_UINT64_FORMAT_x, l_policy_activate->chain_union.chain->id.uint64);
+                    json_object_object_add(l_ret, "chain", json_object_new_string(l_chain_id));
+                }
+            } else {
+                json_object_object_add(l_ret, "chain", json_object_new_string(""));
+            }
+            json_object_object_add(l_ret, "description", json_object_new_string("WIKI"));
+        }
+            break;
+        
+        case DAP_CHAIN_POLICY_DEACTIVATE: {
+            dap_chain_policy_deactivate_t *l_policy_deactivate = (dap_chain_policy_deactivate_t *)a_policy->data;
+            if (l_policy_deactivate->count) {
+                dap_string_t *l_nums_list = dap_string_sized_new(l_policy_deactivate->count * (sizeof(uint32_t) + 4));
+                for (size_t i = 0; i < l_policy_deactivate->count; ++i) {
+                    dap_string_append_printf(l_nums_list, "CN-%u ", l_policy_deactivate->nums[i]);
+                }
+                json_object_object_add(l_ret, "deactivate", json_object_new_string(l_nums_list->str));
+                dap_string_free(l_nums_list, true);
+            } else {
+                json_object_object_add(l_ret, "deactivate", json_object_new_string(""));
+            }
+        }
+            break;
+        default:
+            break;
+    }
+    return l_ret;
+}
\ No newline at end of file
diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h
new file mode 100644
index 0000000000000000000000000000000000000000..883e8469c5a942e044b34c65710af201c12e097c
--- /dev/null
+++ b/modules/chain/include/dap_chain_policy.h
@@ -0,0 +1,109 @@
+/*
+* Authors:
+* Pavel Uhanov <pavel.uhanov@demlabs.net>
+* Cellframe       https://cellframe.net
+* DeM Labs Inc.   https://demlabs.net
+* Copyright  (c) 2017-2025
+* All rights reserved.
+
+This file is part of CellFrame SDK the open source project
+
+CellFrame SDK is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+CellFrame SDK is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dap_common.h"
+#include "dap_chain.h"
+
+#define DAP_CHAIN_POLICY_VERSION                1
+
+#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS            BIT(0)
+#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM     BIT(1)
+#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG        BIT(2)
+
+
+typedef enum {
+    DAP_CHAIN_POLICY_DEACTIVATE = 0,
+    DAP_CHAIN_POLICY_ACTIVATE
+} dap_chain_policy_type_t;
+
+typedef struct dap_chain_policy_deactivate {
+    uint32_t count;
+    uint32_t nums[];
+} DAP_ALIGN_PACKED dap_chain_policy_deactivate_t;
+
+
+typedef struct dap_chain_policy_activate {
+    uint32_t num;
+    int64_t ts_start;
+    uint64_t block_start;
+    union {
+        dap_chain_id_t chain_id;
+        dap_chain_t *chain;
+    } chain_union;
+    uint16_t generation;
+} DAP_ALIGN_PACKED dap_chain_policy_activate_t;
+
+typedef struct dap_chain_policy {
+    uint16_t version;
+    uint16_t type;
+    uint64_t flags;
+    uint64_t data_size;
+    uint8_t data[];
+} DAP_ALIGN_PACKED dap_chain_policy_t;
+
+int dap_chain_policy_init();
+void dap_chain_policy_deinit();
+int dap_chain_policy_net_add(uint64_t a_net_id);
+int dap_chain_policy_net_remove(uint64_t a_net_id);
+int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id);
+int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net_id);
+uint32_t dap_chain_policy_get_last_num(uint64_t a_net_id);
+dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_id);
+json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy);
+json_object *dap_chain_policy_list(uint64_t a_net_id);
+bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id);
+
+DAP_STATIC_INLINE size_t dap_chain_policy_deactivate_calc_size(size_t a_deactivate_count)
+{
+    return sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_deactivate_t) + sizeof(uint32_t) * a_deactivate_count;
+}
+
+DAP_STATIC_INLINE size_t dap_chain_policy_get_size(dap_chain_policy_t *a_policy)
+{
+    return a_policy ? sizeof(dap_chain_policy_t)  + a_policy->data_size : 0;
+}
+
+DAP_STATIC_INLINE const char *dap_chain_policy_to_str(dap_chain_policy_t *a_policy)
+{
+    if(!a_policy)
+        return "NULL";
+    switch (a_policy->type) {
+        case DAP_CHAIN_POLICY_ACTIVATE: return ("DAP_CHAIN_POLICY_ACTIVATE");
+        case DAP_CHAIN_POLICY_DEACTIVATE: return ("DAP_CHAIN_POLICY_DEACTIVATE");
+        default: return ("UNKNOWN");
+    }
+}
+
+/**
+ * @brief check policy num
+ * @param a_num
+ * @return true if valid, fail if not
+ */
+DAP_STATIC_INLINE bool dap_chain_policy_num_is_valid(uint64_t a_num)
+{
+    uint32_t l_num = dap_maxval(l_num);
+    return (a_num && a_num <= l_num);
+}
\ No newline at end of file
diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index c611a4ddf75f81c38a50ddd29a313fad3efdbea7..298cbdd1498cd240e8894446a3b38d27cb35885c 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -75,25 +75,73 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add
     return res;
 }
 
+/**
+ * @brief s_addr_from_str
+ * @param [out] a_addr - pointer to addr fill
+ * @param [in] a_str - string with one addr
+ * @return 0 if pass, other if error
+ */
+static int s_addr_from_str(dap_chain_addr_t *a_addr, const char *a_str)
+{
+    dap_return_val_if_pass(!a_addr || !a_str || !a_str[0], -1);
+    if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) {
+        memset(a_addr, 0, sizeof(dap_chain_addr_t));
+        return 0;
+    }
+    int l_ret = 0;
+    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(strlen(a_str));
+    dap_chain_addr_t *l_addr_cur = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_addr_t, l_ret_size, -2);
+    if (dap_enc_base58_decode(a_str, l_addr_cur) == sizeof(dap_chain_addr_t) && !dap_chain_addr_check_sum(l_addr_cur)) {
+        memcpy(a_addr, l_addr_cur, sizeof(dap_chain_addr_t));
+    } else {
+        l_ret = -3;
+    }
+    DAP_DELETE(l_addr_cur);
+    return l_ret;
+}
+
 /**
  * @brief dap_chain_str_to_addr
- * @param a_addr
- * @return
+ * @param a_str - string with one addr
+ * @return pointer to dap_chain_addr_t if pass, if not - NULL
  */
-dap_chain_addr_t* dap_chain_addr_from_str(const char *a_str)
+dap_chain_addr_t *dap_chain_addr_from_str(const char *a_str)
 {
-    size_t l_str_len = (a_str) ? strlen(a_str) : 0;
-    if(l_str_len <= 0)
+    dap_chain_addr_t *l_ret = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_addr_t, NULL);
+    if (s_addr_from_str(l_ret, a_str)) {
+        DAP_DELETE(l_ret);
         return NULL;
-    if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) {
-        return DAP_NEW_Z(dap_chain_addr_t);
     }
-    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(l_str_len);
-    dap_chain_addr_t *l_addr = DAP_NEW_Z_SIZE(dap_chain_addr_t, l_ret_size);
-    return ( dap_enc_base58_decode(a_str, l_addr) == sizeof(dap_chain_addr_t) ) 
-        && !dap_chain_addr_check_sum(l_addr)
-            ? l_addr
-            : ( DAP_DELETE(l_addr), NULL );
+    return l_ret;
+}
+
+
+/**
+ * @brief parce addrs string div by ',', alloc memory to addrs
+ * @param a_addr_str - ddrs string div by ','
+ * @param a_addr - pointer to memory alloc
+ * @return addr count
+ */
+size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr)
+{
+    dap_return_val_if_pass(!a_addr_str || !a_addr, 0);
+    size_t l_count = dap_str_symbol_count(a_addr_str, ',') + 1;
+    dap_chain_addr_t *l_addr = DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(dap_chain_addr_t, l_count, 0);
+    char **l_addr_str_array = dap_strsplit(a_addr_str, ",", l_count);
+    if (!l_addr_str_array) {
+        DAP_DELETE(l_addr);
+        return 0;
+    }
+    for (size_t i = 0; i < l_count; ++i) {
+        if (s_addr_from_str(l_addr + i, l_addr_str_array[i])) {
+            DAP_DELETE(l_addr);
+            dap_strfreev(l_addr_str_array);
+            return 0;
+        }
+    }
+    dap_strfreev(l_addr_str_array);
+    *a_addr = l_addr;
+    return l_count;
 }
 
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr)
diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c
index 2f61eab67173449aec7130caafa0e0fa8789f4c7..be040aaeb615f2c41983bb88dd58a70b317b3dbd 100644
--- a/modules/common/dap_chain_datum_decree.c
+++ b/modules/common/dap_chain_datum_decree.c
@@ -28,6 +28,7 @@
 #include "dap_chain_datum_decree.h"
 #include "dap_enc_base58.h"
 #include "dap_chain_common.h"
+#include "dap_chain_policy.h"
 #ifdef DAP_OS_UNIX
 #include <arpa/inet.h>
 #endif
@@ -177,9 +178,14 @@ dap_pkey_t *dap_chain_datum_decree_get_pkey(dap_chain_datum_decree_t *a_decree)
 {
     dap_return_val_if_fail(a_decree, NULL);
     dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY);
-    if (!l_tsd)
-        return NULL;
-    return dap_pkey_get_size((dap_pkey_t *)l_tsd->data) == l_tsd->size ? (dap_pkey_t *)l_tsd->data : NULL;
+    return (l_tsd && dap_pkey_get_size((dap_pkey_t *)l_tsd->data) == l_tsd->size) ? (dap_pkey_t *)l_tsd->data : NULL;
+}
+
+dap_chain_policy_t *dap_chain_datum_decree_get_policy(dap_chain_datum_decree_t *a_decree)
+{
+    dap_return_val_if_fail(a_decree, NULL);
+    dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE);
+    return (l_tsd  && dap_chain_policy_get_size((dap_chain_policy_t *)l_tsd->data) == l_tsd->size) ? (dap_chain_policy_t *)l_tsd->data : NULL;
 }
 
 void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type)
@@ -348,7 +354,14 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d
                 break;
             }
             json_object_object_add(a_json_out, "pkey type", json_object_new_string( dap_pkey_type_to_str(((dap_pkey_t *)(l_tsd->data))->header.type) ));
-            break; 
+            break;
+        case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE:
+            if (l_tsd->size != dap_chain_policy_get_size((dap_chain_policy_t *)(l_tsd->data))) {
+                json_object_object_add(a_json_out, "policy_type", json_object_new_string("WRONG SIZE"));
+                break;
+            }
+            json_object_object_add(a_json_out, "policy_type", json_object_new_string( dap_chain_policy_to_str((dap_chain_policy_t *)(l_tsd->data))));
+            break;
         default:
             json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string(""));
             break;
diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c
index 423e44a0ffe6d66df877c9cc63a2901364dc5e3d..f413be3ff7fc6e4c7e5df2f0c147b4fe0ba1945f 100644
--- a/modules/common/dap_chain_datum_token.c
+++ b/modules/common/dap_chain_datum_token.c
@@ -491,7 +491,7 @@ dap_sign_t *dap_chain_datum_emission_get_signs(dap_chain_datum_token_emission_t
     size_t l_count, l_sign_size;
     for (l_count = 0, l_sign_size = 0; l_count < a_emission->data.type_auth.signs_count; ++l_count) {
         l_sign_size = dap_sign_get_size(l_sign);
-        if (!dap_sign_verify_size(l_sign, l_sign_size)) {
+        if (dap_sign_verify_size(l_sign, l_sign_size)) {
             break;
         }
         l_actual_size += l_sign_size;
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index b694961e23c5e5a2bc4ef48342abf7e588f68770..6384a2573f3e918ddf47166e4e0373b7ce272ebc 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -104,7 +104,7 @@ dap_chain_tx_out_cond_subtype_t dap_chain_tx_out_cond_subtype_from_str(const cha
  */
 
 size_t dap_chain_datum_item_tx_get_size(const byte_t *a_item, size_t a_max_size) {
-    dap_return_val_if_fail(a_item, TX_ITEM_TYPE_UNKNOWN);
+    dap_return_val_if_fail(a_item, 0);
     size_t l_ret = 0;
 #define m_tx_item_size(t) ( !a_max_size || sizeof(t) <= a_max_size ? sizeof(t) : 0 )
 #define m_tx_item_size_ext(t, size_field)                                                                                       \
@@ -366,11 +366,11 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                                    uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes,
-                                                                                   size_t a_pkey_hashes_count)
+                                                                                   size_t a_pkey_hashes_count, const char *a_tag_str)
 {
     if (IS_ZERO_256(a_value))
         return NULL;
-    size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t));
+    size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t)) + (a_tag_str ? sizeof(dap_tsd_t) + strlen(a_tag_str) + 1 : 0);
     dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + l_tsd_total_size, NULL);
     l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
     l_item->header.value = a_value;
@@ -381,6 +381,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delega
     byte_t *l_next_tsd_ptr = l_item->tsd;
     for (size_t i = 0; i < a_pkey_hashes_count; i++)
         l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_HASH, a_pkey_hashes + i, sizeof(dap_hash_fast_t));
+    if (a_tag_str)
+        l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_STR, (const void*)a_tag_str, strlen(a_tag_str) + 1);
     return l_item;
 }
 
diff --git a/modules/common/dap_chain_datum_tx_voting.c b/modules/common/dap_chain_datum_tx_voting.c
index 2a161dd3a93ce110042cf4c8c30030a536e9ec28..eb2ab0320c2da6b324b7dcf002790f0b6644c9f7 100644
--- a/modules/common/dap_chain_datum_tx_voting.c
+++ b/modules/common/dap_chain_datum_tx_voting.c
@@ -124,6 +124,18 @@ dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_changing_allowed_tsd_create(bool
     return l_tsd;
 }
 
+dap_chain_tx_tsd_t *dap_chain_datum_voting_token_tsd_create(const char *a_token_ticker)
+{
+    dap_return_val_if_fail(a_token_ticker && *a_token_ticker, NULL);
+    size_t l_ticker_len = strlen(a_token_ticker);
+    if (l_ticker_len >= DAP_CHAIN_TICKER_SIZE_MAX) {
+        log_it(L_ERROR, "Ticker len %zu is too big", l_ticker_len);
+        return NULL;
+    }
+    dap_chain_tx_tsd_t *l_tsd = dap_chain_datum_tx_item_tsd_create((char *)a_token_ticker, VOTING_TSD_TYPE_TOKEN, l_ticker_len);
+    return l_tsd;
+}
+
 dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_tx_cond_tsd_create(dap_chain_hash_fast_t a_tx_hash, int a_out_idx)
 {
     dap_chain_tx_voting_tx_cond_t l_temp = {
@@ -176,6 +188,9 @@ json_object *dap_chain_datum_tx_item_voting_tsd_to_json(dap_chain_datum_tx_t* a_
         case VOTING_TSD_TYPE_ANSWER:
             json_object_array_add(l_answer_array_object, json_object_new_string_len((char*)l_tsd->data, l_tsd->size));
             break;
+        case VOTING_TSD_TYPE_TOKEN:
+            json_object_object_add(l_object, "token", json_object_new_string_len((char*)l_tsd->data, l_tsd->size));
+            break;
         case VOTING_TSD_TYPE_EXPIRE:
             json_object_object_add(l_object, "exired", json_object_new_uint64(*(uint64_t*)l_tsd->data));
             break;
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index 69bc2c00fc68f50e450738672c1e607d3df5152d..0b930d2925c0122e26181a3aecf272f9f850c70d 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -225,6 +225,7 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add
 #define dap_chain_addr_to_str dap_chain_addr_to_str_static
 
 dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
+size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr);
 bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr);
 
 dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
diff --git a/modules/common/include/dap_chain_datum_decree.h b/modules/common/include/dap_chain_datum_decree.h
index f8a49f0a39b5cb20247504ee040204c056a6d9ac..fceff87616ecf26f12f2576bda89a06fbdfa8d59 100644
--- a/modules/common/include/dap_chain_datum_decree.h
+++ b/modules/common/include/dap_chain_datum_decree.h
@@ -27,6 +27,7 @@
 #include "dap_time.h"
 #include "dap_list.h"
 #include "dap_cert.h"
+#include "dap_chain_policy.h"
 #include <stdint.h>
 
 #define DAP_CHAIN_DATUM_DECREE_VERSION  0
@@ -75,7 +76,8 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT                    0x000C
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS          0x000D
 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE         0x000E
-#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE             0x0010 
+#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE             0x0010
+#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY                        0x0012
 
 // DECREE TSD types
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE                               0x0100
@@ -94,7 +96,8 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING                              0x0115
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION                              0x010A
 #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE                      0x010B
-#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY                          0x010D 
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY                          0x010D
+#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE                      0x010E 
 
 
 #ifdef __cplusplus
@@ -132,6 +135,8 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_d
         return "DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE";
     case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE:
         return "DECREE_COMMON_SUBTYPE_STAKE_UPDATE";
+    case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY:
+        return "DECREE_COMMON_SUBTYPE_POLICY";
     default:
         return "DECREE_SUBTYPE_UNKNOWN";
     }
@@ -166,6 +171,8 @@ DAP_STATIC_INLINE uint16_t dap_chain_datum_decree_type_from_str(const char *a_de
         return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE;
     } else if (!dap_strcmp(a_decree_type, "stake_update")) {
         return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE;
+    } else if (!dap_strcmp(a_decree_type, "policy")) {
+        return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY;
     } else {
         return 0;
     }
@@ -207,6 +214,8 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_tsd_type_to_str(uint16_t a_
          return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE";
     case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY:
          return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY";
+    case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE:
+         return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE";
     default:
         return "DECREE_TSD_TYPE_UNKNOWN";
     }
@@ -315,6 +324,12 @@ int dap_chain_datum_decree_get_action(dap_chain_datum_decree_t *a_decree, uint8_
 int dap_chain_datum_decree_get_signature_type(dap_chain_datum_decree_t *a_decree, uint32_t *a_signature_type);
 int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, const char **a_addr);
 dap_pkey_t *dap_chain_datum_decree_get_pkey(dap_chain_datum_decree_t *a_decree);
+/**
+ * @brief get policy from decree tsd
+ * @param a_decree
+ * @return pointer to dap_chain_policy_t if find, if not or error - NULL
+ */
+dap_chain_policy_t *dap_chain_datum_decree_get_policy(dap_chain_datum_decree_t *a_decree);
 
 /**
  * @breif dap_chain_datum_decree_dump Dump information about decree
@@ -358,7 +373,6 @@ void dap_chain_datum_decree_certs_dump_json(json_object * a_json_out, byte_t * a
 dap_chain_datum_decree_t* dap_chain_datum_decree_sign_in_cycle(dap_cert_t ** a_certs, dap_chain_datum_decree_t *a_datum_decree,
                                                   size_t a_certs_count, size_t *a_total_sign_count);
 
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 30394948908f3ea921fa68bc6f614869c5ecc28a..e864aef95f5ddb967bb1c3be3bdb3e6e14676796 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -212,7 +212,7 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock(
 
 dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value,
                                                                                    uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes,
-                                                                                   size_t a_pkey_hashes_count);
+                                                                                   size_t a_pkey_hashes_count, const char *a_tag_str);
 
 /**
  * Create item dap_chain_tx_sig_t
diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h
index 1014316a432d0caf3b3756da7ab321ee3e09f88d..ddc1dc6a87d08c9fb8252c40faf097fe96c3d26d 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -56,6 +56,8 @@ typedef byte_t dap_chain_tx_out_cond_subtype_t;
 #define DAP_CHAIN_TX_OUT_COND_TSD_ADDR                      0xf001
 // Chain hash
 #define DAP_CHAIN_TX_OUT_COND_TSD_HASH                      0xf002
+// Custom str
+#define DAP_CHAIN_TX_OUT_COND_TSD_STR                       0xf003
 
 /**
  * @struct dap_chain_tx_out
diff --git a/modules/common/include/dap_chain_datum_tx_voting.h b/modules/common/include/dap_chain_datum_tx_voting.h
index a87c67824ce16362b1e40c0822a3b47737e94fe9..add632997a948cee77c4aeb2d464f4ff9979ed03 100644
--- a/modules/common/include/dap_chain_datum_tx_voting.h
+++ b/modules/common/include/dap_chain_datum_tx_voting.h
@@ -43,7 +43,8 @@ typedef enum dap_chain_datum_voting_tsd_type {
     VOTING_TSD_TYPE_MAX_VOTES_COUNT,
     VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED,
     VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED,
-    VOTING_TSD_TYPE_VOTE_TX_COND
+    VOTING_TSD_TYPE_VOTE_TX_COND,
+    VOTING_TSD_TYPE_TOKEN
 } dap_chain_datum_voting_tsd_type_t;
 
 typedef struct dap_chain_tx_voting {
@@ -63,13 +64,14 @@ typedef struct dap_chain_tx_vote {
 
 
 typedef struct dap_chain_datum_tx_voting_params {
-    char *voting_question;
+    char       *voting_question;
     dap_list_t *answers_list;
     uint8_t    answers_count;
     dap_time_t voting_expire;
     uint64_t   votes_max_count;
     bool       delegate_key_required;
     bool       vote_changing_allowed;
+    char       token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
 } dap_chain_datum_tx_voting_params_t;
 
 #ifdef __cplusplus
@@ -86,6 +88,7 @@ dap_chain_tx_tsd_t* dap_chain_datum_voting_max_votes_count_tsd_create(uint64_t a
 dap_chain_tx_tsd_t *dap_chain_datum_voting_delegated_key_required_tsd_create(bool a_delegated_key_required);
 dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_changing_allowed_tsd_create(bool a_vote_changing_allowed);
 dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_tx_cond_tsd_create(dap_chain_hash_fast_t a_tx_hash, int a_out_idx);
+dap_chain_tx_tsd_t *dap_chain_datum_voting_token_tsd_create(const char *a_token_ticker);
 
 dap_chain_tx_voting_t *dap_chain_datum_tx_item_voting_create(void);
 json_object *dap_chain_datum_tx_item_voting_tsd_to_json(dap_chain_datum_tx_t* a_tx);
@@ -96,4 +99,4 @@ json_object *dap_chain_datum_tx_item_vote_to_json(dap_chain_tx_vote_t *a_vote, d
 
 #ifdef __cplusplus
 }
-#endif
\ No newline at end of file
+#endif
diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
index 88546b2272cf201be28153caa0099fd8a14a22dc..29c1c0100181c26d9ca10b094636cd8280f67336 100644
--- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c
+++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c
@@ -38,6 +38,7 @@ along with any CellFrame SDK based project.  If not, see <http://www.gnu.org/lic
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_chain_ledger.h"
 #include "dap_chain_node_cli_cmd.h"
+#include "dap_sign.h"
 
 #define LOG_TAG "dap_chain_cs_esbocs"
 
@@ -124,6 +125,16 @@ DAP_STATIC_INLINE size_t s_get_esbocs_message_size(dap_chain_esbocs_message_t *a
     return sizeof(*a_message) + a_message->hdr.sign_size + a_message->hdr.message_size;
 }
 
+static dap_pkey_t *s_get_pkey(dap_sign_t *a_sign, dap_chain_net_id_t a_net_id)
+{
+    if (dap_sign_is_use_pkey_hash(a_sign)) {
+        dap_hash_fast_t l_pkey_hash = {};
+        dap_sign_get_pkey_hash(a_sign, &l_pkey_hash);
+        return dap_chain_net_srv_stake_get_pkey_by_hash(a_net_id, &l_pkey_hash);
+    }
+    return NULL;
+}
+
 static dap_chain_esbocs_session_t *s_session_items;
 
 struct precached_key {
@@ -2584,8 +2595,8 @@ static void s_session_packet_in(dap_chain_esbocs_session_t *a_session, dap_chain
         }
         // check candidate's sign
         size_t l_offset = dap_chain_block_get_sign_offset(l_store->candidate, l_store->candidate_size);
-        int l_sign_verified = dap_sign_verify(l_candidate_sign, l_store->candidate,
-                                                l_offset + sizeof(l_store->candidate->hdr));
+        int l_sign_verified = dap_sign_verify_by_pkey(l_candidate_sign, l_store->candidate,
+                                                l_offset + sizeof(l_store->candidate->hdr), s_get_pkey(l_candidate_sign, l_session->chain->net_id));
         if (l_sign_verified != 0) {
             if (!l_candidate_hash_str)
                 l_candidate_hash_str = dap_chain_hash_fast_to_str_static(l_candidate_hash);
@@ -2774,6 +2785,9 @@ static size_t s_callback_block_sign(dap_chain_cs_blocks_t *a_blocks, dap_chain_b
 
 static uint64_t s_get_precached_key_hash(dap_list_t **a_precached_keys_list, dap_sign_t *a_source_sign, dap_hash_fast_t *a_result)
 {
+    if (DAP_SIGN_GET_PKEY_HASHING_FLAG(a_source_sign->header.hash_type))
+        return !dap_sign_get_pkey_hash(a_source_sign, a_result);
+
     bool l_found = false;
     struct precached_key *l_key = NULL;
     dap_list_t *l_cur;
@@ -2807,7 +2821,11 @@ static uint64_t s_get_precached_key_hash(dap_list_t **a_precached_keys_list, dap
     l_key_new->pkey_size = a_source_sign->header.sign_pkey_size;
     l_key_new->frequency = 0;
     memcpy(l_key_new->sign_pkey, dap_sign_get_pkey(a_source_sign, NULL), l_key_new->pkey_size);
-    dap_sign_get_pkey_hash(a_source_sign, &l_key_new->pkey_hash);
+    if (DAP_SIGN_GET_PKEY_HASHING_FLAG(a_source_sign->header.hash_type)) {
+        memcpy(&l_key_new->pkey_hash, l_key_new->sign_pkey, sizeof(dap_hash_fast_t));
+    } else {
+        dap_sign_get_pkey_hash(a_source_sign, &l_key_new->pkey_hash);
+    }
     *a_precached_keys_list = dap_list_append(*a_precached_keys_list, l_key_new);
     if (a_result)
         *a_result = l_key_new->pkey_hash;
@@ -2918,7 +2936,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl
                 break;
             }
         }
-        if (!dap_sign_verify(l_sign, l_block, l_block_excl_sign_size))
+        if (!dap_sign_verify_by_pkey(l_sign, l_block, l_block_excl_sign_size, s_get_pkey(l_sign, l_esbocs->chain->net_id)))
             l_signs_verified_count++;
     }
     DAP_DELETE(l_signs);
diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c
index 1a883dd8dd234777d93cd68e95586b140b31d11d..f5859e334399a6f45f3b9263500c9ded1b788b64 100644
--- a/modules/net/dap_chain_ledger.c
+++ b/modules/net/dap_chain_ledger.c
@@ -288,8 +288,6 @@ typedef struct dap_ledger_private {
 
 #define PVT(a) ( (dap_ledger_private_t *) a->_internal )
 
-static  dap_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);
 static void s_threshold_emissions_proc( dap_ledger_t * a_ledger);
 static void s_threshold_txs_proc( dap_ledger_t * a_ledger);
 static void s_threshold_txs_free(dap_ledger_t *a_ledger);
@@ -352,7 +350,7 @@ static bool s_tag_check_transfer(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a
     //crosschain transfer
     //regular transfer
     //comission transfer
-    
+
     // fee transfer: in_cond item linked to out_cond_fee
     if (a_items_grp->items_in_cond) 
     {
@@ -3268,6 +3266,9 @@ const char *dap_ledger_tx_action_str(dap_chain_tx_tag_action_type_t a_tag)
     if (a_tag == DAP_CHAIN_TX_TAG_ACTION_CHANGE) return "change";
     if (a_tag == DAP_CHAIN_TX_TAG_ACTION_VOTING) return "voting";
     if (a_tag == DAP_CHAIN_TX_TAG_ACTION_VOTE) return "vote";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD) return "hold";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE) return "take";
+    if (a_tag == DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL) return "refill";
 
     return "WTFSUBTAG";
 
@@ -3288,7 +3289,9 @@ dap_chain_tx_tag_action_type_t dap_ledger_tx_action_str_to_action_t(const char *
     if (strcmp("extend", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EXTEND;
     if (strcmp("close", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CLOSE;
     if (strcmp("change", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_CHANGE;
-
+    if (strcmp("hold", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD;
+    if (strcmp("take", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE;
+    if (strcmp("refill", a_str) == 0) return DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL;
     return DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
 }
 
@@ -4190,13 +4193,14 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
                 debug_if(s_debug_more, L_WARNING, "Verificator check error for voting item");
                 l_err_num = DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET;
             }
-            // if (a_tag) 
+            // if (a_tag)
             //     a_tag->uint64 = DAP_CHAIN_TX_TAG_ACTION_VOTING;
-            if (a_action) 
+            if (a_action)
                *a_action = DAP_CHAIN_TX_TAG_ACTION_VOTING;
         } else if ( dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL) ) {
            if (s_voting_callbacks.voting_callback) {
-               if ((l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, a_tx_hash, false))) {
+               if (!s_check_hal(a_ledger, a_tx_hash) &&
+                       (l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, a_tx_hash, false))) {
                    debug_if(s_debug_more, L_WARNING, "Verificator check error %d for vote", l_err_num);
                    l_err_num = DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE;
                }
@@ -4204,8 +4208,6 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger,
                debug_if(s_debug_more, L_WARNING, "Verificator check error for vote item");
                l_err_num = DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET;
            }
-        //    if (a_tag) 
-        //        a_tag->uint64 = DAP_CHAIN_TX_TAG_ACTION_VOTE;
            if (a_action) 
                *a_action = DAP_CHAIN_TX_TAG_ACTION_VOTE;
         }
@@ -4616,7 +4618,8 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha
         else if (l_action == DAP_CHAIN_TX_TAG_ACTION_VOTE)
             l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, a_tx_hash, true);
     }
-    assert(!l_err_num);
+    if (!s_check_hal(a_ledger, a_tx_hash))
+        assert(!l_err_num);
 
     // add transaction to the cache list
     dap_ledger_tx_item_t *l_tx_item = DAP_NEW_Z_SIZE(dap_ledger_tx_item_t, sizeof(dap_ledger_tx_item_t) + l_outs_count * sizeof(dap_chain_hash_fast_t));
@@ -5273,8 +5276,8 @@ uint256_t dap_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_chain_a
  * a_public_key_size[in] public key size
  * a_tx_first_hash [in/out] hash of the initial transaction/ found transaction, if 0 start from the beginning
  */
-static dap_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)
+dap_chain_datum_tx_t *dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const char *a_token,
+                                                 const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash)
 {
     if(!a_addr || !a_tx_first_hash)
         return NULL;
@@ -5331,20 +5334,7 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const
             break;
     }
     pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
-    return is_tx_found ? l_iter_current : NULL;
-}
-
-/**
- * @brief dap_ledger_tx_find_by_addr
- * @param a_addr
- * @param a_tx_first_hash
- * @return
- */
- dap_chain_datum_tx_t* dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger , const char * a_token ,
-         const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash)
-{
-    dap_ledger_tx_item_t* l_tx_item = tx_item_find_by_addr(a_ledger, a_addr, a_token, a_tx_first_hash);
-    return (l_tx_item) ? l_tx_item->tx : NULL;
+    return is_tx_found ? l_iter_current->tx : NULL;
 }
 
  bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr)
@@ -5374,52 +5364,6 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const
     return false;
  }
 
-/**
- * Get the transaction in the cache by the public key that signed the transaction,
- * starting from the next hash after a_tx_first_hash
- *
- * a_public_key[in] public key that signed the transaction
- * a_public_key_size[in] public key size
- * a_tx_first_hash [in/out] hash of the initial transaction/ found transaction, if 0 start from the beginning
- */
-const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger,
-        char *a_public_key, size_t a_public_key_size, dap_chain_hash_fast_t *a_tx_first_hash)
-{
-    if(!a_public_key || !a_tx_first_hash)
-        return NULL;
-    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
-    dap_chain_datum_tx_t *l_cur_tx = NULL;
-    bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
-    bool is_search_enable = is_null_hash;
-    dap_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp) {
-        dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
-        dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast;
-        // start searching from the next hash after a_tx_first_hash
-        if (!is_search_enable) {
-            is_search_enable = dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash);
-            continue;
-        }
-        // Get sign item from transaction
-        dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_tx_tmp, NULL,
-                NULL, TX_ITEM_TYPE_SIG, NULL);
-        // Get dap_sign_t from item
-        dap_sign_t *l_sig = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig);
-        if(l_sig) {
-            // compare public key in transaction with a_public_key
-            if(a_public_key_size == l_sig->header.sign_pkey_size &&
-                    !memcmp(a_public_key, l_sig->pkey_n_sign, a_public_key_size)) {
-                l_cur_tx = l_tx_tmp;
-                memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t));
-                break;
-            }
-        }
-    }
-    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
-    return l_cur_tx;
-}
-
 /**
  * @brief Get all transactions from the cache with the out_cond item
  * @param a_ledger
@@ -5442,93 +5386,6 @@ dap_list_t* dap_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger, dap_ch
     return l_ret;
 }
 
-
-/**
- * Get the transaction in the cache with the out_cond item
- *
- * a_addr[in] wallet address, whose owner can use the service
- */
-dap_chain_datum_tx_t* dap_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type,
-        dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx, char *a_token_ticker)
-{
-    if (!a_tx_first_hash)
-        return NULL;
-    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
-    dap_chain_datum_tx_t *l_cur_tx = NULL;
-    bool is_null_hash = dap_hash_fast_is_blank(a_tx_first_hash);
-    bool is_search_enable = is_null_hash;
-    dap_ledger_tx_item_t *l_iter_current = NULL, *l_item_tmp = NULL;
-    dap_chain_tx_out_cond_t *l_tx_out_cond = NULL;
-    int l_tx_out_cond_idx = 0;
-    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_pvt->ledger_items, l_iter_current, l_item_tmp) {
-        dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
-        dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast;
-        // start searching from the next hash after a_tx_first_hash
-        if (!is_search_enable) {
-            is_search_enable = dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash);
-            continue;
-        }
-        // Get out_cond item from transaction
-        l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_tmp, a_cond_type, &l_tx_out_cond_idx);
-
-        if(l_tx_out_cond) {
-            l_cur_tx = l_tx_tmp;
-            memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t));
-            if (a_token_ticker) {
-                strcpy(a_token_ticker, l_iter_current->cache_data.token_ticker);
-            }
-            break;
-        }
-    }
-    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
-    if (a_out_cond) {
-        *a_out_cond = l_tx_out_cond;
-    }
-    if (a_out_cond_idx) {
-        *a_out_cond_idx = l_tx_out_cond_idx;
-    }
-    return l_cur_tx;
-}
-
-/**
- * Get the value from all transactions in the cache with out_cond item
- *
- * a_addr[in] wallet address, whose owner can use the service
- * a_sign [in] signature of a_addr hash for check valid key
- * a_sign_size [in] signature size
- *
- * a_public_key[in] public key that signed the transaction
- * a_public_key_size[in] public key size
- */
-uint256_t dap_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type,
-                                                       dap_chain_addr_t *a_addr, dap_chain_tx_out_cond_t **tx_out_cond)
-
-{
-    uint256_t l_ret_value = {};
-
-    dap_chain_datum_tx_t *l_tx_tmp;
-    dap_chain_hash_fast_t l_tx_first_hash = { 0 }; // start hash
-    /* size_t l_pub_key_size = a_key_from->pub_key_data_size;
-     uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(a_key_from, &l_pub_key_size);*/
-    dap_chain_tx_out_cond_t *l_tx_out_cond;
-    // Find all transactions
-    do {
-        l_tx_tmp = dap_ledger_tx_cache_find_out_cond(a_ledger, a_cond_type, &l_tx_first_hash, &l_tx_out_cond, NULL, NULL);
-        // Get out_cond item from transaction
-        if(l_tx_tmp) {
-            UNUSED(a_addr);
-            // TODO check relations a_addr with cond_data and public key
-            if(l_tx_out_cond) {
-                l_ret_value = l_tx_out_cond->header.value;
-                if(tx_out_cond)
-                    *tx_out_cond = l_tx_out_cond;
-            }
-        }
-    } while(l_tx_tmp);
-    return l_ret_value;
-}
-
 /**
  * @brief dap_ledger_get_list_tx_outs_with_val
  * @param a_ledger
@@ -5784,7 +5641,7 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_
 {
     dap_ledger_private_t *l_ledger_pvt = PVT(a_iter->net->pub.ledger);
     pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
-    a_iter->cur_ledger_tx_item = l_ledger_pvt->ledger_items->hh.prev;
+    a_iter->cur_ledger_tx_item = HASH_LAST(l_ledger_pvt->ledger_items);
     a_iter->cur = ((dap_ledger_tx_item_t *)(a_iter->cur_ledger_tx_item))->tx;
     a_iter->cur_hash = ((dap_ledger_tx_item_t *)(a_iter->cur_ledger_tx_item))->tx_hash_fast;
     a_iter->is_unspent = ((dap_ledger_tx_item_t *)(a_iter->cur_ledger_tx_item))->cache_data.ts_spent ? false : true;
@@ -5793,72 +5650,120 @@ dap_chain_datum_tx_t *dap_ledger_datum_iter_get_last(dap_ledger_datum_iter_t *a_
     return a_iter->cur;
 }
 
-
 /**
- * @brief dap_ledger_get_list_tx_cond_outs_with_val
- * @param a_ledger
- * @param a_token_ticker
- * @param a_addr_from
- * @param a_subtype
- * @param a_value_need
- * @param a_value_transfer
- * @return
+ * Get the transaction in the cache by the addr in sig item
+ *
+ * a_addr[in] public key that signed the transaction
+ * a_tx_first_hash [in/out] hash of the initial transaction/ found transaction, if 0 start from the beginning
  */
-dap_list_t *dap_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledger, const char *a_token_ticker,  const dap_chain_addr_t *a_addr_from,
-        dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t a_value_need, uint256_t *a_value_transfer)
+dap_chain_tx_out_cond_t *dap_ledger_out_cond_unspent_find_by_addr(dap_ledger_t *a_ledger, const char *a_token, dap_chain_tx_out_cond_subtype_t a_subtype,
+                                                                  const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash, int *a_out_idx)
 {
-    dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items
-    dap_chain_hash_fast_t l_tx_cur_hash = { 0 };
-    uint256_t l_value_transfer = { };
-    dap_chain_datum_tx_t *l_tx;
-    while( compare256(l_value_transfer, a_value_need) == -1 
-        && ( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash)) )
-    {
-        byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1;
-        TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_COND, l_size, i, l_tx) {
-            ++l_out_idx_tmp;
-            dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*) it;
-            if (a_subtype != l_out_cond->header.subtype || IS_ZERO_256(l_out_cond->header.value) )
-                continue;
-            dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
-            *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx_tmp, l_out_cond->header.value };
-            l_list_used_out = dap_list_append(l_list_used_out, l_item);
-            SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer);
-            // already accumulated the required value, finish the search for 'out' items
-            if ( compare256(l_value_transfer, a_value_need) != -1 ) {
-                break;
+    if (!a_addr || !a_token)
+        return NULL;
+    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
+    dap_chain_tx_out_cond_t *ret = NULL;
+    dap_ledger_tx_item_t *l_iter_start = NULL, *it;
+    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
+    if (a_tx_first_hash && !dap_hash_fast_is_blank(a_tx_first_hash)) {
+        HASH_FIND(hh, l_ledger_pvt->ledger_items, a_tx_first_hash, sizeof(dap_hash_t), l_iter_start);
+        if (!l_iter_start || !l_iter_start->hh.next) {
+            pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
+            return NULL;
+        }
+        // start searching from the next hash after a_tx_first_hash
+        l_iter_start = l_iter_start->hh.next;
+    } else
+        l_iter_start = l_ledger_pvt->ledger_items;
+    for (it = l_iter_start; it; it = it->hh.next, ret = NULL) {
+        // If a_token is setup we check if its not our token - miss it
+        if (*it->cache_data.token_ticker && dap_strcmp(it->cache_data.token_ticker, a_token))
+            continue;
+        // Get 'out_cond' item from transaction
+        byte_t *l_item; size_t l_size; int i, l_out_idx = 0;
+        TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, it->tx) {
+            if (*l_item == TX_ITEM_TYPE_OUT_COND) {
+                dap_chain_tx_out_cond_subtype_t l_subtype = ((dap_chain_tx_out_cond_t *)l_item)->header.subtype;
+                if (l_subtype == a_subtype ||
+                        (a_subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_ALL && l_subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)) {
+                    ret = (dap_chain_tx_out_cond_t *)l_item;
+                    break;
+                }
             }
+            l_out_idx++;
+        }
+        // Don't return regular tx or spent conditions
+        if (!ret || !dap_hash_fast_is_blank(&it->cache_data.tx_hash_spent_fast[l_out_idx]))
+            continue;
+        dap_hash_fast_t l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, it->tx, a_subtype);
+        dap_chain_datum_tx_t *l_tx = dap_hash_fast_is_blank(&l_owner_tx_hash) ? it->tx
+                                                                              : dap_ledger_tx_find_by_hash(a_ledger, &l_owner_tx_hash);
+        if (!l_tx) {
+            log_it(L_ERROR, "Can't find owner for tx %s", dap_hash_fast_to_str_static(&it->tx_hash_fast));
+            continue;
+        }
+        // Get sign item from transaction
+        dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL);
+        // Get dap_sign_t from item
+        dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig);
+        // compare public key in transaction with a_public_key
+        dap_chain_hash_fast_t l_sign_hash = {};
+        dap_sign_get_pkey_hash(l_sign, &l_sign_hash);
+        if (dap_hash_fast_compare(&l_sign_hash, &a_addr->data.hash_fast)) {
+            if (a_tx_first_hash)
+                *a_tx_first_hash = it->tx_hash_fast;
+            if (a_out_idx)
+                *a_out_idx = l_out_idx;
+            break;
         }
     }
-    return compare256(l_value_transfer, a_value_need) > -1 && l_list_used_out
-        ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; })
-        : ( dap_list_free_full(l_list_used_out, NULL), NULL );
+    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
+    return ret;
 }
 
-dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const char *a_token_ticker,  const dap_chain_addr_t *a_addr_from,
-                                             dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t *a_value_transfer)
+dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_subtype,
+                                             const char *a_token_ticker,  const dap_chain_addr_t *a_addr_from)
 {
     dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items
     dap_chain_hash_fast_t l_tx_cur_hash = { };
-    uint256_t l_value_transfer = { };
-    dap_chain_datum_tx_t *l_tx;
-    while(( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash) )) {
-        byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1;
-        TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_COND, l_size, i, l_tx) {
-            ++l_out_idx_tmp;
-            dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*)it;
-            if ( a_subtype != l_out_cond->header.subtype || IS_ZERO_256(l_out_cond->header.value) )
-                continue;
-            dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
-            *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx_tmp, l_out_cond->header.value };
-            l_list_used_out = dap_list_append(l_list_used_out, l_item);
-            SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer);
-        }
+    int l_out_idx;
+    dap_chain_tx_out_cond_t *l_cond;
+    while ( (l_cond = dap_ledger_out_cond_unspent_find_by_addr(a_ledger, a_token_ticker, a_subtype, a_addr_from, &l_tx_cur_hash, &l_out_idx)) ) {
+        dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
+        *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx, l_cond->header.value };
+        l_list_used_out = dap_list_append(l_list_used_out, l_item);
     }
+    return l_list_used_out;
+}
 
-    return l_list_used_out
-        ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; })
-        : ( dap_list_free_full(l_list_used_out, NULL), NULL );
+bool dap_ledger_check_condition_owner(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, dap_chain_tx_out_cond_subtype_t a_cond_subtype,
+                                      int a_out_idx, dap_sign_t *a_owner_sign)
+{
+    dap_return_val_if_fail(a_ledger && a_tx_hash && a_owner_sign, false);
+    // Get first tx
+    dap_chain_datum_tx_t *l_check_tx = dap_ledger_tx_find_by_hash(a_ledger, a_tx_hash);
+    if (!l_check_tx) {
+        log_it(L_ERROR, "Can't find tx %s", dap_hash_fast_to_str_static(a_tx_hash));
+        return false;
+    }
+    if (!dap_chain_datum_tx_out_cond_get(l_check_tx, a_cond_subtype, NULL)) {
+        log_it(L_ERROR, "Can't find owner for tx %s", dap_hash_fast_to_str_static(a_tx_hash));
+        return false;
+    }
+    dap_hash_fast_t l_first_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, l_check_tx, a_cond_subtype);
+    dap_chain_datum_tx_t *l_first_tx = dap_hash_fast_is_blank(&l_first_tx_hash) ? l_check_tx
+                                                                                : dap_ledger_tx_find_by_hash(a_ledger, &l_first_tx_hash);
+    if (!l_first_tx) {
+        log_it(L_ERROR, "Can't find owner tx %s", dap_hash_fast_to_str_static(&l_first_tx_hash));
+        return false;
+    }
+    dap_chain_tx_sig_t *l_first_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_first_tx, NULL, 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_first_tx_sig);
+    if (!l_sign) {
+        log_it(L_ERROR, "Can't find signature for tx %s", dap_hash_fast_to_str_static(&l_first_tx_hash));
+        return false;
+    }
+    return dap_sign_compare_pkeys(a_owner_sign, l_sign);
 }
 
 void dap_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_ledger_tx_add_notify_t a_callback, void *a_arg) {
@@ -5915,39 +5820,3 @@ dap_chain_token_ticker_str_t dap_ledger_tx_calculate_main_ticker_(dap_ledger_t *
         *a_ledger_rc = l_rc;
     return l_ret;
 }
-
-/**
- * @brief dap_ledger_find_pkey_by_hash
- * @param a_ledger to search
- * @param a_pkey_hash - pkey hash
- * @return pointer to dap_pkey_t if finded, other - NULL
- */
-dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_pkey_hash)
-{
-    dap_return_val_if_pass(!a_pkey_hash || dap_hash_fast_is_blank(a_pkey_hash), NULL);
-
-    dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger);
-    dap_ledger_tx_item_t *l_iter_current, *l_item_tmp;
-    dap_pkey_t *l_ret = NULL;
-    pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock);
-    HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp) {
-        dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx;
-        dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast;
-        // Get sign item from transaction
-        dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_tx_tmp, NULL,
-                NULL, TX_ITEM_TYPE_SIG, NULL);
-        // Get dap_sign_t from item
-        dap_sign_t *l_sig = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig);
-        if(l_sig) {
-            // compare public key in transaction with a_public_key
-            dap_chain_hash_fast_t l_sign_hash = {};
-            dap_sign_get_pkey_hash(l_sig, &l_sign_hash);
-            if(!memcmp(&l_sign_hash, a_pkey_hash, sizeof(dap_chain_hash_fast_t))) {
-                l_ret = dap_pkey_get_from_sign(l_sig);
-                break;
-            }
-        }
-    }
-    pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock);
-    return l_ret;
-}
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 6b6d8b2c7e09e0c3100ec656a62e17f1b32ececf..a1950dc3422c605aa006732f37d2464b8f395829 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -108,6 +108,8 @@
 #include "dap_http_ban_list_client.h"
 #include "dap_net.h"
 #include "dap_context.h"
+#include "dap_chain_cs_esbocs.h"
+#include "dap_chain_policy.h"
 
 #include <stdio.h>
 #include <sys/types.h>
@@ -775,6 +777,39 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg)
                                 l_net_name_str),
                 NULL;
     log_it (L_NOTICE, "Node role \"%s\" selected for network '%s'", a_node_role, l_net_name_str);
+    
+    if (dap_chain_policy_net_add(l_ret->pub.id.uint64)) {
+        log_it(L_ERROR, "Can't add net %s to policy module", l_ret->pub.name);
+        DAP_DEL_MULTY(l_ret->pub.name, l_ret);
+        return NULL;
+    }
+    // activate policy
+    uint64_t l_policy_num = dap_config_get_item_uint64(a_cfg, "policy", "activate");
+    dap_chain_policy_t *l_new_policy = NULL;
+    if (l_policy_num) {
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U, l_policy_num);
+        } else {
+            dap_chain_policy_t *l_new_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_activate_t), NULL, l_ret->pub.name, l_ret); 
+            l_new_policy->type = DAP_CHAIN_POLICY_ACTIVATE;
+            l_new_policy->version = DAP_CHAIN_POLICY_VERSION;
+            ((dap_chain_policy_activate_t *)(l_new_policy->data))->num = l_policy_num;
+            l_new_policy->flags = DAP_FLAG_ADD(l_new_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG);
+            dap_chain_policy_add(l_new_policy, l_ret->pub.id.uint64);
+        }
+    }
+    // deactivate policy
+    uint16_t l_policy_count = 0;
+    const char **l_policy_str = dap_config_get_array_str(a_cfg, "policy", "deactivate", &l_policy_count);
+    for (uint16_t i = 0; i < l_policy_count; ++i) {
+        l_policy_num = strtoull(l_policy_str[i], NULL, 10);
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+            log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list", l_policy_num);
+        } else {
+            dap_chain_policy_add_to_exception_list(l_policy_num, l_ret->pub.id.uint64);
+        }
+    }
+    
     l_ret->pub.config = a_cfg;
     l_ret->pub.gdb_groups_prefix
         = dap_config_get_item_str_default( a_cfg, "general", "gdb_groups_prefix", dap_config_get_item_str(a_cfg, "general", "name") );
@@ -1783,6 +1818,7 @@ void dap_chain_net_deinit()
         dap_chain_net_delete(l_net);
     }
     dap_http_ban_list_client_deinit();
+    dap_chain_policy_deinit();
 }
 
 /**
@@ -1820,6 +1856,7 @@ void dap_chain_net_delete(dap_chain_net_t *a_net)
             dap_chain_delete(l_cur);
         }
     }
+    dap_chain_policy_net_remove(a_net->pub.id.uint64);
     HASH_DEL(s_nets_by_name, a_net);
     HASH_DELETE(hh2, s_nets_by_id, a_net);
     DAP_DELETE(a_net);
@@ -2511,7 +2548,7 @@ DAP_INLINE dap_chain_net_state_t dap_chain_net_get_state (dap_chain_net_t *a_net
     return PVT(a_net)->state;
 }
 
-dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t *a_net)
+dap_chain_cell_id_t *dap_chain_net_get_cur_cell( dap_chain_net_t *a_net)
 {
     return  PVT(a_net)->node_info ? &PVT(a_net)->node_info->cell_id: 0;
 }
@@ -2865,7 +2902,7 @@ int dap_chain_datum_remove(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, siz
     return 0;
 }
 
-bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net)
+DAP_INLINE bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net)
 {
     return PVT(a_net)->state == NET_STATE_LOADING;
 }
@@ -3111,7 +3148,6 @@ static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const v
     default:
         break;
     }
-    l_net_pvt->sync_context.stage_last_activity = dap_time_now();
     debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR,
                                     a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node));
 }
diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c
index 509e4e6af5089c1392e43ce6c0fdbbb03924540c..cc93696978515291da98da74b80986254bec10f0 100644
--- a/modules/net/dap_chain_net_decree.c
+++ b/modules/net/dap_chain_net_decree.c
@@ -33,6 +33,7 @@
 #include "dap_chain_net_tx.h"
 #include "dap_chain_net_srv_stake_pos_delegate.h"
 #include "dap_http_ban_list_client.h"
+#include "dap_chain_policy.h"
 
 
 
@@ -632,6 +633,22 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain
                 break;
             dap_chain_esbocs_set_emergency_validator(l_chain, l_action, l_sign_type, &l_hash);
         } break;
+        case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY: {
+            if (!a_apply)
+                break;
+            dap_chain_policy_t *l_policy = NULL;
+            if ( !(l_policy = dap_chain_datum_decree_get_policy(a_decree)) ){
+                log_it(L_WARNING,"Can't get policy from decree.");
+                return -105;
+            }
+            l_policy = DAP_DUP_SIZE_RET_VAL_IF_FAIL(l_policy, dap_chain_policy_get_size(l_policy), -106);
+            if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE) {
+                dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy->data;
+                if(DAP_FLAG_CHECK(l_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM))
+                    l_policy_activate->chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy_activate->chain_union.chain_id);
+            }
+            return dap_chain_policy_add(l_policy, a_net->pub.id.uint64);
+        }
         default:
             return -1;
     }
diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c
index addcb27c56eff00a0018ff62fc0785ebbc1eba8a..937c0464f50f9b54297dfce0366f9d6e62749d47 100644
--- a/modules/net/dap_chain_net_tx.c
+++ b/modules/net/dap_chain_net_tx.c
@@ -1633,7 +1633,7 @@ int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json
             json_object_object_add(json_obj_item,"type", json_object_new_string("voting"));
             json_object_object_add(json_obj_item,"voting_question", json_object_new_string(l_voting_params->voting_question));
             json_object_object_add(json_obj_item,"answer_options", json_object_new_string(""));
-            
+            json_object_object_add(json_obj_item, "token", json_object_new_string(l_voting_params->token_ticker));
             dap_list_t *l_temp = l_voting_params->answers_list;
             uint8_t l_index = 0;
             while (l_temp) {
@@ -1643,7 +1643,7 @@ int dap_chain_net_tx_to_json(dap_chain_datum_tx_t *a_tx, json_object *a_out_json
             }
             if (l_voting_params->voting_expire) {
                 dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_voting_params->voting_expire);
-                json_object_object_add(json_obj_item,"Voting expire", json_object_new_string(l_tmp_buf));                
+                json_object_object_add(json_obj_item, "Voting expire", json_object_new_string(l_tmp_buf));
             }
             if (l_voting_params->votes_max_count) {
                 json_object_object_add(json_obj_item, "Votes max count", json_object_new_uint64(l_voting_params->votes_max_count));
diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c
index 02064b27334c990e575b24a2b3be6277aedd9204..5e9a92d98a602600e6c861d440c6f8355480f6d6 100644
--- a/modules/net/dap_chain_node_cli.c
+++ b/modules/net/dap_chain_node_cli.c
@@ -164,8 +164,9 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                             "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>>\n"
-                            "wallet outputs {-addr <addr> | -w <wallet_name>} -net <net_name> -token <token_tiker> [-value <uint256_value>]\n"
-                            "wallet convert -w <wallet_name> {-password <password> | -remove_password }\n");
+                            "wallet outputs {-addr <addr> | -w <wallet_name>} -net <net_name> -token <token_tiker> [{-cond | -value <uint256_value>}]\n"
+                            "wallet convert -w <wallet_name> {-password <password> | -remove_password }\n"
+                            "wallet find -addr <addr> {-file <file path>}\n");
 
 
     // Token commands
@@ -235,7 +236,7 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                             "token_emit { sign -emission <hash> | -token <mempool_token_ticker> -emission_value <value> -addr <addr> } "
                             "[-chain_emission <chain_name>] -net <net_name> -certs <cert_list>\n");
 
-    dap_cli_server_cmd_add("mempool", com_mempool, "Command for working with mempool",
+    dap_cli_cmd_t *l_cmd_mempool = dap_cli_server_cmd_add("mempool", com_mempool, "Command for working with mempool",
                            "mempool list -net <net_name> [-chain <chain_name>] [-addr <addr>] [-brief] [-limit] [-offset]\n"
                            "\tList mempool (entries or transaction) for (selected chain network or wallet)\n"
                            "mempool check -net <net_name> [-chain <chain_name>] -datum <datum_hash>\n"
@@ -253,15 +254,13 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                            "\tAdd pubic certificate into the mempool to prepare its way to chains\n"
                            "mempool count -net <net_name> [-chain <chain_name>]\n"
                            "\tDisplays the number of elements in the mempool of a given network.");
-    dap_cli_cmd_t *l_cmd_mempool = dap_cli_server_cmd_find("mempool");
-    dap_cli_server_alias_add("mempool_list", "list", l_cmd_mempool);
-    dap_cli_server_alias_add("mempool_check", "check", l_cmd_mempool);
-    dap_cli_server_alias_add("mempool_proc", "proc", l_cmd_mempool);
-    dap_cli_server_alias_add("mempool_proc_all", "proc_all", l_cmd_mempool);
-    dap_cli_server_alias_add("mempool_delete", "delete", l_cmd_mempool);
-    dap_cli_server_alias_add("mempool_add_ca", "add_ca", l_cmd_mempool);
-    dap_cli_server_alias_add("chain_ca_copy", "add_ca", l_cmd_mempool);
-
+    dap_cli_server_alias_add(l_cmd_mempool, "list", "mempool_list");
+    dap_cli_server_alias_add(l_cmd_mempool, "check", "mempool_check");
+    dap_cli_server_alias_add(l_cmd_mempool, "proc", "mempool_proc");
+    dap_cli_server_alias_add(l_cmd_mempool, "proc_all", "mempool_proc_all");
+    dap_cli_server_alias_add(l_cmd_mempool, "delete", "mempool_delete");
+    dap_cli_server_alias_add(l_cmd_mempool, "add_ca", "mempool_add_ca");
+    dap_cli_server_alias_add(l_cmd_mempool, "add_ca", "chain_ca_copy");
 
     dap_cli_server_cmd_add ("chain_ca_pub", com_chain_ca_pub,
                                         "Add pubic certificate into the mempool to prepare its way to chains",
@@ -358,6 +357,26 @@ int dap_chain_node_cli_init(dap_config_t * g_config)
                            "\tTypes decree: fee, owners, owners_min, stake_approve, stake_invalidate, min_value, "
                            "min_validators_count, ban, unban, reward, validator_max_weight, emergency_validators, check_signs_structure\n");
 
+
+    dap_cli_server_cmd_add ("policy", com_policy, "Policy commands",
+                "policy activate - prepare policy activate decree\n"
+                "\t[execute] - used to create policy decree, otherwise show policy decree draft\n"
+                "\t-net <net_name>\n"
+                "\t-num <policy_num>\n"
+                "\t[-ts_start <dd/mm/yy-H:M:S>] - date to start policy\n"
+                "\t[{\n\t\t-block_start <block_num> - block num to start policy\n"
+                "\t\t-chain <chain_name> - chain name to check blocks num\n\t}]\n"
+                "\t-certs <cert1[,cert2,...,certN]> - list signing certs\n"
+                "policy deactivate - prepare policy deactivate decree\n"
+                "\t[execute] - used to create policy decree, otherwise show policy decree draft\n"
+                "\t-net <net_name>\n"
+                "\t-num <num1[,num2,...,numN]> - deactivated policy list\n"
+                "\t-certs <cert1[,cert2,...,certN]> - list signing certs\n"
+                "policy find - find info about policy in net\n"
+                "\t-net <net_name>\n"
+                "\t-num <policy_num>\n"
+                "policy list - show all policies from table in net\n"
+                "\t-net <net_name>\n");
     // Exit - always last!
     dap_cli_server_cmd_add ("exit", com_exit, "Stop application and exit",
                 "exit\n" );
diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c
index 5faab630d1c898bc275d9a905ee4ab73f882a7cf..4413358c8a27fee8f029c46117283fa8476563da 100644
--- a/modules/net/dap_chain_node_cli_cmd.c
+++ b/modules/net/dap_chain_node_cli_cmd.c
@@ -106,6 +106,11 @@
 #include "dap_client_pvt.h"
 #include "dap_enc.h"
 #include "dap_notify_srv.h"
+#include "dap_chain_wallet_cache.h"
+#include "dap_chain_net_srv_stake_pos_delegate.h"
+#include "dap_chain_policy.h"
+#include "dap_time.h"
+
 
 #include "dap_chain_net_tx.h"
 
@@ -1547,9 +1552,11 @@ int com_help(int a_argc, char **a_argv, void **a_str_reply)
 }
 
 
-void s_wallet_list(const char *a_wallet_path, json_object *a_json_arr_out){
+void s_wallet_list(const char *a_wallet_path, json_object *a_json_arr_out, dap_chain_addr_t *a_addr){
     if (!a_wallet_path || !a_json_arr_out)
         return;
+    const char *l_addr_str = NULL;
+    dap_chain_addr_t * l_addr = NULL;
     DIR * l_dir = opendir(a_wallet_path);
     if(l_dir) {
         struct dirent * l_dir_entry = NULL;
@@ -1560,7 +1567,7 @@ void s_wallet_list(const char *a_wallet_path, json_object *a_json_arr_out){
             size_t l_file_name_len = (l_file_name) ? strlen(l_file_name) : 0;
             unsigned int res = 0;
             json_object * json_obj_wall = json_object_new_object();
-            if (!json_obj_wall)
+            if (!json_obj_wall) 
                 return;
             if ( (l_file_name_len > 8) && (!strcmp(l_file_name + l_file_name_len - 8, ".dwallet")) ) {
                 char l_file_path_tmp[MAX_PATH] = {0};
@@ -1568,6 +1575,28 @@ void s_wallet_list(const char *a_wallet_path, json_object *a_json_arr_out){
                 dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_file_name, a_wallet_path, &res);
 
                 if (l_wallet) {
+                    if (a_addr) {
+                        l_addr = dap_chain_wallet_get_addr(l_wallet, a_addr->net_id);
+                        if (l_addr && dap_chain_addr_compare(l_addr, a_addr)) {
+                            json_object_object_add(json_obj_wall, "wallet", json_object_new_string(l_file_name));
+                            if(l_wallet->flags & DAP_WALLET$M_FL_ACTIVE)
+                                json_object_object_add(json_obj_wall, "status", json_object_new_string("protected-active"));
+                            else
+                                json_object_object_add(json_obj_wall, "status", json_object_new_string("unprotected"));
+                            json_object_object_add(json_obj_wall, "deprecated", json_object_new_string(
+                                                        strlen(dap_chain_wallet_check_sign(l_wallet))!=0 ? "true" : "false"));
+                        }
+                        else {
+                            json_object_put(json_obj_wall);
+                            dap_chain_wallet_close(l_wallet);
+                            DAP_DEL_Z(l_addr);
+                            continue;
+                        }
+                        DAP_DEL_Z(l_addr);
+                        dap_chain_wallet_close(l_wallet);
+                        json_object_array_add(a_json_arr_out, json_obj_wall);
+                        break;
+                    }
                     //l_addr = l_net ? dap_chain_wallet_get_addr(l_wallet, l_net->pub.id) : NULL;
                     // const char *l_addr_str = dap_chain_addr_to_str_static(l_addr);
                     json_object_object_add(json_obj_wall, "Wallet", json_object_new_string(l_file_name));
@@ -1581,16 +1610,28 @@ void s_wallet_list(const char *a_wallet_path, json_object *a_json_arr_out){
                     //    json_object_object_add(json_obj_wall, "addr", json_object_new_string(l_addr_str));
                     // }
                     dap_chain_wallet_close(l_wallet);
-                } else{
+                } else if (!a_addr){
                     json_object_object_add(json_obj_wall, "Wallet", json_object_new_string(l_file_name));
                     if(res==4)json_object_object_add(json_obj_wall, "status", json_object_new_string("protected-inactive"));
                     else if(res != 0)json_object_object_add(json_obj_wall, "status", json_object_new_string("invalid"));
                 }
+            } else if (a_addr) {
+                json_object_put(json_obj_wall);
+                continue;
             } else if ((l_file_name_len > 7) && (!strcmp(l_file_name + l_file_name_len - 7, ".backup"))) {
                 json_object_object_add(json_obj_wall, "Wallet", json_object_new_string(l_file_name));
                 json_object_object_add(json_obj_wall, "status", json_object_new_string("Backup"));
             }
-            json_object_array_add(a_json_arr_out, json_obj_wall);
+            if (json_object_object_length(json_obj_wall)) 
+                json_object_array_add(a_json_arr_out, json_obj_wall);
+            else 
+                json_object_put(json_obj_wall);
+        }
+        if (a_addr && (json_object_array_length(a_json_arr_out) == 0)) {
+            json_object * json_obj_out = json_object_new_object();
+            if (!json_obj_out) return;
+            json_object_object_add(json_obj_out, "status", json_object_new_string("not found"));
+            json_object_array_add(a_json_arr_out, json_obj_out);
         }
         closedir(l_dir);
     }
@@ -1610,7 +1651,8 @@ int com_tx_wallet(int a_argc, char **a_argv, void **a_str_reply)
 {
 json_object ** a_json_arr_reply = (json_object **) a_str_reply;
 const char *c_wallets_path = dap_chain_wallet_get_path(g_config);
-enum { CMD_NONE, CMD_WALLET_NEW, CMD_WALLET_LIST, CMD_WALLET_INFO, CMD_WALLET_ACTIVATE, CMD_WALLET_DEACTIVATE, CMD_WALLET_CONVERT, CMD_WALLET_OUTPUTS };
+enum { CMD_NONE, CMD_WALLET_NEW, CMD_WALLET_LIST, CMD_WALLET_INFO, CMD_WALLET_ACTIVATE, 
+            CMD_WALLET_DEACTIVATE, CMD_WALLET_CONVERT, CMD_WALLET_OUTPUTS, CMD_WALLET_FIND};
 int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
 
     // find  add parameter ('alias' or 'handshake')
@@ -1628,6 +1670,8 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
         cmd_num = CMD_WALLET_CONVERT;
     else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "outputs", NULL))
         cmd_num = CMD_WALLET_OUTPUTS;
+    else if(dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "find", NULL))
+        cmd_num = CMD_WALLET_FIND;
 
     l_arg_index++;
 
@@ -1638,7 +1682,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
     }
 
     const char *l_addr_str = NULL, *l_wallet_name = NULL, *l_net_name = NULL, *l_sign_type_str = NULL, *l_restore_str = NULL,
-            *l_pass_str = NULL, *l_ttl_str = NULL;
+            *l_pass_str = NULL, *l_ttl_str = NULL, *l_file_path = NULL;
 
     // find wallet addr
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-addr", &l_addr_str);
@@ -1646,6 +1690,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_name);
     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, "-file", &l_file_path);
 
     // Check if wallet name has only digits and English letter
     if (l_wallet_name && !dap_isstralnum(l_wallet_name)){
@@ -1671,7 +1716,7 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
     switch (cmd_num) {
         // wallet list
         case CMD_WALLET_LIST:
-            s_wallet_list(c_wallets_path, json_arr_out);
+            s_wallet_list(c_wallets_path, json_arr_out, NULL);
             break;
         // wallet info
         case CMD_WALLET_INFO: {
@@ -1841,48 +1886,78 @@ int l_arg_index = 1, l_rc, cmd_num = CMD_NONE;
                     return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_PARAM_ERR;
             }
             json_object * json_obj_wall = json_object_new_object();
-            const char* l_value_str = NULL;
-            dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_value_str);
+            const char *l_value_str = NULL;
+            uint256_t l_value_datoshi = uint256_0, l_value_sum = uint256_0;
+            bool l_cond_outs = dap_cli_server_cmd_check_option(a_argv, l_arg_index, a_argc, "-cond") != -1;
+            if (!l_cond_outs) {
+                dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-value", &l_value_str);
+                if (l_value_str) {
+                    l_value_datoshi = dap_chain_balance_scan(l_value_str);
+                    if (IS_ZERO_256(l_value_datoshi)) {
+                        dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_PARAM_ERR,
+                                                   "Can't convert -value param to 256bit integer");
+                            json_object_put(json_arr_out);
+                            return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_PARAM_ERR;
+                    }
+                }
+            }
 
             dap_list_t *l_outs_list = NULL;
-            uint256_t l_value_sum = uint256_0;
-
-
-
-            if (l_value_str){
-                uint256_t l_value_datoshi = dap_chain_balance_scan(l_value_str);
+            if (l_cond_outs)
+                l_outs_list = dap_ledger_get_list_tx_cond_outs(l_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_ALL, l_token_tiker, l_addr);
+            else if (l_value_str) {
                 if (dap_chain_wallet_cache_tx_find_outs_with_val(l_net, l_token_tiker, l_addr, &l_outs_list, l_value_datoshi, &l_value_sum))
-                    l_outs_list = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_token_tiker, l_addr, l_value_datoshi, &l_value_sum);
+                    l_outs_list = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_token_tiker, l_addr, l_value_datoshi, &l_value_sum); 
             } else {
                 if (dap_chain_wallet_cache_tx_find_outs(l_net, l_token_tiker, l_addr, &l_outs_list, &l_value_sum))
                     l_outs_list = dap_ledger_get_list_tx_outs(l_net->pub.ledger, l_token_tiker, l_addr, &l_value_sum);
             }
             json_object_object_add(json_obj_wall, "wallet_addr", json_object_new_string(dap_chain_addr_to_str_static(l_addr)));
-            const char *l_out_total_value_str = dap_chain_balance_print(l_value_sum);
-            const char *l_out_total_value_coins_str = dap_chain_balance_to_coins(l_value_sum);
-            json_object_object_add(json_obj_wall, "total_value_coins", json_object_new_string(l_out_total_value_coins_str));
-            json_object_object_add(json_obj_wall, "total_value_datoshi", json_object_new_string(l_out_total_value_str));
-            DAP_DEL_Z(l_out_total_value_str);
-            DAP_DEL_Z(l_out_total_value_coins_str);
             struct json_object *l_json_outs_arr = json_object_new_array();
-            for (dap_list_t *l_temp = l_outs_list; l_temp; l_temp = l_temp->next){
+            if (!l_json_outs_arr)
+                return json_object_put(json_arr_out), DAP_CHAIN_NODE_CLI_COM_TX_WALLET_MEMORY_ERR;
+            for (dap_list_t *l_temp = l_outs_list; l_temp; l_temp = l_temp->next) {
+                json_object *json_obj_item = json_object_new_object();
+                if (!json_obj_item)
+                    return json_object_put(json_arr_out), DAP_CHAIN_NODE_CLI_COM_TX_WALLET_MEMORY_ERR;
                 dap_chain_tx_used_out_item_t *l_item = l_temp->data;
-                json_object* json_obj_item = json_object_new_object();
-                const char *l_out_value_str = dap_chain_balance_print(l_item->value);
-                const char *l_out_value_coins_str = dap_chain_balance_to_coins(l_item->value);
-                json_object_object_add(json_obj_item,"item_type", json_object_new_string("unspent_out"));
+                const char *l_out_value_coins_str, *l_out_value_str = dap_uint256_to_char(l_item->value, &l_out_value_coins_str);
+                json_object_object_add(json_obj_item,"item_type", json_object_new_string(l_cond_outs ? "unspent_cond_out" : "unspent_out"));
                 json_object_object_add(json_obj_item,"value_coins", json_object_new_string(l_out_value_coins_str));
                 json_object_object_add(json_obj_item,"value_datosi", json_object_new_string(l_out_value_str));
-                json_object_object_add(json_obj_item,"prev_hash", json_object_new_string(dap_hash_fast_to_str_static(&l_item->tx_hash_fast)));  
-                json_object_object_add(json_obj_item,"out_prev_idx", json_object_new_int64(l_item->num_idx_out));   
+                json_object_object_add(json_obj_item,"prev_hash", json_object_new_string(dap_hash_fast_to_str_static(&l_item->tx_hash_fast)));
+                json_object_object_add(json_obj_item,"out_prev_idx", json_object_new_int64(l_item->num_idx_out));
                 json_object_array_add(l_json_outs_arr, json_obj_item);
-                DAP_DEL_Z(l_out_value_str);
-                DAP_DEL_Z(l_out_value_coins_str);
+                if (l_cond_outs)
+                    SUM_256_256(l_value_sum, l_item->value, &l_value_sum);
             }
             dap_list_free_full(l_outs_list, NULL);
+            const char * l_out_total_value_coins_str, *l_out_total_value_str = dap_uint256_to_char(l_value_sum, &l_out_total_value_coins_str);
+            json_object_object_add(json_obj_wall, "total_value_coins", json_object_new_string(l_out_total_value_coins_str));
+            json_object_object_add(json_obj_wall, "total_value_datoshi", json_object_new_string(l_out_total_value_str));
             json_object_object_add(json_obj_wall, "outs", l_json_outs_arr);
             json_object_array_add(json_arr_out, json_obj_wall);
         } break;
+        case CMD_WALLET_FIND: {
+            if (l_addr_str) {
+                l_addr = dap_chain_addr_from_str(l_addr_str);
+                if (l_addr) {
+                    if (l_file_path)
+                        s_wallet_list(l_file_path, json_arr_out, l_addr);
+                    else 
+                        s_wallet_list(c_wallets_path, json_arr_out, l_addr);
+                }                    
+                else {
+                    dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_ADDR_ERR,
+                        "addr not recognized");
+                    return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_ADDR_ERR;
+                }
+            } else {
+                dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_ADDR_ERR,
+                                                "You should use -addr option for the wallet find command.");
+                return DAP_CHAIN_NODE_CLI_COM_TX_WALLET_ADDR_ERR;
+            }           
+        } break;
         default: {
             if( !l_wallet_name ) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_TX_WALLET_NAME_ERR,
@@ -8023,7 +8098,7 @@ struct json_object *wallet_list_json_collect(){
     struct json_object *l_json = json_object_new_object();
     json_object_object_add(l_json, "class", json_object_new_string("WalletList"));
     struct json_object *l_j_wallets = json_object_new_array();
-    s_wallet_list(dap_chain_wallet_get_path(g_config), l_j_wallets);
+    s_wallet_list(dap_chain_wallet_get_path(g_config), l_j_wallets, NULL);
     json_object_object_add(l_json, "wallets", l_j_wallets);
     return l_json;
 }
@@ -8183,3 +8258,274 @@ int com_exec_cmd(int argc, char **argv, void **reply) {
     dap_json_rpc_request_free(l_request);
     return 0;
 }
+
+static dap_chain_datum_decree_t *s_decree_policy_execute(dap_chain_net_t *a_net, dap_chain_policy_t *a_policy)
+{
+    dap_return_val_if_pass(!a_net || !a_policy, NULL);
+    // create updating decree
+    size_t l_total_tsd_size = sizeof(dap_tsd_t) + dap_chain_policy_get_size(a_policy);
+
+    dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE);
+    if (!l_chain) {
+        log_it(L_ERROR, "No chain supported decree datum type");
+        return NULL;
+    }
+
+    dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, l_chain->id, *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size);
+    if (!l_decree) {
+        log_it(L_CRITICAL, "%s", c_error_memory_alloc);
+        return NULL;
+    }
+    l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY;
+    dap_tsd_write((byte_t*)l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE, a_policy, dap_chain_policy_get_size(a_policy));
+
+    return l_decree;
+}
+
+// Put the decree to mempool
+static char *s_decree_policy_put(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net)
+{
+    size_t l_decree_size = dap_chain_datum_decree_get_size(a_decree);
+    dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_DECREE, a_decree, l_decree_size);
+    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE);
+    if (!l_chain)
+        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE);
+    if (!l_chain) {
+        log_it(L_ERROR, "No chain supported decree datum type");
+        return NULL;
+    }
+    // Processing will be made according to autoprocess policy
+    char *l_ret = dap_chain_mempool_datum_add(l_datum, l_chain, "hex");
+    DAP_DELETE(l_datum);
+    return l_ret;
+}
+
+int com_policy(int argc, char **argv, void **reply) {
+    json_object ** a_json_arr_reply = (json_object **) reply;
+    char **l_deactivate_array = NULL;
+    const char
+        *l_num_str = NULL,
+        *l_net_str = NULL,
+        *l_deactivate_str = NULL,
+        *l_chain_str = NULL,
+        *l_ts_start_str = NULL,
+        *l_block_start_str = NULL,
+        *l_certs_str = NULL;
+    size_t
+        l_deactivate_count = 0,
+        l_certs_count = 0;
+    dap_cert_t **l_certs = NULL;
+    uint64_t l_flags = 0;
+    bool l_execute = false;
+
+    enum { CMD_NONE = 0, CMD_ACTIVATE, CMD_DEACTIVATE, CMD_FIND, CMD_LIST };  
+    int l_arg_index = 1;
+
+    int l_cmd = CMD_NONE;
+    if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "activate", NULL))
+        l_cmd = CMD_ACTIVATE;
+    else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "deactivate", NULL))
+            l_cmd = CMD_DEACTIVATE;
+    else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "find", NULL))
+        l_cmd = CMD_FIND;
+    else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "list", NULL))
+        l_cmd = CMD_LIST;
+
+    if (l_cmd == CMD_NONE) {
+        dap_json_rpc_error_add(*a_json_arr_reply, -4, "Unknown subcommand");
+        return -4;
+    }
+
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-net", &l_net_str);
+
+    if (!l_net_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, -3, "Command policy require args -net");
+        return -4;
+    }
+    dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+    if (!l_net){
+        dap_json_rpc_error_add(*a_json_arr_reply, -3, "Can't find net %s", l_net_str);
+        return -4;
+    }
+
+    if (l_cmd == CMD_LIST) {
+        json_object *l_answer = dap_chain_policy_list(l_net->pub.id.uint64);
+        json_object_array_add(*a_json_arr_reply, l_answer);
+        return 0;
+    }
+
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-num", &l_num_str);
+    if (!l_num_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, -7, "Command policy require args -num");
+        return -7;
+    }
+
+    void *l_policy_data = NULL;
+    size_t l_data_size = 0;
+    uint64_t l_policy_num = 0;
+    int l_policy_type = -1;
+    if (l_cmd == CMD_DEACTIVATE) {
+        l_policy_type = DAP_CHAIN_POLICY_DEACTIVATE;
+        l_deactivate_count = dap_str_symbol_count(l_num_str, ',') + 1;
+        l_deactivate_array = dap_strsplit(l_num_str, ",", l_deactivate_count);
+        l_data_size = sizeof(dap_chain_policy_deactivate_t) + l_deactivate_count * sizeof(uint32_t);
+        l_policy_data = DAP_NEW_Z_SIZE(void, l_data_size);
+        if (!l_policy_data) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "%s", c_error_memory_alloc);
+            dap_strfreev(l_deactivate_array);
+            return -16;
+        }
+        ((dap_chain_policy_deactivate_t *)l_policy_data)->count = l_deactivate_count;
+        for (size_t i = 0; i < l_deactivate_count; ++i) {
+            l_policy_num = strtoull(l_deactivate_array[i], NULL, 10);
+            if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy nums sould be less or equal than %u and not equal 0", dap_maxval((uint32_t)l_policy_num));
+                dap_strfreev(l_deactivate_array);
+                DAP_DELETE(l_policy_data);
+                return -16;
+            }
+            ((dap_chain_policy_deactivate_t *)l_policy_data)->nums[i] = l_policy_num;
+        }
+        dap_strfreev(l_deactivate_array);
+    } else {
+        l_policy_num = strtoull(l_num_str, NULL, 10);
+        if (!dap_chain_policy_num_is_valid(l_policy_num)) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", dap_maxval((uint32_t)l_policy_num));
+            return -16;
+        }
+    }
+
+    uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64);
+
+    if (l_cmd == CMD_FIND) {
+        dap_chain_policy_t *l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64);
+        json_object *l_answer = dap_chain_policy_json_collect(l_policy);
+        if (l_answer) {
+            json_object_object_add(l_answer, "active", json_object_new_string(dap_chain_policy_activated(((dap_chain_policy_activate_t *)(l_policy->data))->num, l_net->pub.id.uint64) ? "true" : "false"));
+            json_object_array_add(*a_json_arr_reply, l_answer);
+        } else {
+            json_object_array_add(*a_json_arr_reply, json_object_new_string("Detailed information not exist"));
+        }
+        return 0;
+    }
+
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-chain", &l_chain_str);
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-ts_start", &l_ts_start_str);
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-block_start", &l_block_start_str);
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-deactivate", &l_deactivate_str);
+    dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-certs", &l_certs_str);
+    l_execute = dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "execute", NULL);
+
+    if (l_execute) {
+        if (!l_certs_str) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -4, "Command 'execute' requires parameter -certs");
+            DAP_DELETE(l_policy_data);
+            return -4;
+        }
+        dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_count);
+        if (!l_certs || !l_certs_count) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -5, "Specified certificates not found");
+            DAP_DELETE(l_policy_data);
+            return -5;
+        }
+    }
+
+    if (l_cmd == CMD_ACTIVATE) {
+        if (l_policy_num == l_last_num) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -15, "Specified policy num already existed");
+            return -15;
+        }
+        l_policy_type = DAP_CHAIN_POLICY_ACTIVATE;
+        l_data_size = sizeof(dap_chain_policy_activate_t);
+        l_policy_data = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(void, l_data_size, -5);
+        dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy_data;
+        
+        l_policy_activate->num = l_policy_num;
+        if (l_ts_start_str) {
+            l_policy_activate->ts_start = dap_time_from_str_custom(l_ts_start_str, "%d/%m/%y-%H:%M:%S");
+            if (!l_policy_activate->ts_start) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -13, "Can't read ts_start \"%s\"", l_ts_start_str);
+                DAP_DELETE(l_policy_activate);
+                return -13;
+            }
+            l_flags = DAP_FLAG_ADD(l_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS);
+        }
+
+        if (l_block_start_str)
+            l_policy_activate->block_start = strtoull(l_block_start_str, NULL, 10);
+        
+        if (l_policy_activate->block_start) {
+            if (!l_chain_str) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -8, "Command policy create with -block_start require args -chain");
+                DAP_DELETE(l_policy_activate);
+                return -8;
+            }
+            dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str);
+            if (!l_chain) {
+                dap_json_rpc_error_add(*a_json_arr_reply, -9, "%s Chain not found", l_chain_str);
+                DAP_DELETE(l_policy_activate);
+                return -9;
+            }
+            l_policy_activate->chain_union.chain = l_chain;
+            l_flags = DAP_FLAG_ADD(l_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM);
+        }
+        if (!l_flags && l_policy_activate->num < l_last_num) {
+            dap_json_rpc_error_add(*a_json_arr_reply, -16, "Specified policy already activated by CN-%u", l_last_num);
+            DAP_DELETE(l_policy_activate);
+            return -16;
+        }
+    }
+
+    dap_chain_policy_t *l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, l_data_size + sizeof(dap_chain_policy_t), -5, l_policy_data);
+    l_policy->data_size = l_data_size;
+    l_policy->version = DAP_CHAIN_POLICY_VERSION;
+    l_policy->type = l_policy_type;
+    l_policy->flags = l_flags;
+    memcpy(l_policy->data, l_policy_data, l_policy->data_size);
+    DAP_DELETE(l_policy_data);
+    // if cmd none - only print preaparing result
+    if (!l_execute) {
+        json_object *l_answer = dap_chain_policy_json_collect(l_policy);
+        char l_time[DAP_TIME_STR_SIZE] = {};
+        dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, dap_time_now());
+        json_object_object_add(l_answer, "Current time", json_object_new_string(l_time));
+        json_object_object_add(l_answer, "Notification", json_object_new_string("It's policy draft, check and use 'execute' command to apply"));
+        if (l_answer) {
+            json_object_array_add(*a_json_arr_reply, l_answer);
+        } else {
+            dap_json_rpc_error_add(*a_json_arr_reply, -11, "Policy draft creation failed");
+            DAP_DELETE(l_policy);
+            return -11;
+        }
+        DAP_DELETE(l_policy);
+        return 0;
+    }
+    // change pointer to id to decree
+    if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE && ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain) {
+        ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain_id = ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain->id;
+    }
+
+    dap_chain_datum_decree_t *l_decree = s_decree_policy_execute(l_net, l_policy);
+    DAP_DELETE(l_policy);
+    size_t l_total_signs_success = 0;
+    l_decree = dap_chain_datum_decree_sign_in_cycle(l_certs, l_decree, l_certs_count, &l_total_signs_success);
+
+    if (!l_decree || l_total_signs_success == 0){
+        dap_json_rpc_error_add(*a_json_arr_reply, -11, "Decree creation failed. Successful count of certificate signing is 0");
+            return -11;
+    }
+
+    char *l_decree_hash_str = NULL;;
+    if (!(l_decree_hash_str = s_decree_policy_put(l_decree, l_net))) {
+        dap_json_rpc_error_add(*a_json_arr_reply, -12, "Policy decree error");
+        return -12;
+    }
+    DAP_DELETE(l_decree);
+
+    char l_approve_str[128];
+    snprintf(l_approve_str, sizeof(l_approve_str), "Policy decree %s successfully created", l_decree_hash_str);
+    json_object_array_add(*a_json_arr_reply, json_object_new_string(l_approve_str));
+    DAP_DELETE(l_decree_hash_str);
+
+    return 0;
+}
diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c
index 0748ba83ce64ac7bdffe97f91b6f8549df941509..48e89da82a7ce68e0aae8d8569d662478b1e76ef 100644
--- a/modules/net/dap_chain_node_cli_cmd_tx.c
+++ b/modules/net/dap_chain_node_cli_cmd_tx.c
@@ -429,7 +429,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
         int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED;
         uint8_t *l_tx_item = NULL;
         size_t l_size; int i, q = 0;
-        // Проход по входам
+        // Inputs iteration
         TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_IN_ALL, l_size, i, l_tx) {
             dap_chain_hash_fast_t *l_tx_prev_hash = NULL;
             int l_tx_prev_out_idx;
@@ -552,7 +552,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
             case TX_ITEM_TYPE_OUT_COND:
                 l_value = ((dap_chain_tx_out_cond_t *)it->data)->header.value;
                 if (((dap_chain_tx_out_cond_t *)it->data)->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) {
-                    SUM_256_256(l_fee_sum, ((dap_chain_tx_out_cond_t *)it->data)->header.value, &l_fee_sum);
+                    SUM_256_256(l_fee_sum, l_value, &l_fee_sum);
                     l_dst_token = l_native_ticker;
                 } else
                     l_dst_token = l_src_token;
@@ -562,7 +562,7 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
 
             if (l_src_addr && l_dst_addr &&
                     dap_chain_addr_compare(l_dst_addr, l_src_addr) &&
-                    dap_strcmp(l_noaddr_token, l_dst_token))
+                    l_noaddr_token && dap_strcmp(l_noaddr_token, l_dst_token))
                 continue;   // sent to self (coinback)
 
             if (l_dst_addr && l_net_fee_used && dap_chain_addr_compare(&l_net_fee_addr, l_dst_addr))
@@ -698,13 +698,10 @@ json_object* dap_db_history_addr(json_object* a_json_arr_reply, dap_chain_addr_t
             json_object_object_add(l_corr_object, "recv_datoshi", json_object_new_string(l_value_str));
         }
         if (l_send_to_same_cond) {
-            json_object *l_cond_recv_value_obj = json_object_object_get(l_cond_recv_object, "recv_datoshi");
-            const char *l_cond_recv_value_str = json_object_get_string(l_cond_recv_value_obj);
-            uint256_t l_cond_recv_value = dap_uint256_scan_uninteger(l_cond_recv_value_str);
+            uint256_t l_cond_recv_value = l_cond_value;
             json_object *l_cond_send_value_obj = json_object_object_get(l_cond_send_object, "send_datoshi");
             const char *l_cond_send_value_str = json_object_get_string(l_cond_send_value_obj);
             uint256_t l_cond_send_value = dap_uint256_scan_uninteger(l_cond_send_value_str);
-            assert(!IS_ZERO_256(l_cond_recv_value) && !IS_ZERO_256(l_cond_send_value));
             int l_direction = compare256(l_cond_recv_value, l_cond_send_value);
             if (l_direction > 0) {
                 SUBTRACT_256_256(l_cond_recv_value, l_cond_send_value, &l_cond_recv_value);
diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h
index f2e43d962d7f7617a4a8457eada2479fa56218a2..a3608c605911e76d277223925f4be24c9d46eb6b 100644
--- a/modules/net/include/dap_chain_ledger.h
+++ b/modules/net/include/dap_chain_ledger.h
@@ -127,6 +127,10 @@ typedef enum dap_chain_tx_tag_action_type {
 
     DAP_CHAIN_TX_TAG_ACTION_VOTING =                1 << 11,
     DAP_CHAIN_TX_TAG_ACTION_VOTE =                  1 << 12,
+
+    DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD =    1 << 13,
+    DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE =    1 << 14,
+    DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL =  1 << 15,
    
     DAP_CHAIN_TX_TAG_ACTION_ALL =                          ~0,
 } dap_chain_tx_tag_action_type_t;
@@ -418,21 +422,11 @@ dap_chain_datum_tx_t* dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const c
 
 bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr);
 
-// Get the transaction in the cache by the public key that signed the transaction, starting with a_tx_first_hash
-const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger,
-        char *a_public_key, size_t a_public_key_size, dap_chain_hash_fast_t *a_tx_first_hash);
-
-// Get the transaction in the cache with the out_cond item
-dap_chain_datum_tx_t* dap_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type,
-                                                              dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond,
-                                                              int *a_out_cond_idx, char *a_token_ticker);
-
 // Get all transactions from the cache with the specified out_cond items
 dap_list_t* dap_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger, dap_chain_net_srv_uid_t a_srv_uid);
 
-// Get the value from all transactions in the cache with out_cond item
-uint256_t dap_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, dap_chain_addr_t *a_addr,
-                                                       dap_chain_tx_out_cond_t **tx_out_cond);
+dap_chain_tx_out_cond_t *dap_ledger_out_cond_unspent_find_by_addr(dap_ledger_t *a_ledger, const char *a_token, dap_chain_tx_out_cond_subtype_t a_subtype,
+                                                                  const dap_chain_addr_t *a_addr, dap_chain_hash_fast_t *a_tx_first_hash, int *a_out_idx);
 
 // Get the list of 'out' items from previous transactions with summary value >= than a_value_need
 // Put this summary value to a_value_transfer
@@ -440,12 +434,8 @@ dap_list_t *dap_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, const c
                                                        uint256_t a_value_need, uint256_t *a_value_transfer);
 dap_list_t *dap_ledger_get_list_tx_outs(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from,
                                         uint256_t *a_value_transfer);
-// Get the list of 'out_cond' items with summary value >= than a_value_need
-dap_list_t *dap_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledger, const char *a_token_ticker,  const dap_chain_addr_t *a_addr_from,
-        dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t a_value_need, uint256_t *a_value_transfer);
-
-dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const char *a_token_ticker,  const dap_chain_addr_t *a_addr_from,
-                                             dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t *a_value_transfer);
+dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_subtype, const char *a_token_ticker,  const dap_chain_addr_t *a_addr_from);
+bool dap_ledger_check_condition_owner(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, dap_chain_tx_out_cond_subtype_t a_cond_subtype, int a_out_idx, dap_sign_t *a_owner_sign);
 // Add new verificator callback with associated subtype. Returns 1 if callback replaced, overwise returns 0
 int dap_ledger_verificator_add(dap_chain_tx_out_cond_subtype_t a_subtype, dap_ledger_verificator_callback_t a_callback,
                                      dap_ledger_updater_callback_t a_callback_added, dap_ledger_delete_callback_t a_callback_deleted);
@@ -471,7 +461,6 @@ bool dap_ledger_cache_enabled(dap_ledger_t *a_ledger);
 void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_cache_tx_check_callback_t a_callback);
 dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(dap_ledger_t *a_ledger, dap_chain_tx_in_cond_t *a_in_cond);
 void dap_ledger_load_end(dap_ledger_t *a_ledger);
-dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_pkey_hash);
 
 #ifdef __cplusplus
 }
diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h
index 7f8a39ea7d0adca1c4474306422d2688aa833d2c..fba416a4c88fb6da4595c5c4e74d2befc43e43f6 100644
--- a/modules/net/include/dap_chain_node_cli_cmd.h
+++ b/modules/net/include/dap_chain_node_cli_cmd.h
@@ -474,6 +474,11 @@ void dap_notify_new_client_send_info(dap_events_socket_t *a_es, void *a_arg);
 
 int com_exec_cmd(int argc, char **argv, void **reply);
 
+/**
+ * Policy management
+ */
+int com_policy(int a_argc, char **a_argv, void **a_str_reply);
+
 #ifdef __cplusplus
 }
 #endif
\ No newline at end of file
diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
index 3df74f13687bcbaa4f17a068c3d1809ae68154db..4a16024466a78f580d011f0bd0402d8d3556ccdb 100644
--- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
+++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c
@@ -47,7 +47,8 @@ enum emit_delegation_error {
     ERROR_COMPOSE,
     ERROR_CREATE,
     ERROR_PLACE,
-    ERROR_SUBCOMMAND
+    ERROR_SUBCOMMAND,
+    ERROR_NETWORK
 };
 
 #define LOG_TAG "dap_chain_net_srv_emit_delegate"
@@ -60,6 +61,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
     uint256_t l_writeoff_value = uint256_0;
     dap_chain_tx_out_cond_t *l_cond_out = NULL;
     dap_chain_addr_t l_net_fee_addr;
+    uint16_t l_change_type = 0;
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_ledger->net->pub.id, NULL, &l_net_fee_addr);
     byte_t *l_item; size_t l_tx_item_size;
     TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx_in) {
@@ -76,7 +78,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
             break;
         case TX_ITEM_TYPE_TSD: {
             dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd;
-            if (l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF)
+            if (l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_tsd->type != DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL)
                 break; // Skip it
             if (l_tsd->size != sizeof(uint256_t)) {
                 log_it(L_ERROR, "TSD section size control error");
@@ -87,6 +89,7 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
                 return -5;
             }
             l_writeoff_value = dap_tsd_get_scalar(l_tsd, uint256_t);
+            l_change_type = l_tsd->type;
             break;
         }
         // Verify signs
@@ -125,13 +128,22 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
     }
 
     uint256_t l_change_value;
-    if (SUBTRACT_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) {
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && SUBTRACT_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) {
         char *l_balance = dap_uint256_decimal_to_char(a_cond->header.value);
-        const char *l_writeoff; dap_uint256_to_char(l_writeoff_value, &l_writeoff);
+        const char *l_writeoff = NULL;
+        dap_uint256_to_char(l_change_value, &l_writeoff);
         log_it(L_ERROR, "Write-off value %s is greater than account balance %s", l_writeoff, l_balance);
         DAP_DELETE(l_balance);
         return -7;
     }
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL && SUM_256_256(a_cond->header.value, l_writeoff_value, &l_change_value)) {
+        char *l_balance = dap_uint256_decimal_to_char(a_cond->header.value);
+        const char *l_refill = NULL;
+        dap_uint256_to_char(l_change_value, &l_refill);
+        log_it(L_ERROR, "Sum of re-fill value %s and account balance %s is owerflow 256 bit num", l_refill, l_balance);
+        DAP_DELETE(l_balance);
+        return -9;
+    }
     if (!IS_ZERO_256(l_change_value)) {
         if (!l_cond_out) {
             log_it(L_ERROR, "Changeback on conditional output is need but not found");
@@ -148,12 +160,9 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
             log_it(L_ERROR, "Condtional output in current TX have different TSD sections vs previous TX's one");
             return -11;
         }
-    } else if (l_cond_out) {
-        log_it(L_ERROR, "Changeback on conditional output is not need but found");
-        return -10;
     }
 
-    if (l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) {
+    if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) {
         log_it(L_WARNING, "Not enough valid signs (%u from %u) for delegated emission",
                                     l_signs_verified, a_cond->subtype.srv_emit_delegate.signers_minimum);
         return DAP_CHAIN_CS_VERIFY_CODE_NOT_ENOUGH_SIGNS;
@@ -163,7 +172,17 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_tx_out_
 
 static bool s_tag_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx,  dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action)
 {   
-    return a_items_grp->items_out_cond_srv_emit_delegate;
+    if (!a_items_grp->items_out_cond_srv_emit_delegate)
+        return false;
+    if (a_action) {
+        if (dap_chain_datum_tx_item_get_tsd_by_type(a_tx, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF))
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_TAKE;
+        else if (dap_chain_datum_tx_item_get_tsd_by_type(a_tx, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL))
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_REFILL;
+        else
+            *a_action = DAP_CHAIN_TX_TAG_ACTION_EMIT_DELEGATE_HOLD;
+    }
+    return true;
 }
 
 // Put a transaction to the mempool
@@ -183,11 +202,11 @@ static char *s_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_t *a_chain, const ch
 
 #define m_sign_fail(e,s) { dap_json_rpc_error_add(a_json_arr_reply, e, s); log_it(L_ERROR, "%s", s); return NULL; }
 
-#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s) }
+#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s); log_it(L_ERROR, "%s", s); }
 
 static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
                                                   const char *a_token_ticker, uint256_t a_value, uint256_t a_fee,
-                                                  uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count)
+                                                  uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count, const char *a_tag_str)
 {
     const char *l_native_ticker = a_net->pub.native_ticker;
     bool l_delegate_native = !dap_strcmp(l_native_ticker, a_token_ticker);
@@ -233,7 +252,7 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
     // add 'out_cond' & 'out_ext' items
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID };
     dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(
-                                                l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count);
+                                                l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count, a_tag_str);
     if (!l_tx_out)
         m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction conditional output");
     dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out);
@@ -266,6 +285,134 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply,
         if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, l_native_ticker) != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
     }
+    // add 'sign' item
+    if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
+        m_tx_fail(ERROR_COMPOSE, "Can't add sign output");
+    return l_tx;
+}
+
+
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
+    uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
+{
+    dap_return_val_if_pass(!a_net || IS_ZERO_256(a_value) || IS_ZERO_256(a_fee), NULL);
+    dap_ledger_t *l_ledger = a_net->pub.ledger;
+    const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash);
+    bool l_refill_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
+    uint256_t l_value = a_value, l_value_transfer = {}, l_fee_transfer = {}; // how many coins to transfer
+    uint256_t l_net_fee, l_fee_total = a_fee;
+    dap_chain_addr_t l_net_fee_addr;
+    // create empty transaction
+    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
+
+    bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
+    if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
+        m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+    if (l_refill_native && SUM_256_256(l_value, l_fee_total, &l_value))
+        m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+
+    // list of transaction with 'out' items to sell
+    dap_chain_addr_t l_owner_addr;
+    dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id);
+    dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_tx_ticker,
+                                                                       &l_owner_addr, l_value, &l_value_transfer);
+    if (!l_list_used_out)
+        m_tx_fail(ERROR_FUNDS, "Nothing to pay for refill (not enough funds)");
+
+    // add 'in' items to pay for delegate
+    uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
+    dap_list_free_full(l_list_used_out, NULL);
+    if (!EQUAL_256(l_value_to_items, l_value_transfer))
+        m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction input");
+
+    if (!l_refill_native) {
+        dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
+                                                                          &l_owner_addr, l_fee_total, &l_fee_transfer);
+        if (!l_list_fee_out)
+            m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
+        // add 'in' items to pay fee
+        uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out);
+        dap_list_free_full(l_list_fee_out, NULL);
+        if (!EQUAL_256(l_value_fee_items, l_fee_transfer))
+            m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input");
+    }
+
+    dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, a_tx_in_hash, false);
+    if (dap_hash_fast_is_blank(&l_final_tx_hash))
+        m_tx_fail(ERROR_FUNDS, "Nothing to refill, can't find tx");
+
+    log_it(L_NOTICE, "Actual TX hash %s will be used for refill TX composing", dap_hash_fast_to_str_static(&l_final_tx_hash));
+    dap_chain_datum_tx_t *l_tx_in = dap_ledger_tx_find_by_hash(l_ledger, &l_final_tx_hash);
+    assert(l_tx_in);
+    int l_prev_cond_idx = 0;
+    dap_chain_tx_out_cond_t *l_cond_prev = dap_chain_datum_tx_out_cond_get(l_tx_in, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_prev_cond_idx);
+    if (!l_cond_prev)
+        m_tx_fail(ERROR_TX_MISMATCH, "Requested conditional transaction requires conditional output");
+
+    if (dap_ledger_tx_hash_is_used_out_item(l_ledger, &l_final_tx_hash, l_prev_cond_idx, NULL))
+        m_tx_fail(ERROR_TX_MISMATCH, "Requested conditional transaction is already used out");
+
+    // add 'in_cond' item
+    if (dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_final_tx_hash, l_prev_cond_idx, -1) != 1) {
+        log_it(L_ERROR, "Can't compose the transaction conditional input");
+        m_tx_fail(ERROR_COMPOSE, "Cant add conditionsl input");
+    }
+
+    uint256_t l_value_back = {};
+    if(SUM_256_256(l_cond_prev->header.value, a_value, &l_value_back)) {
+        m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+    }
+
+    dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size);
+    if (!l_out_cond)
+        m_tx_fail(ERROR_MEMORY, c_error_memory_alloc);
+    l_out_cond->header.value = l_value_back;
+    if (dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond) < 0) {
+        m_tx_fail(ERROR_COMPOSE, "Cant add refill cond output");
+        DAP_DELETE(l_out_cond);
+    }
+    DAP_DELETE(l_out_cond);
+
+    // add track for refill from conditional value
+    dap_chain_tx_tsd_t *l_refill_tsd = dap_chain_datum_tx_item_tsd_create(&a_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL, sizeof(uint256_t));
+    if (dap_chain_datum_tx_add_item(&l_tx, l_refill_tsd) != 1) {
+        DAP_DELETE(l_refill_tsd);
+        m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with withdraw value");
+    }
+    DAP_DELETE(l_refill_tsd);
+
+    //add other tsd if available
+    for ( dap_list_t *l_tsd = tsd_items; l_tsd; l_tsd = l_tsd->next ) {
+        if ( dap_chain_datum_tx_add_item(&l_tx, l_tsd->data) != 1 )
+        m_tx_fail(ERROR_COMPOSE, "Can't add custom TSD section item ");
+    }
+
+    // coin back
+    SUBTRACT_256_256(l_value_transfer, l_value, &l_value_back);
+    if (!IS_ZERO_256(l_value_back)) {
+        int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_value_back)
+                                   : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_value_back, l_tx_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add coin back output");
+    }
+
+    // add fee items
+    if (l_net_fee_used) {
+        int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee)
+                                   : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add net fee output");
+    }
+    if (!IS_ZERO_256(a_fee) && dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1)
+        m_tx_fail(ERROR_COMPOSE, "Cant add validator fee output");
+
+    if (!l_refill_native) {
+        uint256_t l_fee_back = {};
+        // fee coin back
+        SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back);
+        if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker) != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
+    }
 
     // add 'sign' item
     if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
@@ -290,8 +437,13 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e
 }
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-                                                dap_chain_addr_t *a_addr_to, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
+    dap_chain_addr_t *a_to_addr, uint256_t *a_value, uint32_t a_addr_count /*!not change type!*/, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items)
 {
+    dap_return_val_if_pass(!a_to_addr, NULL);
+    dap_return_val_if_pass(!a_value, NULL);
+    dap_return_val_if_pass(!a_addr_count, NULL);
+    dap_return_val_if_pass(!a_enc_key, NULL);
+    dap_return_val_if_pass(!a_tx_in_hash, NULL);
     // create empty transaction
     dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
 
@@ -299,10 +451,18 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash);
     bool l_taking_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker);
 
-    uint256_t l_value = a_value, l_fee_transfer = {}; // how many coins to transfer
+    uint256_t l_value = {}, l_fee_transfer = {}; // how many coins to transfer
     uint256_t l_net_fee, l_fee_total = a_fee;
     dap_chain_addr_t l_net_fee_addr;
 
+    for (size_t i = 0; i < a_addr_count; ++i) {
+        if(IS_ZERO_256(a_value[i])) {
+            m_tx_fail(ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
+        }
+        if (SUM_256_256(l_value, a_value[i], &l_value))
+            m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
+    }
+
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
     if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total))
         m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer");
@@ -310,7 +470,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     dap_chain_addr_t l_owner_addr;
     dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id);
     dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker,
-                                                                      &l_owner_addr, l_fee_total, &l_fee_transfer);
+                            &l_owner_addr, l_fee_total, &l_fee_transfer);
     if (!l_list_fee_out)
         m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)");
     // add 'in' items to pay fee
@@ -344,22 +504,31 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     }
 
     // add 'out' or 'out_ext' item for emission
-    int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_addr_to, a_value) :
-                               dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr_to, a_value, l_tx_ticker);
-    if (rc != 1)
-        m_tx_fail(ERROR_COMPOSE, "Cant add emission output");
+    for (size_t i = 0; i < a_addr_count; ++i) {
+        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr + i, a_value[i]) :
+            dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr + i, a_value[i], l_tx_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add tx output");
+    }
 
     // coin back
     uint256_t l_value_back = {};
     SUBTRACT_256_256(l_cond_prev->header.value, l_value, &l_value_back);
-    if (!IS_ZERO_256(l_value_back)) {
-        dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size);
-        if (!l_out_cond)
-            m_tx_fail(ERROR_COMPOSE, c_error_memory_alloc);
-        l_out_cond->header.value = l_value_back;
-        if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond))
-            m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output");
+    dap_chain_tx_out_cond_t *l_out_cond = DAP_DUP_SIZE(l_cond_prev, sizeof(dap_chain_tx_out_cond_t) + l_cond_prev->tsd_size);
+    if (!l_out_cond)
+        m_tx_fail(ERROR_MEMORY, c_error_memory_alloc);
+    l_out_cond->header.value = l_value_back;
+    
+    if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond)) {
         DAP_DELETE(l_out_cond);
+        m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output");
+    }
+    DAP_DELETE(l_out_cond);
+
+    if (a_addr_count > 1) {
+        dap_chain_tx_tsd_t * l_addr_cnt_tsd = dap_chain_datum_tx_item_tsd_create(&a_addr_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t));
+        if (!l_addr_cnt_tsd || dap_chain_datum_tx_add_item(&l_tx, l_addr_cnt_tsd) != 1 )
+            m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with addr count");
     }
 
     // add track for takeoff from conditional value
@@ -377,7 +546,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     // add fee items
     if (l_net_fee_used) {
         int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee)
-                                 : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
+            : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker);
         if (rc != 1)
             m_tx_fail(ERROR_COMPOSE, "Cant add net fee output");
     }
@@ -388,10 +557,10 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     // fee coin back
     SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back);
     if (!IS_ZERO_256(l_fee_back)) {
-            int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back)
-                                     : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker);
-            if (rc != 1)
-                m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
+        int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back)
+            : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker);
+        if (rc != 1)
+            m_tx_fail(ERROR_COMPOSE, "Cant add fee back output");
     }
 
     // add 'sign' item
@@ -401,6 +570,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje
     return l_tx;
 }
 
+
 #undef m_tx_fail
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *a_tx_in)
@@ -433,7 +603,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object
     }
     dap_chain_datum_tx_t *l_tx = DAP_DUP_SIZE(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in));
     if (!l_tx)
-        m_sign_fail(ERROR_FUNDS, c_error_memory_alloc);
+        m_sign_fail(ERROR_MEMORY, c_error_memory_alloc);
     // add 'sign' item
     if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1)
         m_sign_fail(ERROR_COMPOSE, "Can't add sign output");
@@ -444,7 +614,14 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object
 
 static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
 {
-    const char *l_token_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_signs_min_str = NULL, *l_pkeys_str = NULL;
+    const char *l_token_str = NULL, 
+                *l_value_str = NULL, 
+                *l_wallet_str = NULL, 
+                *l_fee_str = NULL, 
+                *l_signs_min_str = NULL, 
+                *l_pkeys_str = NULL,
+                *l_tag_str = NULL;
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-token", &l_token_str);
     if (!l_token_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation holding requires parameter -token");
@@ -461,7 +638,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     uint256_t l_value = dap_chain_balance_scan(l_value_str);
     if (IS_ZERO_256(l_value)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer>");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
         return ERROR_VALUE;
     }
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str);
@@ -471,7 +648,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     uint256_t l_fee = dap_chain_balance_scan(l_fee_str);
     if (IS_ZERO_256(l_fee)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer>");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer");
         return ERROR_VALUE;
     }
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-signs_minimum", &l_signs_min_str);
@@ -489,11 +666,15 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation holding requires parameter -w");
         return ERROR_PARAM;
     }
+
     dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
     if (!l_wallet) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
         return ERROR_VALUE;
     }
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tag", &l_tag_str);
+
     const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
     dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
     dap_chain_wallet_close(l_wallet);
@@ -524,6 +705,13 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
             DAP_DEL_MULTY(l_enc_key, l_pkey_hashes);
             return ERROR_VALUE;
         }
+        for (size_t j = 0; j < i; ++j) {
+            if (!memcmp(l_pkey_hashes + j, l_pkey_hashes + i, sizeof(dap_chain_hash_fast_t))){
+                dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Find pkey hash %s dublicate", l_hash_str_buf);
+                DAP_DEL_MULTY(l_enc_key, l_pkey_hashes);
+                return ERROR_VALUE;
+            }
+        }
         if (*l_cur_ptr == 0) {
             l_hashes_count = i + 1;
             break;
@@ -541,7 +729,7 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
         return ERROR_VALUE;
     }
     // Create conditional transaction for delegated emissions
-    dap_chain_datum_tx_t *l_tx = s_emitting_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_token_str, l_value, l_fee, l_signs_min, l_pkey_hashes, l_hashes_count);
+    dap_chain_datum_tx_t *l_tx = s_emitting_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_token_str, l_value, l_fee, l_signs_min, l_pkey_hashes, l_hashes_count, l_tag_str);
     DAP_DEL_MULTY(l_enc_key, l_pkey_hashes);
     if (!l_tx) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission");
@@ -563,12 +751,39 @@ static int s_cli_hold(int a_argc, char **a_argv, int a_arg_index, json_object **
     return DAP_NO_ERROR;
 }
 
-static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
+static int s_cli_refill(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
 {
-    const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
+    const char *l_token_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL, *l_tx_in_hash_str = NULL;
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str);
+    if (!l_value_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -value");
+        return ERROR_PARAM;
+    }
+    uint256_t l_value = dap_chain_balance_scan(l_value_str);
+    if (IS_ZERO_256(l_value)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
+        return ERROR_VALUE;
+    }
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str);
+    if (!l_fee_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -fee");
+        return ERROR_PARAM;
+    }
+    uint256_t l_fee = dap_chain_balance_scan(l_fee_str);
+    if (IS_ZERO_256(l_fee)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer");
+        return ERROR_VALUE;
+    }
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str);
+    if (!l_wallet_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -w");
+        return ERROR_PARAM;
+    }
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str);
     if (!l_tx_in_hash_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Refill command requires parameter -tx");
         return ERROR_PARAM;
     }
     dap_hash_fast_t l_tx_in_hash;
@@ -580,16 +795,66 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in ledger", l_tx_in_hash_str);
         return ERROR_VALUE;
     }
-    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str);
-    if (!l_value_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -value");
+
+
+    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
+    if (!l_wallet) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
+        return ERROR_VALUE;
+    }
+    const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
+    dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
+    dap_chain_wallet_close(l_wallet);
+
+    // Create conditional transaction for refill
+    dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_refilling_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_value, l_fee, &l_tx_in_hash, NULL);
+    DAP_DELETE(l_enc_key);
+    if (!l_tx) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for refill shared funds tx");
+        return ERROR_CREATE;
+    }
+    char *l_tx_hash_str = s_tx_put(l_tx, a_chain, a_hash_out_type);
+    DAP_DELETE(l_tx);
+    if (!l_tx_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PLACE, "Can't place transaction for refill shared funds tx in mempool");
+        return ERROR_PLACE;
+    }
+    json_object * l_json_obj_create_val = json_object_new_object();
+    json_object_object_add(l_json_obj_create_val, "status", json_object_new_string("success"));
+    if (dap_strcmp(l_sign_str, ""))
+        json_object_object_add(l_json_obj_create_val, "sign", json_object_new_string(l_sign_str));
+    json_object_object_add(l_json_obj_create_val, "tx_hash", json_object_new_string(l_tx_hash_str));
+    json_object_array_add(*a_json_arr_reply, l_json_obj_create_val);
+    DAP_DELETE(l_tx_hash_str);
+    return DAP_NO_ERROR;
+}
+
+static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
+{
+    const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL;
+    
+    uint256_t *l_value = NULL;
+    dap_chain_addr_t *l_to_addr = NULL;
+    uint32_t
+        l_addr_el_count = 0,  // not change type! use in batching TSD section
+        l_value_el_count = 0;
+    dap_list_t *l_tsd_list = NULL;
+    
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str);
+    if (!l_tx_in_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
         return ERROR_PARAM;
     }
-    uint256_t l_value = dap_chain_balance_scan(l_value_str);
-    if (IS_ZERO_256(l_value)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer>");
+    dap_hash_fast_t l_tx_in_hash;
+    if (dap_chain_hash_fast_from_str(l_tx_in_hash_str, &l_tx_in_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Can't recognize %s as a hex or base58 format hash", l_tx_in_hash_str);
+        return ERROR_VALUE;
+    }
+    if (!dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_tx_in_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in ledger", l_tx_in_hash_str);
         return ERROR_VALUE;
     }
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-fee", &l_fee_str);
     if (!l_fee_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -fee");
@@ -597,7 +862,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     }
     uint256_t l_fee = dap_chain_balance_scan(l_fee_str);
     if (IS_ZERO_256(l_fee)) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer>");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -fee <256 bit integer> and not equal zer");
         return ERROR_VALUE;
     }
 
@@ -614,21 +879,55 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
     const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
     dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
     dap_chain_wallet_close(l_wallet);
-    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-addr_to", &l_addr_str);
+
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-value", &l_value_str);
     if (!l_value_str) {
-        DAP_DELETE(l_enc_key);
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -addr_to");
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -value");
         return ERROR_PARAM;
     }
-    dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_str);
-    if (!l_addr) {
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-to_addr", &l_addr_str);
+    if (!l_addr_str) {
         DAP_DELETE(l_enc_key);
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Incorrect addr format for string %s", l_addr_str);
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -to_addr");
+        return ERROR_PARAM;
+    }
+
+    l_addr_el_count = dap_chain_addr_from_str_array(l_addr_str, &l_to_addr);
+    l_value_el_count = dap_str_symbol_count(l_value_str, ',') + 1;
+
+    if (l_addr_el_count != l_value_el_count) {
+        DAP_DELETE(l_to_addr);
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "num of '-to_addr' and '-value' should be equal");
         return ERROR_VALUE;
     }
-     // Create emission from conditional transaction
-    dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_addr, l_value, l_fee, &l_tx_in_hash, NULL);
-    DAP_DEL_MULTY(l_enc_key, l_addr);
+
+    l_value = DAP_NEW_Z_COUNT(uint256_t, l_value_el_count);
+    if (!l_value) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_MEMORY, c_error_memory_alloc);
+        return ERROR_MEMORY;
+    }
+    char **l_value_array = dap_strsplit(l_value_str, ",", l_value_el_count);
+    if (!l_value_array) {
+        DAP_DELETE(l_value);
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Can't read '-to_addr' arg");
+        return ERROR_PARAM;
+    }
+    for (size_t i = 0; i < l_value_el_count; ++i) {
+        l_value[i] = dap_chain_balance_scan(l_value_array[i]);
+        if(IS_ZERO_256(l_value[i])) {
+            DAP_DELETE(l_value);
+            dap_strfreev(l_value_array);
+            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Format -value <256 bit integer> and not equal zero");
+            return ERROR_VALUE;
+        }
+    }
+    dap_strfreev(l_value_array);
+
+    // Create emission from conditional transaction
+    
+    dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list);
+    DAP_DEL_MULTY(l_value, l_to_addr, l_enc_key);
+    dap_list_free_full(l_tsd_list, NULL);
     if (!l_tx) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_CREATE, "Can't compose transaction for delegated emission");
         return ERROR_CREATE;
@@ -651,7 +950,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object **
 
 static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
 {
-    const char *l_tx_in_hash_str = NULL, *l_wallet_str = NULL;
+    const char *l_tx_in_hash_str = NULL, *l_wallet_str = NULL, *l_cert_str = NULL;
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_in_hash_str);
     if (!l_tx_in_hash_str) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
@@ -667,19 +966,37 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "TX %s not found in mempool", l_tx_in_hash_str);
         return ERROR_VALUE;
     }
+
+    dap_enc_key_t *l_enc_key = NULL;
+    const char *l_sign_str = NULL;
+
     dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-w", &l_wallet_str);
-    if (!l_wallet_str) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -w");
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-cert", &l_cert_str);
+    if (!l_wallet_str && !l_cert_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation sign requires parameter -w or -cert");
         return ERROR_PARAM;
     }
-    dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
-    if (!l_wallet) {
-        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
-        return ERROR_VALUE;
+    if (l_wallet_str) {
+        dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config), NULL);
+        if (!l_wallet) {
+            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified wallet %s not found", l_wallet_str);
+            return ERROR_VALUE;
+        }
+        l_sign_str = dap_chain_wallet_check_sign(l_wallet);
+        l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
+        dap_chain_wallet_close(l_wallet);
+    } else if (l_cert_str) {
+        dap_cert_t *l_cert = dap_cert_find_by_name(l_cert_str);
+        if (!l_cert) {
+            dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Specified certificate %s not found", l_cert_str);
+            return ERROR_VALUE;
+        }
+        if (dap_sign_type_is_depricated(dap_sign_type_from_key_type(l_cert->enc_key->type)))
+            l_sign_str = "The Bliss, Picnic and Tesla signatures is deprecated. We recommend you to create a new wallet with another available signature and transfer funds there.\n";
+        else
+            l_sign_str = "";
+        l_enc_key = dap_cert_get_keys_from_certs(&l_cert, 1, 0);
     }
-    const char *l_sign_str = dap_chain_wallet_check_sign(l_wallet);
-    dap_enc_key_t *l_enc_key = dap_chain_wallet_get_key(l_wallet, 0);
-    dap_chain_wallet_close(l_wallet);
 
      // Create emission from conditional transaction
     dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_sign(*a_json_arr_reply, a_net, l_enc_key, (dap_chain_datum_tx_t *)l_tx_in->data);
@@ -707,6 +1024,70 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
     return DAP_NO_ERROR;
 }
 
+static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object **a_json_arr_reply, dap_chain_net_t *a_net, dap_chain_t *a_chain, const char *a_hash_out_type)
+{
+    const char *l_tx_hash_str = NULL, *l_wallet_str = NULL;
+    dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, a_argc, "-tx", &l_tx_hash_str);
+    if (!l_tx_hash_str) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Emitting delegation taking requires parameter -tx");
+        return ERROR_PARAM;
+    }
+    dap_hash_fast_t l_tx_hash;
+    if (dap_chain_hash_fast_from_str(l_tx_hash_str, &l_tx_hash)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Can't recognize %s as a hex or base58 format hash", l_tx_hash_str);
+        return ERROR_VALUE;
+    }
+    dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, &l_tx_hash, false);
+    dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_final_tx_hash);
+    dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, NULL);
+    if (!l_cond) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_TX_MISMATCH, "Can't find final tx_out_cond");
+        return ERROR_TX_MISMATCH;
+    }
+
+    const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_final_tx_hash);
+    const char *l_balance_coins, *l_balance_datoshi = dap_uint256_to_char(l_cond->header.value, &l_balance_coins);
+    
+    json_object *l_jobj_balance = json_object_new_object();
+    json_object *l_jobj_token = json_object_new_object();
+    json_object *l_jobj_take_verify = json_object_new_object();
+    json_object *l_jobj_pkey_hashes = json_object_new_array();
+    json_object *l_jobj_tags = json_object_new_array();
+    json_object *l_json_jobj_info = json_object_new_object();
+
+    bool l_is_base_hash_type = dap_strcmp(a_hash_out_type, "hex");
+    // tocken block
+    const char *l_description =  dap_ledger_get_description_by_ticker(a_net->pub.ledger, l_tx_ticker);
+    json_object *l_jobj_description = l_description ? json_object_new_string(l_description)
+                                                    : json_object_new_null();
+    json_object_object_add(l_jobj_token, "ticker", json_object_new_string(l_tx_ticker));
+    json_object_object_add(l_jobj_token, "description", l_jobj_description);
+    // balance block
+    json_object_object_add(l_jobj_balance, "coins", json_object_new_string(l_balance_coins));
+    json_object_object_add(l_jobj_balance, "datoshi", json_object_new_string(l_balance_datoshi));
+    // verify block
+    json_object_object_add(l_jobj_take_verify, "signs_minimum", json_object_new_uint64(l_cond->subtype.srv_emit_delegate.signers_minimum));
+    dap_tsd_t *l_tsd = NULL; size_t l_tsd_size = 0;
+    dap_tsd_iter(l_tsd, l_tsd_size, l_cond->tsd, l_cond->tsd_size) {
+        if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_HASH && l_tsd->size == sizeof(dap_hash_fast_t)) {
+            json_object_array_add(l_jobj_pkey_hashes, json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data) : dap_hash_fast_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data)));
+        }
+        if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_STR) {
+            json_object_array_add(l_jobj_tags, json_object_new_string((char*)(l_tsd->data)));
+        }
+    }
+    json_object_object_add(l_jobj_take_verify, "owner_hashes", l_jobj_pkey_hashes);
+    // result block
+    json_object_object_add(l_json_jobj_info, "tx_hash", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_tx_hash) : dap_hash_fast_to_str_static(&l_tx_hash)));
+    json_object_object_add(l_json_jobj_info, "tx_hash_final", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_final_tx_hash) : dap_hash_fast_to_str_static(&l_final_tx_hash)));
+    json_object_object_add(l_json_jobj_info, "tags", l_jobj_tags);
+    json_object_object_add(l_json_jobj_info, "balance", l_jobj_balance);
+    json_object_object_add(l_json_jobj_info, "take_verify", l_jobj_take_verify);
+    json_object_object_add(l_json_jobj_info, "token", l_jobj_token);
+    json_object_array_add(*a_json_arr_reply, l_json_jobj_info);
+    return DAP_NO_ERROR;
+}
+
 /**
  * @brief s_cli_stake_lock
  * @param a_argc
@@ -717,9 +1098,6 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object **
 static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply)
 {
     json_object **a_json_arr_reply = (json_object **)a_str_reply;
-    enum {
-        CMD_NONE, CMD_HOLD, CMD_TAKE, CMD_SIGN
-    };
     int l_arg_index = 1;
     dap_chain_net_t *l_net = NULL;
     dap_chain_t *l_chain = NULL;
@@ -727,7 +1105,7 @@ static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply)
     dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-H", &l_hash_out_type);
     if (!l_hash_out_type)
         l_hash_out_type = "hex";
-    else if (dap_strcmp(l_hash_out_type," hex") && dap_strcmp(l_hash_out_type, "base58")) {
+    else if (dap_strcmp(l_hash_out_type,"hex") && dap_strcmp(l_hash_out_type, "base58")) {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM,
                                 "Invalid parameter -H, valid values: -H <hex | base58>");
         return ERROR_PARAM;
@@ -736,13 +1114,21 @@ static int s_cli_emit_delegate(int a_argc, char **a_argv, void **a_str_reply)
     if (l_err_net_chain)
         return l_err_net_chain;
 
-    int l_cmd_num = CMD_NONE;
+    if (dap_chain_net_get_load_mode(l_net)) {
+        dap_json_rpc_error_add(*a_json_arr_reply, ERROR_NETWORK, "Can't apply command while network in load mode");
+        return ERROR_NETWORK;
+    }
+
     if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "hold", NULL))
         return s_cli_hold(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "refill", NULL))
+        return s_cli_refill(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
     else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "take", NULL))
         return s_cli_take(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
     else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "sign", NULL))
         return s_cli_sign(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
+    else if (dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, dap_min(a_argc, l_arg_index + 1), "info", NULL))
+        return s_cli_info(a_argc, a_argv, l_arg_index + 1, a_json_arr_reply, l_net, l_chain, l_hash_out_type);
     else {
         dap_json_rpc_error_add(*a_json_arr_reply, ERROR_SUBCOMMAND, "Subcommand %s not recognized", a_argv[l_arg_index]);
         return ERROR_SUBCOMMAND;
@@ -753,13 +1139,43 @@ int dap_chain_net_srv_emit_delegate_init()
 {
     dap_ledger_verificator_add(DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, s_emit_delegate_verificator, NULL, NULL);
     dap_cli_server_cmd_add("emit_delegate", s_cli_emit_delegate, "Emitting delegation service commands",
-                "emit_delegate hold -net <net_name> -w <wallet_name> -token <ticker> -value <value> -fee <value>"
-                            "-signs_minimum <value_int> -pkey_hashes <hash1[,hash2,...,hashN]> [-chain <chain_name>] [-H {hex(default) | base58}]\n"
-                "emit_delegate take -net <net_name> -w <wallet_name> -tx <transaction_hash> -addr_to <addr> -value <value> -fee <value> [-chain <chain_name>] [-H {hex(default) | base58}]\n"
-                "emit_delegate sign -net <net_name> -w <wallet_name> -tx <transaction_hash> [-chain <chain_name>] [-H {hex(default) | base58}]\n\n"
-                            "Hint:\n"
-                            "\texample value_coins (only natural) 1.0 123.4567\n"
-                            "\texample value_datoshi (only integer) 1 20 0.4321e+4\n"
+                "emit_delegate hold - to create new delegation\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> - wallet to writeoff value, pay fee and sign tx\n"
+                "\t-token <ticker> - token ticker to hold\n"
+                "\t-value <value> - value to hold\n"
+                "\t-fee <value> - fee value\n"
+                "\t-signs_minimum <value_int> - minimum signs count needed to verify take datum\n"
+                "\t-pkey_hashes <hash1[,hash2,...,hashN]> - owners pkey hashes, who can sign take datum\n"
+                "\t[-tag \"<str>\"] - additional info about tx\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate refill - to refill value\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> - wallet to writeoff value and pay fee\n"
+                "\t-value <value> - value to refill\n"
+                "\t-fee <value> - fee value\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to refill\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate take - create take datum to writeoff value from0 shared funds tx\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> - wallet to pay fee\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to writeoff\n"
+                "\t-to_addr <addr1[,addr2,...,addrN]> - recipient addresses, count should be equal values count\n"
+                "\t-value <value1[,value2,...,valueN]> - value sent to each recipient, count should be equal addresses count\n"
+                "\t-fee <value> - fee value\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate sign - add wallet sign to take datum\n"
+                "\t-net <net_name>\n"
+                "\t-w <wallet_name> | -cert <cert_name> - wallet or cert to sign\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to sign\n"
+                "\t[-H {hex(default) | base58}] - datum hash return format\n"
+                "emit_delegate info - get info about shared funds tx by hash\n"
+                "\t-net <net_name>\n"
+                "\t-tx <transaction_hash> - shared funds tx hash to get info\n"
+                "\t[-H {hex(default) | base58}] - tx hash format\n"
+                "Hint:\n"
+                "\texample value_coins (only natural) 1.0 123.4567\n"
+                "\texample value_datoshi (only integer) 1 20 0.4321e+4\n"
     );
 
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID };
diff --git a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
index 8cca1e2faa3dd7a585a89c9a4cbbd84f001b4f71..d0545c22eb66f6f010095f418facca464cf572c6 100644
--- a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
+++ b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h
@@ -2,6 +2,7 @@
 
 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID 0x07
 #define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF 0x14
+#define DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL 0x15
 
 #include "dap_chain_datum_tx.h"
 #include "dap_chain_mempool.h"
@@ -12,6 +13,8 @@ void dap_chain_net_srv_emit_delegate_deinit();
 
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_rweply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
-                                                dap_chain_addr_t *a_addr_to, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
+                                                dap_chain_addr_t *a_addr_to, uint256_t *a_value, uint32_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items);
+dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key,
+                                                    uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items);
 
 dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_sign(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, dap_chain_datum_tx_t *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 59320cec6de15245daecfc9701db163d7dd24cf3..73fe463d109981f771cd73ad912c6d9687ff4f20 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
@@ -135,17 +135,6 @@ static bool s_tag_check_key_delegation(dap_ledger_t *a_ledger, dap_chain_datum_t
     return false;
 }
 
-static dap_pkey_t *s_get_pkey_by_hash_callback(const uint8_t *a_hash)
-{
-    
-    dap_chain_net_srv_stake_item_t *l_stake = NULL;
-    for (dap_list_t *l_srv_stake_list = s_srv_stake_list; l_srv_stake_list && !l_stake; l_srv_stake_list = l_srv_stake_list->next) {
-        dap_chain_net_srv_stake_t *l_srv_stake = l_srv_stake_list->data;
-        HASH_FIND(hh, l_srv_stake->itemlist, a_hash, sizeof(dap_hash_fast_t), l_stake);
-    }
-    return l_stake ? l_stake->pkey : NULL; 
-}
-
 /**
  * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel
  * @return 0 if everything is okay, lesser then zero if errors
@@ -197,7 +186,6 @@ int dap_chain_net_srv_stake_pos_delegate_init()
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID };
     dap_ledger_service_add(l_uid, "pos_delegate", s_tag_check_key_delegation);
     s_debug_more = dap_config_get_item_bool_default(g_config, "stake", "debug_more", s_debug_more);
-    dap_sign_set_pkey_by_hash_callback(s_get_pkey_by_hash_callback);
     return 0;
 }
 
@@ -278,7 +266,7 @@ static int s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out
             log_it(L_WARNING, "Conditional out and conditional in have different headers");         \
             return -3;                                                                              \
         }                                                                                           \
-        if (l_tx_new_cond->tsd_size != a_cond->tsd_size ||                                          \
+        if (l_tx_new_cond->tsd_size < a_cond->tsd_size ||                                          \
                 memcmp(l_tx_new_cond->tsd, a_cond->tsd, a_cond->tsd_size)) {                        \
             log_it(L_WARNING, "Conditional out and conditional in have different TSD sections");    \
             return -4;                                                                              \
@@ -1172,9 +1160,7 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
     l_decree->header.common_decree_params.net_id = a_net->pub.id;
-    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
-    if (!l_chain)
-        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
+    dap_chain_t *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_DEL_Z(l_decree);
@@ -1237,9 +1223,7 @@ static dap_chain_datum_decree_t *s_decree_pkey_update(dap_chain_net_t *a_net, da
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
     l_decree->header.common_decree_params.net_id = a_net->pub.id;
-    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
-    if (!l_chain)
-        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
+    dap_chain_t *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_DEL_Z(l_decree);
@@ -1274,9 +1258,7 @@ static char *s_stake_decree_put(dap_chain_datum_decree_t *a_decree, dap_chain_ne
 {
     size_t l_decree_size = dap_chain_datum_decree_get_size(a_decree);
     dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_DECREE, a_decree, l_decree_size);
-    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE);
-    if (!l_chain)
-        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE);
+    dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE);
     if (!l_chain) {
         log_it(L_ERROR, "No chain supported decree datum type");
         return NULL;
@@ -1457,9 +1439,7 @@ static dap_chain_datum_decree_t *s_stake_decree_invalidate(dap_chain_net_t *a_ne
     l_decree->header.ts_created = dap_time_now();
     l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON;
     l_decree->header.common_decree_params.net_id = a_net->pub.id;
-    dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
-    if (!l_chain)
-        l_chain =  dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_ANCHOR);
+    dap_chain_t *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_DEL_Z(l_decree);
@@ -2225,8 +2205,9 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
             l_pkey = dap_pkey_get_from_str(l_pkey_full_str);
         } else {
             dap_hash_fast_t l_pkey_hash = {};
-            if (!dap_chain_hash_fast_from_str(l_pkey_str, &l_pkey_hash))
-                l_pkey = dap_ledger_find_pkey_by_hash(l_net->pub.ledger, &l_pkey_hash);
+            if (!dap_chain_hash_fast_from_str(l_pkey_str, &l_pkey_hash)) {
+                l_pkey = dap_chain_cs_blocks_get_pkey_by_hash(l_net, &l_pkey_hash);
+            }
         }
         if (!l_pkey) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "Invalid pkey string format, can't get pkey_full");
@@ -2236,12 +2217,14 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
         if (l_pkey->header.type.type != dap_pkey_type_from_sign_type(l_type).type) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "pkey and sign types is different");
             dap_enc_key_delete(l_enc_key);
+            DAP_DELETE(l_pkey);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
         }
         dap_chain_hash_fast_t l_hash_public_key = {0};
         if (!dap_pkey_get_hash(l_pkey, &l_hash_public_key)) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "Invalid pkey hash format");
             dap_enc_key_delete(l_enc_key);
+            DAP_DELETE(l_pkey);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR;
         }
         dap_chain_addr_fill(&l_signing_addr, l_type, &l_hash_public_key, l_net->pub.id);
@@ -2252,6 +2235,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
         if (dap_chain_node_addr_from_str(&l_node_addr, l_node_addr_str)) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_UNRECOGNIZED_ADDR_ERR, "Unrecognized node addr %s", l_node_addr_str);
             dap_enc_key_delete(l_enc_key);
+            DAP_DELETE(l_pkey);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_UNRECOGNIZED_ADDR_ERR;
         }
     }
@@ -2260,25 +2244,27 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
         if (!l_order) {
             dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_NO_ORDER_ERR, "Specified order not found");
             dap_enc_key_delete(l_enc_key);
+            DAP_DELETE(l_pkey);
             return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_NO_ORDER_ERR;
         }
         if (l_order->direction == SERV_DIR_BUY) { // Staker order
             if (!l_cert_str) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR, "Command 'delegate' requires parameter -cert with this order type");
                 dap_enc_key_delete(l_enc_key);
+                DAP_DELETE(l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_PARAM_ERR;
             }
             if (l_order->ext_size != 0) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_ORDER_SIZE_ERR, "Specified order has invalid size");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_ORDER_SIZE_ERR;
             }
             l_prev_tx = dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_order->tx_cond_hash);
             if (!l_prev_tx) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_NO_TX_IN_LEDGER_ERR, "The order's conditional transaction not found in ledger");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_NO_TX_IN_LEDGER_ERR;
             }
             int l_out_num = 0;
@@ -2286,13 +2272,13 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
             if (!l_cond) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_COND_TX_TYPE_ERR, "The order's conditional transaction has invalid type");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_COND_TX_TYPE_ERR;
             }
             if (dap_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_order->tx_cond_hash, l_out_num, NULL)) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_TX_ALREADY_SENT_ERR, "The order's conditional transaction is already spent");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_TX_ALREADY_SENT_ERR;
             }
             char l_delegated_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
@@ -2305,20 +2291,20 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
             if (l_cond->tsd_size != dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(true, 0)) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_COND_TX_FORMAT_ERR, "The order's conditional transaction has invalid format");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_COND_TX_FORMAT_ERR;
             }
             if (compare256(l_cond->header.value, l_order->price)) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_COND_TX_DIF_VALUE_ERR, "The order's conditional transaction has different value");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_COND_TX_DIF_VALUE_ERR;
             }
             if (!dap_chain_addr_is_blank(&l_cond->subtype.srv_stake_pos_delegate.signing_addr) ||
                     l_cond->subtype.srv_stake_pos_delegate.signer_node_addr.uint64) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_COND_TX_NO_ADDR_OR_KEY_ERR, "The order's conditional transaction gas not blank address or key");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_COND_TX_NO_ADDR_OR_KEY_ERR;
             }
             l_value = l_order->price;
@@ -2393,7 +2379,7 @@ static int s_cli_srv_stake_delegate(int a_argc, char **a_argv, int a_arg_index,
             if (dap_strcmp(l_order->price_ticker, l_delegated_ticker_str)) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_ORDER_ERR, "Specified order is invalid");
                 dap_enc_key_delete(l_enc_key);
-                DAP_DELETE(l_order);
+                DAP_DEL_MULTY(l_order, l_pkey);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_ORDER_ERR;
             }
             l_node_addr = l_order->node_addr;
@@ -2499,15 +2485,13 @@ static int s_cli_srv_stake_pkey_show(int a_argc, char **a_argv, int a_arg_index,
     // search in curren
     dap_chain_net_srv_stake_item_t *l_stake = NULL;
     HASH_FIND(hh, l_srv_stake->itemlist, &l_pkey_hash, sizeof(dap_hash_fast_t), l_stake);
-    dap_pkey_t *l_pkey = l_stake ? l_stake->pkey : NULL;
-    if (!l_pkey) {
-        l_pkey = dap_ledger_find_pkey_by_hash(l_net->pub.ledger, &l_pkey_hash);
-    }
+    dap_pkey_t *l_pkey = (l_stake && l_stake->pkey) ? DAP_DUP_SIZE(l_stake->pkey, dap_pkey_get_size(l_stake->pkey)) : dap_chain_cs_blocks_get_pkey_by_hash(l_net, &l_pkey_hash);
     if (!l_pkey) {
         dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_DELEGATE_INVALID_PKEY_ERR, "pkey not finded");
         return -25;
     }
     const char *l_pkey_str = dap_pkey_to_str(l_pkey, a_hash_out_type);
+    DAP_DELETE(l_pkey);
     json_object* l_json_obj_pkey = json_object_new_object();
     json_object_object_add(l_json_obj_pkey, "hash", json_object_new_string(l_pkey_hash_str));
     json_object_object_add(l_json_obj_pkey, "pkey", json_object_new_string(l_pkey_str));
@@ -3523,6 +3507,13 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                     json_object_object_add(l_json_obj_tx, "node_address", json_object_new_string(l_node_address_text_block));
                     json_object_object_add(l_json_obj_tx, "value_coins", json_object_new_string(l_coins));
                     json_object_object_add(l_json_obj_tx, "value_datoshi", json_object_new_string(l_balance));
+                    dap_hash_fast_t l_owner_hash = dap_ledger_get_first_chain_tx_hash(l_net->pub.ledger, l_datum_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE);
+                    dap_chain_datum_tx_t *l_owner_tx = dap_hash_fast_is_blank(&l_owner_hash) ? l_datum_tx
+                                                                                             : dap_ledger_tx_find_datum_by_hash(l_net->pub.ledger, &l_owner_hash, NULL, false);
+                    assert(l_owner_tx);
+                    dap_sign_t *l_owner_sign = dap_chain_datum_tx_get_sign(l_owner_tx, 0);
+                    dap_chain_addr_t l_owner_addr; dap_chain_addr_fill_from_sign(&l_owner_addr, l_owner_sign, l_net->pub.id);
+                    json_object_object_add(l_json_obj_tx, "owner_addr", json_object_new_string(dap_chain_addr_to_str_static(&l_owner_addr)));
                     json_object_array_add(l_json_arr_tx, l_json_obj_tx);
                     DAP_DELETE(l_node_address_text_block);
                 }
@@ -3550,9 +3541,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_NET_ERR, "Network %s not found", l_net_str);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_NET_ERR;
             }
-            dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
-            if (!l_chain)
-                l_chain =  dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
+            dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
             if (!l_chain) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_ANCHOR_NOT_SUPPORT_ERR, "No chain supported anchor datum type");
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_ANCHOR_NOT_SUPPORT_ERR;
@@ -3614,9 +3603,7 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, void **a_str_reply)
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_NET_ERR, "Network %s not found", l_net_str);
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_NET_ERR;
             }
-            dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
-            if (!l_chain)
-                l_chain =  dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
+            dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(l_net, CHAIN_TYPE_ANCHOR);
             if (!l_chain) {
                 dap_json_rpc_error_add(*a_json_arr_reply, DAP_CHAIN_NODE_CLI_SRV_STAKE_ANCHOR_NOT_SUPPORT_ERR, "No chain supported anchor datum type");
                 return DAP_CHAIN_NODE_CLI_SRV_STAKE_ANCHOR_NOT_SUPPORT_ERR;
@@ -4149,3 +4136,17 @@ size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_
     }
     return l_total_count;
 }
+
+/**
+ * @brief search pkey by hash in delegate table
+ * @param a_net_id net id to search
+ * @param a_hash hash to search
+ * @return pointer to pkey, NULL if error
+ */
+dap_pkey_t *dap_chain_net_srv_stake_get_pkey_by_hash(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_hash)
+{
+    dap_chain_net_srv_stake_t*l_srv_stake = s_srv_stake_by_net_id(a_net_id);
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    HASH_FIND(hh, l_srv_stake->itemlist, a_hash, sizeof(dap_hash_fast_t), l_stake);
+    return l_stake ? l_stake->pkey : 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 3fb0c4e77b259aef36b48a81cb8b34e41756793f..0598e89482123ba586fa31c9395cea25cac9f86b 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
@@ -104,3 +104,4 @@ int dap_chain_net_srv_stake_mark_validator_active(dap_chain_addr_t *a_signing_ad
 dap_chain_net_srv_stake_item_t *dap_chain_net_srv_stake_check_pkey_hash(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_pkey_hash);
 uint256_t dap_chain_net_srv_stake_get_total_weight(dap_chain_net_id_t a_net_id, uint256_t *a_locked_weight);
 size_t dap_chain_net_srv_stake_get_total_keys(dap_chain_net_id_t a_net_id, size_t *a_in_active_count);
+dap_pkey_t *dap_chain_net_srv_stake_get_pkey_by_hash(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_hash);
diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c
index c74cf6fd33c9b20d697e37c1b38737aa0dad1006..fb8f37c799ba841765a9fc03eb37fc23757f4fda 100644
--- a/modules/service/voting/dap_chain_net_srv_voting.c
+++ b/modules/service/voting/dap_chain_net_srv_voting.c
@@ -50,6 +50,7 @@ typedef struct dap_chain_net_voting_params_offsets{
     uint64_t votes_max_count;
     bool delegate_key_required;
     bool vote_changing_allowed;
+    char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
 } dap_chain_net_voting_params_offsets_t;
 
 typedef struct dap_chain_net_vote_option {
@@ -60,7 +61,7 @@ typedef struct dap_chain_net_vote_option {
 typedef struct dap_chain_net_voting_cond_outs {
     dap_chain_hash_fast_t tx_hash;
     int out_idx;
-
+    dap_hash_fast_t pkey_hash;
     UT_hash_handle hh;
 } dap_chain_net_voting_cond_outs_t;
 
@@ -86,9 +87,10 @@ typedef struct dap_chain_net_votings {
 static dap_chain_net_votings_t *s_votings;
 static pthread_rwlock_t s_votings_rwlock;
 
-static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_cond_hash, int a_cond_out_idx);
+static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_cond_hash, int a_cond_out_idx, dap_hash_fast_t *a_vote_hash);
 /// -1 error, 0 - unspent, 1 - spent
-static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_prev_hash, int a_out_idx, dap_hash_fast_t *a_pkey_hash);
+static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash,
+                                              dap_hash_fast_t a_tx_prev_hash, int a_out_idx, dap_hash_fast_t *a_pkey_hash);
 static int s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply);
 static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in);
 static int s_cli_voting(int argc, char **argv, void **a_str_reply);
@@ -114,15 +116,19 @@ int dap_chain_net_srv_voting_init()
 {
     pthread_rwlock_init(&s_votings_rwlock, NULL);
     dap_chain_ledger_voting_verificator_add(s_datum_tx_voting_verification_callback, s_datum_tx_voting_verification_delete_callback);
-    dap_cli_server_cmd_add("voting", s_cli_voting, "Voting commands.", ""
-                            "voting create -net <net_name> -question <\"Question_string\"> -options <\"Option0\", \"Option1\" ... \"OptionN\"> [-expire <voting_expire_time_in_RCF822>] [-max_votes_count <Votes_count>] [-delegated_key_required] [-vote_changing_allowed] -fee <value_datoshi> -w <fee_wallet_name>\n"
-                            "voting vote -net <net_name> -hash <voting_hash> -option_idx <option_index> [-cert <delegate_cert_name>] -fee <value_datoshi> -w <fee_wallet_name>\n"
-                            "voting list -net <net_name>\n"
-                            "voting dump -net <net_name> -hash <voting_hash>\n");
-
-    
+    dap_cli_cmd_t *l_poll_cmd = dap_cli_server_cmd_add(
+                "poll", s_cli_voting, "Voting/poll commands",
+                            "poll create -net <net_name> -question <\"Question_string\"> -options <\"Option0\", \"Option1\" ... \"OptionN\"> [-expire <poll_expire_time_in_RCF822>]"
+                                           " [-max_votes_count <Votes_count>] [-delegated_key_required] [-vote_changing_allowed] -fee <value_datoshi> -w <fee_wallet_name> [-token <ticker>]\n"
+                            "poll vote -net <net_name> -hash <poll_hash> -option_idx <option_index> [-cert <delegate_cert_name>] -fee <value_datoshi> -w <fee_wallet_name>\n"
+                            "poll list -net <net_name>\n"
+                            "poll dump -net <net_name> -hash <poll_hash>\n"
+                            "Hint:\n"
+                            "\texample value_coins (only natural) 1.0 123.4567\n"
+                            "\texample value_datoshi (only integer) 1 20 0.4321e+4\n");
+    dap_cli_server_alias_add(l_poll_cmd, NULL, "voting");
     dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VOTING_ID };
-    dap_ledger_service_add(l_uid, "voting", s_tag_check_voting);
+    dap_ledger_service_add(l_uid, "poll", s_tag_check_voting);
 
     return 0;
 }
@@ -146,7 +152,7 @@ uint64_t* dap_chain_net_voting_get_result(dap_ledger_t* a_ledger, dap_chain_hash
     pthread_rwlock_unlock(&s_votings_rwlock);
     if(!l_voting || l_voting->net_id.uint64 != a_ledger->net->pub.id.uint64){
         char* l_hash_str = dap_hash_fast_to_str_new(a_voting_hash);
-        log_it(L_ERROR, "Can't find voting with hash %s in net %s", l_hash_str, a_ledger->net->pub.name);
+        log_it(L_ERROR, "Can't find poll with hash %s in net %s", l_hash_str, a_ledger->net->pub.name);
         DAP_DEL_Z(l_hash_str);
         return NULL;
     }
@@ -172,7 +178,6 @@ uint64_t* dap_chain_net_voting_get_result(dap_ledger_t* a_ledger, dap_chain_hash
     return l_voting_results;
 }
 
-
 static int s_voting_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply)
 {
     if (!a_apply) {
@@ -181,7 +186,7 @@ static int s_voting_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t
         HASH_FIND(hh, s_votings, a_tx_hash, sizeof(dap_hash_fast_t), l_voting);
         pthread_rwlock_unlock(&s_votings_rwlock);
         if (l_voting && l_voting->net_id.uint64 == a_ledger->net->pub.id.uint64) {
-            log_it(L_DEBUG, "Voting with hash %s is already presents in net %s",  dap_hash_fast_to_str_static(a_tx_hash), a_ledger->net->pub.name);
+            log_it(L_DEBUG, "Poll with hash %s is already presents in net %s",  dap_hash_fast_to_str_static(a_tx_hash), a_ledger->net->pub.name);
             return -1;
         }
 
@@ -203,7 +208,7 @@ static int s_voting_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t
         dap_list_free(l_tsd_list);
 
         if (!l_question_len || !l_options_count) {
-            log_it(L_WARNING, "Voting with hash %s contain no question or answer options", dap_hash_fast_to_str_static(a_tx_hash));
+            log_it(L_WARNING, "Poll with hash %s contain no question or answer options", dap_hash_fast_to_str_static(a_tx_hash));
             return -2;
         }
 
@@ -218,14 +223,29 @@ static int s_voting_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t
 
     dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL);
     for (dap_list_t *it = l_tsd_list; it; it = it->next) {
-        dap_tsd_t* l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)it->data)->tsd;
+        dap_chain_tx_tsd_t *l_tx_tsd = it->data;
+        dap_tsd_t *l_tsd = (dap_tsd_t *)l_tx_tsd->tsd;
+        if (l_tx_tsd->header.size < sizeof(dap_tsd_t) ||
+                l_tx_tsd->header.size != dap_tsd_size(l_tsd)) {
+            log_it(L_WARNING, "Incorrect size %" DAP_UINT64_FORMAT_U " of TX_TSD item for poll %s",
+                   l_tx_tsd->header.size, dap_hash_fast_to_str_static(a_tx_hash));
+            return -DAP_LEDGER_CHECK_INVALID_SIZE;
+        }
         dap_chain_net_vote_option_t *l_vote_option = NULL;
         switch(l_tsd->type){
         case VOTING_TSD_TYPE_QUESTION:
+            if (!l_tsd->size) {
+                log_it(L_WARNING, "Incorrect size %u of TSD section QUESTION for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                return -DAP_LEDGER_CHECK_INVALID_SIZE;
+            }
             l_item->voting_params.voting_question_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx);
             l_item->voting_params.voting_question_length = l_tsd->size;
             break;
         case VOTING_TSD_TYPE_ANSWER:
+            if (!l_tsd->size) {
+                log_it(L_WARNING, "Incorrect size %u of TSD section ANSWER for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                return -DAP_LEDGER_CHECK_INVALID_SIZE;
+            }
             l_vote_option = DAP_NEW_Z(dap_chain_net_vote_option_t);
             l_vote_option->vote_option_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx);
             l_vote_option->vote_option_length = l_tsd->size;
@@ -233,41 +253,50 @@ static int s_voting_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t
             break;
         case VOTING_TSD_TYPE_EXPIRE:
             if (l_tsd->size != sizeof(dap_time_t)) {
-                log_it(L_WARNING, "Incorrect size %u of TSD section EXPIRE vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                log_it(L_WARNING, "Incorrect size %u of TSD section EXPIRE for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
                 return -DAP_LEDGER_CHECK_INVALID_SIZE;
             }
             l_item->voting_params.voting_expire = *(dap_time_t *)l_tsd->data;
             break;
         case VOTING_TSD_TYPE_MAX_VOTES_COUNT:
             if (l_tsd->size != sizeof(uint64_t)) {
-                log_it(L_WARNING, "Incorrect size %u of TSD section MAX_VOTES_COUNT vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                log_it(L_WARNING, "Incorrect size %u of TSD section MAX_VOTES_COUNT for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
                 return -DAP_LEDGER_CHECK_INVALID_SIZE;
             }
             l_item->voting_params.votes_max_count = *(uint64_t *)l_tsd->data;
             break;
         case VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED:
             if (l_tsd->size != sizeof(byte_t)) {
-                log_it(L_WARNING, "Incorrect size %u of TSD section DELEGATED_KEY_REQUIRED vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                log_it(L_WARNING, "Incorrect size %u of TSD section DELEGATED_KEY_REQUIRED for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
                 return -DAP_LEDGER_CHECK_INVALID_SIZE;
             }
             l_item->voting_params.delegate_key_required = *(byte_t *)l_tsd->data;
             break;
         case VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED:
             if (l_tsd->size != sizeof(byte_t)) {
-                log_it(L_WARNING, "Incorrect size %u of TSD section VOTE_CHANGING_ALLOWED vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                log_it(L_WARNING, "Incorrect size %u of TSD section VOTE_CHANGING_ALLOWED for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
                 return -DAP_LEDGER_CHECK_INVALID_SIZE;
             }
             l_item->voting_params.vote_changing_allowed = *(byte_t *)l_tsd->data;
             break;
+        case VOTING_TSD_TYPE_TOKEN:
+            if (!l_tsd->size || l_tsd->size >= DAP_CHAIN_TICKER_SIZE_MAX) {
+                log_it(L_WARNING, "Incorrect size %u of TSD section TOKEN for poll %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash));
+                return -DAP_LEDGER_CHECK_INVALID_SIZE;
+            }
+            strcpy(l_item->voting_params.token_ticker, (char *)l_tsd->data);
         default:
             break;
         }
     }
     dap_list_free(l_tsd_list);
 
+    if (!*l_item->voting_params.token_ticker)
+        strcpy(l_item->voting_params.token_ticker, a_ledger->net->pub.native_ticker);
     pthread_rwlock_wrlock(&s_votings_rwlock);
     HASH_ADD(hh, s_votings, voting_hash, sizeof(dap_hash_fast_t), l_item);
     pthread_rwlock_unlock(&s_votings_rwlock);
+    log_it(L_NOTICE, "Poll with hash %s succefully added to ledger", dap_hash_fast_to_str_static(a_tx_hash));
     return DAP_LEDGER_CHECK_OK;
 }
 
@@ -284,88 +313,62 @@ static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a
     HASH_FIND(hh, s_votings, &l_vote_tx_item->voting_hash, sizeof(dap_hash_fast_t), l_voting);
     pthread_rwlock_unlock(&s_votings_rwlock);
     if (!l_voting || l_voting->net_id.uint64 != a_ledger->net->pub.id.uint64) {
-        log_it(L_ERROR, "Can't find voting with hash %s in net %s",
+        log_it(L_ERROR, "Can't find poll with hash %s in net %s",
                dap_chain_hash_fast_to_str_static(&l_vote_tx_item->voting_hash), a_ledger->net->pub.name);
         return -5;
     }
 
-    dap_hash_fast_t pkey_hash = {};
-    int l_item_cnt = 0;
-    dap_list_t *l_signs_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_SIG, &l_item_cnt);
-
-    if (!l_signs_list) {
-        log_it(L_WARNING, "Can't get signs from tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash));
-        return -9;
+    // Get last sign item from transaction
+    dap_hash_fast_t l_pkey_hash = {};
+    dap_sign_t *l_pkey_sign = NULL;
+    uint8_t *l_tx_item = NULL; size_t l_size; int i, l_sign_num = 0;
+    TX_ITEM_ITER_TX_TYPE(l_tx_item, TX_ITEM_TYPE_SIG, l_size, i, a_tx_in) {
+        l_pkey_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_item);
+        l_sign_num++;
+    }
+    dap_sign_get_pkey_hash(l_pkey_sign, &l_pkey_hash);
+    if (--l_sign_num && dap_chain_datum_tx_verify_sign(a_tx_in, l_sign_num)) {
+        log_it(L_WARNING, "Last vote tx %s sign verification failed", dap_chain_hash_fast_to_str_static(a_tx_hash));
+        return -22;
     }
-    dap_chain_tx_sig_t *l_vote_sig = (dap_chain_tx_sig_t *)(dap_list_last(l_signs_list)->data);
-    dap_sign_get_pkey_hash((dap_sign_t*)l_vote_sig->sig, &pkey_hash);
-    dap_list_free(l_signs_list);
 
-    if (!a_apply) {
-        if (l_vote_tx_item->answer_idx > dap_list_length(l_voting->voting_params.option_offsets_list)) {
-            log_it(L_WARNING, "Invalid vote option index %" DAP_UINT64_FORMAT_U " for vote tx %s",
-                                                    l_vote_tx_item->answer_idx, dap_chain_hash_fast_to_str_static(a_tx_hash));
-            return -6;
-        }
-        if (l_voting->voting_params.votes_max_count && dap_list_length(l_voting->votes) >= l_voting->voting_params.votes_max_count){
-            log_it(L_WARNING, "The required number of votes has been collected for voting %s", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash));
-            return -7;
-        }
-        if (l_voting->voting_params.voting_expire && l_voting->voting_params.voting_expire <= a_tx_in->header.ts_created) {
-            log_it(L_WARNING, "The voting %s has been expired", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash));
-            return -8;
-        }
-
-        if (l_voting->voting_params.delegate_key_required &&
-                !dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &pkey_hash)){
-            log_it(L_WARNING, "Voting %s required a delegated key", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash));
-            return -10;
-        }
-
-        for (dap_list_t *it = l_voting->votes; it; it = it->next) {
-            if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &pkey_hash)) {
-                dap_hash_fast_t *l_vote_hash = &((dap_chain_net_vote_t *)it->data)->vote_hash;
-                if (!l_voting->voting_params.vote_changing_allowed) {
-                    char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE];
-                    dap_hash_fast_to_str(l_vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE);
-                    log_it(L_WARNING, "The voting %s don't allow change your vote %s",
-                           dap_hash_fast_to_str_static(&l_voting->voting_hash), l_vote_hash_str);
-                    return -11;
-                }
-                break;
-            }
-        }
+    if (l_vote_tx_item->answer_idx > dap_list_length(l_voting->voting_params.option_offsets_list)) {
+        log_it(L_WARNING, "Invalid vote option index %" DAP_UINT64_FORMAT_U " for vote tx %s",
+                                                l_vote_tx_item->answer_idx, dap_chain_hash_fast_to_str_static(a_tx_hash));
+        return -6;
+    }
+    if (l_voting->voting_params.votes_max_count && dap_list_length(l_voting->votes) >= l_voting->voting_params.votes_max_count){
+        log_it(L_WARNING, "The required number of votes has been collected for poll %s", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash));
+        return -7;
+    }
+    if (l_voting->voting_params.voting_expire && l_voting->voting_params.voting_expire <= a_tx_in->header.ts_created) {
+        log_it(L_WARNING, "The voting %s has been expired", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash));
+        return -8;
     }
 
-    uint256_t l_weight = {};
+    if (l_voting->voting_params.delegate_key_required &&
+            !dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &l_pkey_hash)){
+        log_it(L_WARNING, "Poll %s required a delegated key", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash));
+        return -10;
+    }
 
-    // check out conds
-    dap_list_t *l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL);
-    for (dap_list_t *it = l_tsd_list; it; it = it->next) {
-        dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)it->data)->tsd;
-        dap_hash_fast_t l_hash = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash;
-        int l_out_idx = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->out_idx;
-        if (l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND) {
-            if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, l_vote_tx_item->voting_hash, l_hash, l_out_idx))
-                continue;
-            dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_hash);
-            dap_chain_tx_out_cond_t *l_prev_out = (dap_chain_tx_out_cond_t*)dap_chain_datum_tx_item_get(l_tx_prev_temp, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_COND, NULL);
-            if (!l_prev_out || l_prev_out->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK)
-                continue;
-            if (SUM_256_256(l_weight, l_prev_out->header.value, &l_weight)) {
-                log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash));
-                return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
+    dap_list_t *l_old_vote = NULL;
+    for (dap_list_t *it = l_voting->votes; it; it = it->next) {
+        if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &l_pkey_hash)) {
+            dap_hash_fast_t *l_vote_hash = &((dap_chain_net_vote_t *)it->data)->vote_hash;
+            if (!l_voting->voting_params.vote_changing_allowed) {
+                char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE];
+                dap_hash_fast_to_str(l_vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE);
+                log_it(L_WARNING, "The poll %s don't allow change your vote %s",
+                       dap_hash_fast_to_str_static(&l_voting->voting_hash), l_vote_hash_str);
+                return -11;
             }
-
-            dap_chain_net_voting_cond_outs_t *l_item = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_net_voting_cond_outs_t, -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY);
-            l_item->tx_hash = l_hash;
-            l_item->out_idx = l_out_idx;
-            pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock);
-            HASH_ADD(hh, l_voting->voting_spent_cond_outs, tx_hash, sizeof(dap_hash_fast_t), l_item);
-            pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock);
+            l_old_vote = it;
+            break;
         }
     }
-    dap_list_free(l_tsd_list);
+
+    uint256_t l_weight = {};
     // check inputs
     dap_list_t *l_ins_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_IN, NULL);
     if (!l_ins_list) {
@@ -374,17 +377,35 @@ static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a
     }
     for (dap_list_t *it = l_ins_list; it; it = it->next) {
         dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)it->data;
-        if (!s_datum_tx_voting_coin_check_spent(a_ledger->net, l_vote_tx_item->voting_hash,
-                                                l_tx_in->header.tx_prev_hash, l_tx_in->header.tx_out_prev_idx, &pkey_hash)) {
-            dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_tx_in->header.tx_prev_hash);
-            dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t *)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_tx_in->header.tx_out_prev_idx);
-            if (!l_prev_out_union)
-                continue;
-            if ((l_prev_out_union->header.type == TX_ITEM_TYPE_OUT || l_prev_out_union->header.type == TX_ITEM_TYPE_OUT_EXT) &&
-                    SUM_256_256(l_weight, l_prev_out_union->header.value, &l_weight)) {
-                log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash));
-                return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
-            }
+        dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_tx_in->header.tx_prev_hash);
+        dap_chain_tx_out_ext_t *l_prev_out_union = (dap_chain_tx_out_ext_t *)dap_chain_datum_tx_out_get_by_out_idx(
+                                                    l_tx_prev_temp, l_tx_in->header.tx_out_prev_idx);
+        if (!l_prev_out_union)
+            return -18;
+        const char *l_ticker_in = NULL;
+        switch (l_prev_out_union->header.type) {
+        case TX_ITEM_TYPE_OUT:
+            l_ticker_in = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_in->header.tx_prev_hash);
+            break;
+        case TX_ITEM_TYPE_OUT_EXT:
+            l_ticker_in = l_prev_out_union->token;
+            break;
+        default:
+            log_it(L_WARNING, "Unexpected tx item %d in vote tx %s", l_prev_out_union->header.type, dap_hash_fast_to_str_static(a_tx_hash));
+            return -19;
+        }
+        if (dap_strcmp(l_ticker_in, l_voting->voting_params.token_ticker))
+            continue;
+        if (s_datum_tx_voting_coin_check_spent(a_ledger->net, l_vote_tx_item->voting_hash,
+                                               l_tx_in->header.tx_prev_hash, l_tx_in->header.tx_out_prev_idx,
+                                               l_old_vote ? &l_pkey_hash : NULL)) {
+            log_it(L_WARNING, "Coin with out number %u for tx %s is spent for poll %s", l_tx_in->header.tx_out_prev_idx,
+                                        dap_hash_fast_to_str_static(a_tx_hash), dap_hash_fast_to_str_static(&l_vote_tx_item->voting_hash));
+            return -20;
+        }
+        if (SUM_256_256(l_weight, l_prev_out_union->header.value, &l_weight)) {
+            log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash));
+            return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
         }
     }
     dap_list_free(l_ins_list);
@@ -394,62 +415,76 @@ static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a
         return -13;
     }
 
+    // check out conds
+    dap_list_t *l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL);
+    for (dap_list_t *it = l_tsd_list; it; it = it->next) {
+        dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)it->data)->tsd;
+        dap_hash_fast_t l_hash = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash;
+        int l_out_idx = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->out_idx;
+        if (l_tsd->type != VOTING_TSD_TYPE_VOTE_TX_COND)
+            return -14;
+        dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_hash);
+        dap_chain_tx_out_cond_t *l_prev_out = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_out_idx);
+        if (!l_prev_out || l_prev_out->header.item_type != TX_ITEM_TYPE_OUT_COND ||
+                l_prev_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE)
+            return -16;
+        if (!dap_ledger_check_condition_owner(a_ledger, &l_hash, l_prev_out->header.subtype, l_out_idx, l_pkey_sign))
+            return -17;
+        if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, l_vote_tx_item->voting_hash, l_hash, l_out_idx,
+                                                  l_old_vote ? &l_pkey_hash : NULL))
+            return -15;
+        if (SUM_256_256(l_weight, l_prev_out->header.value, &l_weight)) {
+            log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash));
+            return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW;
+        }
+    }
+
     if (a_apply) {
+        // Mark conditional outs
+        pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock);
+        if (l_old_vote) {
+            dap_hash_fast_t *l_vote_hash = &((dap_chain_net_vote_t *)l_old_vote->data)->vote_hash;
+            dap_chain_net_voting_cond_outs_t *it = NULL, *tmp;
+            HASH_ITER(hh, l_voting->voting_spent_cond_outs, it, tmp) {
+                if (!dap_hash_fast_compare(l_vote_hash, &it->pkey_hash))
+                    continue;
+                HASH_DEL(l_voting->voting_spent_cond_outs, it);
+                DAP_DELETE(it);
+            }
+        }
+        for (dap_list_t *it = l_tsd_list; it; it = it->next) {
+            dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)it->data)->tsd;
+            if (l_tsd->type != VOTING_TSD_TYPE_VOTE_TX_COND)
+                continue;
+            dap_chain_net_voting_cond_outs_t *l_tx_out = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_net_voting_cond_outs_t, -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY);
+            l_tx_out->tx_hash = ((dap_chain_tx_voting_tx_cond_t *)l_tsd->data)->tx_hash;
+            l_tx_out->out_idx = ((dap_chain_tx_voting_tx_cond_t *)l_tsd->data)->out_idx;
+            l_tx_out->pkey_hash = l_pkey_hash;
+            HASH_ADD(hh, l_voting->voting_spent_cond_outs, tx_hash, sizeof(dap_hash_fast_t), l_tx_out);
+        }
+        pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock);
+
         dap_chain_net_vote_t *l_vote_item = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_net_vote_t, -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY);
         l_vote_item->vote_hash = *a_tx_hash;
-        l_vote_item->pkey_hash = pkey_hash;
+        l_vote_item->pkey_hash = l_pkey_hash;
         l_vote_item->answer_idx = l_vote_tx_item->answer_idx;
         l_vote_item->weight = l_weight;
 
-        // cycle is safe cause return after link deletion
-        for (dap_list_t *it = l_voting->votes; it; it = it->next) {
-            if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &pkey_hash)){
-                if (!l_voting->voting_params.vote_changing_allowed) {
-                    char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE];
-                    dap_hash_fast_to_str(a_tx_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE);
-                    log_it(L_WARNING, "The voting %s don't allow change your vote %s",
-                           dap_hash_fast_to_str_static(&l_voting->voting_hash), l_vote_hash_str);
-                    DAP_DELETE(l_vote_item);
-                    return -11;
-                }
-                dap_hash_fast_t *l_vote_hash = &((dap_chain_net_vote_t *)it->data)->vote_hash;
-                //delete conditional outputs
-                dap_chain_datum_tx_t *l_old_tx = dap_ledger_tx_find_by_hash(a_ledger, l_vote_hash);
-                if (!l_old_tx) {
-                    char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE];
-                    dap_hash_fast_to_str(l_vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE);
-                    log_it(L_ERROR, "Can't find old vote %s of voting %s in ledger",
-                           l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash));
-                }
-                dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(l_old_tx, TX_ITEM_TYPE_TSD, NULL);
-                for (dap_list_t *it_tsd = l_tsd_list; it_tsd; it_tsd = it_tsd->next) {
-                    dap_tsd_t* l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)it_tsd->data)->tsd;
-                    dap_hash_fast_t *l_hash = &((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash;
-                    if (l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND) {
-                        dap_chain_net_voting_cond_outs_t *l_tx_outs = NULL;
-                        pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock);
-                        HASH_FIND(hh, l_voting->voting_spent_cond_outs, l_hash, sizeof(dap_hash_fast_t), l_tx_outs);
-                        if(l_tx_outs)
-                            HASH_DELETE(hh, l_voting->voting_spent_cond_outs, l_tx_outs);
-                        pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock);
-                    }
-                }
-                dap_list_free(l_tsd_list);
-                // change vote & move it to the end of list
-                l_voting->votes = dap_list_remove_link(l_voting->votes, it);
-                l_voting->votes = dap_list_append(l_voting->votes, l_vote_item);
-                char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE];
-                dap_hash_fast_to_str(&((dap_chain_net_vote_t *)it->data)->vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE);
-                DAP_DELETE(it->data);
-                log_it(L_INFO, "Vote %s of voting %s has been changed", l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash));
-                return DAP_LEDGER_CHECK_OK;
-            }
+        if (l_old_vote) {
+            // change vote & move it to the end of list
+            const char *l_vote_hash_str = dap_hash_fast_to_str_static(&((dap_chain_net_vote_t *)l_old_vote->data)->vote_hash);
+            DAP_DELETE(l_old_vote->data);
+            l_voting->votes = dap_list_delete_link(l_voting->votes, l_old_vote);
+            log_it(L_NOTICE, "Vote %s of poll %s has been changed", l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash));
+        } else {
+            const char *l_vote_hash_str = dap_hash_fast_to_str_static(a_tx_hash);
+            log_it(L_NOTICE, "Vote %s of poll %s has been accepted", l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash));
         }
+
         l_voting->votes = dap_list_append(l_voting->votes, l_vote_item);
-        char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE];
-        dap_hash_fast_to_str(a_tx_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE);
-        log_it(L_INFO, "Vote %s of voting %s has been accepted", l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash));
     }
+    dap_list_free(l_tsd_list);
+
     return DAP_LEDGER_CHECK_OK;
 }
 
@@ -459,7 +494,7 @@ int s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_tx
         return s_voting_verificator(a_ledger, a_type, a_tx_in, a_tx_hash, a_apply);
     if (a_type == TX_ITEM_TYPE_VOTE)
         return s_vote_verificator(a_ledger, a_type, a_tx_in, a_tx_hash, a_apply);
-    log_it(L_ERROR, "Item %d is not supported in votings", a_type);
+    log_it(L_ERROR, "Item %d is not supported in polls", a_type);
     return -3;
 }
 
@@ -474,7 +509,7 @@ static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledge
         HASH_FIND(hh, s_votings, &l_hash, sizeof(dap_hash_fast_t), l_voting);
         if(!l_voting){
             char* l_hash_str = dap_hash_fast_to_str_new(&l_hash);
-            log_it(L_ERROR, "Can't find voting with hash %s in net %s", l_hash_str, a_ledger->net->pub.name);
+            log_it(L_ERROR, "Can't find poll with hash %s in net %s", l_hash_str, a_ledger->net->pub.name);
             DAP_DEL_Z(l_hash_str);
             pthread_rwlock_unlock(&s_votings_rwlock);
             return false;
@@ -508,13 +543,13 @@ static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledge
             return false;
         }
 
-        dap_chain_net_votings_t * l_voting = NULL;
+        dap_chain_net_votings_t *l_voting = NULL;
         pthread_rwlock_wrlock(&s_votings_rwlock);
         HASH_FIND(hh, s_votings, &l_vote_tx_item->voting_hash, sizeof(dap_hash_fast_t), l_voting);
         pthread_rwlock_unlock(&s_votings_rwlock);
         if(!l_voting || l_voting->net_id.uint64 != a_ledger->net->pub.id.uint64) {
             char *l_hash_str = dap_chain_hash_fast_to_str_new(&l_hash);
-            log_it(L_ERROR, "Can't find voting with hash %s in net %s", l_hash_str, a_ledger->net->pub.name);
+            log_it(L_ERROR, "Can't find poll with hash %s in net %s", l_hash_str, a_ledger->net->pub.name);
             DAP_DELETE(l_hash_str);
             return false;
         }
@@ -620,10 +655,11 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         const char* l_max_votes_count_str = NULL;
         const char* l_fee_str = NULL;
         const char* l_wallet_str = NULL;
+        const char *l_token_str = NULL;
 
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-question", &l_question_str);
         if (!l_question_str){
-            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_QUESTION_PARAM_MISSING, "Voting requires a question parameter to be valid.");
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_QUESTION_PARAM_MISSING, "Poll requires a question parameter to be valid.");
             return -DAP_CHAIN_NET_VOTE_CREATE_QUESTION_PARAM_MISSING;
         }
 
@@ -636,7 +672,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         dap_list_t *l_options_list = NULL;
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-options", &l_options_list_str);
         if (!l_options_list_str){
-            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_OPTION_PARAM_MISSING, "Voting requires a question parameter to be valid.");
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_OPTION_PARAM_MISSING, "Poll requires a question parameter to be valid.");
             return -DAP_CHAIN_NET_VOTE_CREATE_OPTION_PARAM_MISSING;
         }
         // Parse options list
@@ -652,21 +688,20 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
             return -DAP_CHAIN_NET_VOTE_CREATE_CONTAIN_MAX_OPTIONS;
         }
 
-        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-expire", &l_voting_expire_str);
-        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-max_votes_count", &l_max_votes_count_str);
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-fee", &l_fee_str);
         if (!l_fee_str){
-            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_FEE_PARAM_NOT_VALID, "Voting requires paramete -fee to be valid.");
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_FEE_PARAM_NOT_VALID, "Poll requires parameter -fee to be valid.");
             return -DAP_CHAIN_NET_VOTE_CREATE_FEE_PARAM_NOT_VALID;
         }
         uint256_t l_value_fee = dap_chain_balance_scan(l_fee_str);
 
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-w", &l_wallet_str);
         if (!l_wallet_str){
-            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_WALLET_PARAM_NOT_VALID, "Voting requires parameter -w to be valid.");
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_WALLET_PARAM_NOT_VALID, "Poll requires parameter -w to be valid.");
             return -DAP_CHAIN_NET_VOTE_CREATE_WALLET_PARAM_NOT_VALID;
         }
 
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-expire", &l_voting_expire_str);
         dap_time_t l_time_expire = 0;
         if (l_voting_expire_str)
             l_time_expire = dap_time_from_str_rfc822(l_voting_expire_str);
@@ -675,6 +710,8 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
                                     "Wrong time format. -expire parameter must be in format \"Day Month Year HH:MM:SS Timezone\" e.g. \"19 August 2024 22:00:00 +00\"");
             return -DAP_CHAIN_NET_VOTE_CREATE_WRONG_TIME_FORMAT;
         }
+
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-max_votes_count", &l_max_votes_count_str);
         uint64_t l_max_count = 0;
         if (l_max_votes_count_str)
             l_max_count = strtoul(l_max_votes_count_str, NULL, 10);
@@ -688,8 +725,26 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
             return -DAP_CHAIN_NET_VOTE_CREATE_WALLET_DOES_NOT_EXIST;
         }
 
+
+        dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-token", &l_token_str);
+        if (l_token_str && !dap_ledger_token_ticker_check(l_net->pub.ledger, l_token_str)) {
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_WRONG_TOKEN, "Token %s does not exist", l_token_str);
+            return -DAP_CHAIN_NET_VOTE_CREATE_WRONG_TOKEN;
+        }
+
         char *l_hash_ret = NULL;
-        int res = dap_chain_net_vote_create(l_question_str, l_options_list, l_time_expire, l_max_count, l_value_fee, l_is_delegated_key, l_is_vote_changing_allowed, l_wallet_fee, l_net, l_hash_out_type, &l_hash_ret);
+        int res = dap_chain_net_vote_create(l_question_str,
+                                            l_options_list,
+                                            l_time_expire,
+                                            l_max_count,
+                                            l_value_fee,
+                                            l_is_delegated_key,
+                                            l_is_vote_changing_allowed,
+                                            l_wallet_fee,
+                                            l_net,
+                                            l_token_str,
+                                            l_hash_out_type,
+                                            &l_hash_ret);
         dap_list_free(l_options_list);
         dap_chain_wallet_close(l_wallet_fee);
 
@@ -707,7 +762,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
                 return DAP_CHAIN_NET_VOTE_CREATE_LENGTH_QUESTION_OVERSIZE_MAX;
             } break;
             case DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX, "The voting can contain no more than %d options",
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX, "The poll can contain no more than %d options",
                                                   DAP_CHAIN_DATUM_TX_VOTING_OPTION_MAX_COUNT);
                 return DAP_CHAIN_NET_VOTE_CREATE_COUNT_OPTION_OVERSIZE_MAX;
             } break;
@@ -716,7 +771,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
                 return DAP_CHAIN_NET_VOTE_CREATE_FEE_IS_ZERO;
             } break;
             case DAP_CHAIN_NET_VOTE_CREATE_SOURCE_ADDRESS_IS_INVALID: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_SOURCE_ADDRESS_IS_INVALID, "source address is invalid");
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_SOURCE_ADDRESS_IS_INVALID, "Source address is invalid");
                 return DAP_CHAIN_NET_VOTE_CREATE_SOURCE_ADDRESS_IS_INVALID;
             } break;
             case DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER: {
@@ -729,11 +784,11 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
                 return DAP_CHAIN_NET_VOTE_CREATE_MAX_COUNT_OPTION_EXCEEDED;
             } break;
             case DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_OPTION_TSD_ITEM: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_OPTION_TSD_ITEM, "Can't create voting with expired time");
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_OPTION_TSD_ITEM, "Can't create poll with expired time");
                 return DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_OPTION_TSD_ITEM;
             } break;
             case DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME, "Can't create voting with expired time");
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME, "Can't create poll with expired time");
                 return DAP_CHAIN_NET_VOTE_CREATE_INPUT_TIME_MORE_CURRENT_TIME;
             } break;
             case DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_EXPIRE_TIME: {
@@ -780,10 +835,11 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         }
 
         dap_hash_fast_t l_voting_hash = {};
-        dap_chain_hash_fast_from_str(l_hash_str, &l_voting_hash);
-
+        if (dap_chain_hash_fast_from_str(l_hash_str, &l_voting_hash)) {
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_HASH_INVALID, "Hash string is not recognozed as hex of base58 hash");
+            return -DAP_CHAIN_NET_VOTE_VOTING_HASH_INVALID;
+        }
 
-        dap_chain_hash_fast_t l_pkey_hash;
         dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-cert", &l_cert_name);
         dap_cert_t * l_cert = dap_cert_find_by_name(l_cert_name);
         if (l_cert_name){
@@ -817,8 +873,8 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         }
 
         const char *c_wallets_path = dap_chain_wallet_get_path(g_config);
-        dap_chain_wallet_t *l_wallet_fee = dap_chain_wallet_open(l_wallet_str, c_wallets_path,NULL);
-        if (!l_wallet_fee) {
+        dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, c_wallets_path,NULL);
+        if (!l_wallet) {
             dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_WALLET_DOES_NOT_EXIST, "Wallet %s does not exist", l_wallet_str);
             return -DAP_CHAIN_NET_VOTE_VOTING_WALLET_DOES_NOT_EXIST;
         }
@@ -827,9 +883,9 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
 
         char *l_hash_tx;
 
-        int res = dap_chain_net_vote_voting(l_cert, l_value_fee, l_wallet_fee, l_voting_hash, l_option_idx_count,
+        int res = dap_chain_net_vote_voting(l_cert, l_value_fee, l_wallet, l_voting_hash, l_option_idx_count,
                                             l_net, l_hash_out_type, &l_hash_tx);
-        dap_chain_wallet_close(l_wallet_fee);
+        dap_chain_wallet_close(l_wallet);
 
         switch (res) {
             case DAP_CHAIN_NET_VOTE_VOTING_OK: {
@@ -840,14 +896,14 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
                 return DAP_CHAIN_NET_VOTE_CREATE_OK;
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_VOTE: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_VOTE, "Can't find voting with hash %s", l_hash_str);
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_VOTE, "Can't find poll with hash %s", l_hash_str);
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES: {
                 dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES, 
-                                                  "This voting already received the required number of votes.");
+                                                  "This poll already received the required number of votes.");
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED, "This voting already expired.");
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED, "This poll is already expired.");
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT: {
                 dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT, 
@@ -855,18 +911,13 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED: {
                 dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED, 
-                                                    "This voting required a delegated key. Parameter -cert must contain a valid certificate name");
-            } break;
-            case DAP_CHAIN_NET_VOTE_VOTING_NO_PUBLIC_KEY_IN_CERT: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_NO_PUBLIC_KEY_IN_CERT, 
-                                                    "Can't serialize public key of certificate \"%s\"",
-                                                    l_cert_name);
+                                                    "This poll required a delegated key. Parameter -cert must contain a valid certificate name");
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED: {
                 dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED, "Your key is not delegated.");
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE: {
-                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE, "The voting doesn't allow change your vote.");
+                dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE, "The poll doesn't allow change your vote.");
             } break;
             case DAP_CHAIN_NET_VOTE_VOTING_SOURCE_ADDRESS_INVALID: {
                 dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_VOTING_SOURCE_ADDRESS_INVALID, "source address is invalid");
@@ -910,7 +961,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
     }break;
     case CMD_LIST:{
         json_object* json_vote_out = json_object_new_object();
-        json_object_object_add(json_vote_out, "List of votings in net", json_object_new_string(l_net->pub.name));
+        json_object_object_add(json_vote_out, "list_of_polls", json_object_new_string(l_net->pub.name));
         json_object* json_arr_voting_out = json_object_new_array();
         dap_chain_net_votings_t *l_voting = NULL, *l_tmp;
         pthread_rwlock_rdlock(&s_votings_rwlock);
@@ -918,11 +969,12 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
             if (l_voting->net_id.uint64 != l_net->pub.id.uint64)
                 continue;
             json_object* json_obj_vote = json_object_new_object();
-            json_object_object_add( json_obj_vote, "voting_tx", 
+            json_object_object_add( json_obj_vote, "poll_tx",
                                     json_object_new_string(dap_chain_hash_fast_to_str_static(&l_voting->voting_hash)));            
             char* l_voting_question = (char*)l_voting->voting_params.voting_tx + l_voting->voting_params.voting_question_offset;
             json_object_object_add( json_obj_vote, "question", 
                                     json_object_new_string_len(l_voting_question, l_voting->voting_params.voting_question_length) );
+            json_object_object_add(json_obj_vote, "token", json_object_new_string(l_voting->voting_params.token_ticker));
             json_object_array_add(json_arr_voting_out, json_obj_vote);
         }
         pthread_rwlock_unlock(&s_votings_rwlock);
@@ -937,13 +989,17 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         }
 
         dap_hash_fast_t l_voting_hash = {};
-        dap_chain_hash_fast_from_str(l_hash_str, &l_voting_hash);
+        if (dap_chain_hash_fast_from_str(l_hash_str, &l_voting_hash)) {
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_DUMP_HASH_PARAM_INVALID,
+                                   "Can't recognize hash string as a valid HEX or BASE58 format hash");
+            return -DAP_CHAIN_NET_VOTE_DUMP_HASH_PARAM_INVALID;
+        }
         dap_chain_net_votings_t *l_voting = NULL;
         pthread_rwlock_rdlock(&s_votings_rwlock);
         HASH_FIND(hh, s_votings, &l_voting_hash, sizeof(l_voting_hash), l_voting);
         pthread_rwlock_unlock(&s_votings_rwlock);
         if (!l_voting) {
-            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_DUMP_CAN_NOT_FIND_VOTE, "Can't find voting with hash %s", l_hash_str);
+            dap_json_rpc_error_add(*json_arr_reply, DAP_CHAIN_NET_VOTE_DUMP_CAN_NOT_FIND_VOTE, "Can't find poll with hash %s", l_hash_str);
             return -DAP_CHAIN_NET_VOTE_DUMP_CAN_NOT_FIND_VOTE;
         }
 
@@ -969,10 +1025,11 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         }
 
         json_object* json_vote_out = json_object_new_object();
-        json_object_object_add(json_vote_out, "voting_tx", json_object_new_string(l_hash_str));
+        json_object_object_add(json_vote_out, "poll_tx", json_object_new_string(l_hash_str));
         json_object_object_add(json_vote_out, "question", 
                                json_object_new_string_len((char*)l_voting->voting_params.voting_tx + l_voting->voting_params.voting_question_offset,
                                l_voting->voting_params.voting_question_length));
+        json_object_object_add(json_vote_out, "token", json_object_new_string(l_voting->voting_params.token_ticker));
         if (l_voting->voting_params.voting_expire) {
             char l_tmp_buf[DAP_TIME_STR_SIZE];
             dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_voting->voting_params.voting_expire);
@@ -998,21 +1055,20 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
             json_object* json_vote_obj = json_object_new_object();
             json_object_object_add(json_vote_obj, "option_id", json_object_new_int(i));
             dap_chain_net_vote_option_t* l_vote_option = (dap_chain_net_vote_option_t*)l_option->data;
-            json_object_object_add( json_vote_obj, "vote_tx", 
+            json_object_object_add( json_vote_obj, "option_text",
                                     json_object_new_string_len((char*)l_voting->voting_params.voting_tx + l_vote_option->vote_option_offset,
                                                                 l_vote_option->vote_option_length) );
-            json_object_object_add(json_vote_obj, "voting_power", json_object_new_uint64( l_results[i].num_of_votes) );     
-            int l_percentage = l_votes_count ? (int)((float)l_results[i].num_of_votes/l_votes_count * 100 + 0.5) : 0;
-            json_object_object_add(json_vote_obj, "vote_share", json_object_new_int(l_percentage) );
+            json_object_object_add(json_vote_obj, "votes_count", json_object_new_uint64( l_results[i].num_of_votes) );
+            int l_percentage = l_votes_count ? ((double)(l_results[i].num_of_votes * 100))/l_votes_count + 0.5 : 0;
+            json_object_object_add(json_vote_obj, "votes_percent", json_object_new_int(l_percentage) );
             uint256_t l_weight_percentage = { };
-
             DIV_256_COIN(l_results[i].weights, l_total_weight, &l_weight_percentage);
             MULT_256_COIN(l_weight_percentage, dap_chain_coins_to_balance("100.0"), &l_weight_percentage);
             const char *l_weight_percentage_str = dap_uint256_decimal_to_round_char(l_weight_percentage, 2, true),
                        *l_w_coins, *l_w_datoshi = dap_uint256_to_char(l_results[i].weights, &l_w_coins);
-            json_object_object_add(json_vote_obj, "vote_sum", json_object_new_string(l_w_coins));
-            json_object_object_add(json_vote_obj, "vote_sum_datoshi", json_object_new_string(l_w_datoshi));
-            json_object_object_add(json_vote_obj, "vote_sum_weight", json_object_new_string(l_weight_percentage_str));
+            json_object_object_add(json_vote_obj, "votes_sum", json_object_new_string(l_w_coins));
+            json_object_object_add(json_vote_obj, "votes_sum_datoshi", json_object_new_string(l_w_datoshi));
+            json_object_object_add(json_vote_obj, "votes_sum_weight", json_object_new_string(l_weight_percentage_str));
             json_object_array_add(json_arr_vote_out, json_vote_obj);
         }
         json_object_object_add(json_vote_out, "results", json_arr_vote_out);
@@ -1020,7 +1076,6 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
         const char *l_tw_coins, *l_tw_datoshi = dap_uint256_to_char(l_total_weight, &l_tw_coins);
         json_object_object_add(json_vote_out, "total_sum", json_object_new_string(l_tw_coins));
         json_object_object_add(json_vote_out, "total_sum_datoshi", json_object_new_string(l_tw_datoshi));
-        json_object_object_add(json_vote_out, "ticker", json_object_new_string(l_net->pub.native_ticker));
         json_object_array_add(*json_arr_reply, json_vote_out);
     } break;
     default:
@@ -1029,164 +1084,116 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply)
     return 0;
 }
 
-static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_prev_hash, int a_out_idx, dap_hash_fast_t *a_pkey_hash)
+static int s_tx_is_spent(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash, dap_hash_fast_t *a_voting_hash,
+                         dap_hash_fast_t *a_pkey_hash, dap_chain_net_votings_t *a_voting, dap_time_t a_voting_ts)
 {
-    int l_coin_is_spent = 0;
-
-
-    dap_ledger_t *l_ledger = a_net->pub.ledger;
-    if(!l_ledger){
-        log_it(L_ERROR, "Can't find ledger");
-        return -1;
+    dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_ledger, a_tx_hash);
+    if (!l_tx) {
+        log_it(L_ERROR, "Can't find tx %s", dap_hash_fast_to_str_static(a_tx_hash));
+        return -3;
     }
 
-    dap_chain_datum_tx_t *l_voting_tx = dap_ledger_tx_find_by_hash(l_ledger, &a_voting_hash);
-    const char *l_native_ticker = a_net->pub.native_ticker;
-
-    dap_list_t *l_tx_list = NULL; // "stack" for saving txs on up level
-    dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(l_ledger, &a_tx_prev_hash);
-    if (!l_tx){
-        log_it(L_ERROR, "Can't find tx");
-        return -1;
-    }
-
-    if (l_tx->header.ts_created < l_voting_tx->header.ts_created){
+    if (l_tx->header.ts_created < a_voting_ts)
         return 0;
-    }
-
-    if (s_datum_tx_voting_coin_check_cond_out(a_net, a_voting_hash, a_tx_prev_hash, a_out_idx) != 0){
-        return 1;
-    }
 
     dap_chain_tx_vote_t *l_vote = (dap_chain_tx_vote_t *)dap_chain_datum_tx_item_get(l_tx, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL);
-    if (l_vote && dap_hash_fast_compare(&l_vote->voting_hash, &a_voting_hash)) {
-        dap_chain_net_votings_t *l_voting = NULL;
-        pthread_rwlock_wrlock(&s_votings_rwlock);
-        HASH_FIND(hh, s_votings, &a_voting_hash, sizeof(dap_hash_fast_t), l_voting);
-        pthread_rwlock_unlock(&s_votings_rwlock);
-        if (l_voting) {
-            for (dap_list_t *it = l_voting->votes; it; it = it->next) {
-                dap_chain_net_vote_t *l_vote = (dap_chain_net_vote_t *)it->data;
-                if (dap_hash_fast_compare(&l_vote->vote_hash, &a_tx_prev_hash)) {
-                    if (l_voting->voting_params.vote_changing_allowed &&
-                            !dap_hash_fast_is_blank(a_pkey_hash) &&
-                            dap_hash_fast_compare(&l_vote->pkey_hash, a_pkey_hash))
-                        break;  // it's vote changing, allow it
-                    return 1;
-                }
+    if (l_vote && dap_hash_fast_compare(&l_vote->voting_hash, &a_voting->voting_hash)) {
+        for (dap_list_t *it = a_voting->votes; it; it = it->next) {
+            dap_chain_net_vote_t *l_vote = (dap_chain_net_vote_t *)it->data;
+            if (dap_hash_fast_compare(&l_vote->vote_hash, a_tx_hash)) {
+                if (a_voting->voting_params.vote_changing_allowed &&
+                        !dap_hash_fast_is_blank(a_pkey_hash) &&
+                        dap_hash_fast_compare(&l_vote->pkey_hash, a_pkey_hash))
+                    break;  // it's vote changing, allow it
+                return 1;
             }
         }
     }
 
+    dap_list_t *l_ins_list = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL);
+    l_ins_list = dap_list_concat(l_ins_list, dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_COND, NULL));
+    if (!l_ins_list) // it's emisssion or reward TX, not marked yet
+        return 0;
 
-    dap_list_t *l_ins_list_temp = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL);
-    dap_list_t *l_cond_ins_list = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_COND, NULL);
-    if (!l_ins_list_temp && !l_cond_ins_list){
-        log_it(L_ERROR, "Can't get inputs from tx");
-        return -1;
-    }
-
-    dap_list_t *l_ins_list = NULL;
-    l_ins_list = dap_list_concat(l_ins_list, l_ins_list_temp);
-    l_ins_list = dap_list_concat(l_ins_list, l_cond_ins_list);
-
-    l_tx_list = dap_list_append(l_tx_list, l_ins_list);
-    dap_list_t* l_tx_temp = dap_list_last(l_tx_list);
-
-    while(l_tx_temp && !l_coin_is_spent){
-        if (l_tx_temp->data == NULL){
-            l_tx_list = dap_list_delete_link(l_tx_list, l_tx_temp);
-            l_tx_temp = l_tx_list ? dap_list_last(l_tx_list) : NULL;
-            continue;
-        }
-        dap_list_t *l_ins_list = (dap_list_t*)l_tx_temp->data;
-        dap_chain_tx_in_t* l_temp_in = (dap_chain_tx_in_t*)l_ins_list->data;
-        dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(l_ledger, &l_temp_in->header.tx_prev_hash);
+    dap_hash_fast_t l_prev_hash = {};
+    for (dap_list_t *it = l_ins_list; it; it = it->next) {
+        uint32_t l_prev_idx = -1;
+        if (*(byte_t *)it->data == TX_ITEM_TYPE_IN_COND) {
+            dap_chain_tx_in_cond_t *in = it->data;
+            l_prev_hash = in->header.tx_prev_hash;
+            l_prev_idx = in->header.tx_out_prev_idx;
+        } else {
+            dap_chain_tx_in_t *in = it->data;
+            l_prev_hash = in->header.tx_prev_hash;
+            l_prev_idx = in->header.tx_out_prev_idx;
+        }
+        dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, &l_prev_hash);
 
         const char* l_tx_token = NULL;
-        dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t*)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_temp_in->header.tx_out_prev_idx);
-        if (!l_prev_out_union){
-            l_tx_temp->data = dap_list_remove(l_tx_temp->data, l_temp_in);
-            if (l_tx_temp->data == NULL){
-                l_tx_list = dap_list_delete_link(l_tx_list, l_tx_temp);
-                l_tx_temp = l_tx_list ? dap_list_last(l_tx_list) : NULL;
-            }
-            continue;
-        }
-
-        switch (l_prev_out_union->header.type) {
+        byte_t *l_prev_out_union = dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev, l_prev_idx);
+        switch (*l_prev_out_union) {
         case TX_ITEM_TYPE_OUT:{
-            l_tx_token = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_temp_in->header.tx_prev_hash);
+            dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t *)l_prev_out_union;
+            l_tx_token = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_prev_hash);
         }break;
         case TX_ITEM_TYPE_OUT_EXT:{
-            dap_chain_tx_out_ext_t *l_temp_out = (dap_chain_tx_out_ext_t *)l_prev_out_union;
-            l_tx_token = l_temp_out->token;
+            dap_chain_tx_out_ext_t *l_out = (dap_chain_tx_out_ext_t *)l_prev_out_union;
+            l_tx_token = l_out->token;
         }break;
         case TX_ITEM_TYPE_OUT_COND:{
-            dap_chain_tx_out_cond_t *l_temp_out = (dap_chain_tx_out_cond_t*)l_prev_out_union;
-            if (l_temp_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK ||
-                s_datum_tx_voting_coin_check_cond_out(a_net, a_voting_hash, l_temp_in->header.tx_prev_hash, l_temp_in->header.tx_out_prev_idx) == 0)
+            dap_chain_tx_out_cond_t *l_out = (dap_chain_tx_out_cond_t *)l_prev_out_union;
+            if (l_out->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) {
+                l_tx_token = a_ledger->net->pub.native_ticker;
                 break;
+            }
+            if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, *a_voting_hash, l_prev_hash, l_prev_idx, a_pkey_hash) != 0) {
+                dap_list_free(l_ins_list);
+                return 1;
+            }
+            l_tx_token = dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_prev_hash);
         }
         default:
-            l_tx_temp->data = dap_list_remove((dap_list_t*)l_tx_temp->data, l_temp_in);
-            if (l_tx_temp->data == NULL){
-                l_tx_list = dap_list_delete_link(l_tx_list, l_tx_temp);
-                l_tx_temp = l_tx_list ? dap_list_last(l_tx_list) : NULL;
-            }
-            continue;
+            break;
         }
-
-        if (l_tx_prev_temp->header.ts_created < l_voting_tx->header.ts_created ||
-            dap_strcmp(l_tx_token, l_native_ticker)){
-            l_tx_temp->data = dap_list_remove((dap_list_t*)l_tx_temp->data, l_temp_in);
-            if (l_tx_temp->data == NULL){
-                l_tx_list = dap_list_delete_link(l_tx_list, l_tx_temp);
-                l_tx_temp = l_tx_list ? dap_list_last(l_tx_list) : NULL;
-            }
+        if (dap_strcmp(l_tx_token, a_voting->voting_params.token_ticker))
             continue;
-        }
-
+    }
 
-        dap_chain_tx_vote_t *l_vote =(dap_chain_tx_vote_t *) dap_chain_datum_tx_item_get(l_tx_prev_temp, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL);
-        if(l_vote && dap_hash_fast_compare(&l_vote->voting_hash, &a_voting_hash)){
-            dap_chain_net_votings_t *l_voting = NULL;
-            pthread_rwlock_wrlock(&s_votings_rwlock);
-            HASH_FIND(hh, s_votings, &a_voting_hash, sizeof(dap_hash_fast_t), l_voting);
-            pthread_rwlock_unlock(&s_votings_rwlock);
-            dap_list_t *l_temp = NULL;
-            while (l_temp){
-                dap_chain_net_vote_t *l_vote = (dap_chain_net_vote_t *)l_temp->data;
-                if (dap_hash_fast_compare(&l_vote->vote_hash, &l_temp_in->header.tx_prev_hash)){
-                    l_coin_is_spent = 1;
-                    break;
-                }
-                l_temp = l_temp->next;
-            }
-        }
+    return s_tx_is_spent(a_ledger, &l_prev_hash, a_voting_hash, a_pkey_hash, a_voting, a_voting_ts);
+}
 
 
-        l_ins_list = dap_chain_datum_tx_items_get(l_tx_prev_temp, TX_ITEM_TYPE_IN, NULL);
-        l_tx_list = dap_list_append(l_tx_list, l_ins_list);
-        l_tx_temp->data = dap_list_remove((dap_list_t*)l_tx_temp->data, l_temp_in);
-        l_tx_temp = l_tx_list ? dap_list_last(l_tx_list) : NULL;
+static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash,
+                                              dap_hash_fast_t a_tx_prev_hash, int a_out_idx, dap_hash_fast_t *a_pkey_hash)
+{
+    int l_coin_is_spent = 0;
 
+    dap_chain_net_votings_t *l_voting = NULL;
+    pthread_rwlock_wrlock(&s_votings_rwlock);
+    HASH_FIND(hh, s_votings, &a_voting_hash, sizeof(dap_hash_fast_t), l_voting);
+    pthread_rwlock_unlock(&s_votings_rwlock);
+    if (!l_voting) {
+        log_it(L_ERROR, "Can't find poll %s", dap_hash_fast_to_str_static(&a_voting_hash));
+        return -1;
     }
 
-    if(l_tx_list){
-        l_tx_temp = l_tx_list;
-        while(l_tx_temp){
-            if (l_tx_temp->data)
-                dap_list_free((dap_list_t*)l_tx_temp->data);
-            l_tx_list = dap_list_delete_link(l_tx_list, l_tx_temp);
-            l_tx_temp = dap_list_first(l_tx_list);
-        }
+    dap_ledger_t *l_ledger = a_net->pub.ledger;
+    dap_chain_datum_tx_t *l_voting_tx = dap_ledger_tx_find_by_hash(l_ledger, &a_voting_hash);
+    if (!l_voting_tx) {
+        log_it(L_ERROR, "Can't find poll tx %s", dap_hash_fast_to_str_static(&a_voting_hash));
+        return -2;
     }
 
-    return l_coin_is_spent;
+    if (s_datum_tx_voting_coin_check_cond_out(a_net, a_voting_hash, a_tx_prev_hash, a_out_idx, a_pkey_hash) != 0)
+        return 1;
+
+    return s_tx_is_spent(l_ledger, &a_tx_prev_hash, &a_voting_hash, a_pkey_hash, l_voting, l_voting_tx->header.ts_created);
+
 }
 
-static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_cond_hash, int a_cond_out_idx)
+static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash,
+                                                 dap_hash_fast_t a_tx_cond_hash, int a_cond_out_idx,
+                                                 dap_hash_fast_t *a_pkey_hash)
 {
 
     dap_chain_net_votings_t * l_voting = NULL;
@@ -1194,27 +1201,27 @@ static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_has
     HASH_FIND(hh, s_votings, &a_voting_hash, sizeof(dap_hash_fast_t), l_voting);
     pthread_rwlock_unlock(&s_votings_rwlock);
     if(!l_voting || l_voting->net_id.uint64 != a_net->pub.id.uint64) {
-        log_it(L_ERROR, "Can't find voting with hash %s in net %s",
+        log_it(L_ERROR, "Can't find poll with hash %s in net %s",
             dap_chain_hash_fast_to_str_static(&a_voting_hash), a_net->pub.name);
         return -1;
     }
 
-    dap_chain_net_voting_cond_outs_t *l_tx_outs = NULL;
+    dap_chain_net_voting_cond_outs_t *l_tx_out = NULL;
     pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock);
-    HASH_FIND(hh, l_voting->voting_spent_cond_outs, &a_tx_cond_hash, sizeof(dap_hash_fast_t), l_tx_outs);
+    HASH_FIND(hh, l_voting->voting_spent_cond_outs, &a_tx_cond_hash, sizeof(dap_hash_fast_t), l_tx_out);
     pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock);
 
-    if (!l_tx_outs || l_tx_outs->out_idx != a_cond_out_idx){
-        return 0;
-    }
+    if (l_tx_out && l_tx_out->out_idx == a_cond_out_idx)
+        return a_pkey_hash ? !dap_hash_fast_compare(a_pkey_hash, &l_tx_out->pkey_hash) : 1;
 
-    return 1;
+    return 0;
 }
 
 int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t a_expire_vote,
                               uint64_t a_max_vote, uint256_t a_fee, bool a_delegated_key_required,
                               bool a_vote_changing_allowed, dap_chain_wallet_t *a_wallet,
-                              dap_chain_net_t *a_net, const char *a_hash_out_type, char **a_hash_output) {
+                              dap_chain_net_t *a_net, const char *a_token_ticker,
+                              const char *a_hash_out_type, char **a_hash_output) {
 
     if (strlen(a_question) > DAP_CHAIN_DATUM_TX_VOTING_QUESTION_MAX_LENGTH){
         return DAP_CHAIN_NET_VOTE_CREATE_LENGTH_QUESTION_OVERSIZE_MAX;
@@ -1248,8 +1255,7 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap
     dap_ledger_t* l_ledger = a_net->pub.ledger;
     dap_list_t *l_list_used_out = NULL;
     if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, l_addr_from, &l_list_used_out, l_total_fee, &l_value_transfer) == -101)
-        l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
-                                                                       l_addr_from, l_total_fee, &l_value_transfer);
+        l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, l_addr_from, l_total_fee, &l_value_transfer);
     if (!l_list_used_out) {
         return DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER;
     }
@@ -1332,6 +1338,16 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap
         DAP_DEL_Z(l_vote_changing_item);
     }
 
+    if (a_token_ticker) {
+        dap_chain_tx_tsd_t *l_voting_token_item = dap_chain_datum_voting_token_tsd_create(a_token_ticker);
+        if (!l_voting_token_item) {
+            dap_chain_datum_tx_delete(l_tx);
+            return DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_TOKEN;
+        }
+        dap_chain_datum_tx_add_item(&l_tx, l_voting_token_item);
+        DAP_DEL_Z(l_voting_token_item);
+    }
+
     // add 'in' items
     uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
     assert(EQUAL_256(l_value_to_items, l_value_transfer));
@@ -1339,7 +1355,7 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap
     uint256_t l_value_pack = {};
     // Network fee
     if (l_net_fee_used) {
-        if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee) == 1)
+        if (dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_fee, l_net_fee, l_native_ticker) == 1)
             SUM_256_256(l_value_pack, l_net_fee, &l_value_pack);
         else {
             dap_chain_datum_tx_delete(l_tx);
@@ -1359,7 +1375,7 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap
     uint256_t l_value_back;
     SUBTRACT_256_256(l_value_transfer, l_value_pack, &l_value_back);
     if(!IS_ZERO_256(l_value_back)) {
-        if(dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back) != 1) {
+        if(dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_native_ticker) != 1) {
             dap_chain_datum_tx_delete(l_tx);
             return DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_ADD_OUT_WITH_VALUE_BACK;
         }
@@ -1406,47 +1422,42 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal
     if (l_voting->voting_params.voting_expire && dap_time_now() > l_voting->voting_params.voting_expire)
         return DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED;
 
-    dap_hash_fast_t l_pkey_hash = {0};
+    dap_chain_addr_t *l_addr_from = dap_chain_wallet_get_addr(a_wallet, a_net->pub.id);
+    if (!l_addr_from)
+        return DAP_CHAIN_NET_VOTE_VOTING_SOURCE_ADDRESS_INVALID;
 
+    dap_hash_fast_t l_pkey_hash = {0};
     if (l_voting->voting_params.delegate_key_required) {
         if (!a_cert)
             return DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED;
-        if (!a_cert->enc_key)
+        if (dap_cert_get_pkey_hash(a_cert, &l_pkey_hash))
             return DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT;
-        // Get publivc key hash
-        size_t l_pub_key_size = 0;
-        uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(a_cert->enc_key, &l_pub_key_size);;
-        if (l_pub_key == NULL)
-            return DAP_CHAIN_NET_VOTE_VOTING_NO_PUBLIC_KEY_IN_CERT;
-
-        dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash);
-        DAP_DELETE(l_pub_key);
         if (!dap_chain_net_srv_stake_check_pkey_hash(a_net->pub.id, &l_pkey_hash))
             return DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED;
-        for (dap_list_t *it = l_voting->votes; it; it = it->next)
-            if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &l_pkey_hash) &&
-                    !l_voting->voting_params.vote_changing_allowed)
-                return DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE;
-    }
-
-    dap_enc_key_t *l_priv_key = NULL;
-
-    l_priv_key = dap_chain_wallet_get_key(a_wallet, 0);
-
-    const dap_chain_addr_t *l_addr_from = (const dap_chain_addr_t *) dap_chain_wallet_get_addr(a_wallet, a_net->pub.id);
+    } else
+        l_pkey_hash = l_addr_from->data.hash_fast;
 
-    if (!l_addr_from)
-        return DAP_CHAIN_NET_VOTE_VOTING_SOURCE_ADDRESS_INVALID;
+    bool l_vote_changed = false;
+    for (dap_list_t *it = l_voting->votes; it; it = it->next)
+        if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &l_pkey_hash)) {
+            if (!l_voting->voting_params.vote_changing_allowed)
+                return DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE;
+            l_vote_changed = true;
+            break;
+        }
 
-    const char *l_native_ticker = a_net->pub.native_ticker;
-    uint256_t l_net_fee = {}, l_total_fee = {}, l_value_transfer;
+    const char *l_token_ticker = l_voting->voting_params.token_ticker;
+    uint256_t l_net_fee = {}, l_total_fee = a_fee, l_value_transfer, l_fee_transfer;
     dap_chain_addr_t l_addr_fee = {};
     bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_addr_fee);
-    SUM_256_256(l_net_fee, a_fee, &l_total_fee);
+    if (l_net_fee_used)
+        SUM_256_256(l_net_fee, a_fee, &l_total_fee);
 
-    dap_ledger_t* l_ledger = dap_ledger_by_net_name(a_net->pub.name);
-    dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs(l_ledger, l_native_ticker, l_addr_from, &l_value_transfer);
-    if (!l_list_used_out || compare256(l_value_transfer, l_total_fee) <= 0) {
+    bool l_native_tx = !dap_strcmp(l_token_ticker, a_net->pub.native_ticker);
+    dap_ledger_t *l_ledger = a_net->pub.ledger;
+    dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs(l_ledger, l_token_ticker, l_addr_from, &l_value_transfer);
+    if (!l_list_used_out || (l_native_tx && compare256(l_value_transfer, l_total_fee) < 0)) {
+        dap_list_free_full(l_list_used_out, NULL);
         return DAP_CHAIN_NET_VOTE_VOTING_NOT_ENOUGH_FUNDS_TO_TRANSFER;
     }
 
@@ -1455,24 +1466,42 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal
     dap_list_t *it, *tmp;
     DL_FOREACH_SAFE(l_list_used_out, it, tmp) {
         dap_chain_tx_used_out_item_t *l_out = (dap_chain_tx_used_out_item_t *)it->data;
-        if (s_datum_tx_voting_coin_check_spent(a_net, a_hash, l_out->tx_hash_fast, l_out->num_idx_out, &l_pkey_hash) &&
-                !l_voting->voting_params.vote_changing_allowed) {
-            dap_list_delete_link(l_list_used_out, it);
+        if (s_datum_tx_voting_coin_check_spent(a_net, a_hash, l_out->tx_hash_fast, l_out->num_idx_out,
+                                               l_vote_changed ? &l_pkey_hash : NULL)) {
+            l_list_used_out = dap_list_delete_link(l_list_used_out, it);
             continue;
         }
         if (SUM_256_256(l_value_transfer_new, l_out->value, &l_value_transfer_new))
             return DAP_CHAIN_NET_VOTE_VOTING_INTEGER_OVERFLOW;
     }
 
-    if (IS_ZERO_256(l_value_transfer_new) || compare256(l_value_transfer_new, l_total_fee) <= 0){
+    if (IS_ZERO_256(l_value_transfer_new) || (l_native_tx && compare256(l_value_transfer_new, l_total_fee) <= 0))
         return DAP_CHAIN_NET_VOTE_VOTING_UNSPENT_UTX0_FOR_PARTICIPATION_THIS_VOTING;
-    }
 
     l_value_transfer = l_value_transfer_new;
 
     // create empty transaction
     dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
 
+    uint256_t l_value_back = l_value_transfer, l_fee_back = {};
+    if (!l_native_tx) {
+        dap_list_t *l_list_fee_outs = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker, l_addr_from, l_total_fee, &l_fee_transfer);
+        if (!l_list_fee_outs) {
+            dap_chain_datum_tx_delete(l_tx);
+            return DAP_CHAIN_NET_VOTE_VOTING_NOT_ENOUGH_FUNDS_TO_TRANSFER;
+        }
+        uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_outs);
+        assert(EQUAL_256(l_value_fee_items, l_fee_transfer));
+        dap_list_free_full(l_list_fee_outs, NULL);
+        SUBTRACT_256_256(l_fee_transfer, l_total_fee, &l_fee_back);
+    } else
+        SUBTRACT_256_256(l_value_transfer, l_total_fee, &l_value_back);
+
+    // add 'in' items
+    uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
+    assert(EQUAL_256(l_value_to_items, l_value_transfer));
+    dap_list_free_full(l_list_used_out, NULL);
+
     // Add vote item
     if (a_option_idx > dap_list_length(l_voting->voting_params.option_offsets_list)){
         dap_chain_datum_tx_delete(l_tx);
@@ -1486,17 +1515,13 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal
     dap_chain_datum_tx_add_item(&l_tx, l_vote_item);
     DAP_DEL_Z(l_vote_item);
 
-    // add stake out conds items
-    dap_list_t *l_outs = dap_ledger_get_list_tx_cond_outs(l_ledger, a_net->pub.native_ticker,  l_addr_from,
-                                                          DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK, NULL);
-    dap_list_t *l_temp = l_outs;
-    while(l_temp){
-        dap_chain_tx_used_out_item_t *l_out_item = (dap_chain_tx_used_out_item_t *)l_temp->data;
-        if (dap_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_out_item->tx_hash_fast, l_out_item->num_idx_out, NULL) ||
-            s_datum_tx_voting_coin_check_cond_out(a_net, a_hash, l_out_item->tx_hash_fast, l_out_item->num_idx_out ) != 0){
-            l_temp = l_temp->next;
+    // add out conds items
+    dap_list_t *l_outs = dap_ledger_get_list_tx_cond_outs(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_ALL, l_token_ticker, l_addr_from);
+    for (dap_list_t *it = l_outs; it; it = it->next) {
+        dap_chain_tx_used_out_item_t *l_out_item = (dap_chain_tx_used_out_item_t *)it->data;
+        if (s_datum_tx_voting_coin_check_cond_out(a_net, a_hash, l_out_item->tx_hash_fast, l_out_item->num_idx_out,
+                                                  l_vote_changed ? &l_pkey_hash : NULL) != 0)
             continue;
-        }
         dap_chain_tx_tsd_t *l_item = dap_chain_datum_voting_vote_tx_cond_tsd_create(l_out_item->tx_hash_fast, l_out_item->num_idx_out);
         if(!l_item){
             dap_chain_datum_tx_delete(l_tx);
@@ -1506,55 +1531,44 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal
         }
         dap_chain_datum_tx_add_item(&l_tx, l_item);
         DAP_DEL_Z(l_item);
-        l_temp = l_temp->next;
     }
     dap_list_free_full(l_outs, NULL);
 
-    // add 'in' items
-    uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out);
-    assert(EQUAL_256(l_value_to_items, l_value_transfer));
-    dap_list_free_full(l_list_used_out, NULL);
-    uint256_t l_value_pack = {};
     // Network fee
-    if (l_net_fee_used) {
-        if (dap_chain_datum_tx_add_out_item(&l_tx, &l_addr_fee, l_net_fee) == 1)
-            SUM_256_256(l_value_pack, l_net_fee, &l_value_pack);
-        else {
-            dap_chain_datum_tx_delete(l_tx);
-            return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_NET_FEE_OUT;
-        }
+    if (l_net_fee_used && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_addr_fee, l_net_fee, a_net->pub.native_ticker) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_NET_FEE_OUT;
     }
+
     // Validator's fee
-    if (!IS_ZERO_256(a_fee)) {
-        if (dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) == 1)
-            SUM_256_256(l_value_pack, a_fee, &l_value_pack);
-        else {
-            dap_chain_datum_tx_delete(l_tx);
-            return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_NET_FEE_OUT;
-        }
+    if (!IS_ZERO_256(a_fee) && dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_NET_FEE_OUT;
     }
+
     // coin back
-    uint256_t l_value_back;
-    SUBTRACT_256_256(l_value_transfer, l_value_pack, &l_value_back);
-    if(!IS_ZERO_256(l_value_back)) {
-        if(dap_chain_datum_tx_add_out_item(&l_tx, l_addr_from, l_value_back) != 1) {
-            dap_chain_datum_tx_delete(l_tx);
-            return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_OUT_WITH_VALUE_BACK;
-        }
+    if (!IS_ZERO_256(l_value_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_value_back, l_token_ticker) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_OUT_WITH_VALUE_BACK;
+    }
+    if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, l_addr_from, l_fee_back, a_net->pub.native_ticker) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_OUT_WITH_VALUE_BACK;
     }
 
+    dap_enc_key_t *l_priv_key = dap_chain_wallet_get_key(a_wallet, 0);
     // add 'sign' items with wallet sign
-    if(dap_chain_datum_tx_add_sign_item(&l_tx, l_priv_key) != 1) {
+    if (dap_chain_datum_tx_add_sign_item(&l_tx, l_priv_key) != 1) {
         dap_chain_datum_tx_delete(l_tx);
+        dap_enc_key_delete(l_priv_key);
         return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_SIGN_TX;
     }
+    dap_enc_key_delete(l_priv_key);
 
     // add 'sign' items with delegated key if needed
-    if(a_cert){
-        if(dap_chain_datum_tx_add_sign_item(&l_tx, a_cert->enc_key) != 1) {
-            dap_chain_datum_tx_delete(l_tx);
-            return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_SIGN_TX;
-        }
+    if (a_cert && dap_chain_datum_tx_add_sign_item(&l_tx, a_cert->enc_key) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_SIGN_TX;
     }
 
     size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx);
diff --git a/modules/service/voting/include/dap_chain_net_srv_voting.h b/modules/service/voting/include/dap_chain_net_srv_voting.h
index 4bd1f71694180eb6b8f390da41c401cca1241aec..70509562bd780f59492b249905f881a3866799a3 100644
--- a/modules/service/voting/include/dap_chain_net_srv_voting.h
+++ b/modules/service/voting/include/dap_chain_net_srv_voting.h
@@ -94,13 +94,14 @@ enum DAP_CHAIN_NET_VOTE_CREATE_ERROR {
     DAP_CHAIN_NET_VOTE_CREATE_WALLET_PARAM_NOT_VALID,
     DAP_CHAIN_NET_VOTE_CREATE_WALLET_DOES_NOT_EXIST,
     DAP_CHAIN_NET_VOTE_CREATE_WRONG_TIME_FORMAT,
-
+    DAP_CHAIN_NET_VOTE_CREATE_WRONG_TOKEN,
+    DAP_CHAIN_NET_VOTE_CREATE_CAN_NOT_CREATE_TSD_TOKEN,
     DAP_CHAIN_NET_VOTE_CREATE_UNKNOWN_ERR
 };
 int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap_time_t a_expire_vote,
                              uint64_t a_max_vote, uint256_t a_fee, bool a_delegated_key_required,
                              bool a_vote_changing_allowed, dap_chain_wallet_t *a_wallet,
-                             dap_chain_net_t *a_net, const char *a_hash_out_type, char **a_hash_output);
+                             dap_chain_net_t *a_net, const char *a_token_ticker, const char *a_hash_out_type, char **a_hash_output);
 
 enum DAP_CHAIN_NET_VOTE_VOTING_ERROR{
     DAP_CHAIN_NET_VOTE_VOTING_OK,
@@ -108,7 +109,6 @@ enum DAP_CHAIN_NET_VOTE_VOTING_ERROR{
     DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES,
     DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED,
     DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT,
-    DAP_CHAIN_NET_VOTE_VOTING_NO_PUBLIC_KEY_IN_CERT,
     DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED,
     DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED,
     DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE,
@@ -125,13 +125,13 @@ enum DAP_CHAIN_NET_VOTE_VOTING_ERROR{
     DAP_CHAIN_NET_VOTE_VOTING_NET_PARAM_MISSING,
     DAP_CHAIN_NET_VOTE_VOTING_NET_PARAM_NOT_VALID,
     DAP_CHAIN_NET_VOTE_VOTING_HASH_NOT_FOUND,
+    DAP_CHAIN_NET_VOTE_VOTING_HASH_INVALID,
     DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_CERT,
     DAP_CHAIN_NET_VOTE_VOTING_FEE_PARAM_NOT_VALID,
     DAP_CHAIN_NET_VOTE_VOTING_FEE_PARAM_BAD_TYPE,
     DAP_CHAIN_NET_VOTE_VOTING_WALLET_PARAM_NOT_VALID,
     DAP_CHAIN_NET_VOTE_VOTING_OPTION_IDX_PARAM_NOT_VALID,
     DAP_CHAIN_NET_VOTE_VOTING_WALLET_DOES_NOT_EXIST,
-    
 
     DAP_CHAIN_NET_VOTE_VOTING_UNKNOWN_ERR,
     DAP_CHAIN_NET_VOTE_VOTING_INTEGER_OVERFLOW
@@ -140,6 +140,7 @@ enum DAP_CHAIN_NET_VOTE_VOTING_ERROR{
 
 enum DAP_CHAIN_NET_VOTE_DUMP_ERROR{
     DAP_CHAIN_NET_VOTE_DUMP_HASH_PARAM_NOT_FOUND,
+    DAP_CHAIN_NET_VOTE_DUMP_HASH_PARAM_INVALID,
     DAP_CHAIN_NET_VOTE_DUMP_CAN_NOT_FIND_VOTE,
     DAP_CHAIN_NET_VOTE_DUMP_NO_OPTIONS,
     DAP_CHAIN_NET_VOTE_DUMP_MEMORY_ERR
diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c
index cc844a27f605128d51836bb2775bf75966ceb13c..b21899511e0ddf09ff27e30e2abd03018a534520 100644
--- a/modules/type/blocks/dap_chain_cs_blocks.c
+++ b/modules/type/blocks/dap_chain_cs_blocks.c
@@ -2786,3 +2786,34 @@ static dap_list_t *s_callback_get_txs(dap_chain_t *a_chain, size_t a_count, size
     return l_list;
 }
 
+/**
+ * @brief search pkey in block signs
+ * @param a_chain chain to search
+ * @param a_pkey_hash - pkey hash
+ * @return pointer to dap_pkey_t if finded, other - NULL
+ */
+dap_pkey_t *dap_chain_cs_blocks_get_pkey_by_hash(dap_chain_net_t *a_net, dap_hash_fast_t *a_pkey_hash)
+{
+    dap_return_val_if_pass(!a_pkey_hash, NULL);
+    dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_TX);
+    if (!l_chain || !DAP_CHAIN_CS_BLOCKS(l_chain) || !PVT(DAP_CHAIN_CS_BLOCKS(l_chain)))
+        return NULL;
+    dap_pkey_t *l_ret = NULL;
+    pthread_rwlock_rdlock(&PVT(DAP_CHAIN_CS_BLOCKS(l_chain))->rwlock);
+    for (dap_chain_block_cache_t *l_block_cache = PVT(DAP_CHAIN_CS_BLOCKS(l_chain))->blocks; l_block_cache; l_block_cache = l_block_cache->hh.next) {
+        for (size_t i = 0; i < l_block_cache->sign_count; i++) {
+            dap_sign_t *l_sign = dap_chain_block_sign_get(l_block_cache->block, l_block_cache->block_size, i);
+            if (dap_sign_is_use_pkey_hash(l_sign))
+                continue;
+            dap_chain_hash_fast_t l_sign_hash = {};
+            dap_sign_get_pkey_hash(l_sign, &l_sign_hash);
+            if(!memcmp(&l_sign_hash, a_pkey_hash, sizeof(dap_chain_hash_fast_t))) {
+                l_ret = dap_pkey_get_from_sign(l_sign);
+                break;
+            }
+        }
+    }
+    pthread_rwlock_unlock(&PVT(DAP_CHAIN_CS_BLOCKS(l_chain))->rwlock);
+    return l_ret;
+}
+
diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h
index 489595cd33ee8c2c4361e1bcd74faf23205070e6..00c74e85a2caf537461469ed3cf14ad87fe243c6 100644
--- a/modules/type/blocks/include/dap_chain_cs_blocks.h
+++ b/modules/type/blocks/include/dap_chain_cs_blocks.h
@@ -98,3 +98,5 @@ DAP_STATIC_INLINE char *dap_chain_cs_blocks_get_reward_group(const char *a_net_n
 {
     return dap_strdup_printf("local.%s.rewards", a_net_name);
 }
+
+dap_pkey_t *dap_chain_cs_blocks_get_pkey_by_hash(dap_chain_net_t *a_net, dap_hash_fast_t *a_pkey_hash);
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index 0438874c4406ca89ee081e966e0a08398385146d..b6abfef6d90fe4c5be56f2bc776db390b88a6e2d 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -1101,7 +1101,7 @@ const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet) {
     for (size_t i = 0; i < l_wallet_internal->certs_count; ++i) {
         dap_return_val_if_pass(!l_wallet_internal->certs[i], "The wallet contains an undefined certificate.\n");
         dap_sign_type_t l_sign_type = dap_sign_type_from_key_type(l_wallet_internal->certs[i]->enc_key->type);
-        if (SIG_TYPE_BLISS == l_sign_type.type || SIG_TYPE_PICNIC == l_sign_type.type || SIG_TYPE_TESLA == l_sign_type.type) {
+        if (dap_sign_type_is_depricated(l_sign_type)) {
             return "The Bliss, Picnic and Tesla signatures is deprecated. We recommend you to create a new wallet with another available signature and transfer funds there.\n";
         }
     }
diff --git a/modules/wallet/dap_chain_wallet_cache.c b/modules/wallet/dap_chain_wallet_cache.c
index f4a70a606bd9190c6daa5c5d76f46d025e4cc7d5..2acea49e373b2a76fc5d303b44a8b06e4ed26ae4 100644
--- a/modules/wallet/dap_chain_wallet_cache.c
+++ b/modules/wallet/dap_chain_wallet_cache.c
@@ -678,7 +678,7 @@ static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_ad
         dap_chain_addr_t l_addr;
         uint256_t l_value;
         uint8_t *l_prev_item = NULL;
-        int l_prev_idx;
+        int l_prev_idx = 0;
 
         switch(*l_tx_item) {
         case TX_ITEM_TYPE_IN: {