Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
203 0 0
eosio.system.cpp* E/ @: w5 h, p( e  D7 r& E
// native.hpp (newaccount definition is actually in eosio.system.cpp)
- O: X5 a0 f, }0 _8 @(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)* |, U* M+ P2 Z- e' M( c4 J
// eosio.system.cpp# l  K3 z. D  {2 B1 ^# Q$ y
(setram)(setparams)(setpriv)(rmvproducer)(bidname)) P' \6 K! N! B7 A2 o3 T6 |
// delegate_bandwidth.cpp1 ]) `- p* `+ e5 ?+ A
(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund)
$ Z4 A8 X! L2 D/ }( D// voting.cpp
4 b: d4 K' c' O7 ~(regproducer)(unregprod)(voteproducer)(regproxy)
, C7 A# u2 w+ ]8 O' t* g( t/ A// producer_pay.cpp/ n2 [# J6 n: ?. y. F" K  E
(onblock)(claimrewards)( J% Q# R: N* t  j; O" M# v
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。
( x7 Y) h/ {9 gdelegate_bandwidth.cpp
" y- d% [) `4 z0 X//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买) N0 h# ~+ C0 ?) I9 a, S9 Z
void system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {
: a) g" _8 S. }2 r- y+ e      //在数据库中查询RAMCORE发行量,默认为1000000000000007 W; C* Z9 b5 r  ?% }
      auto itr = _rammarket.find(S(4,RAMCORE));
0 A3 E6 g5 u, s) p. A! T$ v      auto tmp = *itr;7 f$ g8 F. |' ?( I7 N1 m8 V
      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );
. N0 n/ U# C4 J0 B5 w      //通过转化后,调用buyram使用EOS购买0 O; F6 ]- K4 V, D
      buyram( payer, receiver, eosout );
0 ^: \0 j" q' ~! b# N* N9 @7 U   }
  s# B( O, T+ k0 ]( t" r0 _$ F解析( X2 q+ a& [: W: L: t6 ~* }
RAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。
/ @3 D! D7 X! n+ p& b' \' tcore_symbol.hpp8 v  P' e# b# n# q8 m
#define CORE_SYMBOL S(4,SYS)
* H3 e7 @: Y2 ^& g% v9 |# D  _delegate_bandwidth.cpp
0 ]2 o8 O# D' ]0 y2 h2 R$ [/ @void system_contract::buyram(account_name payer, account_name receiver, asset quant)( [$ `( m5 C+ v! B* _
{
7 }' i4 l' _+ ?8 |      //验证权限
7 Q- I# ^" f1 X2 J; s3 Y      require_auth(payer);8 t& S7 X, K! F4 i  q
      //不能为0& K' i( A- i1 Y$ v) S
      eosio_assert(quant.amount > 0, "must purchase a positive amount");6 r. M5 f: r( W3 p- r' p  y
      auto fee = quant;
( N2 ?. g4 `" z/ m8 w, M" i8 Z      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)
5 c- J" L  H9 ]# R% j) e; L  t      {
4 y/ k, y; c; [8 D- \/ k            INLINE_ACTION_SENDER(eosio::token, transfer)0 n% V# f; L" C! v$ n
            (N(eosio.token), {payer, N(active)},
/ I7 E+ Z# {; D; a             {payer, N(eosio.ramfee), fee, std::string("ram fee")});
5 l. {( Z" V/ v) g9 q      }
) K2 [1 H( X8 \; Y+ y7 N' v      int64_t bytes_out;" G# U5 L4 E6 `" f; G/ |5 x
      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量, {/ _; P4 _; L) e& B9 U
      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");; C, N1 V4 c- g" f. s& \8 G
      _rammarket.modify(market, 0, [&](auto &es) {
0 ^! h; B# f/ ]" L/ M+ w' _            //转化方法请参考下半部分  i: A; \* g- {8 u) f; [5 W6 ?
            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;
) K' X* ?6 v; @. V9 y# q: u9 a      });
- {* N  d( ^& d4 ]! I1 ]) \      //剩余总量大于0判断* x' }5 \/ p* y
      eosio_assert(bytes_out > 0, "must reserve a positive amount");5 Y9 C; f+ C; J& C. }
      //更新全局变量,总共可以使用的内存大小" w/ J* n7 g9 o* A6 K
      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);4 r: h$ k# \( D: t& @/ W
      //更新全局变量,购买RAM冻结总金额
& c2 O- ?6 y9 r% R" s# d( S+ N      _gstate.total_ram_stake += quant_after_fee.amount;
( z' _  Z; @$ {0 l- b      user_resources_table userres(_self, receiver);
1 ]. U. N2 R' c6 E9 X$ S      auto res_itr = userres.find(receiver);0 g& G- r/ L: W: _9 ~$ ~) Z) g
      if (res_itr == userres.end())
+ i" t4 n1 y# R8 p1 q      {
8 o$ z4 v# U9 Q; A7 D            //在userres表中添加ram相关记录
! o% @% f2 A# P% m            res_itr = userres.emplace(receiver, [&](auto &res) {) U2 N; d% S* x' y! s9 z; @
                  res.owner = receiver;
