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

Release 2.11.x #347

Merged
merged 75 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
646b9bd
mitigate 2 types of data incoherency instead of error
Jun 13, 2024
4de8b5f
fix compile
Jun 13, 2024
9bbcfde
add testing only actions to system contract
Jun 14, 2024
3c17c56
compile
Jun 14, 2024
3c409d6
compile
Jun 14, 2024
0100d8d
serialize test methods
Jun 17, 2024
2d8b5da
comment out fatal error, allow logic to correct it
Jun 17, 2024
af3ff80
quick dev test with old logic
Jun 18, 2024
f5f34d4
comment out incoherency checks
Jun 18, 2024
b5c77e6
get ride of testing only code
Jun 18, 2024
c1b49f2
re add test only for one dev round
Jun 20, 2024
5b2d867
compile
Jun 20, 2024
435e197
comments
Jun 20, 2024
0817797
revision on incoherent lock cleanup
Jun 20, 2024
fb004b9
remove test only code, final PR for release
Jun 20, 2024
2c95bd5
Merge pull request #345 from fioprotocol/BD-4643-fiocontracts-develop…
misterleet Jun 26, 2024
dfe71e9
add new action to fio.token
Jun 27, 2024
33766ce
compile
Jun 27, 2024
97c8703
implement flow for account 1
Jul 1, 2024
9d9d511
compile
Jul 1, 2024
48d4fa5
compile
Jul 1, 2024
12adf3e
dev
Jul 1, 2024
57f8566
dev
Jul 1, 2024
d58ae9b
dev
Jul 1, 2024
2b75167
dev
Jul 1, 2024
34a36dd
dev
Jul 1, 2024
718ccb8
dev
Jul 1, 2024
f196926
dev
Jul 1, 2024
179653c
dev
Jul 1, 2024
39dc049
test code for setup of locks for FIP48
Jul 2, 2024
c50c08d
modify for initial testing
Jul 2, 2024
41ea816
add debug
Jul 2, 2024
8594f1c
debug
Jul 3, 2024
b7f33cc
debug
Jul 3, 2024
437e862
debug token logistics
Jul 3, 2024
c6409ad
change logic on check of from
Jul 3, 2024
5b337df
add in final update of receiver account locks
Jul 3, 2024
f4300cf
compile
Jul 3, 2024
22b6b22
develop code for all 13 realloaction actions
Jul 8, 2024
29022c5
add account reallocation for account 9
Jul 8, 2024
20ef19c
remove dev debug code
Jul 8, 2024
61c8525
remove comments, prep for team review
Jul 9, 2024
cb39cd4
add new action for fipxlviiilck
Jul 11, 2024
af04ae7
add data struct and items for reallocation list
Jul 11, 2024
70cf5fd
add logic to remove reallocation locks, and adapt receiver locks
Jul 11, 2024
f9d3673
compile
Jul 11, 2024
6533314
compile
Jul 11, 2024
09df83a
compile
Jul 11, 2024
797cdc7
compile
Jul 11, 2024
6657e1f
compile
Jul 11, 2024
e70ea0f
typo
Jul 11, 2024
6fda6ab
compile
Jul 11, 2024
dda1c8d
typo
Jul 11, 2024
e5a47e4
more editable for account and amount.
Jul 11, 2024
2993d29
refactor reallocation funds management and locks
Jul 11, 2024
4ae8305
compile
Jul 11, 2024
fe74fc0
remove artifacts of initial implementation
Jul 12, 2024
093b0dc
set up contracts with main net account info
Jul 12, 2024
153d56e
compile
Jul 12, 2024
7ab4557
add memo as per fip 48
Jul 12, 2024
5644274
implement findings of second code review
Jul 15, 2024
c87e832
debug for addaddress bug
Jul 16, 2024
ccd56c0
add exception handling on get_balance return 0
Jul 16, 2024
0782fa8
compile
Jul 16, 2024
4cd8925
move error handling
Jul 16, 2024
96d8bbe
use find instead of get on get_balance, return 0 if no key found
Jul 16, 2024
93a390b
compile
Jul 16, 2024
a2e8dce
compile
Jul 16, 2024
c0cdd41
compile
Jul 16, 2024
c7e5c5b
remove debug code
Jul 16, 2024
9b2ef34
use operational token amounts
Jul 17, 2024
73da265
use total transfer amount of FIP
Jul 17, 2024
3fbd43d
remove testing only action in prep for release
Jul 17, 2024
b7345fc
fix up comments to clarify BD-4662
Jul 17, 2024
b681385
Merge pull request #346 from fioprotocol/feature/BD-4650-fiocontracts…
misterleet Jul 29, 2024
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
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))