Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文

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

945坏男人
107 0 0
eosio.system.cpp
- q$ L$ ?+ U; h& U* P// native.hpp (newaccount definition is actually in eosio.system.cpp)+ T$ m9 _# W6 z  e$ Z& t
(newaccount)(updateauth)(deleteauth)(linkauth)(unlinkauth)(canceldelay)(onerror)
2 Y9 g* L+ c1 r4 a& C. c// eosio.system.cpp
5 j3 e8 F0 m' d9 j& \(setram)(setparams)(setpriv)(rmvproducer)(bidname)
6 m. o$ k& z: c2 J* q9 B  M// delegate_bandwidth.cpp2 u. Q6 o: b' N  J# w9 q
(buyrambytes)(buyram)(sellram)(delegatebw)(undelegatebw)(refund), f+ K5 a  J* Q5 p, K% z1 l7 |
// voting.cpp7 n3 L  f3 [8 f2 O
(regproducer)(unregprod)(voteproducer)(regproxy), W% q: L9 m/ A8 g7 [  Q
// producer_pay.cpp9 k# s- u' \8 K2 B' {$ H/ t
(onblock)(claimrewards)% l+ {& K( O; c* h5 B. g  B# L+ j* q
ram,cpu和net操作相关方法的都定义在delegate_bandwidth.cpp,其中和RAM相关的是buyrambytes(通过指定字节数购买ram),buyram(通过指定货币购买ram)。# n* ~  \" p6 l3 D2 _
delegate_bandwidth.cpp
5 z& c$ g/ J" u) k* g//根据当前市场的份额,将需要购买的字节数转化为指定的EOS进行购买
% p+ P7 O# e: s+ Vvoid system_contract::buyrambytes( account_name payer, account_name receiver, uint32_t bytes ) {6 E9 j/ O, W7 e. m+ M+ F, f( p/ X
      //在数据库中查询RAMCORE发行量,默认为100000000000000" s; {# M/ v, A- l# ^6 T% d' Z
      auto itr = _rammarket.find(S(4,RAMCORE));
" g7 x9 b" {4 j& }      auto tmp = *itr;
, ?) C7 E4 C) S      auto eosout = tmp.convert( asset(bytes,S(0,RAM)), CORE_SYMBOL );7 V6 R$ w, |) K6 k: l) J* e" u6 u
      //通过转化后,调用buyram使用EOS购买
# j$ T* n; z+ \( l7 _      buyram( payer, receiver, eosout );& F. [" J9 B8 S4 D8 u6 Y, ]& U
   }! f9 A  L  g2 f. t