7 J5 E6 Q8 J7 Y0 H* N5 C                  res.ram_bytes = bytes_out;
0 b7 V$ o- `/ @2 \            });
6 s7 m! b3 }& U( r( Z0 s' ]      }0 y0 v1 b# F' ~& o0 Y& o
      else
" P9 k$ {5 N4 z% E      {$ d  l% q. ^6 W$ D1 z! i) o
            //在userres表中修改ram相关记录0 `; |. c* `' u# n3 b
            userres.modify(res_itr, receiver, [&](auto &res) {
1 `7 d$ k3 F  b                  res.ram_bytes += bytes_out;
4 @4 B6 G8 N0 c" h$ a            });0 l4 ]( o  Q' b8 f
      }
* _' \% ?, T. A      //更新账号的RAM拥有量
7 m/ c  \  S5 v/ }& M. P  T8 b7 d' S0 x      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);
4 D2 W6 b) Y1 A& o" M$ h. e1 h* B}
* c& D3 b1 v! p, p. J1 N相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。
( r/ j9 H) n- Kexchange_state.cpp
) W7 e3 m/ ^% B3 dasset exchange_state::convert_to_exchange( connector& c, asset in ) {/ b# E, \: y/ s7 Q: ^! b
      real_type R(supply.amount);   //RAM已经售出的总量
3 M3 f0 G9 c6 U* h* m      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量9 w- F0 |2 D! F0 q  z: v9 j1 m. [) Q
      real_type F(c.weight/1000.0);
0 i& Q# c2 k& C3 @      real_type T(in.amount);
& H4 N+ V0 `- ~/ P      real_type ONE(1.0);' h1 D- V6 y9 _! J- f) o6 n$ \$ z
      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量
0 j* q, ]. m9 G+ k' Y& b; z      //print( "E: ", E, "\n");: Y' j1 ~4 n) T4 G/ s" z/ W8 F
      int64_t issued = int64_t(E);
! A* r' i/ Q/ o+ @4 v& K% C      supply.amount += issued;//更新RAM已经售出的总量# U9 Y$ h. ^( I7 z2 Y: s) N5 |# V
      c.balance.amount += in.amount;//更新RAM总购买金额; h4 J$ L+ m- r( [( _6 Q( ~
      return asset( issued, supply.symbol );
, O1 O7 [' q, @! ]4 i2 G   }$ ]6 g0 j, |/ B# M% y
   * E+ o. u4 M' i2 D
asset exchange_state::convert( asset from, symbol_type to ) {
: d: q1 h" S- y) n" @      auto sell_symbol  = from.symbol;  ) J- ?$ b" x7 A6 C5 s; i
      auto ex_symbol    = supply.symbol;
' K( Q% v% U8 u- Q2 Y4 T      auto base_symbol  = base.balance.symbol;  ; ]5 @5 O7 }8 \; T! U7 L( T
      auto quote_symbol = quote.balance.symbol;: F5 T3 }& m8 H/ d: z  x
        \: x" b1 ~2 f7 B, S# Q
     //根据币种转化可以购买的RAM量
) c( {2 E: {/ z      if( sell_symbol != ex_symbol ) {/ p4 B* L; }) x9 r: {- y
         if( sell_symbol == base_symbol ) {
, m, O' I  A! P- O7 L            from = convert_to_exchange( base, from );, @2 y/ R' L2 l1 x9 V7 I
         } else if( sell_symbol == quote_symbol ) {
/ o4 k) \+ K9 g" O+ g8 `. M" W            from = convert_to_exchange( quote, from );
* t5 z$ o) N/ W1 }, j! y' S7 H$ j         } else { 3 }5 O% L( r% s5 t/ I% b
            eosio_assert( false, "invalid sell" );
2 _- c, P# X* X         }! M4 \( z* h1 T' A. z
      } else {
" N4 `1 ?% [7 N. Y( O         if( to == base_symbol ) {5 C! q+ d! b# p+ g
            from = convert_from_exchange( base, from ); , T3 Z  L6 f" H- B( c3 d
         } else if( to == quote_symbol ) {
9 k4 d% P: q9 p            from = convert_from_exchange( quote, from );
  F" U" Y  y2 y7 R; A1 k         } else {+ V/ D* v7 [8 t' @/ g9 m
            eosio_assert( false, "invalid conversion" );
  A3 o  V8 k4 {3 _; ~4 F! P         }
. Y: f  i; C, F9 N, r      }" e2 V5 i4 _3 L+ d7 A) `
      if( to != from.symbol )
, I# {3 G. M( a8 K- p" _( L         return convert( from, to );
: T; D  s0 N$ a      return from;  C+ I0 u. \* E+ g( Z
   }$ v3 B- f' N# T( w
convert_to_exchange的转化公式如下。
6 k4 b' j: H0 d) i0 ?6 u
8 `: u5 `. g8 P6 V; ?# _! E6 _ram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10