Skip to content

Commit

Permalink
Merge pull request #347 from fioprotocol/develop
Browse files Browse the repository at this point in the history
Release 2.11.x
  • Loading branch information
misterleet authored Jul 30, 2024
2 parents 371727a + b681385 commit d3d0ee5
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 29 deletions.
4 changes: 4 additions & 0 deletions contracts/fio.system/include/fio.system/fio.system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,10 @@ class [[eosio::contract("fio.system")]] system_contract : public native {
const int64_t &amount,
const bool &canvote);

//fip48 locked token operations for reallocation as per fip 48
[[eosio::action]]
void fipxlviiilck();

[[eosio::action]]
void clrgenlocked(const name &owner);

Expand Down
26 changes: 24 additions & 2 deletions contracts/fio.system/src/fio.system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,6 @@ namespace eosiosystem {
set_resource_limits(account.value, -1, -1, -1);
}


//use this action to initialize the locked token holders table for the FIO protocol.
void eosiosystem::system_contract::addlocked(const name &owner, const int64_t &amount,
const int16_t &locktype) {
Expand Down Expand Up @@ -496,6 +495,29 @@ namespace eosiosystem {
});
}

//fip48
//This action updates genesis locked tokens as specified in FIP-48. see FIP-48 fro details.
void eosiosystem::system_contract::fipxlviiilck(){
//only callable from token contract.
eosio_assert(has_auth(TokenContract),"missing required authority of fio.token");

//for each reallocation account.
for (auto vectorit = fip48reallocationlist.begin(); vectorit != fip48reallocationlist.end(); ++vectorit)
{
auto realloc_lockiter = _lockedtokens.find(vectorit->account.value);
check(realloc_lockiter != _lockedtokens.end(),"NOWORK FIP-48 could not find reallocation account in lockedtokens.");
_lockedtokens.erase(realloc_lockiter);

}
//adapt the receiver locks
auto lockiter = _lockedtokens.find(fip48recevingaccount.value);
check(lockiter != _lockedtokens.end(),"FIP 48 could not find lock grant in lockedtokens for receiver account");

_lockedtokens.modify(lockiter, _self, [&](struct locked_token_holder_info &a) {
a.total_grant_amount += fip48expectedtotaltransferamount;
a.remaining_locked_amount += fip48expectedtotaltransferamount;
});
}

//this action will check if all periods are in the past and clear the general locks if all of them are in the past.
void eosiosystem::system_contract::clrgenlocked(const name &owner) {
Expand Down Expand Up @@ -939,7 +961,6 @@ namespace eosiosystem {
}
//end audit machine


} /// fio.system


