I have issued some tokens base on eosio.token in jungle testnet, and I am able to transfer the tokens between accounts. Now if I want to enforce some control to the tokens sent ( for example, time lock, I do not want the receiver to transfer the tokens to someone else in 2 years). How should I program this function? Thank you for the help!
4 Answers
How about this ?
/// @abi action
void transfer( account_name from,
account_name to,
asset quantity,
string memo );
///@abi action
void transferf(account_name from,
account_name to,
asset quantity,
string memo,
uint32_t frozen_days);
...
void token::claim( account_name owner ) {
require_auth(owner);
frozens frozen_balance( _self, owner );
uint32_t n = now();
for (auto itr = frozen_balance.begin(); itr != frozen_balance.end();) {
if ( n >= itr->time_limit ){
add_balance( owner, itr->balance, _self);
itr = frozen_balance.erase(itr);
}else {
itr++;
}
}
}
void token::add_frozen_balance( account_name owner, asset value, uint32_t frozen_days, account_name ram_payer )
{
frozens frozen_balance( _self, owner );
frozen_balance.emplace(ram_payer, [&]( auto& row ){
row.pkey = frozen_balance.available_primary_key();
row.balance = value;
row.time_limit = now() + (frozen_days * 86400);
});
}
...
void token::transferf( account_name from,
account_name to,
asset quantity,
string memo,
uint32_t frozen_days)
{
eosio_assert( from != to, "cannot transfer to self" );
require_auth( from );
eosio_assert( is_account( to ), "to account does not exist");
auto sym = quantity.symbol.name();
stats statstable( _self, sym );
const auto& st = statstable.get( sym );
require_recipient( from );
require_recipient( to );
eosio_assert( quantity.is_valid(), "invalid quantity" );
eosio_assert( quantity.amount > 0, "must transfer positive quantity" );
eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" );
eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" );
sub_balance( from, quantity );
add_frozen_balance( to, quantity, frozen_days, from );
}
-
Nice piece of code, add_frozen_balance can be skipped here you can shift more logic to claim function otherwise this is also fine.. Commented Nov 21, 2018 at 4:02
-
@NirdeshKumarChoudhary Thank you for your comment, could i get detail idea please? :) Commented Nov 21, 2018 at 5:13
-
Your time complexity in the claim function is O(n) and in case of limited ram this is not good Idea. All you can do rather than using for loop differred your transaction by a longer period sayd max limit is 45 days (that depend on your usecase). And try to optimize the accessing of table. Commented Nov 21, 2018 at 6:34
-
@NirdeshKumarChoudhary Thank you so much. I will try to optimize code. Commented Nov 21, 2018 at 6:42
You cannot enforce time lock on eosio.token
contract because you do not have ownership over the contract and you can't modify the logic in the contract.
However, you can create your own token contract based on eosio.token
and add the time lock logic in your transfer
function.
You will need to save the timestamp when the recipient receives the token into a vector
or multi-index
table depending on your requirements.
-
1He's referring to the contract, not the account github.com/EOSIO/eosio.contracts/tree/master/eosio.token– SandwichCommented Sep 14, 2018 at 10:56
-
Thank you. Is there any code example that can show me how to create the lock ? Commented Sep 14, 2018 at 14:55
You can do that by slightly modifying your token contract.
Things what you need to do is add one more variable for timestamp in your account table or anything else that tracks users.
After that add timestamp by increasing it to two year when user purchase token.
Modify transfer function accordingly that every time checks that timestamp and allow users to transfer tokens after varification.
-
Thank you. Is there any code example that can show me how to create the lock ? Commented Sep 14, 2018 at 14:56
Hope this will be helpful for you!!! https://github.com/yashbhavsar007/tokentime
-
do you think you could paste here some of the relevant bits just in case the link won't point to an existing resource later on when others visit the question? Commented Sep 19, 2018 at 13:06
-
it cannot be understood from a little bit of code..but i will try to put it here if i manage to do so..and i will also manage not to remove code from my repo– Mr.YCommented Sep 19, 2018 at 13:11
-
@Mr.Y why don't you use deferred transaction concept here.... In your case how your transfer function call itself for check the time limit... Commented Nov 20, 2018 at 11:12
-
@NirdeshKumarChoudhary We can do it by deferred transaction also but as it mentioned in eosio's official documentation "There is no guarantee that a deferred action will be executed" that's why i have not executed it over here.– Mr.YCommented Nov 20, 2018 at 12:02
-
you just check once the time condition but if you want your transaction to be complete you have to call transfer action until time reach to now(). How did you mange that...? Commented Nov 20, 2018 at 12:30