Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
83 0 0
eosio.system.cpp
6 n+ M9 U3 ?- g3 e// native.hpp (newaccount definition is actually in eosio.system.cpp)
* I: N  q, \" w* U7 W; G# I4 u! \(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)
7 W  H2 k0 R- K7 T// eosio.system.cpp$ V$ P! a* _; g% M) D. g9 x" j; Z, }
(setram)(setparams)(setpriv)(rmvproducer)(bidname)2 I- D1 ^+ s7 H6 f+ ]* d
// delegate_bandwidth.cpp' ?/ h  L% N+ C/ s! x
(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)
3 h5 E- @" L% u// voting.cpp
( q' k. T. b4 C' p(regproducer)(unregprod)(voteproducer)(regproxy)) ?% g( A# o6 _+ I5 w  z
// producer_pay.cpp( ^: ^) T7 P+ ]- w- I! h
(onblock)(claimrewards)) U+ h) T7 s- `3 _2 d8 ?  D4 ?4 o' f3 l
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。
% h3 ^; {: F- U& g& Pdelegate_bandwidth.cpp
/ C4 S* G% o: A1 O& k, N* J//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买
( U) `: H6 [, G! o; {  c: c& Xvoid system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {- e6 ]: ~, `& u( `/ R
      //在数据库中查询RAMCORE发行量,默认为100000000000000. q7 x2 N7 w/ T/ C! L
      auto itr = _rammarket.find(S(4,RAMCORE));
. S/ ]2 I. [1 t. z      auto tmp = *itr;8 F0 W3 U1 b8 F/ u$ F# b
      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );) V7 B! o4 ?# F0 f% h
      //通过转化后,调用buyram使用EOS购买
* H3 _% j8 Q+ t4 w# U# c      buyram( payer, receiver, eosout );
6 A. f3 S4 k, v   }
' O* ~! D" C) o' k7 s8 ]( _解析
% \# v- ?  @7 p/ R% a0 J* gRAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。, E0 E5 W, D' P/ {
core_symbol.hpp" g# k" C* `  W, L
#define CORE_SYMBOL S(4,SYS)) P9 n3 g0 k) O/ q' T4 N. w
delegate_bandwidth.cpp- R" Q7 r$ R  v: ]  u- z7 K
void system_contract::buyram(account_name payer, account_name receiver, asset quant), U5 c  F6 A7 t  ]
{
. A# D. o; j6 {7 e8 u      //验证权限$ f2 A6 ^2 f- ^6 V0 y. U& R
      require_auth(payer);
+ O6 i2 p3 ?& X. K      //不能为08 g: i' g" |7 v. G  ~2 y8 H
      eosio_assert(quant.amount > 0, "must purchase a positive amount");
! h* I, F. t& {6 x7 |6 w: _      auto fee = quant;
; E9 x8 a* ~) o- N% r      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)* M/ y! }/ }$ r! e
      {
2 X8 n1 J  J# i6 }            INLINE_ACTION_SENDER(eosio::token, transfer)+ f% k, s, z, Q1 |' F% |/ g" z2 o
            (N(eosio.token), {payer, N(active)},
* ]; I4 E7 H' s/ |* L  @) X             {payer, N(eosio.ramfee), fee, std::string("ram fee")});6 l1 D4 @8 _! V
      }
" F6 R3 ?5 t- [5 {      int64_t bytes_out;' r# ~! b. r% m, c+ |
      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量- _7 f) ~  p" |! D, k4 b
      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");
9 p; L# @5 L  i  R      _rammarket.modify(market, 0, [&](auto &es) {$ N2 z- |  Q0 ?7 r$ r6 ^& W
            //转化方法请参考下半部分
5 c. |3 X0 v  y! {4 ]. Q7 M2 }            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;
& E& n' [5 _; }5 M  t: U      });8 V. j( m, X2 x4 B/ i  y. V
      //剩余总量大于0判断
+ l; I5 N0 u0 r" a! w      eosio_assert(bytes_out > 0, "must reserve a positive amount");) k( I7 |: v2 T0 b
      //更新全局变量,总共可以使用的内存大小7 k' C' D; ]3 r" C+ I1 b
      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);
; h- F) j& g* X: y! Y      //更新全局变量,购买RAM冻结总金额
# `2 ]( `( |, y3 C1 m: }* H      _gstate.total_ram_stake += quant_after_fee.amount;( r' y6 Y/ W/ |( O1 u
      user_resources_table userres(_self, receiver);0 N7 e8 g& F0 |, K
      auto res_itr = userres.find(receiver);: }- W- G) w% u
      if (res_itr == userres.end()); [& K4 R' A  z8 [6 I0 S6 M
      {
4 |& A& p1 G* ^- a7 Q            //在userres表中添加ram相关记录
. J/ k! N+ R7 x+ u            res_itr = userres.emplace(receiver, [&](auto &res) {
% g) \/ w- Q# c' N3 [9 f' g                  res.owner = receiver;
; A" h- c0 U5 s; ?) Y' }                  res.ram_bytes = bytes_out;
# w! Y# m4 L0 v/ u- [- w" B            });
/ R( _9 w, K, {. c. Y5 Z. y! x      }; n& t: S8 Z& C
      else" u  T3 [: z* |
      {
! Y" v- I6 N% W: \( R* x            //在userres表中修改ram相关记录4 Z3 ^5 m7 K# f4 Q
            userres.modify(res_itr, receiver, [&](auto &res) {
' {  w1 n2 ~. q2 l. g# y, |) F                  res.ram_bytes += bytes_out;! s5 E/ {! `/ Q, p, V, R
            });
