Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stake in a box #314 #315 #316

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions cyber.bios/include/cyber.bios/cyber.bios.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace cyber {
using eosio::time_point_sec;
using eosio::contract;
using eosio::asset;
using eosio::symbol_code;

struct permission_level_weight {
permission_level permission;
Expand Down Expand Up @@ -110,7 +111,6 @@ namespace cyber {
eosio::multi_index<"stake.autorc"_n, auto_recall, autorc_key_index>;
void autorcs_dummy() { autorcs autorcs_tabl(_self, _self.value); } // an ugly way to make abi appear

void check_stake(name account);
public:
using contract::contract;
[[eosio::action]]
Expand Down Expand Up @@ -183,10 +183,9 @@ namespace cyber {

[[eosio::action]]
void providebw(name provider, name account) {} // defined in cyberway/libraries/chain/cyberway/cyberway_contract.cpp

[[eosio::on_notify(CYBER_STAKE "::withdraw")]] void on_stake_withdraw(name account, asset quantity);
[[eosio::on_notify(CYBER_STAKE "::provide")]] void on_stake_provide(name provider_name, name consumer_name, asset quantity);


[[eosio::action]]
void checkstake(name account, symbol_code token_code);
};

} /// namespace cyber
15 changes: 2 additions & 13 deletions cyber.bios/src/cyber.bios.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,23 +156,12 @@ void bios::newaccount(name creator, name newact, ignore<authority> owner, ignore
}
}

void bios::check_stake(name account) {
auto token_code = system_token.code();
void bios::checkstake(name account, symbol_code token_code) {
eosio::check(token_code == system_token.code(), "unsupported token_code");
auto cost = eosio::get_used_resources_cost(account);
auto effective_stake = stake::get_effective_stake(account, token_code);
eosio::check(!stake::enabled(token_code) || (effective_stake >= cost),
"no staked tokens available due to resource usage");
}

void bios::on_stake_withdraw(name account, asset quantity) {
(void)quantity;
check_stake(account);
}

void bios::on_stake_provide(name provider_name, name consumer_name, asset quantity) {
(void)quantity;
(void)consumer_name;
check_stake(provider_name);
}

}
21 changes: 20 additions & 1 deletion cyber.stake/include/cyber.stake/cyber.stake.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ struct structures {
symbol_code token_code;
int64_t total;
};

struct box {
uint64_t id;
name treasurer;
name title;
asset quantity;
uint64_t primary_key()const { return id; }
using key_t = std::tuple<name, name>;
key_t by_key()const { return std::make_tuple(treasurer, title); }
};
};

