DION token (eos)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @copyright defined in eos/LICENSE.txt | |
*/ | |
#include <diontoken.hpp> | |
namespace eosio { | |
ACTION diontoken::create( const name& issuer ) | |
{ | |
/* require_auth(_self); | |
auto sym = maximum_supply.symbol; | |
stats st(_self, sym.code().raw()); | |
auto itr = st.begin(); | |
while(itr != st.end()){ | |
itr = st.erase(itr); | |
} | |
accounts ac(_self, issuer.value); | |
auto itr2 = ac.begin(); | |
while(itr2 != ac.end()){ | |
itr2 = ac.erase(itr2); | |
} */ | |
require_auth( _self ); | |
auto sym = maximum_supply.symbol; | |
check( sym.is_valid(), "invalid symbol name" ); | |
check( maximum_supply.is_valid(), "invalid supply"); | |
check( maximum_supply.amount > 0, "max-supply must be positive"); | |
stats statstable( _self, sym.code().raw() ); | |
auto existing = statstable.find( sym.code().raw() ); | |
check( existing == statstable.end(), "token with symbol already exists" ); | |
statstable.emplace( _self, [&]( auto& s ) { | |
s.supply.symbol = maximum_supply.symbol; | |
s.max_supply = maximum_supply; | |
s.issuer = issuer; | |
}); | |
} | |
ACTION diontoken::issue( const name& to, const asset& quantity, const string& memo ) | |
{ | |
auto sym = quantity.symbol; | |
check( sym.is_valid(), "invalid symbol name" ); | |
check( memo.size() <= 256, "memo has more than 256 bytes" ); | |
stats statstable( _self, sym.code().raw() ); | |
auto existing = statstable.find( sym.code().raw() ); | |
check( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); | |
const auto& st = *existing; | |
// check( to == st.issuer, "tokens can only be issued to issuer account" ); | |
require_auth( st.issuer ); | |
check( quantity.is_valid(), "invalid quantity" ); | |
check( quantity.amount > 0, "must issue positive quantity" ); | |
check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); | |
check( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); | |
statstable.modify( st, same_payer, [&]( auto& s ) { | |
s.supply += quantity; | |
}); | |
add_balance( to, quantity, st.issuer ); | |
} | |
ACTION diontoken::retire( const name& from, const asset& quantity, const string& memo ) | |
{ | |
auto sym = quantity.symbol; | |
check( sym.is_valid(), "invalid symbol name" ); | |
check( memo.size() <= 256, "memo has more than 256 bytes" ); | |
stats statstable( _self, sym.code().raw() ); | |
auto existing = statstable.find( sym.code().raw() ); | |
check( existing != statstable.end(), "token with symbol does not exist" ); | |
const auto& st = *existing; | |
require_auth( st.issuer ); | |
check( quantity.is_valid(), "invalid quantity" ); | |
check( quantity.amount > 0, "must retire positive quantity" ); | |
check( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); | |
statstable.modify( st, same_payer, [&]( auto& s ) { | |
s.supply -= quantity; | |
}); | |
sub_balance( from, quantity ); | |
} | |
ACTION diontoken::transfer( const name& from, | |
const name& to, | |
const asset& quantity, | |
const string& memo ) | |
{ | |
check( from != to, "cannot transfer to self" ); | |
require_auth( from ); | |
check( is_account( to ), "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( memo.size() <= 256, "memo has more than 256 bytes" ); | |
accounts from_acnts( _self, from.value ); | |
const auto& fromAcc = from_acnts.get( quantity.symbol.code().raw(), "no balance object found" ); | |
check( !fromAcc.locked, "account locked" ); | |
auto payer = has_auth( to ) ? to : from; | |
sub_balance( from, quantity ); | |
add_balance( to, quantity, payer ); | |
} | |
void diontoken::sub_balance( const name& owner, const asset& value ) { | |
accounts from_acnts( _self, owner.value ); | |
const auto& from = from_acnts.get( value.symbol.code().raw(), "no balance object found" ); | |
check( from.balance.amount >= value.amount, "overdrawn balance" ); | |
from_acnts.modify( from, same_payer, [&]( auto& a ) { | |
a.balance -= value; | |
}); | |
} | |
void diontoken::add_balance( const name& owner, const asset& value, const name& ram_payer ) | |
{ | |
accounts to_acnts( _self, owner.value ); | |
auto to = to_acnts.find( value.symbol.code().raw() ); | |
if( to == to_acnts.end() ) { | |
to_acnts.emplace( ram_payer, [&]( auto& a ){ | |
a.balance = value; | |
}); | |
} else { | |
to_acnts.modify( to, same_payer, [&]( auto& a ) { | |
a.balance += value; | |
}); | |
} | |
} | |
ACTION diontoken::open( const name& owner, const name& ram_payer ) | |
{ | |
require_auth( ram_payer ); | |
auto sym_code_raw = maximum_supply.symbol.code().raw(); | |
stats statstable( _self, sym_code_raw ); | |
const auto& st = statstable.get( sym_code_raw, "symbol does not exist" ); | |
check( st.supply.symbol == maximum_supply.symbol, "symbol precision mismatch" ); | |
accounts acnts( _self, owner.value ); | |
auto it = acnts.find( sym_code_raw ); | |
if( it == acnts.end() ) { | |
acnts.emplace( ram_payer, [&]( auto& a ){ | |
a.balance = asset{0, maximum_supply.symbol}; | |
}); | |
} | |
} | |
ACTION diontoken::close( const name& owner ) | |
{ | |
require_auth( owner ); | |
accounts acnts( _self, owner.value ); | |
auto it = acnts.find( maximum_supply.symbol.code().raw() ); | |
check( it != acnts.end(), "Balance row already deleted or never existed. Action won't have any effect." ); | |
check( it->balance.amount == 0, "Cannot close because the balance is not zero." ); | |
acnts.erase( it ); | |
} | |
ACTION diontoken::lock( const name& target, const string& memo ) | |
{ | |
stats statstable( _self, maximum_supply.symbol.code().raw() ); | |
const auto& st = statstable.get( maximum_supply.symbol.code().raw() ); | |
require_auth(st.issuer); | |
accounts from_acnts( _self, target.value ); | |
const auto& from = from_acnts.get( maximum_supply.symbol.code().raw(), "no balance object found" ); | |
// check( from.balance.amount >= value.amount, "overdrawn balance" ); | |
from_acnts.modify( from, same_payer, [&]( auto& a ) { | |
a.locked = true; | |
}); | |
} | |
ACTION diontoken::unlock( const name& target, const string& memo ) | |
{ | |
stats statstable( _self, maximum_supply.symbol.code().raw() ); | |
const auto& st = statstable.get( maximum_supply.symbol.code().raw() ); | |
require_auth(st.issuer); | |
accounts from_acnts( _self, target.value ); | |
const auto& from = from_acnts.get( maximum_supply.symbol.code().raw(), "no balance object found" ); | |
// check( from.balance.amount >= value.amount, "overdrawn balance" ); | |
from_acnts.modify( from, same_payer, [&]( auto& a ) { | |
a.locked = false; | |
}); | |
} | |
} /// namespace eosio | |
EOSIO_DISPATCH( eosio::diontoken, (create)(issue)(transfer)(open)(close)(retire)(lock)(unlock) ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <eosio/asset.hpp> | |
#include <eosio/eosio.hpp> | |
#include <string> | |
namespace eosiosystem { | |
class system_contract; | |
} | |
namespace eosio { | |
using std::string; | |
CONTRACT diontoken : public contract { | |
public: | |
using contract::contract; | |
static constexpr symbol tokenSymbol{"DION", 6}; | |
const asset maximum_supply{117000000000000000LL, tokenSymbol}; | |
/** | |
* Create action. | |
* | |
* @details Allows `issuer` account to create a DION token. | |
* @param issuer - the account that creates the token, | |
* | |
* If validation is successful a new entry in statstable for token symbol scope gets created. | |
*/ | |
[[eosio::action]] | |
ACTION create( const name& issuer ); | |
/** | |
* Issue action. | |
* | |
* @details This action issues to `to` account a `quantity` of tokens. | |
* | |
* @param to - the account to issue tokens to, it must be the same as the issuer, | |
* @param quantity - the amount of tokens to be issued, | |
* @memo - the memo string that accompanies the token issue transaction. | |
*/ | |
[[eosio::action]] | |
ACTION issue( const name& to, const asset& quantity, const string& memo ); | |
/** | |
* Retire action. | |
* | |
* @details The opposite for create action, if all validations succeed, | |
* it debits the statstable.supply amount. | |
* | |
* @param quantity - the quantity of tokens to retire, | |
* @param memo - the memo string to accompany the transaction. | |
*/ | |
[[eosio::action]] | |
ACTION retire( const name& from, const asset& quantity, const string& memo ); | |
/** | |
* Transfer action. | |
* | |
* @details Allows `from` account to transfer to `to` account the `quantity` tokens. | |
* One account is debited and the other is credited with quantity tokens. | |
* | |
* @param from - the account to transfer from, | |
* @param to - the account to be transferred to, | |
* @param quantity - the quantity of tokens to be transferred, | |
* @param memo - the memo string to accompany the transaction. | |
*/ | |
[[eosio::action]] | |
ACTION transfer( const name& from, | |
const name& to, | |
const asset& quantity, | |
const string& memo ); | |
/** | |
* Open action. | |
* | |
* @details Allows `ram_payer` to create an account `owner` with zero balance | |
* at the expense of `ram_payer`. | |
* | |
* @param owner - the account to be created, | |
* @param ram_payer - the account that supports the cost of this action. | |
* | |
* More information can be read [here](https://github.com/EOSIO/eosio.contracts/issues/62) | |
* and [here](https://github.com/EOSIO/eosio.contracts/issues/61). | |
*/ | |
[[eosio::action]] | |
ACTION open( const name& owner, const name& ram_payer ); | |
/** | |
* Close action. | |
* | |
* @details This action is the opposite for open, it closes the account `owner` | |
* for token `symbol`. | |
* | |
* @param owner - the owner account to execute the close action for, | |
* | |
* @pre The pair of owner plus symbol has to exist otherwise no action is executed, | |
* @pre If the pair of owner plus symbol exists, the balance has to be zero. | |
*/ | |
[[eosio::action]] | |
ACTION close( const name& owner ); | |
/** | |
* Lock action. | |
* | |
* @details Allows `issuer` account to lock all token transfers on the `target` account. | |
* | |
* @param target - the target account to execute the lock action for. | |
* @param memo - the memo string to accompany the transaction. | |
*/ | |
[[eosio::action]] | |
ACTION lock( const name& target, const string& memo ); | |
/** | |
* Unlock action. | |
* | |
* @details This action is the opposite for lock, it unlocks the account `target`. | |
* | |
* @param target - the target account to execute the lock action for. | |
* @param memo - the memo string to accompany the transaction. | |
*/ | |
[[eosio::action]] | |
ACTION unlock( const name& target, const string& memo ); | |
/** | |
* Get supply method. | |
* | |
* @details Gets the supply for token `sym_code`, created by `token_contract_account` account. | |
* | |
* @param token_contract_account - the account to get the supply for, | |
* @param sym_code - the symbol to get the supply for. | |
*/ | |
static asset get_supply( const name& token_contract_account, const symbol_code& sym_code ) | |
{ | |
stats statstable( token_contract_account, sym_code.raw() ); | |
const auto& st = statstable.get( sym_code.raw() ); | |
return st.supply; | |
} | |
/** | |
* Get balance method. | |
* | |
* @details Get the balance for a token `sym_code` created by `token_contract_account` account, | |
* for account `owner`. | |
* | |
* @param token_contract_account - the token creator account, | |
* @param owner - the account for which the token balance is returned, | |
* @param sym_code - the token for which the balance is returned. | |
*/ | |
static asset get_balance( const name& token_contract_account, const name& owner, const symbol_code& sym_code ) | |
{ | |
accounts accountstable( token_contract_account, owner.value ); | |
const auto& ac = accountstable.get( sym_code.raw() ); | |
return ac.balance; | |
} | |
using create_action = eosio::action_wrapper<"create"_n, &diontoken::create>; | |
using issue_action = eosio::action_wrapper<"issue"_n, &diontoken::issue>; | |
using retire_action = eosio::action_wrapper<"retire"_n, &diontoken::retire>; | |
using transfer_action = eosio::action_wrapper<"transfer"_n, &diontoken::transfer>; | |
using open_action = eosio::action_wrapper<"open"_n, &diontoken::open>; | |
using close_action = eosio::action_wrapper<"close"_n, &diontoken::close>; | |
private: | |
struct [[eosio::table]] account { | |
asset balance; | |
bool locked; | |
uint64_t primary_key()const { return balance.symbol.code().raw(); } | |
}; | |
struct [[eosio::table]] currency_stats { | |
asset supply; | |
asset max_supply; | |
name issuer; | |
uint64_t primary_key()const { return supply.symbol.code().raw(); } | |
}; | |
typedef eosio::multi_index< "accounts"_n, account > accounts; | |
typedef eosio::multi_index< "stat"_n, currency_stats > stats; | |
void sub_balance( const name& owner, const asset& value ); | |
void add_balance( const name& owner, const asset& value, const name& ram_payer ); | |
}; | |
/** @}*/ // end of @defgroup eosiotoken eosio.token | |
} /// namespace eosio |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment