message: delegatebw to another account should always pull tokens from source's liquid balance
diff: @@ -207,6 +207,9 @@ namespace eosiosystem {
  {
  require_auth( from );
  eosio_assert( stake_net_delta != asset(0) || stake_cpu_delta != asset(0), "should stake non-zero amount" );
  + eosio_assert( std::abs( (stake_net_delta + stake_cpu_delta).amount )
  + >= std::max( std::abs( stake_net_delta.amount ), std::abs( stake_cpu_delta.amount ) ),
  + "net and cpu deltas cannot be opposite signs" );
  account_name source_stake_from = from;
  if ( transfer ) {
  @@ -273,6 +276,14 @@ namespace eosiosystem {
  auto net_balance = stake_net_delta;
  auto cpu_balance = stake_cpu_delta;
  bool need_deferred_trx = false;
  +
  +
  + // net and cpu are same sign by assertions in delegatebw and undelegatebw
  + // redundant assertion also at start of changebw to protect against misuse of changebw
  + bool is_undelegating = (net_balance.amount + cpu_balance.amount ) < 0;
  + bool is_delegating_to_self = (!transfer && from == receiver);
  +
  + if( is_delegating_to_self || is_undelegating ) {
  if ( req != refunds_tbl.end() ) { //need to update refund
  refunds_tbl.modify( req, 0, [&]( refund_request& r ) {
  if ( net_balance < asset(0) || cpu_balance < asset(0) ) {
  @@ -293,6 +304,7 @@ namespace eosiosystem {
  cpu_balance = asset(0);
  }
  });
  +
  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
  @@ -302,6 +314,7 @@ namespace eosiosystem {
  } else {
  need_deferred_trx = true;
  }
  +
  } else if ( net_balance < asset(0) || cpu_balance < asset(0) ) { //need to create refund
  refunds_tbl.emplace( from, [&]( refund_request& r ) {
  r.owner = from;
  @@ -317,6 +330,7 @@ namespace eosiosystem {
  });
  need_deferred_trx = true;
  } // else stake increase requested with no existing row in refunds_tbl -> nothing to do with refunds_tbl
  + } /// end if is_delegating_to_self || is_undelegating
  if ( need_deferred_trx ) {
  eosio::transaction out;
  