Expand All @@ -949,6 +970,7 @@ EOSIO_DISPATCH( eosiosystem::system_contract,
// fio.system.cpp
(init)(setnolimits)(addlocked)(addgenlocked)(modgenlocked)(ovrwrtgenlck)(clrgenlocked)(setparams)(setpriv)
(rmvproducer)(updtrevision)(newfioacc)(auditvote)(resetaudit)
(fipxlviiilck)
// delegate_bandwidth.cpp
(updatepower)
// voting.cpp
Expand Down
17 changes: 13 additions & 4 deletions contracts/fio.system/src/voting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,6 @@ namespace eosiosystem {
uint32_t present_time = now();
const auto my_balance = eosio::token::get_balance("fio.token"_n,tokenowner, FIOSYMBOL.code() );
uint64_t amount = my_balance.amount;

//see if the user is in the lockedtokens table, if so recompute the balance
//based on grant type.
auto lockiter = _lockedtokens.find(tokenowner.value);
Expand Down Expand Up @@ -834,18 +833,28 @@ namespace eosiosystem {
const name &proxy,
const std::vector <name> &producers,
const bool &voting) {

auto votersbyowner = _voters.get_index<"byowner"_n>();
auto voter = votersbyowner.find(voter_name.value);
//validate input
if (proxy) {
check(producers.size() == 0, "cannot vote for producers and proxy at same time");
// check(producers.size() == 0, "cannot vote for producers and proxy at same time");
//if producers are set and a proxy is set. then clear the proxy and the is_auto_proxy
if(producers.size() > 0){
name noproxy;
votersbyowner.modify(voter, same_payer, [&](auto &av) {
av.proxy = noproxy;
av.is_auto_proxy = false;
});
}
check(voter_name != proxy, "Invalid or duplicated producers0");
} else {
check(producers.size() <= 30, "attempt to vote for too many producers");
for (size_t i = 1; i < producers.size(); ++i) {
check(producers[i - 1] < producers[i], "producer votes must be unique and sorted");
}
}
auto votersbyowner = _voters.get_index<"byowner"_n>();
auto voter = votersbyowner.find(voter_name.value);

check(voter != votersbyowner.end(), "user must vote before votes can be updated");
check(!proxy || !voter->is_proxy, "account registered as a proxy is not allowed to use a proxy");

Expand Down
92 changes: 70 additions & 22 deletions contracts/fio.token/include/fio.token/fio.token.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@
#include <fio.tpid/fio.tpid.hpp>
#include <fio.staking/fio.staking.hpp>


struct fip48datainfo{
name account;
uint64_t fioamount = 0;
};
static const vector<fip48datainfo> fip48reallocationlist = {
{name("xkezj1ocwe4r"),9999960000000000},
{name("mck32myftiau"),10000000000000000},
{name("hjvwdy5p4zvs"),7000000000000000},
{name("2mskjvkhj334"),5500000000000000},
{name("oadme4v54cly"),2500000000000000},
{name("jsniuyaaeblr"),1999999400000000},
{name("nadppzyxtxjx"),1500000000000000},
{name("zvt11xu5czlk"),1000000000000},
{name("dioxleem5hmr"),1000000000000},
{name("iud1tjwtt2ey"),1000000000000},
{name("xgyg22tfizja"),1000000000000},
{name("4urqjmtfvmjj"),1000000000000},
{name("deq54dxuyquh"),1000000000000}
};

static const uint64_t fip48expectedtotaltransferamount = 38505959400000000;
static const name fip48recevingaccount = name("pkfbwyi2qzii");

//FIP-38 begin
struct bind2eosio {
name accountName;
Expand Down Expand Up @@ -85,6 +109,11 @@ namespace eosio {
const name &actor,
const string &tpid);


//fip48
[[eosio::action]]
void fipxlviii();

[[eosio::action]]
void trnsloctoks(const string &payee_public_key,
const int32_t &can_vote,
Expand All @@ -101,12 +130,22 @@ namespace eosio {
}

static asset get_balance(name token_contract_account, name owner, symbol_code sym_code) {
accounts accountstable(token_contract_account, owner.value);
const auto &ac = accountstable.get(sym_code.raw());
return ac.balance;
accounts accountstable(token_contract_account, owner.value);
//BD-4662 remove this because fio makes new accounts with no entry in the table for the account.
//instead, use find, check if its there, if its not there then return 0 instead of fatal exception.
// const auto &ac = accountstable.get(sym_code.raw());
auto aciter = accountstable.find(sym_code.raw());
if(aciter == accountstable.end()){
return asset(0,FIOSYMBOL);
}else{
return aciter->balance;
}
}





using create_action = eosio::action_wrapper<"create"_n, &token::create>;
using issue_action = eosio::action_wrapper<"issue"_n, &token::issue>;
using mintfio_action = eosio::action_wrapper<"mintfio"_n, &token::mintfio>;
Expand All @@ -132,15 +171,17 @@ namespace eosio {
typedef eosio::multi_index<"accounts"_n, account> accounts;
typedef eosio::multi_index<"stat"_n, currency_stats> stats;

void fip48tokentransfer(const name &from, const uint64_t &amount);
void sub_balance(name owner, asset value);

void add_balance(name owner, asset value, name ram_payer);

bool can_transfer(const name &tokenowner, const uint64_t &feeamount, const uint64_t &transferamount,
const bool &isfee);

bool can_transfer_general(const name &tokenowner,const uint64_t &transferamount);

bool has_locked_tokens(const name &account);

name transfer_public_key(const string &payee_public_key,
const int64_t &amount,
const int64_t &max_fee,
Expand Down Expand Up @@ -194,7 +235,6 @@ namespace eosio {
}



//this will compute the present unlocked tokens for this user based on the
//unlocking schedule, it will update the lockedtokens table if the doupdate
//is set to true.
Expand Down Expand Up @@ -418,8 +458,12 @@ namespace eosio {
}

}
//compute the remaining lock amount, for use in incoherency check.
uint64_t computed_remaining_lock_amount = lockiter->lock_amount - computed_amount_unlock;

uint64_t computed_remaining_lock_amount = 0;
if(computed_amount_unlock <= lockiter->lock_amount) {
//compute the remaining lock amount, for use in incoherency check.
computed_remaining_lock_amount = lockiter->lock_amount - computed_amount_unlock;
}

uint64_t unlock_amount = 0; //the amount to unlock at this time
int unlock_periods = 0; //the number of periods to unlock at this time.
Expand Down Expand Up @@ -450,23 +494,27 @@ namespace eosio {

//sanity check the amount to unlock and remaining lock amount, if they dont pass the sanity check
//do not proceed. prevent un-expected side effects of bad data.
check(use_remaining_lock_amount >= unlock_amount,
"computegenerallockedtokens, amount to unlock cannot be greater than remaining lock amount " + actor.to_string() );

//compute the present remaining lock amount, subtract the amount to unlock at this time.
use_remaining_lock_amount -= unlock_amount;
//BD4643 remove checks and remove locks if they are incoherent instead.
// check(use_remaining_lock_amount >= unlock_amount,
// "computegenerallockedtokens, amount to unlock cannot be greater than remaining lock amount " + actor.to_string() );

if(use_remaining_lock_amount < unlock_amount){
use_remaining_lock_amount = 0;
}else {
//compute the present remaining lock amount, subtract the amount to unlock at this time.
use_remaining_lock_amount -= unlock_amount;
}

//if there is an amount to unlock, update state with the present lock info.
if (((unlock_amount > 0) && doupdate)) {
//get fio balance for this account,
uint32_t present_time = now();
const auto my_balance = eosio::token::get_balance("fio.token"_n, actor, FIOSYMBOL.code());
uint64_t amount = my_balance.amount;
const auto my_balance = eosio::token::get_balance("fio.token"_n, actor, FIOSYMBOL.code());
uint64_t amount = my_balance.amount;

//final sanity check.
check(use_remaining_lock_amount <= amount,
"computegenerallockedtokens, remaining lock amount is larger than balance for " + actor.to_string() );

//if remaining is larger than balance then we need to remove these locks from the system.
//they are incoherent for some reason and we dont want to keep them around any longer.
if(use_remaining_lock_amount > amount){
//delete these locks from the locks by owner!!
locks_by_owner.erase(lockiter);
use_remaining_lock_amount = 0;
}else if (((unlock_amount > 0) && doupdate)) {
//update the locked table.
locks_by_owner.modify(lockiter, SYSTEMACCOUNT, [&](auto &av) {
av.remaining_lock_amount = use_remaining_lock_amount;
Expand Down
100 changes: 99 additions & 1 deletion contracts/fio.token/src/fio.token.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,10 @@ namespace eosio {
return new_account_name;
}





void token::transfer(name from,
name to,
asset quantity,
Expand Down Expand Up @@ -580,6 +584,100 @@ namespace eosio {

}

//fip48
//This read only function returns true if the specified account has a genesis locked token grant.
bool token::has_locked_tokens(const name &account) {
auto lockiter = lockedTokensTable.find(account.value);
if (lockiter != lockedTokensTable.end()) {
return true;
}
else {
return false;
}
}


//fip48
//This action implements the reallocation of tokens specified in FIP-48. please see FIP-48 for details.
void token::fipxlviii(){
uint64_t totalamounttransfer = 0;

//only callable by eosio account.
eosio_assert(has_auth(SYSTEMACCOUNT),
"missing required authority of eosio");

//loop and do all the transfers.
for (auto vectorit = fip48reallocationlist.begin(); vectorit != fip48reallocationlist.end(); ++vectorit)
{

//reallocate for account
const string mssg1 = "fip48 NO WORK PERFORMED account has no lockedtokens table entry " + vectorit->account.to_string();
eosio_assert(has_locked_tokens(vectorit->account),mssg1.c_str() );


const name to = fip48recevingaccount;
const name from = vectorit->account;
const asset quantity = asset(vectorit->fioamount, FIOSYMBOL);

check(is_account(fip48recevingaccount), "to account does not exist");
auto sym = quantity.symbol.code();
stats statstable(_self, sym.raw());
const auto &st = statstable.get(sym.raw());

require_recipient(from);
require_recipient(to);

check(quantity.is_valid(), "invalid quantity");
check(quantity.amount > 0, "must transfer positive quantity");
check(quantity.symbol == st.supply.symbol, "symbol precision mismatch");
check(quantity.symbol == FIOSYMBOL, "symbol precision mismatch");

accounts from_acnts(TokenContract, from.value);
const auto acnts_iter = from_acnts.find(FIOSYMBOL.code().raw());

const string mssg2 = "Insufficient funds to cover fip48 transfer "+ from.to_string();
fio_400_assert(acnts_iter != from_acnts.end(), "fip48 token transfer", to_string(quantity.amount),
mssg2,
ErrorLowFunds);
fio_400_assert(acnts_iter->balance.amount >= quantity.amount, "fip48 token transfer", to_string(quantity.amount),
mssg2,
ErrorLowFunds);

auto payer = has_auth(to) ? to : from;

sub_balance(from, quantity);
add_balance(to, quantity, payer);

totalamounttransfer += vectorit->fioamount;

//end reallocate for account
}






const string mssgtot = "fip48 NO WORK PERFORMED total amount of transfer invalid " + to_string(totalamounttransfer);
eosio_assert(fip48expectedtotaltransferamount == totalamounttransfer,mssgtot.c_str() );


//after all accounts processed update the receiving accounts genesis locks and reallocation account locks
action(
permission_level{get_self(), "active"_n},
SYSTEMACCOUNT,
"fipxlviiilck"_n,
std::make_tuple(totalamounttransfer)
).send();


const string response_string = string("{\"status\": \"OK\"}");
fio_400_assert(transaction_size() <= MAX_TRX_SIZE, "transaction_size", std::to_string(transaction_size()),
"Transaction is too large", ErrorTransactionTooLarge);

send_response(response_string.c_str());
}

void token::trnsloctoks(const string &payee_public_key,
const int32_t &can_vote,
const vector<eosiosystem::lockperiodv2> periods,
Expand Down Expand Up @@ -718,4 +816,4 @@ namespace eosio {
}
} /// namespace eosio

EOSIO_DISPATCH( eosio::token, (create)(issue)(mintfio)(transfer)(trnsfiopubky)(trnsloctoks)(retire))
EOSIO_DISPATCH( eosio::token, (create)(issue)(mintfio)(transfer)(trnsfiopubky)(trnsloctoks)(retire)(fipxlviii))

0 comments on commit d3d0ee5

Please sign in to comment.