Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

RAM购买机制结合多种合约详解

945坏男人
201 0 0
eosio.system.cpp
: o+ o- I3 h4 J- s// native.hpp (newaccount definition is actually in eosio.system.cpp)
! R' W9 ], _6 N. n/ m6 t& x(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)
+ ?7 M6 d; O7 w2 F/ }) o" r4 {// eosio.system.cpp0 J0 s' w, M5 {" E; g$ P2 k6 `- y1 [
(setram)(setparams)(setpriv)(rmvproducer)(bidname)
2 F, t) X$ M3 r  c2 F! @3 W) m// delegate_bandwidth.cpp2 t1 H) v' F! A1 o6 o
(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)
3 W* F- l1 |5 X! V$ p) I// voting.cpp% p1 j8 y- R% X3 p1 z4 Y
(regproducer)(unregprod)(voteproducer)(regproxy)+ @5 H( R/ x# g9 D3 O
// producer_pay.cpp
  t6 o  q/ z! N(onblock)(claimrewards)4 F5 e) G8 Q/ [4 L, h
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。
9 \3 U+ O& Z  V# @, R% Edelegate_bandwidth.cpp& u/ K5 H' q9 f1 |: g7 f
//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买# \, R/ _( U5 w# {
void system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {2 L8 v, Y8 c0 B8 c# z
      //在数据库中查询RAMCORE发行量,默认为100000000000000
- e0 i+ H( J, q& F& z      auto itr = _rammarket.find(S(4,RAMCORE));. Y: u6 C" F! ]4 k4 y. u- u/ O
      auto tmp = *itr;# @- F8 |1 A, D4 `( v, q+ q
      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );
4 I5 e: D4 G( b+ o7 ]      //通过转化后,调用buyram使用EOS购买
; W8 s* T0 ^& V# r; Q- @      buyram( payer, receiver, eosout );' _3 ?5 T; G9 \- {6 L' F
   }2 x6 G1 ~1 t9 m% H) l5 I5 _
解析
6 ?9 T7 |+ q" I' b' F* `RAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。
& c2 B/ O# r, A& bcore_symbol.hpp+ K+ L/ n& @3 {; `
#define CORE_SYMBOL S(4,SYS)2 B. n5 [9 K4 s/ ~4 s6 |
delegate_bandwidth.cpp6 x9 d5 d; {4 w# {2 I( C! U$ x2 c
void system_contract::buyram(account_name payer, account_name receiver, asset quant)( k( s' H8 m5 p  w) y6 @
{5 W% B; b& I* ^$ ]% h6 E, b* y: Z# _
      //验证权限& \) S  T4 S4 n
      require_auth(payer);
* Y2 z+ d- L( j      //不能为0. o3 |* p! ?  k. _! @$ r
      eosio_assert(quant.amount > 0, "must purchase a positive amount");" P/ O: T, }. M  B
      auto fee = quant;* G4 j7 Q- Q4 ~8 X. `$ {
      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)5 G0 W( N; ]/ |5 X5 k7 J* X  Q
      {, I) h- \5 _7 q- Y
            INLINE_ACTION_SENDER(eosio::token, transfer)
: Y9 o4 C$ d: i& A. q$ r            (N(eosio.token), {payer, N(active)},
. }" A( g* s' w& B+ a$ i' c             {payer, N(eosio.ramfee), fee, std::string("ram fee")});
5 d- o  o( U4 A# s      }, {- F  Z( ]; q
      int64_t bytes_out;
9 V$ b6 y1 R+ Q) X" @" N$ K      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量
6 [: @8 n) C2 F4 K      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");# |: N0 ^, C' u; G
      _rammarket.modify(market, 0, [&](auto &es) {- J3 g9 B* g; b9 u7 i  {8 k: m: ~9 }
            //转化方法请参考下半部分+ v. \' u' v: O
            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;, }2 {1 X4 Q* @8 }" E  `% v2 U
      });
: I2 o" G& ~# u% Q      //剩余总量大于0判断% w, G5 k8 F% R7 m& h
      eosio_assert(bytes_out > 0, "must reserve a positive amount");
/ ?% @2 Y" r5 {* e% p( h      //更新全局变量,总共可以使用的内存大小" Z! r6 {8 A) v8 P2 Y& K
      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);* P) e; R% [1 S. i: [4 T
      //更新全局变量,购买RAM冻结总金额
6 ?& I. B6 J2 d$ y) T, `$ e# ]' S4 W- R# t      _gstate.total_ram_stake += quant_after_fee.amount;3 x% d& T( q# r$ A  S9 I
      user_resources_table userres(_self, receiver);
" x. u$ l9 v2 W& s  J      auto res_itr = userres.find(receiver);
; \6 f$ _/ N0 A8 Q3 p      if (res_itr == userres.end())
" ]8 p* t6 S; Z9 U( d      {' u0 o" b$ ~. b% G* k" m' h. A
            //在userres表中添加ram相关记录; _* o- ]( N8 w/ Y, |
            res_itr = userres.emplace(receiver, [&](auto &res) {6 k/ O7 b+ b1 ^) {* i* @
                  res.owner = receiver;
& c4 @4 `* i& a. m2 N                  res.ram_bytes = bytes_out;
" h: s( ?; w5 |  j' n6 R3 T7 @            });1 v" ]/ U# s/ A6 D+ d# l/ E
      }