6 N* S( U% d5 D3 Y- k; \" z/ Q      }& x7 W1 f+ e, m2 b8 u# Z, _8 p2 x
      //更新账号的RAM拥有量! I; \8 q" U9 C1 S: T
      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);
! e/ T) v6 {# x2 l$ V# j}
( u, b9 q8 s: K8 O6 W; h1 I  a5 w8 U+ p相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。, @- ^3 D# o( k) v7 Q* ~& `
exchange_state.cpp+ b1 }8 N5 G! ]# l2 k% T
asset exchange_state::convert_to_exchange( connector& c, asset in ) {
0 O2 J+ X% H3 E& @      real_type R(supply.amount);   //RAM已经售出的总量3 j' D3 c9 A0 B! P$ Q5 m! T1 u) W
      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量6 ]# Y9 M! {6 y; X9 F! ?9 B& ~, {
      real_type F(c.weight/1000.0);3 E3 O8 o- Z. [8 C9 W$ z$ v
      real_type T(in.amount);
; X8 d. S. j/ v8 Q$ n9 M% W3 x      real_type ONE(1.0);
2 E5 u$ N, i% L$ I$ ^9 x      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量
4 x2 q) [0 H/ p4 u* `( V* w/ W      //print( "E: ", E, "\n");1 Q' b( {$ i0 y/ b9 e$ A+ Y
      int64_t issued = int64_t(E);
3 e, q, Y0 y0 y8 t  a0 K( g- j      supply.amount += issued;//更新RAM已经售出的总量
. S8 V' M! @, e+ r3 J      c.balance.amount += in.amount;//更新RAM总购买金额
7 G8 x1 ^. K; F6 u& B: D      return asset( issued, supply.symbol );
0 c* \9 _( h4 Z7 B; C) m9 F; s   }0 N5 Z4 b, _, X' }9 R9 L
   
1 I* [+ y9 ]2 kasset exchange_state::convert( asset from, symbol_type to ) {& i) ~+ \9 u) k
      auto sell_symbol  = from.symbol;  
0 U3 K) [: E- o# C4 ^) i      auto ex_symbol    = supply.symbol; $ j- I( \8 X( s" n5 g6 v/ I# B& m
      auto base_symbol  = base.balance.symbol;  0 v- \; ?( y) y9 v3 `/ t
      auto quote_symbol = quote.balance.symbol;
$ k- a. z% q+ I9 A$ H* E5 _      
2 H5 f4 N- g9 p7 j     //根据币种转化可以购买的RAM量% v7 X) v1 p( X; ^$ T2 I# H5 H8 H
      if( sell_symbol != ex_symbol ) {% h  T' |3 D8 X6 h. C
         if( sell_symbol == base_symbol ) {
0 T2 @9 `2 \) P' L. O* `            from = convert_to_exchange( base, from );, s- S  F8 W* c! E7 v' n
         } else if( sell_symbol == quote_symbol ) {( M4 N9 v% b2 o) ^( R  _
            from = convert_to_exchange( quote, from );/ h/ r9 u% R; @% E% ]
         } else {
6 \- \3 z+ S& j$ \; S+ q' i" W            eosio_assert( false, "invalid sell" );
' q" n0 u; y* Z; T0 b+ a' p         }
, X3 b( Y1 B: E: i# Z, h8 s! e      } else {0 L- }3 m9 [* }* ]5 Q5 P
         if( to == base_symbol ) {+ J+ R- \# B0 V+ F
            from = convert_from_exchange( base, from ); 0 T, b. D2 e2 m
         } else if( to == quote_symbol ) {+ a( B1 e) m  J& P
            from = convert_from_exchange( quote, from ); 8 p+ Y7 m. G- |% J: U/ A7 e0 [
         } else {
& ?. D1 _0 G% c& c6 a. r( f            eosio_assert( false, "invalid conversion" );
9 N. P. D7 v6 d/ x8 m5 z         }
* o7 H  o" r" l# a- X1 R      }
7 F+ O! a+ J. m3 b6 O      if( to != from.symbol )+ p: }# Q& g% a7 x
         return convert( from, to );" u! j$ [4 _9 _9 K' G2 e% \5 }
      return from;+ b; N) C8 v# U  b5 E. m+ S, r7 N
   }
+ h3 X; w1 x* B) K* _$ y" Rconvert_to_exchange的转化公式如下。6 y& W' }* K7 v" }  X
# X& x; Y+ A1 {5 l. w& {# E7 ?+ m. F) t
ram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10