diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b42568ef18b03473a9a18d2e7fa2eb87093f28c..b8ab298486152842388a0616cc148ffd7c142227 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,6 +117,12 @@ if (CELLFRAME_MODULES MATCHES "srv-xchange")
     set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_xchange )
 endif()
 
+# Enable service of delegated stake
+if (CELLFRAME_MODULES MATCHES "srv-stake")
+    message("[+] Module 'srv-stake'")
+    set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_net_srv_stake )
+endif()
+
 if (WIN32)
     set(CELLFRAME_LIBS ${CELLFRAME_LIBS} KERNEL32 USER32 SHELL32 WINMM GDI32 ADVAPI32
 					 Ole32 Version Imm32 OleAut32 ws2_32 ntdll psapi 
diff --git a/modules/CMakeLists.txt b/modules/CMakeLists.txt
index 0b39d4eb7bde8e6af5bbeec9aaf22674322845ee..49f99545f1a23285076ede10e04aa18cf5b63243 100644
--- a/modules/CMakeLists.txt
+++ b/modules/CMakeLists.txt
@@ -81,6 +81,11 @@ if (CELLFRAME_MODULES MATCHES "srv-xchange")
     add_subdirectory(service/xchange)
 endif()
 
+# Service of delegated stake
+if (CELLFRAME_MODULES MATCHES "srv-stake")
+    add_subdirectory(service/stake)
+endif()
+
 # Unit tests
 if( BUILD_TESTS)
     add_subdirectory(test)
diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c
index 6c1d7bf8be1dfda11e53aa0a0979cccb91b89fb2..f3a06becbe67b868448ae8ba67762d5ad5d6b7c4 100644
--- a/modules/chain/dap_chain_ledger.c
+++ b/modules/chain/dap_chain_ledger.c
@@ -672,8 +672,10 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
      3. hash(tx1) == tx2.dap_chain_datump_tx_in.tx_prev_hash
      &&
      4. tx1.dap_chain_datum_tx_out.addr.data.key == tx2.dap_chain_datum_tx_sig.pkey for unconditional output
-     &&
-     5. tx1.dap_chain_datum_tx_out.condition == verify_svc_type(tx2) for conditional ouput
+     \\
+     5a. tx1.dap_chain_datum_tx_sig.pkey == tx1.dap_chain_datum_tx_sig.pkey for conditional owner
+     \\
+     5b. tx1.dap_chain_datum_tx_out.condition == verify_svc_type(tx2) for conditional output
      &&
      6. sum(  find (tx2.input.tx_prev_hash).output[tx2.input_tx_prev_idx].value )  ==  sum (tx2.outputs.value) per token
      */
@@ -854,19 +856,31 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
                 l_err_num = -8;
                 break;
             }
-            dap_chain_tx_out_cond_t * l_tx_prev_out_cond = (dap_chain_tx_out_cond_t *)l_tx_prev_out;
-            dap_chain_ledger_verificator_t *l_verificator;
-            int l_tmp = (int)l_tx_prev_out_cond->header.subtype;
-            HASH_FIND_INT(s_verificators, &l_tmp, l_verificator);
-            if (!l_verificator || !l_verificator->callback) {
-                log_it(L_ERROR, "No verificator set for conditional output subtype %d", l_tmp);
-                l_err_num = -13;
-                break;
-            }
-            // 5. Call verificator for conditional output
-            if (l_verificator->callback(l_tx_prev_out_cond, a_tx) == false) {
-                l_err_num = -14;
-                break;
+            // 5a. Check for condition owner
+            dap_chain_tx_sig_t *l_tx_prev_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_tx_prev, NULL, TX_ITEM_TYPE_SIG, NULL);
+            dap_sign_t *l_prev_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_prev_sig);
+            size_t l_prev_pkey_ser_size = 0;
+            const uint8_t *l_prev_pkey_ser = dap_sign_get_pkey(l_prev_sign, &l_prev_pkey_ser_size);
+            dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
+            dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
+            size_t l_pkey_ser_size = 0;
+            const uint8_t *l_pkey_ser = dap_sign_get_pkey(l_sign, &l_pkey_ser_size);
+            dap_chain_tx_out_cond_t *l_tx_prev_out_cond = (dap_chain_tx_out_cond_t *)l_tx_prev_out;
+            if (l_pkey_ser_size != l_prev_pkey_ser_size ||
+                    memcmp(l_prev_pkey_ser, l_pkey_ser, l_prev_pkey_ser_size)) {
+                // 5b. Call verificator for conditional output
+                dap_chain_ledger_verificator_t *l_verificator;
+                int l_tmp = (int)l_tx_prev_out_cond->header.subtype;
+                HASH_FIND_INT(s_verificators, &l_tmp, l_verificator);
+                if (!l_verificator || !l_verificator->callback) {
+                    log_it(L_ERROR, "No verificator set for conditional output subtype %d", l_tmp);
+                    l_err_num = -13;
+                    break;
+                }
+                if (l_verificator->callback(l_tx_prev_out_cond, a_tx) == false) {
+                    l_err_num = -14;
+                    break;
+                }
             }
             bound_item->out.tx_prev_out_cond = l_tx_prev_out_cond;
             // calculate sum of values from previous transactions
@@ -1672,7 +1686,7 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led
  * a_addr[in] wallet address, whose owner can use the service
  */
 dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger,
-        dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx)
+        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;
@@ -1700,6 +1714,9 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le
         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->token_tiker);
+            }
             break;
         }
     }
@@ -1737,7 +1754,7 @@ uint64_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, da
     // Find all transactions
     do {
 
-        l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(a_ledger, &l_tx_first_hash, &l_tx_out_cond, NULL);
+        l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(a_ledger, &l_tx_first_hash, &l_tx_out_cond, NULL, NULL);
 
         // Get out_cond item from transaction
         if(l_tx_tmp) {
@@ -1800,7 +1817,7 @@ dap_list_t *dap_chain_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, c
                 l_list_used_out = dap_list_append(l_list_used_out, item);
                 l_value_transfer += item->value;
                 // already accumulated the required value, finish the search for 'out' items
-                if(l_value_transfer >= a_value_need) {
+                if (l_value_transfer >= a_value_need) {
                     break;
                 }
             }
diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h
index db95aaa85b98308319e27a94da96b5fb0d154911..29b7b7e9f0ecf06987174d0b66e1ca87b3370b82 100644
--- a/modules/chain/include/dap_chain_ledger.h
+++ b/modules/chain/include/dap_chain_ledger.h
@@ -175,7 +175,8 @@ const dap_chain_datum_tx_t* dap_chain_ledger_tx_find_by_pkey(dap_ledger_t *a_led
         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_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_first_hash, dap_chain_tx_out_cond_t **a_out_cond, int *a_out_cond_idx);
+dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, 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 the value from all transactions in the cache with out_cond item
 uint64_t dap_chain_ledger_tx_cache_get_out_cond_value(dap_ledger_t *a_ledger, dap_chain_addr_t *a_addr,
diff --git a/modules/common/dap_chain_common.c b/modules/common/dap_chain_common.c
index fac77070ae0205b4d5a195f8a09a097f730fb04d..c5c66ffa67a9db408fc330a9242713819cd34652 100644
--- a/modules/common/dap_chain_common.c
+++ b/modules/common/dap_chain_common.c
@@ -228,27 +228,14 @@ dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str( const char * a_net_srv_u
  * @param a_net_id
  * @return
  */
-void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t *a_net_id)
+void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t *a_net_id)
 {
-    if(!a_addr || !a_key || !a_net_id)
+    if(!a_addr || !a_pkey_hash || !a_net_id)
         return;
     a_addr->addr_ver = DAP_CHAIN_ADDR_VERSION_CURRENT;
     a_addr->net_id.uint64 = a_net_id->uint64;
-    a_addr->sig_type.raw = dap_sign_type_from_key_type(a_key->type).raw;
-    // key -> serialized key
-    dap_chain_hash_fast_t l_hash_public_key;
-    size_t l_pub_key_data_size;
-    uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_data_size);
-    if ( l_pub_key_data == NULL ){
-        log_it(L_ERROR,"Can't fill address from key, its empty");
-        return;
-    }
-
-    // serialized key -> key hash
-
-    if(dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key))
-        memcpy(a_addr->data.hash, l_hash_public_key.raw, sizeof(l_hash_public_key.raw));
-    DAP_DELETE(l_pub_key_data);
+    a_addr->sig_type.raw = a_type.raw;
+    memcpy(a_addr->data.hash, a_pkey_hash, sizeof(dap_chain_hash_fast_t));
     // calc checksum
     dap_hash_fast(a_addr, sizeof(dap_chain_addr_t) - sizeof(dap_chain_hash_fast_t), &a_addr->checksum);
 }
diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c
index 6c44465b08399af133461ab20a4e36ea8c868ebf..de892d7e9671b7db9a21d70fccc1cb963315c4ce 100644
--- a/modules/common/dap_chain_datum_tx_items.c
+++ b/modules/common/dap_chain_datum_tx_items.c
@@ -256,7 +256,7 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc
 }
 
 
-dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_net_id,
+dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_net_id,
                                                                              const char *a_token, uint64_t a_value,
                                                                              const void *a_params, uint32_t a_params_size)
 {
@@ -277,6 +277,23 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap
     return l_item;
 }
 
+dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake(dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value, long double a_fee_value,
+                                                                           dap_chain_addr_t *a_fee_addr, const void *a_params, uint32_t a_params_size)
+{
+    dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + a_params_size);
+    l_item->header.item_type = TX_ITEM_TYPE_OUT_COND;
+    l_item->header.value = a_value;
+    l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE;
+    l_item->subtype.srv_stake.srv_uid = a_srv_uid;
+    l_item->subtype.srv_stake.fee_value = a_fee_value;
+    memcpy(&l_item->subtype.srv_stake.fee_addr, a_fee_addr, sizeof(dap_chain_addr_t));
+    l_item->params_size = a_params_size;
+    if (a_params_size) {
+        memcpy(l_item->params, a_params, a_params_size);
+    }
+    return l_item;
+}
+
 /**
  * Create item dap_chain_tx_sig_t
  *
diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h
index a4a11b7d27703246ffc778bfcb9940b75f291938..c8617a1dac04c4635fde8d8141a04cde98ef4db5 100644
--- a/modules/common/include/dap_chain_common.h
+++ b/modules/common/include/dap_chain_common.h
@@ -207,7 +207,7 @@ dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
 dap_chain_net_id_t dap_chain_net_id_from_str(const char* a_str);
 dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
 
-void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t *a_net_id);
+void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t *a_net_id);
 
 int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr);
 
diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h
index 7ef0ab207c26e21ea3c702865a6c4c59815528cb..6665d3eef27458f969d0d985b8e4797976023164 100644
--- a/modules/common/include/dap_chain_datum_tx_items.h
+++ b/modules/common/include/dap_chain_datum_tx_items.h
@@ -96,13 +96,21 @@ dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_pay(dap_enc
         uint64_t a_value, uint64_t a_value_max_per_unit, dap_chain_net_srv_price_unit_uid_t a_unit,
                                                                  const void *a_cond, size_t a_cond_size);
 /**
- * Create item dap_chain_tx_out_cond_t fo eXchange service
+ * Create item dap_chain_tx_out_cond_t for eXchange service
  *
  * return item, NULL Error
  */
 dap_chain_tx_out_cond_t* dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid,
                                                                              dap_chain_net_id_t a_net_id, const char *a_token, uint64_t a_value,
                                                                              const void *a_params, uint32_t a_params_size);
+
+/**
+ * Create item dap_chain_tx_out_cond_t for stake service
+ *
+ * return item, NULL Error
+ */
+dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake(dap_chain_net_srv_uid_t a_srv_uid, uint64_t a_value, long double a_fee_value,
+                                                                           dap_chain_addr_t *a_fee_addr, const void *a_params, uint32_t a_params_size);
 /**
  * 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 d5889678e3fffd92af325926d6567c9582fa6ac3..519d94ce6d39976230cf3038b523459255557fbf 100644
--- a/modules/common/include/dap_chain_datum_tx_out_cond.h
+++ b/modules/common/include/dap_chain_datum_tx_out_cond.h
@@ -31,7 +31,8 @@
 
 typedef enum dap_chain_tx_out_cond_subtype {
     DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY = 0x01,
-    DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE = 0x02
+    DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE = 0x02,
+    DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE = 0x03
 } dap_chain_tx_out_cond_subtype_t;
 
 /**
@@ -71,6 +72,14 @@ typedef struct dap_chain_tx_out_cond {
             // Total amount of datoshi to change to
             uint64_t value;
         } srv_xchange;
+        struct {
+            // Service uid that only could be used for this outout
+            dap_chain_net_srv_uid_t srv_uid;
+            // Fee address
+            dap_chain_addr_t fee_addr;
+            // Fee value in percent
+            long double fee_value;
+        } srv_stake;
     } subtype;
     uint32_t params_size; // Condition parameters size
     uint8_t params[]; // condition parameters, pkey, hash or smth like this
diff --git a/modules/consensus/dag-poa/CMakeLists.txt b/modules/consensus/dag-poa/CMakeLists.txt
index 4a78a37e527bf4d67eeebd2b11f8d9833747f269..f918a704c31b806b221c5b6cebd1b47cddc6a7bf 100644
--- a/modules/consensus/dag-poa/CMakeLists.txt
+++ b/modules/consensus/dag-poa/CMakeLists.txt
@@ -11,6 +11,6 @@ endif()
 
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_DAG_CS_POA_SRCS} ${DAP_CHAIN_DAG_CS_POA_HEADERS})
 
-target_link_libraries(dap_chain_cs_dag_poa dap_core dap_crypto dap_chain dap_chain_cs_dag )
+target_link_libraries(dap_chain_cs_dag_poa dap_core dap_crypto dap_chain dap_chain_cs_dag dap_chain_net_srv_stake)
 target_include_directories(dap_chain_cs_dag_poa INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
diff --git a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
index 6a7e51bb0af704a6d467fca1c5c613b1f6324ac1..4d5bf15f7be6323f6f48f6e0312f51e47182136f 100644
--- a/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
+++ b/modules/consensus/dag-poa/dap_chain_cs_dag_poa.c
@@ -43,6 +43,7 @@
 #include "dap_chain_cs_dag.h"
 #include "dap_chain_cs_dag_event.h"
 #include "dap_chain_cs_dag_poa.h"
+#include "dap_chain_net_srv_stake.h"
 
 #include "dap_cert.h"
 
@@ -306,12 +307,33 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_
     dap_chain_cs_dag_poa_pvt_t * l_poa_pvt = PVT ( DAP_CHAIN_CS_DAG_POA( a_dag ) );
     if ( a_dag_event->header.signs_count >= l_poa_pvt->auth_certs_count_verify ){
         size_t l_verified = 0;
-        for ( uint16_t i = 0; i < a_dag_event->header.signs_count; i++ ){
-            for ( uint16_t j = 0; j < l_poa_pvt->auth_certs_count; j++){
-                if( dap_cert_compare_with_sign ( l_poa_pvt->auth_certs[j],
-                            dap_chain_cs_dag_event_get_sign(a_dag_event,i) ) == 0 )
+        for ( uint16_t i = 0; i < a_dag_event->header.signs_count; i++ ) {
+            dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event, 0);
+            if ( l_sign == NULL){
+                log_it(L_WARNING, "Event is NOT signed with anything");
+                return -4;
+            }
+            for (uint16_t j = 0; j < l_poa_pvt->auth_certs_count; j++) {
+                if (dap_cert_compare_with_sign ( l_poa_pvt->auth_certs[j], l_sign) == 0)
                     l_verified++;
             }
+            if (i == 0) {
+                dap_chain_hash_fast_t l_pkey_hash;
+                if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) {
+                    log_it(L_WARNING, "Event's sign has no any key");
+                    return -5;
+                }
+                dap_chain_addr_t l_addr = {};
+                dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &a_dag->chain->net_id);
+                dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event);
+                if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) {
+                    dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
+                    if (!dap_chain_net_srv_stake_validator(&l_addr, l_tx)) {
+                        return -6;
+                    }
+                }
+            }
+
         }
         return l_verified >= l_poa_pvt->auth_certs_count_verify ? 0 : -1;
     }else
diff --git a/modules/consensus/dag-pos/CMakeLists.txt b/modules/consensus/dag-pos/CMakeLists.txt
index 7b4a426675bc89fd898bc30f98622907f672a4a5..21638a18436e71592a70b85f75840bd5ec557c1b 100644
--- a/modules/consensus/dag-pos/CMakeLists.txt
+++ b/modules/consensus/dag-pos/CMakeLists.txt
@@ -11,6 +11,6 @@ endif()
 
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_CS_DAG_POS_SRCS} ${DAP_CHAIN_CS_DAG_POS_HEADERS})
 
-target_link_libraries(dap_chain_cs_dag_pos dap_core dap_crypto dap_chain dap_chain_cs_dag )
+target_link_libraries(dap_chain_cs_dag_pos dap_core dap_crypto dap_chain dap_chain_cs_dag dap_chain_net_srv_stake)
 target_include_directories(dap_chain_cs_dag_pos INTERFACE .)
 target_include_directories(${PROJECT_NAME} PUBLIC include)
diff --git a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
index a37e7a5fabb1e1a0cbab42cec4b692d894fd3baf..689e2dda83b53ce4e40b7b3f0404b74f26723a5c 100644
--- a/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
+++ b/modules/consensus/dag-pos/dap_chain_cs_dag_pos.c
@@ -30,7 +30,7 @@
 #include "dap_chain_cs.h"
 #include "dap_chain_cs_dag.h"
 #include "dap_chain_cs_dag_pos.h"
-
+#include "dap_chain_net_srv_stake.h"
 #include "dap_chain_ledger.h"
 
 #define LOG_TAG "dap_chain_cs_dag_pos"
@@ -224,21 +224,28 @@ static int s_callback_event_verify(dap_chain_cs_dag_t * a_dag, dap_chain_cs_dag_
         dap_chain_addr_t l_addr = { 0 };
 
         for ( size_t l_sig_pos=0; l_sig_pos < a_dag_event->header.signs_count; l_sig_pos++ ){
-            dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event,0);
+            dap_sign_t * l_sign = dap_chain_cs_dag_event_get_sign(a_dag_event, 0);
             if ( l_sign == NULL){
                 log_it(L_WARNING, "Event is NOT signed with anything");
                 return -4;
             }
 
-            dap_enc_key_t * l_key = dap_sign_to_enc_key( l_sign);
-            if ( l_key == NULL){
+            dap_chain_hash_fast_t l_pkey_hash;
+            if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) {
                 log_it(L_WARNING, "Event's sign has no any key");
                 return -5;
             }
-
-            dap_chain_addr_fill (&l_addr,l_key,&a_dag->chain->net_id );
-            dap_enc_key_delete (l_key); // TODO cache all this operations to prevent useless memory copy ops
-
+            dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &a_dag->chain->net_id);
+
+            if (l_sig_pos == 0) {
+                dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_chain_cs_dag_event_get_datum(a_dag_event);
+                if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) {
+                    dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_datum->data;
+                    if (!dap_chain_net_srv_stake_validator(&l_addr, l_tx)) {
+                        return -6;
+                    }
+                }
+            }
             /*
             dap_chain_datum_t *l_datum = dap_chain_cs_dag_event_get_datum(a_dag_event);
             // transaction include emission?
diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c
index 427e30be8e3912d25e316080f3848a4c8a21d491..ee54f8d1166054e7c1e7fcf7e5ad89884314f85e 100644
--- a/modules/net/dap_chain_net.c
+++ b/modules/net/dap_chain_net.c
@@ -62,6 +62,7 @@
 #include "dap_cert.h"
 #include "dap_chain_common.h"
 #include "dap_chain_net.h"
+#include "dap_chain_net_srv.h"
 #include "dap_chain_node_client.h"
 #include "dap_chain_node_cli.h"
 #include "dap_chain_node_cli_cmd.h"
@@ -249,10 +250,8 @@ static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, c
                                                      const size_t a_value_len)
 {
     (void) a_op_code;
-    UNUSED(a_key);
-    UNUSED(a_value_len);
     UNUSED(a_prefix);
-    UNUSED(a_group);
+    UNUSED(a_value_len);
     if (a_arg) {
         dap_chain_net_t * l_net = (dap_chain_net_t *) a_arg;
         s_net_set_go_sync(l_net);
@@ -264,6 +263,31 @@ static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, c
             }
         }*/
     }