* w9 T+ m* v3 x5 t, M      else
" x) v) q: W7 n% I) \      {
  t( T( Z4 S" ]# s2 s, B            //在userres表中修改ram相关记录
$ [/ [: F/ p* K+ \            userres.modify(res_itr, receiver, [&](auto &res) {
1 C+ `8 @9 E& i                  res.ram_bytes += bytes_out;- B+ _' L. R5 {7 o: j2 {! F
            });
8 R- G; m" }! ]4 D7 @5 [3 [% ?      }: K9 r2 L1 h7 {  t$ y
      //更新账号的RAM拥有量; k9 [2 _. ]+ `- k+ L
      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);
, ?4 N8 ?! l( Y6 o}: Y9 c1 X0 p7 X7 c0 M
相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。
% j6 e2 k0 y4 k/ w) Iexchange_state.cpp' |/ K) _. \) a- s. P. N
asset exchange_state::convert_to_exchange( connector& c, asset in ) {5 x0 J! P: Z& s8 @+ o
      real_type R(supply.amount);   //RAM已经售出的总量7 D- B' P& u9 h' v
      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量( E' y  y: h/ S* `2 u6 ^9 i
      real_type F(c.weight/1000.0);( t/ E2 G3 C+ z; d- j
      real_type T(in.amount);
1 C$ v2 K0 f; y8 N' \      real_type ONE(1.0);
5 I; b' \3 J3 R% u1 N      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量
  U" B9 R8 @6 m7 l, r      //print( "E: ", E, "\n");0 B8 V4 L7 V% G; k* h+ L
      int64_t issued = int64_t(E);( M( F/ H! z* k- v9 ^/ C- o0 ]6 m! o
      supply.amount += issued;//更新RAM已经售出的总量
' z. s7 e/ ~8 V5 G7 U1 a! t- R      c.balance.amount += in.amount;//更新RAM总购买金额
* i6 R8 J6 \* N" G- W6 {      return asset( issued, supply.symbol );
) C4 o8 R. B4 F" u: L( A   }
8 r! G' x9 k9 M   ! q; E) n7 p4 ]" N
asset exchange_state::convert( asset from, symbol_type to ) {( a/ q8 L6 i3 D+ i
      auto sell_symbol  = from.symbol;  . R1 E! V3 O1 J- w2 s; z0 s
      auto ex_symbol    = supply.symbol; % x0 ~2 {8 @5 W4 b( }
      auto base_symbol  = base.balance.symbol;  
1 U& o$ V$ Q( p) `, a( i6 R+ R      auto quote_symbol = quote.balance.symbol;
$ i" i) j" S) P) i7 I" x      
: I3 n% E+ {2 e0 L* }& x. U. N) v: F     //根据币种转化可以购买的RAM量
! `: X* i9 |. o7 c9 y5 U      if( sell_symbol != ex_symbol ) {/ h# E$ {! h: g  }; H5 P( V
         if( sell_symbol == base_symbol ) {
% X/ p6 M5 i& J, z4 y2 X$ T+ S0 U            from = convert_to_exchange( base, from );
- P; R- L6 n9 ^0 Q; j         } else if( sell_symbol == quote_symbol ) {
" P7 ^8 h; k% F2 R% k) G; ^. P            from = convert_to_exchange( quote, from );1 f& r% o8 |, J7 v( p
         } else {
* V& k3 k3 ]& W6 u" u. s            eosio_assert( false, "invalid sell" );* V+ X2 Q$ J. @7 |( j& s2 H
         }
3 [3 @1 Y2 t6 Q1 Z) {      } else {
+ s& s5 \1 _1 W         if( to == base_symbol ) {
8 v* ]* C4 n, c0 i. g7 @            from = convert_from_exchange( base, from );
3 D7 O: d3 _6 J) ~3 k* h" y         } else if( to == quote_symbol ) {
& T( e( G( L( O/ q            from = convert_from_exchange( quote, from ); ) @1 q; s/ w" t' u2 W
         } else {. \7 Y6 T+ o0 [0 k- e" J1 C
            eosio_assert( false, "invalid conversion" );( V& n5 T" B7 b8 t
         }
: S1 @# F8 W8 y1 n0 W      }
, n: E7 `9 [8 m5 c+ W8 c      if( to != from.symbol )8 Q4 r6 E8 c8 S) x& ~
         return convert( from, to );
8 N5 V9 Y4 k: Z4 {$ T/ @      return from;
+ q6 I0 R1 E; |   }; d6 Y2 d- k) Y/ m
convert_to_exchange的转化公式如下。
$ w9 W/ A! D/ F9 ~! t! P* d& ~2 L& Q0 U$ e7 S: y9 Z9 u0 g
ram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10