Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
109 0 0
eosio.system.cpp5 e1 }; U8 L% o
// native.hpp (newaccount definition is actually in eosio.system.cpp)6 `; N! Y# N6 \0 P* K$ ^9 [1 m
(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)* Q; G: `7 S# c; A+ b
// eosio.system.cpp6 z! B1 g# Q& Z/ ?# L$ z, C
(setram)(setparams)(setpriv)(rmvproducer)(bidname)
' o: v  k; w7 s" T; `// delegate_bandwidth.cpp6 Z5 H4 R  j5 H- _/ y) p, \) D3 }
(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)
  [) H! J2 M% o7 J9 ^4 ?1 z// voting.cpp
* H, A) u, Q% s: b0 S(regproducer)(unregprod)(voteproducer)(regproxy)7 O, m  }. {" J! \* i% {3 r
// producer_pay.cpp
* M; C) w* m! C3 M) W" s! {5 _(onblock)(claimrewards)5 S3 i: I+ k% I% Q5 W
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。+ u; p  N* |7 E
delegate_bandwidth.cpp- j% R0 A& y' S' i" J
//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买
+ c) @/ n5 ^" P( J8 z" a; Evoid system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {, _& g! S& F' y. J8 s! Z1 p
      //在数据库中查询RAMCORE发行量,默认为100000000000000
. R5 ~, d% R" E$ l/ f      auto itr = _rammarket.find(S(4,RAMCORE));
* F; f7 i# v1 k( \/ n* _      auto tmp = *itr;
" o* L8 E- J- h$ U6 A( ^      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );
- e8 S, {: `  a7 j      //通过转化后,调用buyram使用EOS购买) l1 O/ ?' U. z) E+ G
      buyram( payer, receiver, eosout );
7 o( a6 r: c- k) Z   }$ Q) @) B9 {3 a' v2 e3 ^. p* Q9 Y
解析
: E/ _" c" @( Y1 \, G8 ?( jRAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。7 Y0 R' U( ~( R6 H& U# D% Q* ^
core_symbol.hpp
. C8 E% B5 F, }. e8 A2 G& f" T% S#define CORE_SYMBOL S(4,SYS)
# }) p1 _8 ?8 X# idelegate_bandwidth.cpp9 g) Z5 c( t! I
void system_contract::buyram(account_name payer, account_name receiver, asset quant)9 h" q& n1 U6 }' ]7 E
{3 ?+ B! Z( S9 ^/ z3 T8 Q% N
      //验证权限! u8 v, I+ L; D9 v1 W+ n
      require_auth(payer);7 _4 E6 q3 V, T# x0 L% a) i
      //不能为0) y" t4 T1 p# T0 y5 L1 F
      eosio_assert(quant.amount > 0, "must purchase a positive amount");
  t" }5 ]1 t0 Q* ]      auto fee = quant;
- P6 u+ j6 t4 S! I1 q# M8 k      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0): z: V+ ~$ w. w
      {
) S; j6 {5 i6 c. }* Y            INLINE_ACTION_SENDER(eosio::token, transfer)0 k2 {3 b3 z2 F+ r2 I6 e
            (N(eosio.token), {payer, N(active)},
7 L% m& |! n" d3 U- ?) |             {payer, N(eosio.ramfee), fee, std::string("ram fee")});
' y7 G; G! N8 m* d      }
% |1 t. Z! a1 ^" h- O( j      int64_t bytes_out;
( l/ j% l1 B2 i2 f2 y      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量
6 T. L7 }8 O% p* k7 W# A3 v& F      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");# A5 r$ o# E! X
      _rammarket.modify(market, 0, [&](auto &es) {
5 p8 j" l2 Q- o2 E, ~            //转化方法请参考下半部分! F& p2 X& r0 O
            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;7 O5 E- J0 c- R/ c# w6 x" M( z
      });
6 z  \( _) d- q% m5 P      //剩余总量大于0判断
2 P# N0 c& \  s      eosio_assert(bytes_out > 0, "must reserve a positive amount");% y4 R: U& E. {7 G! f# o5 N/ n
      //更新全局变量,总共可以使用的内存大小3 u6 B8 }, A+ M4 F' M3 ?
      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);# h  n2 P2 e" i( l) [7 n' t
      //更新全局变量,购买RAM冻结总金额
+ P$ V) r; B7 W  x3 W5 k8 B( t$ ~      _gstate.total_ram_stake += quant_after_fee.amount;
& A/ e4 ~. c, X( t, M* _      user_resources_table userres(_self, receiver);3 Z8 _/ e, Q  L1 x1 h
      auto res_itr = userres.find(receiver);
( ]* ]8 U4 u& h- ~- H( ~      if (res_itr == userres.end())7 y" p( j. Q6 M4 S: L- z
      {6 x5 h$ U+ r6 _& |
            //在userres表中添加ram相关记录6 _0 Y( x, v  O: d8 e
            res_itr = userres.emplace(receiver, [&](auto &res) {
  N6 n1 r$ e. q( j                  res.owner = receiver;
2 Z- r, E, J4 ~+ r4 c- _* U" i                  res.ram_bytes = bytes_out;/ y0 I  c7 |! J- j, l7 n, `
            });