+    if (!dap_config_get_item_bool_default(g_config, "srv", "order_signed_only", false)) {
+        return;
+    }
+    dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg;
+    char *l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(l_net);
+    if (strcmp(a_group, l_gdb_group_str)) {
+        dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_value;
+        if (l_order->version == 1) {
+            dap_chain_global_db_gr_del((char *)a_key, a_group);
+        } else {
+            dap_sign_t *l_sign = (dap_sign_t *)&l_order->ext[l_order->ext_size];
+            dap_chain_hash_fast_t l_pkey_hash;
+            if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) {
+                return;
+            }
+            dap_chain_addr_t l_addr = {0};
+            dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &l_net->pub.id);
+            uint64_t l_solvency = dap_chain_ledger_calc_balance(l_net->pub.ledger, &l_addr, l_order->price_ticker);
+            if (l_solvency < l_order->price) {
+                dap_chain_global_db_gr_del((char *)a_key, a_group);
+            }
+            // TODO check for delegated key
+        }
+        DAP_DELETE(l_gdb_group_str);
+    }
 }
 
 /**
diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c
index 0d7344a2ab84bb8884966b631a32a38933b19219..a5274d3e875da7fc7587b376b2ef2429a88f5cf1 100644
--- a/modules/net/srv/dap_chain_net_srv.c
+++ b/modules/net/srv/dap_chain_net_srv.c
@@ -458,7 +458,7 @@ static int s_cli_net_srv( int argc, char **argv, void *arg_func, char **a_str_re
                 size_t l_ext_len = l_ext? strlen(l_ext) + 1 : 0;
                 char * l_order_new_hash_str = dap_chain_net_srv_order_create(
                             l_net,l_direction, l_srv_uid, l_node_addr,l_tx_cond_hash, l_price, l_price_unit,
-                            l_price_token, l_expires, (uint8_t *)l_ext, l_ext_len, l_region_str, l_continent_num);
+                            l_price_token, l_expires, (uint8_t *)l_ext, l_ext_len, l_region_str, l_continent_num, NULL);
                 if (l_order_new_hash_str)
                     dap_string_append_printf( l_string_ret, "Created order %s\n", l_order_new_hash_str);
                 else{
diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c
index 3030b70ed983b28c18232549336acded255c861e..91e4b5c6ca96c0ffe57c5ac0802929acc2978a91 100644
--- a/modules/net/srv/dap_chain_net_srv_order.c
+++ b/modules/net/srv/dap_chain_net_srv_order.c
@@ -78,7 +78,12 @@ void dap_chain_net_srv_order_deinit()
 
 size_t dap_chain_net_srv_order_get_size(dap_chain_net_srv_order_t *a_order)
 {
-    return a_order ? sizeof(dap_chain_net_srv_order_t) + a_order->ext_size : 0;
+    size_t l_sign_size = 0;
+    if (a_order->version > 1) {
+        dap_sign_t *l_sign = (dap_sign_t *)&a_order->ext[a_order->ext_size];
+        l_sign_size = dap_sign_get_size(l_sign);
+    }
+    return a_order ? sizeof(dap_chain_net_srv_order_t) + a_order->ext_size + l_sign_size : 0;
 }
 
 /**
@@ -218,7 +223,8 @@ char * dap_chain_net_srv_order_create(
         const uint8_t *a_ext,
         uint32_t a_ext_size,
         const char *a_region,
-        int8_t a_continent_num
+        int8_t a_continent_num,
+        dap_enc_key_t *a_key
         )
 {
     UNUSED(a_expires);
@@ -235,7 +241,7 @@ char * dap_chain_net_srv_order_create(
         }
 
         dap_chain_hash_fast_t l_order_hash;
-        l_order->version = 1;
+        l_order->version = a_key ? 2 : 1;
         l_order->srv_uid = a_srv_uid;
         l_order->direction = a_direction;
         l_order->ts_created = (dap_chain_time_t) time(NULL);
@@ -250,7 +256,16 @@ char * dap_chain_net_srv_order_create(
 
         if ( a_price_ticker)
             strncpy(l_order->price_ticker, a_price_ticker,sizeof(l_order->price_ticker)-1);
-
+        if (a_key) {
+            dap_sign_t *l_sign = dap_sign_create(a_key, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size, 0);
+            if (!l_sign) {
+                return NULL;
+            }
+            size_t l_sign_size = dap_sign_get_size(l_sign); // sign data
+            l_order = DAP_REALLOC(l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size + l_sign_size);
+            memcpy(&l_order->ext[l_order->ext_size], l_sign, l_sign_size);
+            DAP_DELETE(l_sign);
+        }
         size_t l_order_size = dap_chain_net_srv_order_get_size(l_order);
         dap_hash_fast( l_order, l_order_size, &l_order_hash );
         char * l_order_hash_str = dap_chain_hash_fast_to_str_new( &l_order_hash );
diff --git a/modules/net/srv/include/dap_chain_net_srv_order.h b/modules/net/srv/include/dap_chain_net_srv_order.h
index 369fba674c2c195c7c788a5c15f87edb6069237d..aa695855af8500fb8a961ab15e74272b1d5aba7c 100644
--- a/modules/net/srv/include/dap_chain_net_srv_order.h
+++ b/modules/net/srv/include/dap_chain_net_srv_order.h
@@ -104,7 +104,8 @@ char *dap_chain_net_srv_order_create(dap_chain_net_t * a_net,
         const uint8_t *a_ext,
         uint32_t a_ext_size,
         const char *a_region,
-        int8_t a_continent_num
+        int8_t a_continent_num,
+        dap_enc_key_t *a_key
         );
 
 int dap_chain_net_srv_order_save(dap_chain_net_t * a_net, dap_chain_net_srv_order_t *a_order);
diff --git a/modules/service/stake/CMakeLists.txt b/modules/service/stake/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6c00ea94b1b832f9ee0023e01e4f901ec06ac06f
--- /dev/null
+++ b/modules/service/stake/CMakeLists.txt
@@ -0,0 +1,12 @@
+cmake_minimum_required(VERSION 2.8)
+project (dap_chain_net_srv_stake)
+  
+file(GLOB DAP_SRV_STAKE_SRCS *.c)
+
+file(GLOB DAP_SRV_STAKE_HEADERS include/*.h)
+
+add_library(${PROJECT_NAME} STATIC ${DAP_SRV_STAKE_SRCS} ${DAP_SRV_STAKE_HEADERS})
+
+target_include_directories(dap_chain_crypto INTERFACE .)
+target_include_directories(${PROJECT_NAME} PUBLIC include)
+target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_chain dap_chain_crypto dap_chain_net dap_chain_net_srv)
diff --git a/modules/service/stake/dap_chain_net_srv_stake.c b/modules/service/stake/dap_chain_net_srv_stake.c
new file mode 100644
index 0000000000000000000000000000000000000000..79bb415aaeab23a785d5b1c8f79987c23a713cc5
--- /dev/null
+++ b/modules/service/stake/dap_chain_net_srv_stake.c
@@ -0,0 +1,770 @@
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) 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.
+
+    DAP 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 DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <math.h>
+#include "dap_string.h"
+#include "dap_chain_common.h"
+#include "dap_chain_node_cli.h"
+#include "dap_chain_mempool.h"
+#include "dap_chain_net_srv_common.h"
+#include "dap_chain_net_srv_stake.h"
+
+#define LOG_TAG "dap_chain_net_srv_stake"
+
+static int s_cli_srv_stake(int a_argc, char **a_argv, void *a_arg_func, char **a_str_reply);
+
+static dap_chain_net_srv_stake_t *s_srv_stake;
+
+/**
+ * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel
+ * @param vpn_addr Zero if only client mode. Address if the node shares its local VPN
+ * @param vpn_mask Zero if only client mode. Mask if the node shares its local VPN
+ * @return 0 if everything is okay, lesser then zero if errors
+ */
+int dap_chain_net_srv_stake_init()
+{
+    dap_chain_node_cli_cmd_item_create("srv_stake", s_cli_srv_stake, NULL, "Delegated stake service commands",
+    "srv_stake order create -net <net name> -from_addr <addr> -token <ticker> -coins <value> -to_addr <addr> -fee_percent <value>\n"
+        "\tCreate a new order with specified amount of datoshi to delegate it to the specified address."
+        "The fee with specified percent with this delagation will be returned to the fee address pointed by delegator\n"
+    "srv_stake order remove -net <net name> -order <order hash>\n"
+         "\tRemove order with specified hash\n"
+    "srv_stake order update -net <net name> -order <order hash> {-from_addr <addr> | -token <ticker> -coins <value> | "
+                                                                "-to_addr <addr> | -fee_percent <value>}\n"
+         "\tUpdate order with specified hash\n"
+    "srv_stake order list -net <net name>\n"
+         "\tGet the stake orders list within specified net name\n"
+    "srv_stake delegate -order <order hash> -net <net name> -wallet <wallet_name> -fee_addr <addr>\n"
+         "\tDelegate tokens with specified order within specified net name. Specify fee address\n"
+    "srv_stake transactions -net <net name> {-addr <addr from>}"
+         "\tShow the list of active stake transactions (optional delegated from addr)"
+    "srv_stake invalidate -net <net name> -tx <transaction hash> -wallet <wallet name>"
+         "\tInvalidate stake transaction by hash within net name and return stake to specified wallet"
+    );
+    s_srv_stake = DAP_NEW_Z(dap_chain_net_srv_stake_t);
+    uint16_t l_net_count;
+    dap_chain_net_t **l_net_list = dap_chain_net_list(&l_net_count);
+    for (uint16_t i = 0; i < l_net_count; i++) {
+        dap_ledger_t *l_ledger = l_net_list[i]->pub.ledger;
+        dap_chain_datum_tx_t *l_tx_tmp;
+        dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; // start hash
+        dap_chain_tx_out_cond_t *l_out_cond;
+        int l_out_cond_idx;
+        char l_token[DAP_CHAIN_TICKER_SIZE_MAX];
+        // Find all transactions
+        do {
+            l_tx_tmp = dap_chain_ledger_tx_cache_find_out_cond(l_ledger, &l_tx_cur_hash, &l_out_cond, &l_out_cond_idx, l_token);
+            if (!l_tx_tmp) {
+                break;
+            }
+            if (l_out_cond->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE)
+                continue;
+            if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &l_tx_cur_hash, l_out_cond_idx))
+                continue;
+            // Create the stake item
+            dap_chain_net_srv_stake_item_t *l_stake = DAP_NEW_Z(dap_chain_net_srv_stake_item_t);
+            l_stake->net = l_net_list[i];
+            dap_stpcpy(l_stake->token, l_token);
+            l_stake->value = l_out_cond->header.value;
+            dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_tx_tmp, NULL,
+                    TX_ITEM_TYPE_SIG, NULL);
+            dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
+            dap_chain_hash_fast_t l_pkey_hash;
+            if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) {
+                continue;
+            }
+            dap_chain_addr_fill(&l_stake->addr_from, l_sign->header.type, &l_pkey_hash, &l_net_list[i]->pub.id);
+            memcpy(&l_stake->addr_to, l_out_cond->params, sizeof(dap_chain_addr_t));
+            memcpy(&l_stake->addr_fee, &l_out_cond->subtype.srv_stake.fee_addr, sizeof(dap_chain_addr_t));
+            l_stake->fee_value = l_out_cond->subtype.srv_stake.fee_value;
+            memcpy(&l_stake->tx_hash, &l_tx_cur_hash, sizeof(dap_chain_hash_fast_t));
+            HASH_ADD(hh, s_srv_stake->itemlist, tx_hash, sizeof(dap_chain_hash_fast_t), l_stake);
+        } while (l_tx_tmp);
+    }
+    DAP_DELETE(l_net_list);
+    return 0;
+}
+
+void dap_chain_net_srv_stake_deinit()
+{
+    dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp;
+    HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) {
+        HASH_DEL(s_srv_stake->itemlist, l_stake);
+        DAP_DELETE(l_stake);
+    }
+    DAP_DELETE(s_srv_stake);
+}
+
+bool dap_chain_net_srv_stake_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx)
+{
+    UNUSED(a_cond);
+    UNUSED(a_tx);
+    return false;
+}
+
+bool dap_chain_net_srv_stake_validator(dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx)
+{
+    dap_chain_net_srv_stake_item_t *l_stake = NULL;
+    HASH_FIND(hh, s_srv_stake->itemlist, a_addr, sizeof(dap_chain_addr_t), l_stake);
+    if (l_stake == NULL) { // public key not delegated for this network
+        return true;
+    }
+    uint64_t l_outs_sum = 0, l_fee_sum = 0;
+    dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, NULL);
+    uint32_t l_out_idx_tmp = 0; // current index of 'out' item
+    for (dap_list_t *l_list_tmp = l_list_out_items; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp), l_out_idx_tmp++) {
+        dap_chain_tx_item_type_t l_type = *(uint8_t *)l_list_tmp->data;
+        if (l_type == TX_ITEM_TYPE_OUT_COND) {
+            dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t *)l_list_tmp->data;
+            l_outs_sum += l_out_cond->header.value;
+        }
+        if (l_type == TX_ITEM_TYPE_OUT) {
+            dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t *)l_list_tmp->data;
+            if (memcmp(&l_stake->addr_fee, &l_out->addr, sizeof(dap_chain_addr_t))) {
+                l_fee_sum += l_out->header.value;
+            } else {
+                l_outs_sum += l_out->header.value;
+            }
+        } else { // TX_ITEM_TYPE_OUT_EXT
+            dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t *)l_list_tmp->data;
+            if (memcmp(&l_stake->addr_fee, &l_out_ext->addr, sizeof(dap_chain_addr_t))) {
+                l_fee_sum += l_out_ext->header.value;
+            } else {
+                l_outs_sum += l_out_ext->header.value;
+            }
+        }
+    }
+    dap_list_free(l_list_out_items);
+    if (l_outs_sum * l_stake->fee_value / 100.0 < l_fee_sum) {
+        return false;
+    }
+    return true;
+}
+
+static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_srv_stake_item_t *a_stake, dap_chain_wallet_t *a_wallet)
+{
+    if (!a_stake || !a_stake->net || !a_stake->addr_to.addr_ver || !a_stake->addr_from.addr_ver ||
+            !a_stake->addr_fee.addr_ver || !*a_stake->token || !a_wallet) {
+        return NULL;
+    }
+
+    // create empty transaction
+    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
+
+    dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_stake->net->pub.name);
+    dap_chain_addr_t *l_owner_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_stake->net->pub.id);
+    if (memcmp(l_owner_addr, &a_stake->addr_from, sizeof(dap_chain_addr_t))) {
+        log_it(L_WARNING, "Odree and wallet address do not match");
+        return NULL;
+    }
+    dap_enc_key_t *l_owner_key = dap_chain_wallet_get_key(a_wallet, 0);
+    uint64_t l_value_sell = 0; // how many coins to transfer
+    // list of transaction with 'out' items to sell
+    dap_list_t *l_list_used_out = dap_chain_ledger_get_list_tx_outs_with_val(l_ledger, a_stake->token, l_owner_addr, a_stake->value, &l_value_sell);
+    if(!l_list_used_out) {
+        dap_chain_datum_tx_delete(l_tx);
+        DAP_DELETE(l_owner_addr);
+        log_it(L_WARNING, "Nothing to change (not enough funds)");
+        return NULL;
+    }
+
+    // add 'in' items to sell
+    uint64_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, free);
+    if (l_value_to_items != l_value_sell) {
+        dap_chain_datum_tx_delete(l_tx);
+        DAP_DELETE(l_owner_addr);
+        log_it(L_ERROR, "Can't compose the transaction input");
+        return NULL;
+    }
+
+    // add 'out_cond' & 'out' items
+    {
+        dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_ID };
+        dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_stake(l_uid, a_stake->value, a_stake->fee_value, &a_stake->addr_fee,
+                                                                                              (void *)&a_stake->addr_to, sizeof(dap_chain_addr_t));
+        if (!l_tx_out) {
+            dap_chain_datum_tx_delete(l_tx);
+            DAP_DELETE(l_owner_addr);
+            log_it(L_ERROR, "Can't compose the transaction conditional output");
+            return NULL;
+        }
+        dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out);
+        DAP_DELETE(l_tx_out);
+        // coin back
+        uint64_t l_value_back = l_value_sell - a_stake->value;
+        if (l_value_back) {
+            if (dap_chain_datum_tx_add_out_item(&l_tx, l_owner_addr, l_value_back) != 1) {
+                dap_chain_datum_tx_delete(l_tx);
+                DAP_DELETE(l_owner_addr);
+                log_it(L_ERROR, "Cant add coin back output");
+                return NULL;
+            }
+        }
+    }
+    DAP_DELETE(l_owner_addr);
+
+    // add 'sign' item
+    if(dap_chain_datum_tx_add_sign_item(&l_tx, l_owner_key) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        log_it(L_ERROR, "Can't add sign output");
+        return NULL;
+    }
+
+    return l_tx;
+}
+
+// Put the transaction to mempool or directly to chains & write transaction's hash to the price
+static bool s_stake_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_net_t *a_net)
+{
+    // Put the transaction to mempool or directly to chains
+    size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx);
+    dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, a_tx, l_tx_size);
+    DAP_DELETE(a_tx);
+    dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_TX);
+    if (!l_chain) {
+        return false;
+    }
+    // Processing will be made according to autoprocess policy
+    if (dap_chain_mempool_datum_add(l_datum, l_chain)) {
+        DAP_DELETE(l_datum);
+        return false;
+    }
+    return true;
+}
+
+static bool s_stake_tx_invalidate(dap_chain_net_srv_stake_item_t *a_stake, dap_chain_wallet_t *a_wallet)
+{
+    // create empty transaction
+    dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
+
+    dap_ledger_t *l_ledger = dap_chain_ledger_by_net_name(a_stake->net->pub.name);
+    dap_chain_addr_t *l_owner_addr = (dap_chain_addr_t *)dap_chain_wallet_get_addr(a_wallet, a_stake->net->pub.id);
+    dap_enc_key_t *l_owner_key = dap_chain_wallet_get_key(a_wallet, 0);
+
+    // create and add reciept
+    dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED};
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_ID };
+    dap_chain_datum_tx_receipt_t *l_receipt =  dap_chain_datum_tx_receipt_create(l_uid, l_unit, 0, a_stake->value, NULL, 0);
+    dap_chain_datum_tx_add_item(&l_tx, (byte_t *)l_receipt);
+    DAP_DELETE(l_receipt);
+
+    // add 'in' item to buy from conditional transaction
+    dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_ledger, &a_stake->tx_hash);
+    if (!l_cond_tx) {
+        log_it(L_WARNING, "Requested conditional transaction not found");
+        return false;
+    }   
+    int l_prev_cond_idx;
+    dap_chain_tx_out_cond_t *l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_cond_tx, &l_prev_cond_idx);
+    if (dap_chain_ledger_tx_hash_is_used_out_item(l_ledger, &a_stake->tx_hash, l_prev_cond_idx)) {
+        log_it(L_WARNING, "Requested conditional transaction is already used out");
+        return false;
+    }
+    dap_chain_datum_tx_add_in_cond_item(&l_tx, &a_stake->tx_hash, l_prev_cond_idx, 0);
+
+    // add 'out' item
+    if (dap_chain_datum_tx_add_out_item(&l_tx, l_owner_addr, l_tx_out_cond->header.value) == -1) {
+        dap_chain_datum_tx_delete(l_tx);
+        DAP_DELETE(l_owner_addr);
+        log_it(L_ERROR, "Cant add returning coins output");
+        return false;
+    }
+    DAP_DELETE(l_owner_addr);
+
+    // add 'sign' items
+    if(dap_chain_datum_tx_add_sign_item(&l_tx, l_owner_key) != 1) {
+        dap_chain_datum_tx_delete(l_tx);
+        log_it( L_ERROR, "Can't add sign output");
+        return false;
+    }
+    if (!s_stake_tx_put(l_tx, a_stake->net)) {
+        return false;
+    }
+    return true;
+}
+
+char *s_stake_order_create(dap_chain_net_srv_stake_item_t *a_item)
+{
+    dap_chain_hash_fast_t l_tx_hash = {};
+    dap_srv_stake_order_ext_t l_ext;
+    memcpy(&l_ext.addr_from, &a_item->addr_from, sizeof(dap_chain_addr_t));
+    memcpy(&l_ext.addr_to, &a_item->addr_to, sizeof(dap_chain_addr_t));
+    l_ext.fee_value = a_item->fee_value;
+    uint32_t l_ext_size = sizeof(dap_srv_stake_order_ext_t);
+    dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_item->net);
+    dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 =  SERV_UNIT_UNDEFINED};
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_ID };
+    char *l_order_hash_str = dap_chain_net_srv_order_create(a_item->net, SERV_DIR_BUY, l_uid, *l_node_addr,
+                                                            l_tx_hash, a_item->value, l_unit, a_item->token, 0,
+                                                            (uint8_t *)&l_ext, l_ext_size, NULL, 0, NULL);
+    return l_order_hash_str;
+}
+
+dap_chain_net_srv_stake_item_t *s_stake_item_from_order(dap_chain_net_t *a_net, dap_chain_net_srv_order_t *a_order)
+{
+    dap_chain_net_srv_stake_item_t *l_item = DAP_NEW_Z(dap_chain_net_srv_stake_item_t);
+    dap_srv_stake_order_ext_t *l_ext = (dap_srv_stake_order_ext_t *)a_order->ext;
+    memcpy(&l_item->addr_from, &l_ext->addr_from, sizeof(dap_chain_addr_t));
+    memcpy(&l_item->addr_to, &l_ext->addr_to, sizeof(dap_chain_addr_t));
+    l_item->fee_value = l_ext->fee_value;
+    l_item->net = a_net;
+    l_item->value = a_order->price;
+    strcpy(l_item->token, a_order->price_ticker);
+    return l_item;
+}
+
+static int s_cli_srv_stake_order(int a_argc, char **a_argv, int a_arg_index, char **a_str_reply)
+{
+    enum {
+        CMD_NONE, CMD_CREATE, CMD_REMOVE, CMD_LIST, CMD_UPDATE
+    };
+    int l_cmd_num = CMD_NONE;
+    if(dap_chain_node_cli_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "create", NULL)) {
+        l_cmd_num = CMD_CREATE;
+    }
+    else if(dap_chain_node_cli_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "remove", NULL)) {
+        l_cmd_num = CMD_REMOVE;
+    }
+    else if(dap_chain_node_cli_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "list", NULL)) {
+        l_cmd_num = CMD_LIST;
+    }
+    else if(dap_chain_node_cli_find_option_val(a_argv, a_arg_index, min(a_argc, a_arg_index + 1), "update", NULL)) {
+        l_cmd_num = CMD_UPDATE;
+    }
+    int l_arg_index = a_arg_index + 1;
+    switch (l_cmd_num) {
+        case CMD_CREATE: {
+            const char *l_net_str = NULL, *l_token_str = NULL, *l_coins_str = NULL;
+            const char *l_addr_from_str = NULL, *l_addr_to_str = NULL, *l_fee_str = NULL;
+            dap_chain_net_t *l_net = NULL;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -net");
+                return -3;
+            }
+            l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-token", &l_token_str);
+            if (!l_token_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -token");
+                return -5;
+            }
+            if (!dap_chain_ledger_token_ticker_check(l_net->pub.ledger, l_token_str)) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_str);
+                return -6;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_coins_str);
+            if (!l_coins_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -coins");
+                return -7;
+            }
+            uint64_t l_value = strtoull(l_coins_str, NULL, 10);
+            if (!l_value) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
+                return -8;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_from", &l_addr_from_str);
+            if (!l_addr_from_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -addr_from");
+                return -9;
+            }
+            dap_chain_addr_t *l_addr_from = dap_chain_addr_from_str(l_addr_from_str);
+            if (!l_addr_from) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
+                return -10;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_to", &l_addr_to_str);
+            if (!l_addr_to_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -addr_to");
+                return -9;
+            }
+            dap_chain_addr_t *l_addr_to = dap_chain_addr_from_str(l_addr_to_str);
+            if (!l_addr_to) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
+                return -10;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-fee_percent", &l_fee_str);
+            if (!l_fee_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order create' required parameter -fee_percent");
+                return -11;
+            }
+            long double l_fee = strtold(l_fee_str, NULL);
+            if (!l_fee) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Format -fee_percent <long double> %");
+                return -12;
+            }
+            // Create the stake item
+            dap_chain_net_srv_stake_item_t *l_stake = DAP_NEW_Z(dap_chain_net_srv_stake_item_t);
+            l_stake->net = l_net;
+            dap_stpcpy(l_stake->token, l_token_str);
+            l_stake->value = l_value;
+            memcpy(&l_stake->addr_from, l_addr_from, sizeof(dap_chain_addr_t));
+            memcpy(&l_stake->addr_to, l_addr_to, sizeof(dap_chain_addr_t));
+            DAP_DELETE(l_addr_from);
+            DAP_DELETE(l_addr_to);
+            l_stake->fee_value = l_fee;
+            // Create the order & put it to GDB
+            char *l_order_hash_str = s_stake_order_create(l_stake);
+            if (l_order_hash_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
+                DAP_DELETE(l_order_hash_str);
+                DAP_DELETE(l_stake);
+            } else {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the order");
+                DAP_DELETE(l_stake);
+                return -15;
+            }
+        } break;
+        case CMD_REMOVE: {
+            const char *l_net_str = NULL, *l_order_hash_str = NULL;
+            dap_chain_net_t *l_net = NULL;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order remove' requires parameter -net");
+                return -3;
+            }
+            l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order remove' requires parameter -order");
+                return -13;
+            }
+            if (dap_chain_net_srv_order_delete_by_hash_str(l_net, l_order_hash_str)) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't remove order %s\n", l_order_hash_str);
+                return -14;
+            }
+            dap_chain_node_cli_set_reply_text(a_str_reply, "Stake order successfully removed");
+        } break;
+        case CMD_UPDATE: {
+            const char *l_net_str = NULL, *l_token_str = NULL, *l_coins_str = NULL;
+            const char *l_addr_from_str = NULL, *l_addr_to_str = NULL, *l_fee_str = NULL;
+            char *l_order_hash_str = NULL;
+            dap_chain_net_t *l_net = NULL;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order update' required parameter -net");
+                return -3;
+            }
+            l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order update' requires parameter -order");
+                return -13;
+            }
+            dap_chain_net_srv_order_t *l_order =  dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
+            if (!l_order) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't find order %s\n", l_order_hash_str);
+                return -14;
+            }
+            dap_chain_net_srv_stake_item_t *l_stake = s_stake_item_from_order(l_net, l_order);
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-token", &l_token_str);
+            if (l_token_str) {
+                if (!dap_chain_ledger_token_ticker_check(l_net->pub.ledger, l_token_str)) {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Token ticker %s not found", l_token_str);
+                    return -6;
+                }
+                strcpy(l_stake->token, l_token_str);
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_coins_str);
+            if (l_coins_str) {
+                uint64_t l_value = strtoull(l_coins_str, NULL, 10);
+                if (!l_value) {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Format -coins <unsigned long long>");
+                    return -8;
+                }
+                l_stake->value = l_value;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_from", &l_addr_from_str);
+            if (l_addr_from_str) {
+                dap_chain_addr_t *l_addr_from = dap_chain_addr_from_str(l_addr_from_str);
+                if (!l_addr_from) {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
+                    return -10;
+                }
+                memcpy(&l_stake->addr_from, l_addr_from, sizeof(dap_chain_addr_t));
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-addr_to", &l_addr_to_str);
+            if (l_addr_to_str) {
+                dap_chain_addr_t *l_addr_to = dap_chain_addr_from_str(l_addr_to_str);
+                if (!l_addr_to) {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
+                    return -10;
+                }
+                memcpy(&l_stake->addr_to, l_addr_to, sizeof(dap_chain_addr_t));
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-fee_percent", &l_fee_str);
+            if (l_fee_str) {
+                long double l_fee = strtold(l_fee_str, NULL);
+                if (!l_fee) {
+                    dap_chain_node_cli_set_reply_text(a_str_reply, "Format -fee_percent <long double> %");
+                    return -12;
+                }
+            }
+            if (!l_token_str && !l_coins_str && !l_addr_from_str && !l_addr_to_str && !l_fee_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "At least one of updating parameters is mandatory");
+                return -16;
+            }
+            // Create the order & put it to GDB
+            dap_chain_net_srv_order_delete_by_hash_str(l_net, l_order_hash_str);
+            l_order_hash_str = s_stake_order_create(l_stake);
+            if (l_order_hash_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Successfully created order %s", l_order_hash_str);
+                DAP_DELETE(l_order_hash_str);
+                DAP_DELETE(l_stake);
+            } else {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't compose the order");
+                DAP_DELETE(l_stake);
+                return -15;
+            }
+        } break;
+        case CMD_LIST: {
+            const char *l_net_str = NULL;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'order list' required parameter -net");
+                return -3;
+            }
+            dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            char * l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(l_net);
+            size_t l_orders_count = 0;
+            dap_global_db_obj_t * l_orders = dap_chain_global_db_gr_load(l_gdb_group_str, &l_orders_count);
+            dap_chain_net_srv_stake_item_t *l_stake;
+            dap_string_t *l_reply_str = dap_string_new("");
+            for (size_t i = 0; i < l_orders_count; i++) {
+                dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)l_orders[i].value;
+                if (l_order->srv_uid.uint64 != DAP_CHAIN_NET_SRV_STAKE_ID)
+                    continue;
+                // TODO add filters to list (token, address, etc.)
+                l_stake = s_stake_item_from_order(l_net, l_order);
+                char *l_addr = dap_chain_addr_to_str(&l_stake->addr_to);
+                dap_string_append_printf(l_reply_str, "%s %lu %s %s %llf\n", l_orders[i].key, l_stake->value, l_stake->token,
+                                         l_addr, l_stake->fee_value);
+                DAP_DELETE(l_addr);
+                DAP_DELETE(l_stake);
+            }
+            dap_chain_global_db_objs_delete(l_orders, l_orders_count);
+            DAP_DELETE( l_gdb_group_str);
+            if (!l_reply_str->len) {
+                dap_string_append(l_reply_str, "No orders found");
+            }
+            *a_str_reply = dap_string_free(l_reply_str, false);
+        } break;
+        default: {
+            dap_chain_node_cli_set_reply_text(a_str_reply, "Subcommand %s not recognized", a_argv[a_arg_index]);
+            return -2;
+        }
+    }
+    return 0;
+}
+
+static int s_cli_srv_stake(int a_argc, char **a_argv, void *a_arg_func, char **a_str_reply)
+{
+    UNUSED(a_arg_func);
+    enum {
+        CMD_NONE, CMD_ORDER, CMD_DELEGATE, CMD_TX, CMD_INVALIDATE
+    };
+    int l_arg_index = 1;
+    int l_cmd_num = CMD_NONE;
+    if (dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "order", NULL)) {
+        l_cmd_num = CMD_ORDER;
+    }
+    else if (dap_chain_node_cli_find_option_val(a_argv, l_arg_index, min(a_argc, l_arg_index + 1), "delegate", NULL)) {
+        l_cmd_num = CMD_DELEGATE;
+    }
+    switch (l_cmd_num) {
+        case CMD_ORDER:
+            return s_cli_srv_stake_order(a_argc, a_argv, l_arg_index + 1, a_str_reply);
+        case CMD_DELEGATE: {
+            const char *l_net_str = NULL, *l_wallet_str = NULL, *l_order_hash_str = NULL, *l_addr_fee_str = NULL;
+            l_arg_index++;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -net");
+                return -3;
+            }
+            dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str);
+            if (!l_wallet_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -wallet");
+                return -17;
+            }
+            dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
+            if (!l_wallet) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Specified wallet not found");
+                return -18;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-order", &l_order_hash_str);
+            if (!l_order_hash_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -order");
+                return -13;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-fee_addr", &l_addr_fee_str);
+            if (!l_addr_fee_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -fee_addr");
+                return -9;
+            }
+            dap_chain_addr_t *l_addr_fee = dap_chain_addr_from_str(l_addr_fee_str);
+            if (!l_addr_fee) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Wrong address format");
+                return -10;
+            }
+            dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str);
+            if (l_order) {
+                dap_chain_net_srv_stake_item_t *l_stake = s_stake_item_from_order(l_net, l_order);
+                memcpy(&l_stake->addr_fee, l_addr_fee, sizeof(dap_chain_addr_t));
+                DAP_DELETE(l_addr_fee);
+                // Create conditional transaction
+                dap_chain_datum_tx_t *l_tx = s_stake_tx_create(l_stake, l_wallet);
+                dap_chain_wallet_close(l_wallet);
+                if (l_tx && s_stake_tx_put(l_tx, l_net)) {
+                    // TODO send request to order owner to delete it
+                    dap_chain_net_srv_order_delete_by_hash_str(l_net, l_order_hash_str);
+                }
+                DAP_DELETE(l_order);
+                dap_chain_node_cli_set_reply_text(a_str_reply, l_tx ? "Stake transaction has done" :
+                                                                      "Stake transaction error");
+                if (!l_tx) {
+                    DAP_DELETE(l_stake);
+                    return -19;
+                }
+                HASH_ADD(hh, s_srv_stake->itemlist, addr_to, sizeof(dap_chain_addr_t), l_stake);
+            } else {
+                DAP_DELETE(l_addr_fee);
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Specified order not found");
+                return -14;
+            }
+        } break;
+        case CMD_TX: {
+            const char *l_net_str = NULL;
+            l_arg_index++;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'transactions' required parameter -net");
+                return -3;
+            }
+            dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp;
+            dap_string_t *l_reply_str = dap_string_new("");
+            HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) {
+                if (l_stake->net->pub.id.uint64 != l_net->pub.id.uint64) {
+                    continue;
+                }
+                char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_stake->tx_hash);
+                char *l_addr_from_str = dap_chain_addr_to_str(&l_stake->addr_from);
+                char *l_addr_to_str = dap_chain_addr_to_str(&l_stake->addr_to);
+                char *l_addr_fee_str = dap_chain_addr_to_str(&l_stake->addr_fee);
+                dap_string_append_printf(l_reply_str, "%s %s %lu %s %s %s %llf\n", l_tx_hash_str, l_stake->token,
+                                         l_stake->value, l_addr_from_str, l_addr_to_str,
+                                         l_addr_fee_str, l_stake->fee_value);
+                DAP_DELETE(l_tx_hash_str);
+                DAP_DELETE(l_addr_from_str);
+                DAP_DELETE(l_addr_to_str);
+                DAP_DELETE(l_addr_fee_str);
+            }
+            if (!l_reply_str->len) {
+                dap_string_append(l_reply_str, "Pricelist is empty");
+            }
+            *a_str_reply = dap_string_free(l_reply_str, false);
+        } break;
+        case CMD_INVALIDATE: {
+            const char *l_net_str = NULL, *l_wallet_str = NULL, *l_tx_hash_str = NULL;
+            l_arg_index++;
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str);
+            if (!l_net_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -net");
+                return -3;
+            }
+            dap_chain_net_t *l_net = dap_chain_net_by_name(l_net_str);
+            if (!l_net) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Network %s not found", l_net_str);
+                return -4;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-wallet", &l_wallet_str);
+            if (!l_wallet_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -wallet");
+                return -17;
+            }
+            dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config));
+            if (!l_wallet) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Specified wallet not found");
+                return -18;
+            }
+            dap_chain_node_cli_find_option_val(a_argv, l_arg_index, a_argc, "-tx", &l_tx_hash_str);
+            if (!l_tx_hash_str) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Command 'delegate' required parameter -tx");
+                return -13;
+            }
+            dap_chain_hash_fast_t l_tx_hash = {};
+            dap_chain_str_to_hash_fast(l_tx_hash_str, &l_tx_hash);
+            dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp;
+            HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) {
+                if (!memcmp(&l_stake->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) {
+                    break;
+                }
+            }
+            if (!l_stake) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Transaction %s not found", l_tx_hash_str);
+                dap_chain_wallet_close(l_wallet);
+                return -20;
+            }
+            bool l_success = s_stake_tx_invalidate(l_stake, l_wallet);
+            dap_chain_wallet_close(l_wallet);
+            if (l_success) {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Stake successfully returned to owner");
+                HASH_DEL(s_srv_stake->itemlist, l_stake);
+            } else {
+                dap_chain_node_cli_set_reply_text(a_str_reply, "Can't invalidate transaction %s", l_tx_hash_str);
+                return -21;
+            }
+        } break;
+        default: {
+            dap_chain_node_cli_set_reply_text(a_str_reply, "Command %s not recognized", a_argv[l_arg_index]);
+            return -1;
+        }
+    }
+    return 0;
+}
diff --git a/modules/service/stake/include/dap_chain_net_srv_stake.h b/modules/service/stake/include/dap_chain_net_srv_stake.h
new file mode 100644
index 0000000000000000000000000000000000000000..6cc4feab7e7c9aad1fafa3b1991b3d4a5f8c649b
--- /dev/null
+++ b/modules/service/stake/include/dap_chain_net_srv_stake.h
@@ -0,0 +1,70 @@
+/*
+ * Authors:
+ * Roman Khlopkov <roman.khlopkov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * DeM Labs Open source community https://gitlab.demlabs.net
+ * Copyright  (c) 2017-2020
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+    DAP (Deus Applicaions Prototypes) 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.
+
+    DAP 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 DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#pragma once
+
+#include "dap_chain_net_srv.h"
+#include "dap_chain_net_srv_order.h"
+
+#define DAP_CHAIN_NET_SRV_STAKE_ID 0x3
+
+typedef struct dap_chain_net_srv_stake_item {
+    dap_chain_net_t *net;
+    char token[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint64_t value;
+    dap_chain_addr_t addr_from;
+    dap_chain_addr_t addr_to;
+    dap_chain_addr_t addr_fee;
+    long double fee_value;
+    dap_chain_hash_fast_t tx_hash;
+    dap_chain_hash_fast_t order_hash;
+    UT_hash_handle hh;
+} dap_chain_net_srv_stake_item_t;
+
+/*typedef struct dap_chain_net_srv_xchange_db_item {
+    char token_sell[DAP_CHAIN_TICKER_SIZE_MAX];
+    char token_buy[DAP_CHAIN_TICKER_SIZE_MAX];
+    uint8_t padding[4];
+    uint64_t net_sell_id;
+    uint64_t net_buy_id;
+    uint64_t datoshi_sell;
+    long double rate;
+    dap_chain_hash_fast_t tx_hash;
+    dap_chain_hash_fast_t order_hash;
+    char wallet_str[];
+} DAP_ALIGN_PACKED dap_chain_net_srv_xchange_db_item_t;*/
+
+typedef struct dap_srv_stake_order_ext {
+    dap_chain_addr_t addr_from;
+    dap_chain_addr_t addr_to;
+    long double fee_value;
+} dap_srv_stake_order_ext_t;
+
+typedef struct dap_chain_net_srv_stake {
+    dap_chain_net_srv_stake_item_t *itemlist;
+} dap_chain_net_srv_stake_t;
+
+int dap_chain_net_srv_xchange_init();
+void dap_chain_net_srv_xchange_deinit();
+bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx);
diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c
index 77ea96341e182ecfca7a42715e522add61497f38..5ac9c7f983bb46e7d0e40ad1b922a2acbda0c7b4 100644
--- a/modules/service/xchange/dap_chain_net_srv_xchange.c
+++ b/modules/service/xchange/dap_chain_net_srv_xchange.c
@@ -49,40 +49,40 @@ static dap_chain_net_srv_xchange_t *s_srv_xchange;
  */
 int dap_chain_net_srv_xchange_init()
 {
-        dap_chain_node_cli_cmd_item_create("srv_xchange", s_cli_srv_xchange, NULL, "eXchange service commands",
-        "srv_xchange price create -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>"
-                                            "-wallet <name> -coins <value> -rate <value>\n"
-            "\tCreate a new price with specified amount of datoshi to exchange with specified rate (sell : buy)\n"
-        "srv_xchange price remove -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>\n"
-             "\tRemove price with specified tickers within specified net names\n"
-        "srv_xchange price list\n"
-             "\tList all active prices\n"
-        "srv_xchange price update -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>"
-                                            "{-coins <value> | rate <value> | -wallet <name>}\n"
-             "\tUpdate price with specified tickers within specified net names\n"
-        "srv_xchange orders -net <net name>\n"
-             "\tGet the exchange orders list within specified net name\n"
-        "srv_xchange purchase -order <order hash> -net <net name> -wallet <wallet_name> -coins <value>\n"
-             "\tExchange tokens with specified order within specified net name. Specify how datoshies to buy\n"
-        "srv_xchange enable\n"
-             "\tEnable eXchange service\n"
-        "srv_xchange disable\n"
-             "\tDisable eXchange service\n"
-        );
-        dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID };
-        dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, s_callback_requested, s_callback_response_success,
-                                                           s_callback_response_error, s_callback_receipt_next_success);
-        s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t);
-        l_srv->_inhertor = s_srv_xchange;
-        s_srv_xchange->enabled = false;
-        size_t l_prices_count = 0;
-        dap_global_db_obj_t *l_prices = dap_chain_global_db_gr_load(GROUP_LOCAL_XCHANGE, &l_prices_count);
-        for (size_t i = 0; i < l_prices_count; i++) {
-            dap_chain_net_srv_xchange_price_t *l_price = s_xchange_db_load(l_prices[i].key, l_prices[i].value);
-            HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price);
-        }
-        dap_chain_global_db_objs_delete(l_prices, l_prices_count);
-        return 0;
+    dap_chain_node_cli_cmd_item_create("srv_xchange", s_cli_srv_xchange, NULL, "eXchange service commands",
+    "srv_xchange price create -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>"
+                                        "-wallet <name> -coins <value> -rate <value>\n"
+        "\tCreate a new price with specified amount of datoshi to exchange with specified rate (sell : buy)\n"
+    "srv_xchange price remove -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>\n"
+         "\tRemove price with specified tickers within specified net names\n"
+    "srv_xchange price list\n"
+         "\tList all active prices\n"
+    "srv_xchange price update -net_sell <net name> -token_sell <token ticker> -net_buy <net_name> -token_buy <token ticker>"
+                                        "{-coins <value> | rate <value> | -wallet <name>}\n"
+         "\tUpdate price with specified tickers within specified net names\n"
+    "srv_xchange orders -net <net name>\n"
+         "\tGet the exchange orders list within specified net name\n"
+    "srv_xchange purchase -order <order hash> -net <net name> -wallet <wallet_name> -coins <value>\n"
+         "\tExchange tokens with specified order within specified net name. Specify how datoshies to buy\n"
+    "srv_xchange enable\n"
+         "\tEnable eXchange service\n"
+    "srv_xchange disable\n"
+         "\tDisable eXchange service\n"
+    );
+    dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID };
+    dap_chain_net_srv_t* l_srv = dap_chain_net_srv_add(l_uid, s_callback_requested, s_callback_response_success,
+                                                       s_callback_response_error, s_callback_receipt_next_success);
+    s_srv_xchange = DAP_NEW_Z(dap_chain_net_srv_xchange_t);
+    l_srv->_inhertor = s_srv_xchange;
+    s_srv_xchange->enabled = false;
+    size_t l_prices_count = 0;
+    dap_global_db_obj_t *l_prices = dap_chain_global_db_gr_load(GROUP_LOCAL_XCHANGE, &l_prices_count);
+    for (size_t i = 0; i < l_prices_count; i++) {
+        dap_chain_net_srv_xchange_price_t *l_price = s_xchange_db_load(l_prices[i].key, l_prices[i].value);
+        HASH_ADD_KEYPTR(hh, s_srv_xchange->pricelist, l_price->key_ptr, strlen(l_price->key_ptr), l_price);
+    }
+    dap_chain_global_db_objs_delete(l_prices, l_prices_count);
+    return 0;
 }
 
 void dap_chain_net_srv_xchange_deinit()
