Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
110 0 0
eosio.system.cpp" K% \$ j% j1 \& k" m2 C& V: f
// native.hpp (newaccount definition is actually in eosio.system.cpp)
- g# M0 y4 c3 H) n( L(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)
( p- s- R: ~9 `. q7 Q! y# u! ?// eosio.system.cpp
; k. M! u! u9 ^, o# \% ]5 F(setram)(setparams)(setpriv)(rmvproducer)(bidname)
$ W  r! K  y2 f) t0 p9 o// delegate_bandwidth.cpp
5 x, ^2 N* A* p* |(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)
7 t, t# m7 h9 N1 L/ X  p3 ^// voting.cpp
" o* i" v8 R. j- H$ x, O(regproducer)(unregprod)(voteproducer)(regproxy)2 W+ s" V! T2 y% e
// producer_pay.cpp4 A- c6 E1 w6 z5 W  F1 F
(onblock)(claimrewards)
1 Y9 O* S, D' X! w: Jram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。7 m3 N" k3 C7 N2 ^( Q
delegate_bandwidth.cpp
% k* s7 {+ R* c1 M! [$ w) D//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买' F6 D7 m3 [2 N' P' H" {
void system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {
; K' O" O) |8 [- z$ w- B) p" o6 t      //在数据库中查询RAMCORE发行量,默认为100000000000000$ w# x- A3 v3 c
      auto itr = _rammarket.find(S(4,RAMCORE));+ z8 w% S) w0 o% B' ?3 I
      auto tmp = *itr;2 D4 l1 l$ S' B
      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );2 k! s- h7 Z+ P# x$ i/ Y- C; K% J
      //通过转化后,调用buyram使用EOS购买
* m! W* ?9 W; u3 ^* B! A. A      buyram( payer, receiver, eosout );
  \1 a+ U  E) L% _; Q   }  |! c" N6 Q; q% T2 F/ P2 P8 K
解析
6 g1 S5 @$ m* \& X; wRAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。
* F- M8 y# l8 C) Mcore_symbol.hpp
) _) f/ d7 a- F2 \; ?#define CORE_SYMBOL S(4,SYS)3 y2 p" H8 Z3 m4 @
delegate_bandwidth.cpp% ?  }. y  N. q: b4 y
void system_contract::buyram(account_name payer, account_name receiver, asset quant)
, R. t4 E4 {! u! M4 b{2 A! S/ x  I' V6 I( B3 g
      //验证权限. Q, y$ t9 A& e0 t7 E. I6 S
      require_auth(payer);+ I9 f8 Q$ k. {4 L* H# L$ O- X0 a
      //不能为0
& u9 b7 m1 g' t% ?1 B      eosio_assert(quant.amount > 0, "must purchase a positive amount");8 g9 e$ H7 T! ~, F' D
      auto fee = quant;
% q" c5 M- g) S+ @* k2 j      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)- t9 ]3 ?* H4 k6 k6 O
      {% m+ |' |0 ]2 `$ z& _/ _- d; [
            INLINE_ACTION_SENDER(eosio::token, transfer)
0 N) D& ]9 J; u6 H            (N(eosio.token), {payer, N(active)},
* h6 K5 s$ D' o$ t9 w* p             {payer, N(eosio.ramfee), fee, std::string("ram fee")});
6 z/ Y- V. u0 N/ l( T+ Y0 {      }: S; {3 R+ D1 u2 n! y3 A! V$ g
      int64_t bytes_out;5 f/ M9 n& V4 ?! b# S1 c
      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量8 {8 |3 ]/ {1 H* p- R4 L
      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");( f, j5 p0 y1 U$ Z& \
      _rammarket.modify(market, 0, [&](auto &es) {
, b0 q. s2 d* R  ?3 }9 d( v2 m            //转化方法请参考下半部分
4 f  b1 H) q- S& m            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;- C& C0 C* O/ [5 E- I+ T
      });
0 T2 `$ A$ F2 g4 w) \3 ^( @4 h3 z! G0 C      //剩余总量大于0判断
. f% S+ k8 W3 C# g% }      eosio_assert(bytes_out > 0, "must reserve a positive amount");
' z- p; x* X) ^% `$ W      //更新全局变量,总共可以使用的内存大小
1 q) ^6 o7 e2 t! R      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);
- a7 u9 Y1 m9 S5 @/ z3 `      //更新全局变量,购买RAM冻结总金额
# P5 L) q1 e1 |- Y2 ?      _gstate.total_ram_stake += quant_after_fee.amount;8 x6 |% a0 D* {
      user_resources_table userres(_self, receiver);
9 m6 V. y! z( a  p' d2 T6 P      auto res_itr = userres.find(receiver);
% M& l: G$ K' f8 m      if (res_itr == userres.end()), f( Y$ L' C: h4 x+ e+ d, A
      {# v. v! `1 m( q
            //在userres表中添加ram相关记录
6 |0 h( j( L  Y9 M7 w! x            res_itr = userres.emplace(receiver, [&](auto &res) {
" `' W9 b4 Q4 E6 g9 u                  res.owner = receiver;
! E. O6 a( L9 H# d                  res.ram_bytes = bytes_out;
7 L: y- m9 `+ j* d4 \) h7 u            });
/ `0 E  y; B% `0 l      }8 b' r2 ~! d5 I. z$ S
      else, a& }1 o0 }- E  C" N$ }9 C
      {
4 j8 J6 x/ F( ~8 i9 m$ @            //在userres表中修改ram相关记录
, X4 u- v6 a2 k            userres.modify(res_itr, receiver, [&](auto &res) {
  u) Z* C4 [$ Y; y, q                  res.ram_bytes += bytes_out;5 ?; t# `! @5 J6 Z
            });- Z( Z# _( P) h$ ?( p( S
      }
9 k" _4 h! T. K( U4 _1 J- y      //更新账号的RAM拥有量' [9 `( v# L5 m5 v
      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);2 P; b# {  l2 W% e
}
. G$ [  f% D  K; I8 H. ~! C相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。6 x5 d) ]( a: X4 y
exchange_state.cpp6 w+ G- S" e+ X. ~7 x
asset exchange_state::convert_to_exchange( connector& c, asset in ) {
: t8 P* Z" I1 w) R; k$ Y, F. S( Z/ X      real_type R(supply.amount);   //RAM已经售出的总量) E1 e, l& Q* ]1 f' J5 A; S
      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量
/ X7 g5 g" `! R      real_type F(c.weight/1000.0);8 p' Z  n1 \8 v, P
      real_type T(in.amount);
7 y$ i. g8 f. M$ M- @6 g      real_type ONE(1.0);
3 ~' G# x* b& _7 K0 o8 `, i      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量5 I, `1 M7 [( N
      //print( "E: ", E, "\n");
$ C5 A0 Y! A& H3 ]% H      int64_t issued = int64_t(E);3 w6 W9 ]+ Q" ^( \+ f
      supply.amount += issued;//更新RAM已经售出的总量% s0 `) A( S9 b" _1 N
      c.balance.amount += in.amount;//更新RAM总购买金额3 I% p5 K0 E% |
      return asset( issued, supply.symbol );+ c: ?/ d2 ~- m8 c
   }
