Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
129 0 0
eosio.system.cpp
! i  U) H4 W7 t8 L' c6 |// native.hpp (newaccount definition is actually in eosio.system.cpp)7 \7 @+ r- B8 S8 l% Y! u
(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)
  ?/ n5 p5 w0 Z5 Z// eosio.system.cpp
$ j7 r4 E# T7 ]  F(setram)(setparams)(setpriv)(rmvproducer)(bidname)
: |6 G5 t, R+ ?1 |% K# W// delegate_bandwidth.cpp
# u: Y  `2 D3 o. Z(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)+ u: n( H7 B- I1 _
// voting.cpp3 o9 i) T; p3 o  E0 {( L
(regproducer)(unregprod)(voteproducer)(regproxy); B6 w) X% U" x5 k. M) v* v7 m
// producer_pay.cpp
( G7 u0 [4 b* F6 t(onblock)(claimrewards): u( n: [5 H2 P0 r, r6 w- O4 T3 f
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。
$ [$ u- e9 \' K0 y1 E# U7 P* vdelegate_bandwidth.cpp
' c1 ^, w& P# f) D$ I" ~//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买
6 i1 c. z# V$ I0 @/ Z8 |$ kvoid system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {
6 A9 z, e! W* M8 _  g5 Y4 N      //在数据库中查询RAMCORE发行量,默认为1000000000000002 j3 ~: j) m4 ?! r4 t4 t# t
      auto itr = _rammarket.find(S(4,RAMCORE));
* g; b) f6 I% {0 a8 J      auto tmp = *itr;% X! f5 S0 S/ q4 j" j1 L3 z3 @, R
      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );
% b3 U, z5 `4 E% W, `  `      //通过转化后,调用buyram使用EOS购买5 \2 l* F( j1 {1 R9 k  B
      buyram( payer, receiver, eosout );2 \* `2 s) u; F* Y9 |! q
   }. l$ Z8 E! S: J
解析3 G; g! P8 J. \/ f" 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购买。
+ o' l5 V9 d2 L4 e7 u5 J4 r; `1 ~core_symbol.hpp
( {& E4 F  ~6 t8 e#define CORE_SYMBOL S(4,SYS)3 p2 ]' \! a9 O2 F# E% V# ]
delegate_bandwidth.cpp
1 }+ u+ ]+ a* y/ }0 \. ?0 F( uvoid system_contract::buyram(account_name payer, account_name receiver, asset quant)
4 R4 i' r. Q( W0 E0 }4 _) `3 J{% x: ?0 q; D0 ?  l
      //验证权限
! I' T$ y( G9 o3 w      require_auth(payer);+ c; g# ^9 t) S+ d4 p
      //不能为0
. W1 G# U, M3 e5 r      eosio_assert(quant.amount > 0, "must purchase a positive amount");
: Z8 `) x+ M  J; g7 z      auto fee = quant;$ s( T$ q; C+ ]
      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)
( `3 U# R$ s1 S" ?3 ?      {
& M. V, ~/ s  ?5 @7 H            INLINE_ACTION_SENDER(eosio::token, transfer)% e4 P' p) s# E6 c
            (N(eosio.token), {payer, N(active)},. o9 L0 B4 H1 h( P
             {payer, N(eosio.ramfee), fee, std::string("ram fee")});
" F, N- L/ _2 o      }
1 L8 ^+ g4 z& z& S4 b$ y! h- O2 N      int64_t bytes_out;2 `0 T# \$ A* U0 L
      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量
+ {4 t) |" b/ i$ U& W( E      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");- K# T; o" }/ `; K( Z
      _rammarket.modify(market, 0, [&](auto &es) {
9 \- u' |8 f8 C7 \6 q' h8 V# o            //转化方法请参考下半部分/ X: d. `0 C( b, O
            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;6 |0 k, g: p2 A# B, s* F
      });
5 J. Q6 r1 H7 w! z$ z, t" q      //剩余总量大于0判断1 ]& ?; c- C; `; U$ `3 z7 V
      eosio_assert(bytes_out > 0, "must reserve a positive amount");
. B" q* q' b4 d7 Q      //更新全局变量,总共可以使用的内存大小
5 O0 [: ~1 `5 J. I: [/ {5 `' J      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);
+ A7 n' V2 q9 @* [6 F8 x      //更新全局变量,购买RAM冻结总金额
4 [- L6 Z* Y! c8 N" C0 X9 R) b      _gstate.total_ram_stake += quant_after_fee.amount;
, M  T* U1 q" N1 O8 `/ c      user_resources_table userres(_self, receiver);5 L2 i4 W' p; \) O
      auto res_itr = userres.find(receiver);
4 L' ]+ j0 r# Q      if (res_itr == userres.end())
$ C0 U3 ^& ?# @+ ?      {
# ?/ ]6 a8 L1 ]- a( }2 S' p6 I            //在userres表中添加ram相关记录1 ^, }0 ]5 k! z$ I$ Q. y
            res_itr = userres.emplace(receiver, [&](auto &res) {
8 U) k: F* e7 r  o# F                  res.owner = receiver;
( G& x" K9 G; S4 p( }0 u                  res.ram_bytes = bytes_out;
' o- M4 l* j9 d/ t; j9 G            });  U4 {) d# R. D9 N/ {- G9 w% ?
      }0 X3 J8 x& l+ t+ n3 i  P- c3 [0 j
      else
' I6 m" `: {9 y* `8 i      {
1 `2 c" h1 P3 k/ E            //在userres表中修改ram相关记录3 m7 L$ `! O9 e! j: p/ ?: ?
            userres.modify(res_itr, receiver, [&](auto &res) {; M1 f; W! N8 t# o0 m# I0 o9 b
                  res.ram_bytes += bytes_out;
  w1 w5 Q2 _7 v7 [0 B            });0 \2 X$ I% W6 P8 d) E
      }# S, }  j4 X3 g5 o! m! k
      //更新账号的RAM拥有量
1 T' z4 v: z0 N, l3 B0 L      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);5 o" M, p/ a. Q: L
}0 h6 g; W6 ~# A/ Z& o. {$ x* p
相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。
( }& W9 r# V. w: z; sexchange_state.cpp
# l) j, z: D% R. u: n8 dasset exchange_state::convert_to_exchange( connector& c, asset in ) {
7 z; z* K2 G+ |, \; a      real_type R(supply.amount);   //RAM已经售出的总量
1 c( ]! q: z  R& p  W      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量; G3 e5 J/ A/ {. ?7 T0 t" g2 R
      real_type F(c.weight/1000.0);
' ^4 `' s6 C  W      real_type T(in.amount);* E8 ~8 _1 q; y  {; W( X
      real_type ONE(1.0);
: `0 V" @' F# J      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量
) G0 A4 ^6 ~) u0 t* p9 m5 ~  a# J      //print( "E: ", E, "\n");
5 A- o6 \4 o6 u; M( L4 q& R      int64_t issued = int64_t(E);  Y7 R3 ?: ?0 D" [) [
      supply.amount += issued;//更新RAM已经售出的总量
1 F* w! a3 b) `% @+ N3 P      c.balance.amount += in.amount;//更新RAM总购买金额6 X% e1 R4 _( g! Q  H
      return asset( issued, supply.symbol );  n! f( _, b3 g
   }: Y5 x/ K& m- q0 M/ Y
   0 H" V  D  L# F5 s; t
asset exchange_state::convert( asset from, symbol_type to ) {
  ?8 M9 r' j+ z  O% |" h% M% T) }      auto sell_symbol  = from.symbol;  
' M6 J4 d- A: Y1 ?  v      auto ex_symbol    = supply.symbol;
, [! J& R% X* ?7 i/ V) p( x      auto base_symbol  = base.balance.symbol;  ( w& \' ]! E' k4 N
      auto quote_symbol = quote.balance.symbol;
+ {4 C. C5 _5 I      
1 C( q# S( |& o     //根据币种转化可以购买的RAM量* V4 _# l. `6 p9 T4 T( f
      if( sell_symbol != ex_symbol ) {* k, N$ e% g& V5 ^8 t
         if( sell_symbol == base_symbol ) {- l) B0 p+ Z  d
            from = convert_to_exchange( base, from );
( q7 H  r7 n( P0 \& d" I         } else if( sell_symbol == quote_symbol ) {
7 _3 E0 n. Z0 s, @8 Y. Q            from = convert_to_exchange( quote, from );" p# Z1 w6 l- E0 l
         } else { . C* q$ `* F% I  X. \  u
            eosio_assert( false, "invalid sell" );. O7 o; `5 _% i0 a
         }+ c* C7 A3 H! r7 g. w' a
      } else {
+ F0 h0 ~! l. q/ e8 S$ d! A         if( to == base_symbol ) {
" v6 [4 f) k0 L5 J6 p# x# }: q- @            from = convert_from_exchange( base, from );
& F; g; d# T. i9 [* r0 {         } else if( to == quote_symbol ) {- k6 a2 S' d. X  c: a) I, s/ k
            from = convert_from_exchange( quote, from );
) C. q+ `1 d4 b         } else {
  y: d# T/ ?5 W2 c. ]6 O            eosio_assert( false, "invalid conversion" );
3 j6 }6 j7 G( O1 a7 o; j         }& H2 _, y: U4 Z, n
      }, _: ^" t1 u1 v+ s% a
      if( to != from.symbol )( u) Y/ z, ]3 ~0 A
         return convert( from, to );1 g# @" h: @& m! T: v
      return from;
, q) V+ ]+ K, s; \/ `$ g8 j& G- k5 p2 Z   }
% i. o$ g9 k  V1 X6 F3 D3 ^" Iconvert_to_exchange的转化公式如下。
4 ]$ l; w0 c' ?3 j3 y  s: |$ t) h# j' ?1 \7 |6 u8 W9 N( H) K
ram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10