COOPENOMICS  v1
Кооперативная Экономика
global_state.hpp
См. документацию.
1#pragma once
2
3#include <eosio/binary_extension.hpp>
4
5using namespace eosio;
6using std::string;
7
8namespace Capital {
9
13 // Значения по умолчанию держатся В СООТВЕТСТВИИ с defaultConfig бэкенда
14 // (controller/src/extensions/capital/capital-extension.module.ts): именно он
15 // задаёт конфигурацию кооперативу при онбординге, а эти значения работают
16 // ровно до неё. Пока они расходились, кооператив без явной настройки жил по
17 // другим правилам, чем показывал интерфейс.
18 struct config {
20 double expense_pool_percent = 100;
22 uint32_t voting_period_in_days = 1;
23 double authors_voting_percent = 62.8;
25
26 // Параметры геймификации
28 uint64_t level_depth_base = 100000000;
31 };
32
41 struct [[eosio::table, eosio::contract(CAPITAL)]] global_state {
42 eosio::name coopname;
43 asset global_available_invest_pool = asset(0, _root_govern_symbol);
44 asset program_membership_funded = asset(0, _root_govern_symbol);
45 asset program_membership_available = asset(0, _root_govern_symbol);
46 asset program_membership_distributed = asset(0, _root_govern_symbol);
48
50
51 // ВНИМАНИЕ: поля программных расходов добавлены ПОСЛЕ config и обёрнуты в
52 // binary_extension. Поля в таблицу EOSIO можно дописывать только в ХВОСТ
53 // struct и только через binary_extension — иначе ломается десериализация
54 // уже записанного global_state. Инцидент 2026-06-16: эти поля были вставлены
55 // перед config напрямую (без extension) и задеплоены на прод — таблица state
56 // перестала читаться (get table → "Invalid symbol", action'ы падали на unpack).
57 // Инвариант: оба поля материализуются вместе (всегда оба has_value или оба
58 // пустые), чтобы порядок хвостовых extension оставался консистентным.
59 eosio::binary_extension<asset> program_expense_pool;
60 eosio::binary_extension<asset> program_expense_reserved;
61
62 uint64_t primary_key() const { return coopname.value; }
63 };
64
65 typedef eosio::multi_index<"state"_n, global_state> global_state_table;
66
67
68
69
70namespace State {
71
80inline asset ext_or_zero(const eosio::binary_extension<asset>& v, const eosio::symbol& sym) {
81 if (!v.has_value()) {
82 return asset(0, sym);
83 }
84 const asset &a = v.value();
85 if (a.symbol == sym) {
86 return a;
87 }
88 eosio::check(a.amount == 0,
89 "program_expense_* содержит ненулевую сумму с несовместимым символом");
90 return asset(0, sym);
91}
92
100inline void update_global_state(const global_state& gs){
101 global_state_table global_state_inst(_capital, _capital.value);
102 auto itr = global_state_inst.find(gs.coopname.value);
103 check(itr != global_state_inst.end(), "Глобальное состояние не найдено");
105 const asset reserved = ext_or_zero(gs.program_expense_reserved, _root_govern_symbol);
106 global_state_inst.modify(itr, _capital, [&](auto& s) {
107 s = gs;
108 s.program_expense_pool = pool;
109 s.program_expense_reserved = reserved;
110 });
111}
112
118inline global_state get_global_state(name coopname) {
119 global_state_table global_state_inst(_capital, _capital.value);
120 auto itr = global_state_inst.find(coopname.value);
121 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
122 return global_state(*itr);
123}
124
130inline void is_initialized(name coopname) {
131 global_state_table global_state_inst(_capital, _capital.value);
132 auto itr = global_state_inst.find(coopname.value);
133 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
134}
135
140inline void topup_program_expense_pool(eosio::name coopname, const asset &amount) {
141 global_state_table global_state_inst(_capital, _capital.value);
142 auto itr = global_state_inst.find(coopname.value);
143 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
144 eosio::check(amount.is_valid() && amount.amount > 0, "Сумма пополнения должна быть положительной");
145 eosio::check(amount.symbol == _root_govern_symbol, "Символ суммы пополнения должен совпадать с символом программы");
146 eosio::check(itr->global_available_invest_pool >= amount,
147 "Недостаточно свободных инвестиций программы для пополнения пула расходов");
148
149 global_state_inst.modify(itr, _capital, [&](auto &s) {
150 asset pool = ext_or_zero(s.program_expense_pool, amount.symbol);
151 asset reserved = ext_or_zero(s.program_expense_reserved, amount.symbol);
152 s.global_available_invest_pool -= amount;
153 pool += amount;
154 s.program_expense_pool = pool;
155 s.program_expense_reserved = reserved;
156 });
157}
158
163inline void reserve_program_expense(eosio::name coopname, const asset &amount) {
164 global_state_table global_state_inst(_capital, _capital.value);
165 auto itr = global_state_inst.find(coopname.value);
166 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
167 eosio::check(amount.is_valid() && amount.amount > 0, "Сумма резерва должна быть положительной");
168 eosio::check(ext_or_zero(itr->program_expense_pool, amount.symbol) >= amount,
169 "Недостаточно средств в пуле программных расходов");
170
171 global_state_inst.modify(itr, _capital, [&](auto &s) {
172 asset pool = ext_or_zero(s.program_expense_pool, amount.symbol);
173 asset reserved = ext_or_zero(s.program_expense_reserved, amount.symbol);
174 pool -= amount;
175 reserved += amount;
176 s.program_expense_pool = pool;
177 s.program_expense_reserved = reserved;
178 });
179}
180
185inline void release_program_expense(eosio::name coopname, const asset &amount) {
186 global_state_table global_state_inst(_capital, _capital.value);
187 auto itr = global_state_inst.find(coopname.value);
188 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
189 eosio::check(amount.is_valid() && amount.amount > 0, "Сумма освобождения должна быть положительной");
190 eosio::check(ext_or_zero(itr->program_expense_reserved, amount.symbol) >= amount,
191 "Зарезервированных программных расходов меньше указанной суммы");
192
193 global_state_inst.modify(itr, _capital, [&](auto &s) {
194 asset pool = ext_or_zero(s.program_expense_pool, amount.symbol);
195 asset reserved = ext_or_zero(s.program_expense_reserved, amount.symbol);
196 reserved -= amount;
197 pool += amount;
198 s.program_expense_pool = pool;
199 s.program_expense_reserved = reserved;
200 });
201}
202
208inline void consume_program_expense(eosio::name coopname, const asset &amount) {
209 global_state_table global_state_inst(_capital, _capital.value);
210 auto itr = global_state_inst.find(coopname.value);
211 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
212 eosio::check(amount.is_valid() && amount.amount > 0, "Сумма списания должна быть положительной");
213 eosio::check(ext_or_zero(itr->program_expense_reserved, amount.symbol) >= amount,
214 "Зарезервированных программных расходов меньше указанной суммы");
215
216 global_state_inst.modify(itr, _capital, [&](auto &s) {
217 asset pool = ext_or_zero(s.program_expense_pool, amount.symbol);
218 asset reserved = ext_or_zero(s.program_expense_reserved, amount.symbol);
219 reserved -= amount;
220 s.program_expense_pool = pool;
221 s.program_expense_reserved = reserved;
222 });
223}
224
230inline void spend_program_expense_pool(eosio::name coopname, const asset &amount) {
231 global_state_table global_state_inst(_capital, _capital.value);
232 auto itr = global_state_inst.find(coopname.value);
233 eosio::check(itr != global_state_inst.end(), "Контракт не инициализирован");
234 eosio::check(amount.is_valid() && amount.amount > 0, "Сумма списания должна быть положительной");
235 eosio::check(ext_or_zero(itr->program_expense_pool, amount.symbol) >= amount,
236 "Недостаточно средств в пуле программных расходов для покрытия перерасхода — пополните пул (topupprogexp)");
237
238 global_state_inst.modify(itr, _capital, [&](auto &s) {
239 asset pool = ext_or_zero(s.program_expense_pool, amount.symbol);
240 asset reserved = ext_or_zero(s.program_expense_reserved, amount.symbol);
241 pool -= amount;
242 s.program_expense_pool = pool;
243 s.program_expense_reserved = reserved;
244 });
245}
246}// namespace State
247
248}// namespace Capital
static constexpr eosio::name _capital
Definition: consts.hpp:166
static constexpr eosio::symbol _root_govern_symbol
Definition: consts.hpp:231
contract
Definition: eosio.msig_tests.cpp:977
share_type amount
Definition: eosio.token_tests.cpp:174
void release_program_expense(eosio::name coopname, const asset &amount)
Освобождает зарезервированное при отклонении программного расхода: program_expense_reserved -= amount...
Definition: global_state.hpp:185
void consume_program_expense(eosio::name coopname, const asset &amount)
Окончательное списание программного расхода (callback onpgexpdone, CLOSED): program_expense_reserved ...
Definition: global_state.hpp:208
global_state get_global_state(name coopname)
Получает текущее глобальное состояние.
Definition: global_state.hpp:118
asset ext_or_zero(const eosio::binary_extension< asset > &v, const eosio::symbol &sym)
Значение binary_extension<asset> или ноль с символом sym.
Definition: global_state.hpp:80
void reserve_program_expense(eosio::name coopname, const asset &amount)
Резервирует средства под approved/authorized программный расход: program_expense_pool -= amount,...
Definition: global_state.hpp:163
void is_initialized(name coopname)
Проверяет что контракт инициализирован.
Definition: global_state.hpp:130
void update_global_state(const global_state &gs)
Обновляет глобальное состояние новыми значениями.
Definition: global_state.hpp:100
void spend_program_expense_pool(eosio::name coopname, const asset &amount)
Прямое списание из свободного пула программных расходов — превышение факта над резервом при закрытии ...
Definition: global_state.hpp:230
void topup_program_expense_pool(eosio::name coopname, const asset &amount)
Пополняет пул программных расходов на amount из общего пула инвестиций программы. Вызывается из actio...
Definition: global_state.hpp:140
Definition: balances.cpp:6
eosio::multi_index<"state"_n, global_state > global_state_table
Таблица для хранения глобального состояния.
Definition: global_state.hpp:65
Definition: eosio.msig.hpp:34
Конфигурация контракта, управляемая пользователем.
Definition: global_state.hpp:18
double energy_decay_rate_per_day
Скорость уменьшения энергии в день
Definition: global_state.hpp:27
uint32_t voting_period_in_days
Период голосования в днях
Definition: global_state.hpp:22
double creators_voting_percent
Процент премий создателей для голосования
Definition: global_state.hpp:24
double authors_voting_percent
Процент премий авторов для голосования
Definition: global_state.hpp:23
double coordinator_bonus_percent
Процент премий координатора от инвестиций
Definition: global_state.hpp:19
double expense_pool_percent
Процент инвестиций в пул расходов
Definition: global_state.hpp:20
double energy_gain_coefficient
Множитель скорости набора уровней (по умолчанию 1.0 — вклад размером level_depth_base даёт ровно один...
Definition: global_state.hpp:30
uint32_t coordinator_invite_validity_days
Срок действия приглашения координатора (дней)
Definition: global_state.hpp:21
uint64_t level_depth_base
Базовая сумма вкладов для уровня 1 (10000 RUB при точности рубля 4 знака: 10000 × 10^4)
Definition: global_state.hpp:28
double level_growth_coefficient
Коэффициент роста требований для следующих уровней (по умолчанию 1.5)
Definition: global_state.hpp:29
Таблица глобального состояния хранит общие данные контракта благороста.
Definition: global_state.hpp:41
eosio::binary_extension< asset > program_expense_pool
Доступная сумма программы под целевые расходы (без аллокации в проекты)
Definition: global_state.hpp:59
eosio::name coopname
Имя кооператива
Definition: global_state.hpp:42
double program_membership_cumulative_reward_per_share
Накопительное вознаграждение на долю в членских взносах
Definition: global_state.hpp:47
config config
Управляемая конфигурация контракта
Definition: global_state.hpp:49
uint64_t primary_key() const
Первичный ключ (1)
Definition: global_state.hpp:62
eosio::binary_extension< asset > program_expense_reserved
Сумма, зарезервированная под approved/authorized программные расходы
Definition: global_state.hpp:60