Please remind that this gist is for documenting and understanding what is going on current ram cost approaches and its consequences technically.
Ideal state after eosio resignation below:
- EOS token stat
- max_supply : 10000000000
- supply : 1000000000
- RAM Bancor state
- quote.balance.amount = 1000000000.0000 / 1000
Suppose we all agree that ideal state after resignation of system accounts is same with above.
Code below:
auto itr = _rammarket.find(S(4,RAMCORE));
if( itr == _rammarket.end() ) {
auto system_token_supply = eosio::token(N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name()).amount;
if( system_token_supply > 0 ) {
itr = _rammarket.emplace( _self, [&]( auto& m ) {
m.supply.amount = 100000000000000ll;
m.supply.symbol = S(4,RAMCORE);
m.base.balance.amount = int64_t(_gstate.free_ram());
m.base.balance.symbol = S(0,RAM);
m.quote.balance.amount = system_token_supply / 1000;
m.quote.balance.symbol = CORE_SYMBOL;
});
}
} else {
//print( "ram market already created" );
}
}
- via system_contract::system_contract() in eosio.system.cpp
- rammarket is a eosio::multi_index named
rammarket
. - when
eosio.system
contract issetcode
ed,_rammarket
is initialized, - once initialized, rammarket will be never initialized again in case of another
setcode
ofeosio.system
.
Let's check what will happen to three important balances of bancor which make ram market of EOSIO.
- suppy.amount for RAMCORE, a relay token, which represents supply of relay token of bancor.
- base.balance.amount for RAM which represents real ram availble to buy and is RAM connector balance of bancor.
- quote.balance.amount for EOS which represents EOS connector balance of bancor.
In current EOSIO, relay token RAMCORE is used only in conversion which is only between EOS and RAM. Therefore supply of RAMCORE never changes as long as this example of conversion is unchanged.
base.balance.amount for RAM which represents real ram availble to buy and is RAM connector balance of bancor.
// in eosio.system.hpp
uint64_t free_ram()const { return max_ram_size - total_ram_bytes_reserved; }
uint64_t max_ram_size = 64ll*1024 * 1024 * 1024;
uint64_t total_ram_bytes_reserved = 0;
int64_t total_ram_stake = 0;
- eosio_global_state is eosio::singleton which is a single table on database.
- With
setram
action ineosio.system
, it can be changed easily. - When block producers are going to increase RAM capacity of EOS blockchain, it is conceivable that
setram
will be pushed through consensus of block producers.
system_token_supply
is the trickest part.
// in eosio.token.hpp
struct currency_stats {
asset supply;
asset max_supply;
account_name issuer;
uint64_t primary_key()const { return supply.symbol.name(); }
};
typedef eosio::multi_index<N(accounts), account> accounts;
typedef eosio::multi_index<N(stat), currency_stats> stats;
- stats is a eosio::multi_index named
stat
max_supply
is determined only when creating a token.supply
starts at 0 and is increased bytoken::issue
.
asset token::get_supply( symbol_name sym )const
{
stats statstable( _self, sym );
const auto& st = statstable.get( sym );
return st.supply;
}
- Yes, get_supply returns current accummulated issued amount.
- And there is NO action or method to decrease the supply of a token at this time.
get_supply
is used via system_contract::claimrewards for claiming rewards and provides current EOS supply amount to calculate inflation.
Please keep in mind that these descriptions below are intended to explain, not to criticize a specific method.
- system.setcode of
eosio.token
contract on account eosio.token - token.create with 10000000000.0000 EOS : Should work with 5% inflation, for the next 50 years (end of uint32 block_num anyway)
- token.issue with 1000011821.0000 EOS : 1B coins, as per distribution model + gift of RAM to new users.
- system.setcode of
eosio.system
contract on account eosio for the first time. - snapshot.create_accounts with buy_ram_bytes 8192.
- system.setcode of
eosio.bios
contract on account eosio. - system.setcode of
eosio.system
contract on account eosio for the second time. - system.resign_accounts for resignation of system accounts.
- token creation
- when creating a EOS token with 10000000000.0000, max_supply in token stats is set as 10000000000.0000 EOS.
- when issuing 1000011821.0000 EOS, then supply in token stats is set as 1000011821.0000 EOS.
- first
eosio.system
setcode- rammarket is created with bancor state below:
- RAMCORE : supply.amount = 100000000000000ll
- RAM : base.balance.amount = current available RAM bytes via
base.balance.amount = int64_t(_gstate.free_ram());
- EOS(CORE) : quote.balance.amount = 1000011821.0000 / 1000 via codes below.
- rammarket is created with bancor state below:
auto system_token_supply = eosio::token(N(eosio.token)).get_supply(eosio::symbol_type(system_token_symbol).name()).amount;
m.quote.balance.amount = system_token_supply / 1000;
- snapshot.create_accounts
- no changes in RAMCORE supply.amount
- RAM base.balance.amount decreases according to conversion of ram buys.
- EOS(CORE) quote.balance.amount increases according to ram buys.
- RAM price is determined with starting EOS quote.balance.amount (1000011821.0000 / 1000), not (1000000000.0000 / 1000).
- second
eosio.system
setcode- Because rammarket already exists, its values is not initialized again.
- resignation of system accounts
- This step disables authorization for system accounts.
- But resignation doesn't change EOS supply value of token stats
- Also doesn't change EOS balance of bancor state either.
- effects to token stats
- EOS token supply is 1000011821.0000.
- slightly increased supply is used when calculating inflation.
- effects to bancor
- quote.balance.amount starts with (1000011821.0000 / 1000), not (1000000000.0000 / 1000)
- Because of this, price of RAM starts slightly higher and grows slightly steeper.
To get the ideal state, it is necessary to change eosio.token
and eosio.system
accordingly.
- EOS token supply correction, which is similar what @nsrempel suggested on EOS Validation (EMLG) telegram channel, but not with each account but once with total delta.
- See comment below for patch of unissue on eosio master (commit id 379cb1a9e2a6557221d946eef4c5c83ddd156799, Tue Jun 5 18:00:26 2018 -0500).
Considering validation tools already check every account balance i think something simpler like
void token::unissue(quantity){
statstable.modify( st, 0, [&]( auto& s ) {
s.supply -= quantity;
});
}
would be preferable in the eosio.token contract, then reconfirm balances = total supply
- correction of EOS balance of bancor, suggested by @EOSeoul_hyunwoong and implemented by me.
- 'mitigatebiosramcost' with total delta.
- https://gist.github.com/redjade/c22b2d7fcab068af67c0de31724eb710
It seems that difficulty of implementation and inclusion into the boot sequence is not that high.
- https://storage.googleapis.com/website-bancor/2018/04/01ba8253-bancor_protocol_whitepaper_en.pdf
- https://drive.google.com/file/d/0B3HPNP-GDn7aRkVaV3dkVl9NS2M/view
- EOSIO/eos#3032
- EOSIO/eos#3070
- https://eosio.stackexchange.com/questions/317/is-there-a-math-error-in-bancor-paper
- https://gist.github.com/redjade/ca88d90e3f838c57ea7a1a287b23e30a
I totally trust and rely on two wonderful mathematicians, @sergioyuhjtman from EOS Argentina and @hyunwoongJi from EOSeoul. We discussed and examined Bancor and its implementation in EOSIO thoroughly for weeks with mutual respect and understanding.
I hope future reviewers including mathematicians, developers and economists interested in EOSIO can join this discussion and conclude what is desirable.
Here comes
token::unissue
patch on EOSIO master (commit id379cb1a9e2a6557221d946eef4c5c83ddd156799
, Tue Jun 5 18:00:26 2018 -0500)