/ c; V6 }. V$ }3 M  `/ }   & [$ T  _6 L! v0 _& U6 o3 t
asset exchange_state::convert( asset from, symbol_type to ) {
3 _/ _. k8 v- d, X: Y* N      auto sell_symbol  = from.symbol;  
2 |- I' ~4 R9 _6 y+ J, n2 V& `, h      auto ex_symbol    = supply.symbol; 1 e: m# ~( p/ d% p1 c5 U, [) E2 x
      auto base_symbol  = base.balance.symbol;  
: a- j: e# K% ~' N# m      auto quote_symbol = quote.balance.symbol;
5 S5 N, @" H! s8 j8 `/ s      4 v$ y/ w( S7 U4 k: P
     //根据币种转化可以购买的RAM量, y0 y3 Q6 C; D+ G. ^
      if( sell_symbol != ex_symbol ) {
6 l2 b$ T+ ^6 d- f8 H  [         if( sell_symbol == base_symbol ) {
8 C$ D# A% [, j/ @$ ^            from = convert_to_exchange( base, from );+ ?- f3 F! D6 j% i
         } else if( sell_symbol == quote_symbol ) {! d9 R2 Q* _1 f. w- Q) i
            from = convert_to_exchange( quote, from );7 |9 d! O. I4 y0 f5 N
         } else {
$ S' H! y& p7 V3 @+ F            eosio_assert( false, "invalid sell" );" p+ D% ^" g4 M7 ~6 {. k" d
         }: b; R& u- Q5 E
      } else {: ^/ m0 }8 @6 E- M/ h
         if( to == base_symbol ) {
/ D% [$ `9 ?4 o# B& k9 W- V9 q0 t) h" ~$ E            from = convert_from_exchange( base, from ); 0 `+ B+ I9 H  a; r* ?2 p
         } else if( to == quote_symbol ) {: `# {. T' `+ N1 I0 `' r
            from = convert_from_exchange( quote, from ); - F5 s4 [3 S  i6 R; i
         } else {; X$ A# J' p; Y* l; C/ R6 C  p+ p, @
            eosio_assert( false, "invalid conversion" );
8 a/ G% a# [% \9 X% U         }3 h* J. @6 j+ Y$ n. g
      }$ i. F( F% g0 u- H8 z
      if( to != from.symbol )
  w9 y9 U- R) u- c- O9 J( W* ~         return convert( from, to );: p  G0 W' Y2 C% a1 q
      return from;
5 ?$ g) {1 z( O   }
$ b- x3 S/ m& N2 D& B2 {convert_to_exchange的转化公式如下。7 o, i7 _" t, K& c6 d' S9 d6 I, t
+ U+ {0 ~7 t% V6 C, _
ram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10