@@ -100,43 +100,32 @@ void dap_chain_net_srv_xchange_deinit()
 
 bool dap_chain_net_srv_xchange_verificator(dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx)
 {
-    /* Check only one of following conditions for verification success
-     * 1. addr(a_cond.params).data.key == a_tx.sign.pkey -- for condition owner
-     * 2. a_cond.srv_xchange.(value && token && addr) == a_tx.out.(value && token && addr) -- for exchange
+    /* Check the condition for verification success
+     * a_cond.srv_xchange.rate >= a_tx.out.rate
      */
-    dap_chain_addr_t *l_seller_addr = (dap_chain_addr_t *)a_cond->params;
-    dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL);
-    dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig);
-    size_t l_pkey_ser_size = 0;
-    const uint8_t *l_pkey_ser = dap_sign_get_pkey(l_sign, &l_pkey_ser_size);
-    if (!memcmp(l_seller_addr->data.key, l_pkey_ser, l_pkey_ser_size)) {
-        // it's the condition owner, let the transaction to be performed
-        return true;
-    } else {
-        dap_list_t *l_list_out = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_EXT, NULL);
-        long double l_seller_rate = (long double)a_cond->header.value / a_cond->subtype.srv_xchange.value;
-        uint64_t l_out_val = 0, l_back_val = 0;
-        char *l_ticker_ctrl = NULL;
-        for (dap_list_t *l_list_tmp = l_list_out; l_list_tmp;  l_list_tmp = l_list_tmp->next) {
-            dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)l_list_tmp->data;
-            if (memcmp(&l_tx_out->addr, &a_cond->params, sizeof(dap_chain_addr_t))) {
-                continue;
-            }
-            if (strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.token)) {
-                if (l_ticker_ctrl && strcmp(l_ticker_ctrl, l_tx_out->token)) {
-                    return false;   // too many tokens
-                }
-                l_ticker_ctrl = l_tx_out->token;
-                l_back_val += l_tx_out->header.value;
-            } else {                // buying token
-                l_out_val += l_tx_out->header.value;
-            }
+    dap_list_t *l_list_out = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_EXT, NULL);
+    long double l_seller_rate = (long double)a_cond->header.value / a_cond->subtype.srv_xchange.value;
+    uint64_t l_out_val = 0, l_back_val = 0;
+    char *l_ticker_ctrl = NULL;
+    for (dap_list_t *l_list_tmp = l_list_out; l_list_tmp;  l_list_tmp = l_list_tmp->next) {
+        dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)l_list_tmp->data;
+        if (memcmp(&l_tx_out->addr, &a_cond->params, sizeof(dap_chain_addr_t))) {
+            continue;
         }