using agent_id_index = eosio::indexed_by<"agentid"_n, eosio::const_mem_fun<structures::agent, uint64_t, &structures::agent::primary_key> >;
Expand Down Expand Up @@ -235,6 +245,10 @@ struct structures {
using susps_idx_t = decltype(susps(_self, _self.value).get_index<"bykey"_n>());

using losses_singleton [[eosio::order("id","asc")]] = eosio::singleton<"losses"_n, structures::losses>;

using box_key_index [[eosio::order("treasurer"), eosio::order("title")]] =
eosio::indexed_by<"bykey"_n, eosio::const_mem_fun<structures::box, structures::box::key_t, &structures::box::by_key> >;
using boxes [[eosio::order("id")]] = eosio::multi_index<"box"_n, structures::box, box_key_index>;

void update_stake_proxied(symbol_code token_code, name agent_name) {
eosio::update_stake_proxied(token_code, agent_name, true);
Expand All @@ -248,7 +262,7 @@ struct structures {
void add_proxy(symbol_code token_code, grants& grants_table, const structures::agent& grantor_as_agent, const structures::agent& agent,
int16_t pct, int64_t share, int16_t break_fee = -1, int64_t break_min_own_staked = -1);

void change_balance(name account, asset quantity);
void sub_own_funds(name account, asset quantity);

static inline void staking_exists(symbol_code token_code) {
params params_table(table_owner, table_owner.value);
Expand Down Expand Up @@ -281,6 +295,8 @@ struct structures {

void check_suspense(susps& susps_table, susps_idx_t& susps_idx, symbol_code token_code, name account, name action_name);
void set_suspense(name ram_payer, susps& susps_table, susps_idx_t& susps_idx, symbol_code token_code, name account, name action_name, int delay);

void send_checkstake(name account, symbol_code token_code);

public:

Expand Down Expand Up @@ -431,5 +447,8 @@ struct structures {

[[eosio::action]] void setautorc(name account, symbol_code token_code, bool break_fee_enabled, bool break_min_stake_enabled);
[[eosio::action]] void setautorcmode(symbol_code token_code, bool enabled);

[[eosio::action]] void constrain(name treasurer, name title, asset quantity);
[[eosio::action]] void release(name treasurer, name title, name owner);
};
} /// namespace cyber
152 changes: 138 additions & 14 deletions cyber.stake/src/cyber.stake.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ void stake::delegatevote(name grantor_name, name recipient_name, asset quantity)

void stake::recallvote(name grantor_name, name recipient_name, symbol_code token_code, int16_t pct) {
require_auth(grantor_name);
eosio::recall_stake_proxied(token_code, grantor_name, recipient_name, pct);
eosio::recall_stake_proxied(token_code, grantor_name, recipient_name, pct, false);
}

void stake::check_grant_terms(const structures::agent& agent, int16_t break_fee, int64_t break_min_own_staked) {
Expand Down Expand Up @@ -264,15 +264,16 @@ void stake::on_transfer(name from, name to, asset quantity, std::string memo) {
modify_stat(token_code, [&](auto& s) { s.total_staked += quantity.amount; });
}

void stake::withdraw(name account, asset quantity) {
require_auth(account);
eosio::check(quantity.amount > 0, "must withdraw positive quantity");
auto token_code = quantity.symbol.code();
params params_table(table_owner, table_owner.value);
const auto& param = params_table.get(token_code.raw(), "no staking for token");
eosio::check(param.token_symbol == quantity.symbol, "quantity precision mismatch");
void stake::send_checkstake(name account, symbol_code token_code) {
eosio::action(
eosio::permission_level{_self, config::active_name},
eosio::token::get_issuer(config::token_name, token_code), "checkstake"_n,
std::make_tuple(account, token_code)
).send();
}

update_stake_proxied(token_code, account);
void stake::sub_own_funds(name account, asset quantity) {
auto token_code = quantity.symbol.code();
agents agents_table(table_owner, table_owner.value);
auto agents_idx = agents_table.get_index<"bykey"_n>();
auto agent = get_agent_itr(token_code, agents_idx, account);
Expand All @@ -294,14 +295,24 @@ void stake::withdraw(name account, asset quantity) {
a.shares_sum -= shares_diff;
a.own_share -= shares_diff;
});

if (!agent->proxy_level) {
set_votes(token_code, std::map<name, int64_t>{{account, -quantity.amount}});
}
modify_stat(token_code, [&](auto& s) { s.total_staked += -quantity.amount; });
}

require_recipient(eosio::token::get_issuer(config::token_name, quantity.symbol.code()));
void stake::withdraw(name account, asset quantity) {
require_auth(account);
eosio::check(quantity.amount > 0, "must withdraw positive quantity");
auto token_code = quantity.symbol.code();
params params_table(table_owner, table_owner.value);
const auto& param = params_table.get(token_code.raw(), "no staking for token");
eosio::check(param.token_symbol == quantity.symbol, "quantity precision mismatch");

update_stake_proxied(token_code, account);
sub_own_funds(account, quantity);
modify_stat(token_code, [&](auto& s) { s.total_staked += -quantity.amount; });
send_checkstake(account, token_code);
INLINE_ACTION_SENDER(eosio::token, transfer)(config::token_name, {_self, config::active_name},
{_self, account, quantity, "unstaked tokens"});
}
Expand Down Expand Up @@ -656,7 +667,7 @@ void stake::update_provided(name grantor_name, name recipient_name, asset quanti
}

int64_t available = grantor->get_own_funds() - grantor->provided;
eosio::check(available > 0, "SYSTEM: incorrect available");
eosio::check(available >= 0, "SYSTEM: incorrect available");
eosio::check(to_provide <= available, "not enough staked tokens");

if (prov_itr != provs_index.end()) {
Expand All @@ -673,7 +684,7 @@ void stake::update_provided(name grantor_name, name recipient_name, asset quanti
}
agents_idx.modify(grantor, name(), [&](auto& a) { a.provided += to_provide; });
agents_idx.modify(recipient, name(), [&](auto& a) { a.received += quantity.amount; });
require_recipient(eosio::token::get_issuer(config::token_name, quantity.symbol.code()));
send_checkstake(grantor_name, token_code);
}
else {
auto to_deprive = -quantity.amount;
Expand Down Expand Up @@ -836,4 +847,117 @@ void stake::returnlosses() {
losses_state.set(s, _self);
}

void stake::constrain(name treasurer, name title, asset quantity) {
require_auth(treasurer);

auto token_code = quantity.symbol.code();
params params_table(table_owner, table_owner.value);
const auto& param = params_table.get(token_code.raw(), "no staking for token");
eosio::check(param.token_symbol == quantity.symbol, "quantity precision mismatch");
update_stake_proxied(token_code, treasurer);

agents agents_table(table_owner, table_owner.value);
auto agents_idx = agents_table.get_index<"bykey"_n>();
auto treasurer_itr = get_agent_itr(token_code, agents_idx, treasurer);

int64_t available = treasurer_itr->get_own_funds() - treasurer_itr->provided;
eosio::check(available >= 0, "SYSTEM: incorrect available");
eosio::check(quantity.amount <= available, "not enough staked tokens");

agents_idx.modify(treasurer_itr, name(), [&](auto& a) { a.provided += quantity.amount; });
send_checkstake(treasurer, token_code);

boxes boxes_table(_self, _self.value);
auto boxes_idx = boxes_table.get_index<"bykey"_n>();
eosio::check(boxes_idx.find({treasurer, title}) == boxes_idx.end(), "non-unique title");

boxes_table.emplace(treasurer, [&](auto& b) { b = {
.id = boxes_table.available_primary_key(),
.treasurer = treasurer,
zxcat marked this conversation as resolved.
Show resolved Hide resolved
.title = title,
.quantity = quantity
};});

eosio::action(
eosio::permission_level{_self, config::active_name},
config::box_name, "packup"_n,
std::make_tuple(_self, treasurer, title)
).send();
}

void stake::release(name treasurer, name title, name owner) {
require_auth(config::box_name);

boxes boxes_table(_self, _self.value);
auto boxes_idx = boxes_table.get_index<"bykey"_n>();
auto box_itr = boxes_idx.find({treasurer, title});
eosio::check(box_itr != boxes_idx.end(), "SYSTEM: nothing to release");

auto quantity = box_itr->quantity;
auto token_code = quantity.symbol.code();
auto amount = box_itr->quantity.amount;
update_stake_proxied(token_code, treasurer);

{
agents agents_table(table_owner, table_owner.value);
auto agents_idx = agents_table.get_index<"bykey"_n>();
auto treasurer_itr = get_agent_itr(token_code, agents_idx, treasurer);

eosio::check(amount <= treasurer_itr->provided, "SYSTEM: box_itr->quantity.amount > treasurer_itr->provided");
agents_idx.modify(treasurer_itr, name(), [&](auto& a) { a.provided -= amount; });
}

boxes_idx.erase(box_itr);

if (treasurer == owner) {
return;
}

auto prev_recipient = name();
int32_t add_pct = 1;
int64_t balance = 0;
while (true) {
agents agents_table(table_owner, table_owner.value);
auto agents_idx = agents_table.get_index<"bykey"_n>();
auto treasurer_itr = get_agent_itr(token_code, agents_idx, treasurer);
balance = treasurer_itr->balance;
if (balance >= amount) {
break;
}

grants grants_table(table_owner, table_owner.value);
auto grants_idx = grants_table.get_index<"bykey"_n>();
auto grant_itr = grants_idx.lower_bound(std::make_tuple(token_code, treasurer, name()));
if (grant_itr == grants_idx.end() || (grant_itr->token_code != token_code) || (grant_itr->grantor_name != treasurer)) {
break;
}

auto recipient_itr = get_agent_itr(token_code, agents_idx, grant_itr->recipient_name);
int64_t granted = safe_prop(recipient_itr->get_total_funds(), grant_itr->share, recipient_itr->shares_sum);
int64_t shortage = amount - balance;

auto cur_pct = config::_100percent;

if (granted > shortage) {
if (grant_itr->recipient_name == prev_recipient) {
add_pct = std::min<int32_t>(add_pct * 10, config::_100percent);
}
cur_pct = std::min<int64_t>((shortage * config::_100percent / granted) + add_pct, config::_100percent);
}
prev_recipient = grant_itr->recipient_name;
agents_table.flush_cache();
grants_table.flush_cache();
eosio::recall_stake_proxied(token_code, treasurer, prev_recipient, cur_pct, true);
}
quantity.amount = std::min(amount, balance); //it seems that balance cannot be less than amount but just in case

sub_own_funds(treasurer, quantity);
modify_stat(token_code, [&](auto& s) { s.total_staked -= quantity.amount; });

eosio::check(eosio::token::balance_exist(::cyber::config::token_name, owner, token_code), "owner balance does not exist");

INLINE_ACTION_SENDER(eosio::token, transfer)(config::token_name, {_self, config::active_name},
{_self, owner, quantity, "released tokens"});
}

} /// namespace cyber
Loading