- i2 b$ S2 x$ c/ O! P8 @8 c      }
+ |/ m# x: `3 B; Y/ h! R! a5 x      else2 w$ L, T; O( W0 |: j7 x2 G) N
      {! G5 j5 d) p9 w! ]0 U4 Y- P8 E+ Q
            //在userres表中修改ram相关记录
' `& E, l: T# g- ]% P1 _' ^6 i& t            userres.modify(res_itr, receiver, [&](auto &res) {
1 R( O) {- o! [9 a1 w6 c. w1 ]                  res.ram_bytes += bytes_out;- u8 K  G$ p6 j
            });$ I/ n9 u3 D1 O, K9 \1 t
      }
: n5 i$ i$ G. ^+ G      //更新账号的RAM拥有量
, L+ I; V/ x6 S& C* S      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);/ U" o( \; M5 j$ y) [
}1 z9 W& k# `$ b, T! }" p
相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。4 V( L1 D5 n: I) |6 P6 i
exchange_state.cpp) h; W) }8 ]0 a/ e6 K  ]7 ?' X$ x
asset exchange_state::convert_to_exchange( connector& c, asset in ) {# f4 H2 z3 E' O  v' j$ v
      real_type R(supply.amount);   //RAM已经售出的总量
% o# r0 h. E! P# |" h* T      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量- R. d4 P8 |6 ]7 a$ G
      real_type F(c.weight/1000.0);1 T7 @" N7 ~# K/ \. `, |
      real_type T(in.amount);
7 H" `4 k* S2 N9 \. s7 c, H      real_type ONE(1.0);
+ i. M. p" \% m      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量0 h! R1 e0 y  C" u" E3 Y, l, o& i; G
      //print( "E: ", E, "\n");
. r0 `4 u" D; y- [, H9 s2 W5 Z; F      int64_t issued = int64_t(E);8 |6 o$ k! z( W6 Z
      supply.amount += issued;//更新RAM已经售出的总量# j% J1 r4 I3 e, X* M
      c.balance.amount += in.amount;//更新RAM总购买金额
0 O* \6 g" Y. V. o: _( s      return asset( issued, supply.symbol );
- j# f5 D3 r- o, W" c, P0 B8 k   }! t+ @, W3 S+ O- ~) m1 k$ T
   4 S, x/ O9 \- e; V& U+ Q
asset exchange_state::convert( asset from, symbol_type to ) {
5 U+ M4 j- P9 ^* f; n      auto sell_symbol  = from.symbol;  
/ Z& t) B% d7 r; v5 r: L      auto ex_symbol    = supply.symbol; " f5 {  Z2 i5 i7 i; V6 X
      auto base_symbol  = base.balance.symbol;  * C& {- a/ t& E) y" h+ ?9 m: T! h
      auto quote_symbol = quote.balance.symbol;
; P% Q8 `0 a  o8 r% j8 `      
) Y9 f5 X7 o# _$ Y& ]& p! G     //根据币种转化可以购买的RAM量
4 J2 d* y4 }4 ^      if( sell_symbol != ex_symbol ) {
7 q7 j3 P4 Z+ N  @- t; b. s         if( sell_symbol == base_symbol ) {
& j% d9 T4 N9 K            from = convert_to_exchange( base, from );
! e, `6 ^+ b. s) y         } else if( sell_symbol == quote_symbol ) {
5 s1 A: D9 t) L+ `            from = convert_to_exchange( quote, from );
- \$ h0 L7 L0 Q6 s/ {1 l         } else {
9 `, W8 V6 n( b9 ~8 |9 ~            eosio_assert( false, "invalid sell" );
4 r, H. U5 z9 e4 R% D. f         }
! i( n9 w5 K1 H) h      } else {1 B9 {. E3 D" m7 j
         if( to == base_symbol ) {4 m# \) n# [* u+ w: d/ R. m5 v2 r
            from = convert_from_exchange( base, from );
5 m6 T. k4 g* C8 L# W) O         } else if( to == quote_symbol ) {$ e" z) R- b! ]* w% \( A2 s
            from = convert_from_exchange( quote, from );
: h4 b) [4 k# z( j7 @         } else {
% y7 f# Q8 j' B" l  g1 H8 T            eosio_assert( false, "invalid conversion" );
" C' w, Q9 t, S4 `. v         }: v: P% ?) b3 b+ J
      }# Z# c. M4 |4 c. E7 J- q
      if( to != from.symbol )  \: N1 q* z( y0 `; q4 ?
         return convert( from, to );& Z2 o& w0 I: p! K$ B, G1 c- H+ Z
      return from;  Z# X3 C. j6 K( c
   }6 p% C# Q, H+ O) g. V; I
convert_to_exchange的转化公式如下。
% e' S3 L5 Y9 V+ ]" V! v
/ V, P, w7 ^0 ^: dram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10