提交 7e33a806 编写于 作者: A Anton Perkov

refund from net stake is not allowed to go to cpu stake and vice versa #3180

上级 7091a1a9
......@@ -63,12 +63,13 @@ namespace eosiosystem {
struct refund_request {
account_name owner;
time request_time;
eosio::asset amount;
eosio::asset net_amount;
eosio::asset cpu_amount;
uint64_t primary_key()const { return owner; }
// explicit serialization macro is not necessary, used here only to improve compilation time
EOSLIB_SERIALIZE( refund_request, (owner)(request_time)(amount) )
EOSLIB_SERIALIZE( refund_request, (owner)(request_time)(net_amount)(cpu_amount) )
};
/**
......@@ -223,10 +224,10 @@ namespace eosiosystem {
}
void system_contract::changebw( account_name from, account_name receiver,
asset stake_net_quantity, asset stake_cpu_quantity, bool transfer )
const asset stake_net_delta, const asset stake_cpu_delta, bool transfer )
{
require_auth( from );
eosio_assert( stake_net_quantity != asset(0) || stake_cpu_quantity != asset(0), "should stake non-zero amount" );
eosio_assert( stake_net_delta != asset(0) || stake_cpu_delta != asset(0), "should stake non-zero amount" );
account_name source_stake_from = from;
if ( transfer ) {
......@@ -241,14 +242,14 @@ namespace eosiosystem {
itr = del_tbl.emplace( from, [&]( auto& dbo ){
dbo.from = from;
dbo.to = receiver;
dbo.net_weight = stake_net_quantity;
dbo.cpu_weight = stake_cpu_quantity;
dbo.net_weight = stake_net_delta;
dbo.cpu_weight = stake_cpu_delta;
});
}
else {
del_tbl.modify( itr, 0, [&]( auto& dbo ){
dbo.net_weight += stake_net_quantity;
dbo.cpu_weight += stake_cpu_quantity;
dbo.net_weight += stake_net_delta;
dbo.cpu_weight += stake_cpu_delta;
});
}
eosio_assert( asset(0) <= itr->net_weight, "insufficient staked net bandwidth" );
......@@ -265,13 +266,13 @@ namespace eosiosystem {
if( tot_itr == totals_tbl.end() ) {
tot_itr = totals_tbl.emplace( from, [&]( auto& tot ) {
tot.owner = receiver;
tot.net_weight = stake_net_quantity;
tot.cpu_weight = stake_cpu_quantity;
tot.net_weight = stake_net_delta;
tot.cpu_weight = stake_cpu_delta;
});
} else {
totals_tbl.modify( tot_itr, from == receiver ? from : 0, [&]( auto& tot ) {
tot.net_weight += stake_net_quantity;
tot.cpu_weight += stake_cpu_quantity;
tot.net_weight += stake_net_delta;
tot.cpu_weight += stake_cpu_delta;
});
}
eosio_assert( asset(0) <= tot_itr->net_weight, "insufficient staked total net bandwidth" );
......@@ -284,46 +285,53 @@ namespace eosiosystem {
}
} // tot_itr can be invalid, should go out of scope
// transfer money or schedule a refund
asset total_update = stake_net_quantity + stake_cpu_quantity;
if ( N(eosio) != source_stake_from ) { //for eosio transfer/refund doesn't make sense
// create refund or update from existing refund
if ( N(eosio) != source_stake_from ) { //for eosio both transfer and refund make no sense
refunds_table refunds_tbl( _self, from );
auto req = refunds_tbl.find( from );
//create/update/delete refund
asset update_balance = total_update;
auto net_balance = stake_net_delta;
auto cpu_balance = stake_cpu_delta;
bool need_deferred_trx = false;
if ( req != refunds_tbl.end() ) {
if ( req != refunds_tbl.end() ) { //need to update refund
refunds_tbl.modify( req, 0, [&]( refund_request& r ) {
r.amount -= update_balance;
if ( r.amount < asset(0) ){
update_balance = -r.amount;
r.amount = asset(0);
r.net_amount -= net_balance;
if ( r.net_amount < asset(0) ) {
net_balance = -r.net_amount;
r.net_amount = asset(0);
}
r.cpu_amount -= cpu_balance;
if ( r.cpu_amount < asset(0) ){
cpu_balance = -r.cpu_amount;
r.cpu_amount = asset(0);
}
r.request_time = now();
});
eosio_assert( asset(0) <= req->amount, "negative refund amount" ); //should never happen
eosio_assert( asset(0) <= req->net_amount, "negative net refund amount" ); //should never happen
eosio_assert( asset(0) <= req->cpu_amount, "negative cpu refund amount" ); //should never happen
if ( req->amount == asset(0) ) {
if ( req->net_amount == asset(0) && req->cpu_amount == asset(0) ) {
refunds_tbl.erase( req );
need_deferred_trx = false;
} else {
need_deferred_trx = true;
}
} else if ( update_balance < asset(0) ) {
} else if ( net_balance < asset(0) && cpu_balance < asset(0) ) { //need to create refund
refunds_tbl.emplace( from, [&]( refund_request& r ) {
r.owner = from;
r.amount = -total_update;
if ( net_balance < asset(0) ) {
r.net_amount = -net_balance;
net_balance = asset(0);
} // else r.net_amount = 0 by default constructor
if ( cpu_balance < asset(0) ) {
r.cpu_amount = -cpu_balance;
cpu_balance = asset(0);
} // else r.cpu_amount = 0 by default constructor
r.request_time = now();
});
need_deferred_trx = true;
} // else stake increases with no existing row in refunds_tbl -> nothing to do with refunds_tbl
if ( asset(0) < update_balance ) {
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {from,N(active)},
{ source_stake_from, N(eosio), asset(update_balance), std::string("stake bandwidth") } );
}
} // else stake increase requested with no existing row in refunds_tbl -> nothing to do with refunds_tbl
if ( need_deferred_trx ) {
eosio::transaction out;
......@@ -333,10 +341,17 @@ namespace eosiosystem {
} else {
//cancel_deferred( from );
}
auto transfer_amount = net_balance + cpu_balance;
if ( asset(0) < transfer_amount ) {
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {from,N(active)},
{ source_stake_from, N(eosio), asset(transfer_amount), std::string("stake bandwidth") } );
}
}
// update voting power
{
asset total_update = stake_net_delta + stake_cpu_delta;
auto from_voter = _voters.find(from);
if( from_voter == _voters.end() ) {
from_voter = _voters.emplace( from, [&]( auto& v ) {
......@@ -393,7 +408,7 @@ namespace eosiosystem {
// consecutive missed blocks.
INLINE_ACTION_SENDER(eosio::token, transfer)( N(eosio.token), {N(eosio),N(active)},
{ N(eosio), req->owner, req->amount, std::string("unstake") } );
{ N(eosio), req->owner, req->net_amount + req->cpu_amount, std::string("unstake") } );
refunds_tbl.erase( req );
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册