-        long double l_buyer_rate = (a_cond->header.value - l_back_val) / (long double)l_out_val;
-        if (l_seller_rate < l_buyer_rate) {
-            return false;           // wrong changing rate
+        if (strcmp(l_tx_out->token, a_cond->subtype.srv_xchange.token)) {
+            if (l_ticker_ctrl && strcmp(l_ticker_ctrl, l_tx_out->token)) {
+                return false;   // too many tokens
+            }
+            l_ticker_ctrl = l_tx_out->token;
+            l_back_val += l_tx_out->header.value;
+        } else {                // buying token
+            l_out_val += l_tx_out->header.value;
         }
     }
+    long double l_buyer_rate = (a_cond->header.value - l_back_val) / (long double)l_out_val;
+    if (l_seller_rate < l_buyer_rate) {
+        return false;           // wrong changing rate
+    }
     return true;
 }
 
@@ -412,7 +401,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha
     uint64_t l_datoshi_buy = ceill(a_price->datoshi_sell / a_price->rate);
     char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net_buy, SERV_DIR_SELL, l_uid, *l_node_addr,
                                                             l_tx_hash, l_datoshi_buy, l_unit, a_price->token_buy, 0,
-                                                            (uint8_t *)&l_ext, l_ext_size, NULL, 0);
+                                                            (uint8_t *)&l_ext, l_ext_size, NULL, 0, NULL);
     return l_order_hash_str;
 }
 
diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c
index 6c13fe137dea20560006b88dc5218052d9ad64b8..f43a37fd4caccb6c9307dd8ab025defc4044c3f1 100644
--- a/modules/type/dag/dap_chain_cs_dag.c
+++ b/modules/type/dag/dap_chain_cs_dag.c
@@ -1266,16 +1266,16 @@ static int s_cli_dag(int argc, char ** argv, void *arg_func, char **a_str_reply)
                             dap_string_append_printf(l_str_tmp,"\t\t\t\tERROR: wrong sign size 0, stop parsing headers\n");
                             break;
                         }
-                        dap_enc_key_t * l_sign_key = dap_sign_to_enc_key(l_sign);
                         dap_chain_addr_t l_addr = {0};
-                        dap_chain_addr_fill(&l_addr,l_sign_key,&l_net->pub.id);
+                        dap_chain_hash_fast_t l_pkey_hash;
+                        dap_sign_get_pkey_hash(l_sign, &l_pkey_hash);
+                        dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, &l_net->pub.id);
                         char * l_addr_str = dap_chain_addr_to_str(&l_addr);
                         dap_string_append_printf(l_str_tmp,"\t\t\t\t\t\ttype: %s\taddr: %s"
                                                            "n", dap_sign_type_to_str( l_sign->header.type ),
                                                  l_addr_str );
                         l_offset += l_sign_size;
                         DAP_DELETE( l_addr_str);