解析
! y4 \' _6 W' P; x4 }! W; f9 kRAM的交易机制采用Bancor算法,使每字节的价格保持不变,通过中间代币(RAMCORE)来保证EOS和RAM之间的交易流通性。从上源码看首先获得RAMCORE的发行量,再通过tmp.convert方法RAM->RAMCORE,RAMCORE->EOS(CORE_SYMBOL)再调用buyram进行购买。这里的CORE_SYMBOL不一定是指EOS,查看core_symbol.hpp,发现源码内定义为SYS,也就是说在没有修改的前提下,需要提前发行SYS代币,才能进行RAM购买。
# ?9 N0 ?  p0 z: y0 w- |/ h! y0 Dcore_symbol.hpp
$ ^- @3 h* }- J9 i#define CORE_SYMBOL S(4,SYS)( G: e, Z5 S! D$ w( G4 j6 t
delegate_bandwidth.cpp
* J( [& s. f& Z- `void system_contract::buyram(account_name payer, account_name receiver, asset quant)! ~4 ~' w5 a0 ?2 t3 K
{
6 l. j. b1 `( a( s* }      //验证权限
( D+ ]7 v! F% N& K      require_auth(payer);
/ V! @3 U( x( Y: D( ~+ i/ O      //不能为0
" S* ^' f8 m" I# X4 j      eosio_assert(quant.amount > 0, "must purchase a positive amount");
/ J5 p: b# w4 X+ c      auto fee = quant;
" R# x% B; u/ ]. L5 O& O% w( s      //手续费为0.5%,如果amoun为1则手续费为1,如果小于1,则手续费在amoun 0)1 \6 F" p4 S) @* I$ R
      {
7 ]1 `  D) \# |9 n. b% B* a( ]# R            INLINE_ACTION_SENDER(eosio::token, transfer)
- X1 c  X; O# S' c4 U1 M7 o; k            (N(eosio.token), {payer, N(active)},
. w' Z0 J+ B6 F9 j  X( P2 V             {payer, N(eosio.ramfee), fee, std::string("ram fee")});6 {$ ^3 D! I% b# l
      }' D& o* x% p0 U- [) K. e3 m& j
      int64_t bytes_out;. y/ f' @7 C% h2 v0 Y5 V! Y
      //根据ram市场里的EOS和RAM实时汇率计算出能够购买的RAM总量
# `+ ^9 y! B) `, i- w4 O      const auto &market = _rammarket.get(S(4, RAMCORE), "ram market does not exist");
: o1 f' A/ c1 L6 i0 D$ ^3 P" c: W/ @      _rammarket.modify(market, 0, [&](auto &es) {( b: ^) Q0 C' Y8 i( ]5 `; D0 V
            //转化方法请参考下半部分
( _$ M& s0 w  J  w: m& L# b            bytes_out = es.convert(quant_after_fee, S(0, RAM)).amount;
. X3 c9 i9 [$ k0 l$ D      });
) i0 n3 j" S; ^9 A/ \6 K- K      //剩余总量大于0判断
# e9 O+ X; m4 ^6 a2 X! m3 v      eosio_assert(bytes_out > 0, "must reserve a positive amount");- Y( t, x- V/ ~0 m
      //更新全局变量,总共可以使用的内存大小" W" \; Y5 Z. [% }
      _gstate.total_ram_bytes_reserved += uint64_t(bytes_out);! \1 u' Z, f4 w3 o" e
      //更新全局变量,购买RAM冻结总金额
  [3 ]" t  K* D/ H( `      _gstate.total_ram_stake += quant_after_fee.amount;
0 M* {" B* m5 H; t      user_resources_table userres(_self, receiver);
7 e# `, B6 d6 G5 i! T      auto res_itr = userres.find(receiver);
8 r3 M2 C( m0 h  L      if (res_itr == userres.end())
$ R* G) {) t% B/ l      {
% I6 o& D9 M0 h+ [+ g# _! w0 Z            //在userres表中添加ram相关记录
9 o' S) P  ?$ [/ N            res_itr = userres.emplace(receiver, [&](auto &res) {
7 P0 a2 l2 u( `; z  I5 c6 m/ q                  res.owner = receiver;: e+ I, A, d! O6 t+ h/ U! y
                  res.ram_bytes = bytes_out;
' p0 u9 C6 ~+ U5 x            });# C! p4 g5 O; D( |4 b- T* B
      }) i4 O3 G6 H; x+ A" I
      else8 a2 M. N6 x+ [: k
      {
8 n) N5 q7 Y0 s/ D4 N: k            //在userres表中修改ram相关记录: Z9 R0 }9 U* r1 d2 G: R- Q5 h! g
            userres.modify(res_itr, receiver, [&](auto &res) {
; q. n4 F( A+ q                  res.ram_bytes += bytes_out;
' a8 f8 Q; K1 q% D3 R% V2 v$ I" P            });
) r! z( A# Y4 u8 Q$ C: A      }( S7 [$ K, p9 Y2 C# P8 T: z
      //更新账号的RAM拥有量' ]: _, F8 c/ X, C
      set_resource_limits(res_itr->owner, res_itr->ram_bytes, res_itr->net_weight.amount, res_itr->cpu_weight.amount);4 e' y9 {% W: ]$ k, [, C+ c8 V# }
}
5 o' G# g6 m* `+ n" z7 _相关注释已经在代码中,这里还会用到一个比较重要的内容,那就是代币转化为RAM的公式,此方法请参考下面, 这方面还未深入研究会在接下来补充。, P" M1 [5 B  ^3 ~- W- S, a0 E
exchange_state.cpp& k- \' A$ |% A$ T, t/ G
asset exchange_state::convert_to_exchange( connector& c, asset in ) {
" L6 r# w+ b( ]      real_type R(supply.amount);   //RAM已经售出的总量2 x7 W" E2 D9 f6 k: Y
      real_type C(c.balance.amount+in.amount);  //RAM总购买金额+本次购买的量7 [- d3 a/ ]7 i8 M0 e8 M
      real_type F(c.weight/1000.0);
1 {. d# ]2 K2 }3 v; t! Y      real_type T(in.amount);
1 l; z; \; x9 q      real_type ONE(1.0);, F. x3 ]+ `" M1 Y) U: `
      real_type E = -R * (ONE - std::pow( ONE + T / C, F) );//换算出EOS对应的RAM量
6 G3 ]7 I, d6 a5 R1 B' A; X+ X" r6 F      //print( "E: ", E, "\n");% X, P6 ~2 \# I6 b
      int64_t issued = int64_t(E);2 b, U$ O: L3 h% g
      supply.amount += issued;//更新RAM已经售出的总量
" r! [% b6 S, o) v      c.balance.amount += in.amount;//更新RAM总购买金额
. F4 h7 n2 ?/ H+ S' p" R- _      return asset( issued, supply.symbol );2 t& a% Y3 I5 o, z( Y* a
   }
) W: u3 k5 {6 _3 ?- }   
+ d8 O0 L) R9 z8 c: Jasset exchange_state::convert( asset from, symbol_type to ) {) N7 C5 y2 w$ W1 S
      auto sell_symbol  = from.symbol;  
9 V9 ~) c' J/ h+ A( y3 V$ i      auto ex_symbol    = supply.symbol;
# r3 Z, O* E  G3 K* C8 }$ N8 g5 K      auto base_symbol  = base.balance.symbol;  
- m% W% X; ]0 J      auto quote_symbol = quote.balance.symbol;
1 @6 G+ w$ v7 w+ `- d% V      & G6 w% ~* _, F
     //根据币种转化可以购买的RAM量
. w# a7 n7 b+ J$ r) ^      if( sell_symbol != ex_symbol ) {
3 k% @- u; J0 Q% g1 X         if( sell_symbol == base_symbol ) {
$ B: b  U( ^" w2 n            from = convert_to_exchange( base, from );
1 Y  S% q' I; G8 |         } else if( sell_symbol == quote_symbol ) {
5 A: O) r3 q: A" _1 c            from = convert_to_exchange( quote, from );
1 F) `3 a, c3 W( {  E$ F( a9 `- ^         } else { 0 J! G8 n% z+ u, e" g
            eosio_assert( false, "invalid sell" );
+ S+ i* C5 _/ f; X# V6 ]         }5 f$ X5 r5 q: o( {2 L+ O
      } else {
8 G! O/ O+ E3 Z; }% P2 B" q         if( to == base_symbol ) {. Q6 x1 r0 }  R9 S6 x! V7 e" B
            from = convert_from_exchange( base, from ); 5 y* ]- ^  i: T6 H
         } else if( to == quote_symbol ) {  I; y2 o+ D9 J/ x6 D( w+ {3 t9 L3 E
            from = convert_from_exchange( quote, from );
( u, j% T: {+ }/ w" I; I         } else {; w( q9 C; H5 s* V
            eosio_assert( false, "invalid conversion" );
3 V- c! W  O# a  d/ P* c         }$ `- H1 n4 s4 K$ L
      }
4 R8 E: M) m3 R7 Q% H- l      if( to != from.symbol )( D7 J1 a, h) d. t! w) O* x
         return convert( from, to );  p. y8 n. j2 v  f) {- S1 F
      return from;
$ D  w2 P7 |4 ?7 ]   }
0 a3 c; ~" W2 T# y4 L9 Pconvert_to_exchange的转化公式如下。
3 w% Z2 m( Z7 f- |2 ^/ u
* v7 Q1 F2 ^; E/ M  G2 g, I: r( Qram购买的量是一个绝对值,是根据购买EOS的金额和当前市场内ram的数量计算出来的。一般来说在ram总量不增加的情况下,一样金额的EOS,所能获得的ram会越来越少。所以如果早期你购买了ram,然后过段时间后通过sellram卖掉ram可能还能挣钱。
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

945坏男人 初中生
  • 粉丝

    0

  • 关注

    0

  • 主题

    10