Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
204 0 0
eosio.system.cpp, }' K2 G' R0 Y1 W0 K$ v/ p9 H! b& W
// native.hpp (newaccount definition is actually in eosio.system.cpp)
9 }' \+ W; ^* Y(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)' c5 h1 d/ }' h" h" g/ Y
// eosio.system.cpp) X: p: b; t+ P9 L7 w. [. `
(setram)(setparams)(setpriv)(rmvproducer)(bidname)' Z' i. @5 c0 V! H, Y, h
// delegate_bandwidth.cpp
! o2 v" J5 f) c(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)
5 g; w: q: r/ g// voting.cpp
$ z- v) |0 p( n. D7 D( a7 I$ f(regproducer)(unregprod)(voteproducer)(regproxy)
- H" b& t' }; V0 I$ Z# D// producer_pay.cpp
6 F; d4 Q) _8 A0 B5 f2 ~6 f(onblock)(claimrewards)9 [+ T% f4 i) t( d6 i
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。
( `1 r+ u# w& o- I& w7 Gdelegate_bandwidth.cpp
$ i- q2 v$ Z5 d2 Z//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买
- D2 s5 [% z& u% {void system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {" I4 v" O, S! }! |" K/ P9 t
      //在数据库中查询RAMCORE发行量,默认为100000000000000- A# |/ x+ K7 b1 |
      auto itr = _rammarket.find(S(4,RAMCORE));; S0 |" H5 q; q
      auto tmp = *itr;$ l# R  ?' F8 h- }# h! m
      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );
' b0 }, n0 B3 u% Y7 q      //通过转化后,调用buyram使用EOS购买
3 W! d" M* n- l3 k: ]3 ?; D      buyram( payer, receiver, eosout );
% w! ~  I  N" R4 ]; a   }) I2 r) k* K2 o' g3 w/ I; |
解析
% H2 e: F+ f5 i% mRAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。
# _6 B& c$ y1 [  F& a6 dcore_symbol.hpp  K; w2 j2 V7 W0 }: m% Y9 l
#define CORE_SYMBOL S(4,SYS)
( x1 d9 W$ n' ?) zdelegate_bandwidth.cpp
3 e% C7 }/ N' c- D+ ]void system_contract::buyram(account_name payer, account_name receiver, asset quant)* K' T; \0 W, J# M7 ~  H
{
) Z+ f& ]! |" L0 L' R      //验证权限' L* m9 H) f7 `1 J
      require_auth(payer);" I" j; M6 S- j1 [! \& `
      //不能为0+ q' W. S" F( f! @9 m
      eosio_assert(quant.amount > 0, "must purchase a positive amount");3 f4 t7 r0 J/ Z
      auto fee = quant;1 T, d  B+ m: Z$ Z" d$ w  J9 S6 x
      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)
* j4 u+ D( s% W' z" k# V, t6 x$ ~, R# y      {
- E2 G( o3 g! r- r4 V            INLINE_ACTION_SENDER(eosio::token, transfer)
2 n/ d; \: y+ f+ C. s; z            (N(eosio.token), {payer, N(active)},8 [! |3 }- B5 I
             {payer, N(eosio.ramfee), fee, std::string("ram fee")});. q6 d; Y+ v1 o* y. d
      }
- Z1 u# @: S/ D( j- O      int64_t bytes_out;3 J- q% V/ T' x8 Y
      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量* b- r1 k* r1 e, P2 _- @
      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");
1 O" ~+ P# l5 h" M) Y3 k      _rammarket.modify(market, 0, [&](auto &es) {
% X% G+ z- ?7 q0 ~# j4 Y            //转化方法请参考下半部分
7 P2 S. a- O+ `* N: D' B            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;4 B* W$ K+ i. i" g
      });
; b, S# H; l& k+ P5 M      //剩余总量大于0判断
, z- |0 m9 u* ]; C. G0 n: ^      eosio_assert(bytes_out > 0, "must reserve a positive amount");: a7 D7 j. R' ~* e3 R
      //更新全局变量,总共可以使用的内存大小* I% U; ]0 T3 W: u
      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);9 J8 K  Q8 ]3 w" l+ S: W# S
      //更新全局变量,购买RAM冻结总金额3 s: T& J" P. b9 a& ?& @) T
      _gstate.total_ram_stake += quant_after_fee.amount;' \% A2 R, ~7 J+ E& N
      user_resources_table userres(_self, receiver);