-                        dap_enc_key_delete(l_sign_key);
                     }
                     dap_chain_net_dump_datum(l_str_tmp, l_datum);
 
diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c
index ac14456bde419486265b174b99dd99f16ae910b8..b392881900937d5a02ce6aa61a609d6c1b3096e5 100644
--- a/modules/wallet/dap_chain_wallet.c
+++ b/modules/wallet/dap_chain_wallet.c
@@ -205,8 +205,19 @@ dap_chain_addr_t* dap_chain_wallet_get_addr(dap_chain_wallet_t * a_wallet, dap_c
  */
 dap_chain_addr_t * dap_cert_to_addr(dap_cert_t * a_cert, dap_chain_net_id_t a_net_id)
 {
+    dap_sign_type_t l_type = dap_sign_type_from_key_type(a_cert->enc_key->type);
+    size_t l_pub_key_data_size;
+    uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_cert->enc_key, &l_pub_key_data_size);
+    if (!l_pub_key_data) {
+        log_it(L_ERROR,"Can't fill address from key, its empty");
+        return NULL;
+    }
+    dap_chain_hash_fast_t l_hash_public_key;
+    // serialized key -> key hash
+    dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key);
     dap_chain_addr_t * l_addr = DAP_NEW_Z(dap_chain_addr_t);
-    dap_chain_addr_fill(l_addr, a_cert->enc_key, &a_net_id);
+    dap_chain_addr_fill(l_addr, l_type, &l_hash_public_key, &a_net_id);
+    DAP_DELETE(l_pub_key_data);
     return l_addr;
 }