, x# K; B' a! j( Z! r      auto res_itr = userres.find(receiver);
1 J; D, Z# I3 |) U/ N) T/ r* Q      if (res_itr == userres.end())' P# D7 _# N- H" Z+ v
      {. Q- R6 N6 N, T5 {9 V
            //在userres表中添加ram相关记录  ~. T2 r5 R' F% Z: P
            res_itr = userres.emplace(receiver, [&](auto &res) {; t* _* ^2 d$ ?, p
                  res.owner = receiver;7 R, L; ]4 ]. Y4 W( w' ^, x
                  res.ram_bytes = bytes_out;
. A3 g: |5 C. A6 I) z            });
% b0 e. n& k" d) c4 K      }
5 @4 N: ?* j- M" Y+ v      else
1 [/ C5 f9 L0 e* T  }' \1 |$ ^      {- Q# _; p/ r5 T3 ]
            //在userres表中修改ram相关记录% d" c& g2 ?+ B) P7 A
            userres.modify(res_itr, receiver, [&](auto &res) {2 B. h7 z- u% H  y. H3 u; v
                  res.ram_bytes += bytes_out;- v( v( C; H, z( k5 s
            });$ o5 F4 m0 S, C% \
      }+ ^4 z. D, @. l* ^
      //更新账号的RAM拥有量5 o1 i1 s' ~. `: Z/ O
      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);
, D& |2 n9 a# L0 K+ d" W" N8 j$ D6 S}( R# E, t. w9 p! [! ?
相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。- _+ v8 ~( e4 [1 }
exchange_state.cpp: j7 o+ G* f' i! ?
asset exchange_state::convert_to_exchange( connector& c, asset in ) {( T' I/ h; {1 A  m9 x8 Q* q5 l
      real_type R(supply.amount);   //RAM已经售出的总量
4 w1 N' ~, g* Z) R; D! \      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量
( Y- c- w- z! C      real_type F(c.weight/1000.0);
- j. p# _5 B, H" ^/ L! W8 V      real_type T(in.amount);
  Z4 j/ Y7 H& `/ c) S      real_type ONE(1.0);
! W0 b5 u. J6 c7 b8 m( F- Z      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量
+ \" {  _9 ^8 M      //print( "E: ", E, "\n");5 l. p7 w# o2 j" h0 ?0 D
      int64_t issued = int64_t(E);
2 p$ \( b9 C; K- Q/ Z9 B. a      supply.amount += issued;//更新RAM已经售出的总量/ D% d0 m* k; z& H# D! ^, f
      c.balance.amount += in.amount;//更新RAM总购买金额
# ?2 ?! k# R! |8 K- r      return asset( issued, supply.symbol );( W8 B* t) y! [$ ]( R5 s% N9 G
   }
  B: [8 `( D% S& J   9 g. |: n+ m9 g) q- t+ y
asset exchange_state::convert( asset from, symbol_type to ) {* u, }5 S# y, Z5 ~* f' w# o
      auto sell_symbol  = from.symbol;  * l! A3 q9 O6 H$ `+ l
      auto ex_symbol    = supply.symbol; 9 y6 y$ {. N! E0 y1 S' k
      auto base_symbol  = base.balance.symbol;  
9 _1 e* g% e& }5 ^& d      auto quote_symbol = quote.balance.symbol;
( T+ ^4 f) J' @0 D+ d' `' u: n9 S      3 K  ^/ c3 k: d& r, B
     //根据币种转化可以购买的RAM量
, x- x9 ^  \; G/ N      if( sell_symbol != ex_symbol ) {
2 {9 V  e( V& E2 Y- M# P* l         if( sell_symbol == base_symbol ) {
! e- z2 S2 D) ~2 x6 u4 W# x            from = convert_to_exchange( base, from );
% n9 ^9 s; U1 Q% g; Z         } else if( sell_symbol == quote_symbol ) {
: X5 B" x. a2 m  s2 N' V$ p            from = convert_to_exchange( quote, from );" h5 s, G0 b  K' U2 c
         } else { ' E7 i% @% r9 K4 K4 E: W
            eosio_assert( false, "invalid sell" );
" Q# _7 }# K0 Z! X         }
( a8 A1 t- W2 a0 n) U, J      } else {$ F! ]  M& T/ r) y0 B
         if( to == base_symbol ) {
( m1 N8 x) \$ k$ G5 U% G" [8 g2 Q: z            from = convert_from_exchange( base, from ); 7 O, V3 p( K6 G8 U  S
         } else if( to == quote_symbol ) {
% L& P) `# h7 H9 \3 b) A: }            from = convert_from_exchange( quote, from );
0 Q1 o9 }3 i. D5 n7 ]' I( t         } else {5 X% Z& x6 ]( s: ]2 U% ^- C: c
            eosio_assert( false, "invalid conversion" );' _! d) A' B- o% ^
         }
( \' p  c, i9 b/ \% i1 c7 v      }
' c5 i- x0 W9 R7 h% O. _      if( to != from.symbol )
' m7 F# j+ `3 B0 W- E: l         return convert( from, to );
/ q/ Z) P( ~$ ]- f8 h# d& _      return from;% R/ q  ]9 ^" D4 C4 e
   }: z$ Z: [' W0 a' P: o6 t. c5 i. T4 w6 l
convert_to_exchange的转化公式如下。: w4 o$ P) U9 H" D9 J9 Y6 @5 g
; E% Y3 @+ c  W0 F
ram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10