Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
在以太坊上发行的大量ERC20-Token是没有价值锚定的,其价值完全依赖于项目方的技术与运营能力,若项目失败了,则通证(TOKEN)价值就很可能归零。
; E1 E& _3 I8 x0 W6 [+ k: E0 \2 ]& p7 L0 X) t" k; f5 L8 |
若利用智能合约的强大而灵活的“资金流转控制”能力,在通证合约中控制着一定量的储备金,让通证与储备金之间拥有一定的兑换能力,那么Token的价值就可以储备金为锚定物,而不完全依赖于项目方。通证持有者也就不用承担项目失败或者项目方可能诈骗跑路的风险。
4 n3 y/ P* E1 o& m1 E# J4 x4 H) h  k+ N* R, h3 P
若通证与锚定物之间的兑换算法采用了Bancor算法,又符合ERC20标准,则被称为智能通证(Smart-Token) 。为了简单起见,以下的论述以ETH作为锚定物举例说明。购买与售卖Token的过程如下:
! N& y" J2 v. c9 S% ]2 O! `. J“购买者”发送一定量的ETH到Token合约地址,触发了合约代码自动执行"购买功能代码",获得对应数量的Token;“售卖者”发送一定量的Token到Token合约地址,触发了合约代码自动执行“售卖功能代码”,获得对应数量的ETH。* Q& `" m- r  `5 _0 a6 X3 y5 x
, N. n' I  O; }4 h
若AToken与BToken都是以ETH为锚定物的智能通证,那么Token持有者无需通过交易所,仅仅凭借智能合约提供的买卖与兑换功能,就能实现AToken与BToken的自由兑换,比如AToken–>ETH–>BToken,多种智能通证之间通过共同的锚定物串接起来,就形成了一个价值网络(Bancor Network)。; P  Q: B: C0 u* L
* h" [/ ]) T5 @1 x8 d) D5 E, ~
【核心智能合约简单描述】1 q0 |1 X- q* \. A* A1 O7 q
1,contract BancorConverter9 ?' v  E+ N5 z' E
功能说明:代币转换器,允许一个智能代币和其他代币之间的转换,ERC20连接器的余额可以是虚拟的,从而不需要依赖于真实的余额,这有助于避免在一个协约中有大量金额的风险。转换器可以升级。% _. O& R1 s( g" L2 f, `
2,ITokenConverter
1 \5 \- ?1 @( v* N" q( J% Y& _功能说明:BancorConverter的父类接口之一,EIP228 Token Converter接口,用于智能代币的买卖和数量计算接口。1 Q8 {9 z8 \- d
3,SmartTokenController
; l* o/ S( k9 S, H功能说明:BancorConverter的父类接口之一,智能代币管理器。智能代币管理器是一个可以升级的模块,从而允许更多功能和问题修复。当它接受了代币的所有权,它会成为代币的唯一管理器,执行各个功能。
( C# g, f; n' E; v# B1 l; H  }4,Managed
$ m6 f* y+ Y; X) q功能说明: BancorConverter的父类之一,提供协议管理的支持。
4 v$ L' }* g/ P; w5,IBancorConverterExtensions
- j  l+ Z6 F" \+ m6 ^  L" m' \; S功能说明:BancorConverter的公开变量类,bancor converter extensions 协议。能返回formula,gasPriceLimit,quickConverter等3类接口合约。
0 D, k& X+ C% }4 @- @: A#4,核心函数分析+ h' e7 M+ o& Q1 @7 {+ \# _
##4.1 convert(…)函数# h! [: `/ w2 ]/ \7 X) R6 M8 N
convert(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256)功能: 将一定数量的_fromToken 转换为 _toToken;源码:
8 t4 n) J: C9 c' @

2 S! I  i% Z% J% G/**
2 ~* U9 a& Q+ ?        @dev 将一定数量的_fromToken 转换为 _toToken( E9 v7 u) v( n% P( l
        @param _fromToken  用来转换ERC20代币/ s  ^* i% ?5 S: }+ S5 c
        @param _toToken    被转换到的ERC20代币
! v; o& L" W8 e6 X1 O7 T        @param _amount     转换的数量,基于fromToken4 N+ W/ }+ _9 b; N* i0 v& W7 n
        @param _minReturn  限制转换的结果需要高于minReturn,否则取消
6 M, E: z. h) x2 l6 B( m7 M; |        @return conversion 返回数量9 p8 c& t6 M5 M7 J, b4 N
    */0 m, q- [. j+ i1 d9 A9 @& E
    function convert(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256) {8 H8 p$ x* x5 P3 f$ m
            convertPath = [_fromToken, token, _toToken];
7 p6 R6 b. t& T, N# I/ t            return quickConvert(convertPath, _amount, _minReturn);
2 v/ Z" K0 a! L7 t. U! R4 b+ I: _    }, o! V, \; V- _
/**0 B9 q% C2 ~/ o
        @dev 通过之前定义的转换路径来转换代币! _9 o7 T2 {# ]  p. O3 G/ D! w
        注意:当从ERC20代币进行转换,需要提前设置补贴
" U6 N- Y  _# A# m) Z1 A        @param _path        转换路径! g9 ^) o' M" }$ B; Y0 B
        @param _amount      转换的数量
! l5 Y: a: E8 H9 h) ^! ^8 G8 I        @param _minReturn   限制转换的结果需要高于minReturn,否则取消
) V, {# u- g9 ?8 O1 w        @return 返回数量
& u7 _3 T( d7 l8 L" S! q/ l    */: W6 c; B. V( Q
    quickConvertfunction quickConvert(IERC20Token[] _path, uint256 _amount, uint256 _minReturn)
6 w) S1 r+ I) q! |8 l. W        public
. c1 P* r7 \. t! B' u6 c+ a        payable0 j- v. s, v: q& G4 R: l3 i
        validConversionPath(_path)1 X1 Z6 d4 H1 {+ T- t$ R
        returns (uint256)
5 O6 R6 {$ V. x    {
, L: x3 d8 O: L0 X" V4 Z! O        return quickConvertPrioritized(_path, _amount, _minReturn, 0x0, 0x0, 0x0, 0x0, 0x0);  l4 k0 ]  p+ r% ^
    }& |( q. T# h5 J* J; Q2 v
/**& X7 ?( q; k& r/ w+ K# y
        @dev 通过之前定义的转换路径来转换代币
! p2 _. h3 a' r        注意:当从ERC20代币进行转换,需要提前设置补贴5 i$ Y, b7 r6 L; P7 h% t1 m9 [; s
        @param _path        转换路径
5 U" N# P3 S" o        @param _amount      转换的数量% H  D# y) z6 F; b+ P, k
        @param _minReturn   限制转换的结果需要高于minReturn,否则取消- \* {; @: e" f0 B  B5 M
        @param _block       如果当前的区块超过了参数,则取消
5 n& ^" j. F" z1 K+ ?8 ~5 E- {        @param _nonce       发送者地址的nonce3 X0 l, f& Q& M6 [
        @param _v           通过交易签名提取
( Z5 j+ v8 G- K+ @, u& L  G        @param _r           通过交易签名提取+ ]) l( d" j) W3 f, U
        @param _s           通过交易签名提取4 n( [) Q2 U  i, D8 k9 ?$ H, P
        @return 返回数量! Y- S& k0 s* {5 N& l
    */0 f  }5 E' B3 Z& m9 s- f
    function quickConvertPrioritized(IERC20Token[] _path, uint256 _amount, uint256 _minReturn, uint256 _block, uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s)! K1 s) u3 _+ a, A5 o* O: D
        public' S- b, b1 y# N. F
        payable3 `+ J& g# o' w% S
        validConversionPath(_path)
* c& r' E2 V' v- B( ?" m4 m: E4 U        returns (uint256)! s: y  Q' r; Y& \3 f+ \4 W- D
    {: j6 e5 [6 e4 e: F8 e( Q
        IERC20Token fromToken = _path[0];5 a! U8 V0 o. c- Q& G# u
        IBancorQuickConverter quickConverter = extensions.quickConverter();
6 ]( V" }7 m" f/ G+ q& L        // 我们需要从调用者向快速转换着把源代币转化
3 b( _, Y* k, A5 x+ |        // 因此他能基于调用者进行转换1 D) b7 ^- m' h& H1 u7 h. o
        if (msg.value == 0) {/ w( u/ e8 m4 I9 b
            // 如果不是ETH,把源代币发给快速调用者' h. o, e- A/ i$ b) V
            // 如果是智能代币,不需要补贴 —— 销毁代币,然后发给快速转换者
6 T7 _+ A6 [# k# M, D' L            if (fromToken == token) {4 E% M3 b/ t( h
                token.destroy(msg.sender, _amount); // 销毁调用者的_amount代币
  ?0 I, |/ }+ w* z                token.issue(quickConverter, _amount); // 把_amount的新代币发给快速转换者
0 ~7 F  T3 {& m. x  D            } else {( h7 }3 H0 }# x# ?3 r3 a, q- F
                // 否则,我们假设有了补贴,发给快速转换者* u, e' h- }8 H7 g7 [
                assert(fromToken.transferFrom(msg.sender, quickConverter, _amount));6 A' @& x$ p" O8 w6 ?8 q. \
            }4 \2 V: G' ]* y2 ]8 p0 `( J
        }. N% G9 O% p8 V# S9 L" \3 _
        // 执行转换,把ETH转回
! Z% v: ?* _: ?) p, o        return quickConverter.convertForPrioritized.value(msg.value)(_path, _amount, _minReturn, msg.sender, _block, _nonce, _v, _r, _s);
/ o$ b' [! h# I+ N    }
, E$ r3 t) r  W# E$ s: x1 E' G6 h$ e" [
##4.2 change(…)函数
" z1 N% E$ `2 O- z** function change**(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256)功能: 将一定数量的_fromToken 转换为 _toToken。弃用了,向后兼容。设计思路和源码结构挺好的代码:
: W4 U! p4 T& v5 s7 k2 E/ Q4 L
( a3 w3 S. n' a& V: j! `9 l" Z
既然是过期代码,源代码就不放了。
; y) d3 ^2 Y9 Y+ k/ ?##4.3 getReturn(…)函数
! D1 }& e( Q/ l( F! N/ F% G/ S2 [+ `* c: t# I
function getReturn(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount) public view returns (uint256)
$ C1 M. l( `4 {$ {7 q# b

- O9 \& k9 V, v+ f4 E$ _0 ^功能9 D. u: S. x( o9 f
返回从一个代币转换为另一个代币的预期数
源码:
1 z, z: Q1 b1 e) U

( G+ }: ]6 r: N" j7 a; o/**
2 }5 H, f) {1 j, g' M' w        @dev 返回从一个代币转换为另一个代币的预期数量
# A8 W9 c0 q3 Q        @param _fromToken  ERC20 被转换的代币% B& @2 }1 k- B2 |
        @param _toToken    ERC20 转换成的代币
9 Q3 q" L; x/ x" r4 M4 [) y" E        @param _amount     转换的数量
- [4 o, x' s/ b/ q: t# F        @return 与其转换的数量, F1 M) s) E: D9 ~' M0 F. E/ ?
    */
2 W2 \" O1 R! E9 }* J, `4 ^! F    function getReturn(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount) public view returns (uint256) {
; G% |- z+ @. o$ x' @        require(_fromToken != _toToken); // 验证输入! u. X" b0 V" `# G( u) t/ Q* ]6 O
        // 基于当前代币转换
% p: Y7 D) A% n" T, B9 f) L        if (_toToken == token)6 F/ `) \" U9 M" @, @
            return getPurchaseReturn(_fromToken, _amount);
  @( ^9 R! D9 d4 u" q        else if (_fromToken == token)
/ k1 s- [+ y+ u* q* h7 ?$ u. B- @            return getSaleReturn(_toToken, _amount);
. q: g# q6 q- p        // 在两个连接器之间转换1 z. B! ^0 G3 B$ C/ {6 h8 P
        uint256 purchaseReturnAmount = getPurchaseReturn(_fromToken, _amount);  D2 i, y/ Q; n+ Q6 A
        return getSaleReturn(_toToken, purchaseReturnAmount, safeAdd(token.totalSupply(), purchaseReturnAmount));* T" {) W# E: R3 T" M. N0 S
    }
& S. l5 w& z+ o2 Z% R( L/**
  O. W8 Q& r% w) M2 f' @1 L& ^$ }        @dev 返回通过一个连接器代币购买代币的预期结果
! z! m: z7 O5 y: p3 F: u        @param _connectorToken  连接器代币协约地址
$ X. g! f& e! h$ \8 n        @param _depositAmount   买入的数量0 `5 O* }' [3 o; Y( u
        @return 预期的数量0 m& _8 R+ Z4 g5 D5 Q/ t; y9 G2 I2 r, B& h
    */3 }0 j$ Z+ }  }" F& J
    function getPurchaseReturn(IERC20Token _connectorToken, uint256 _depositAmount)
$ G) N0 N: v0 p) Z5 {+ u, h0 R; D' F        public
* e5 E( e6 @8 F# ~0 g( E6 k        view
7 z1 j8 o* a0 \3 _: C        active4 ^; T; ?# ^' x8 n! c# D8 {
        validConnector(_connectorToken)" {& Y% g5 j$ W# K9 x3 g& z( G
        returns (uint256)
& X/ |% ]; A$ S2 ^7 L    {1 ^; K- c) C0 x& y
        Connector storage connector = connectors[_connectorToken];4 D# ^& X8 ?* z: W8 c9 p7 ^
        require(connector.isPurchaseEnabled); // validate input* A5 y4 ~. h, m' d* E* v7 s
        uint256 tokenSupply = token.totalSupply();
; c. _0 h! u6 k4 d& B" ^: {        uint256 connectorBalance = getConnectorBalance(_connectorToken);
& X* L' r8 {2 X+ |4 k        uint256 amount = extensions.formula().calculatePurchaseReturn(tokenSupply, connectorBalance, connector.weight, _depositAmount);
: ~) T7 ?) f+ I6 d7 m1 a! f9 z2 H        // 扣除费用
7 F, g2 x1 V" q2 Y0 I        uint256 feeAmount = getConversionFeeAmount(amount);
1 f6 ]- @$ A, [% r% o$ T# K        return safeSub(amount, feeAmount);2 _) V  I/ Z- |, u/ Y$ s
    }
/ V' h+ T/ U1 z; j2 ?/**: U3 |  d5 P* O) }7 O; c
        @dev 返回通过一个连接器代币卖出代币的预期结果' C( ^% H* N* {9 J( K- \
        @param _connectorToken  连接器代币协约地址
! X% v0 U! W% m0 o+ `2 ]! @        @param _sellAmount      卖出的数量
- y" \+ o1 {  [- v        @return 预期得到的数量
' z% ]6 W  P4 W: B2 h    */
7 [) U& C. q9 Q1 H5 V( l5 f    function getSaleReturn(IERC20Token _connectorToken, uint256 _sellAmount) public view returns (uint256) {$ M* B% b) _+ G; N- o
        return getSaleReturn(_connectorToken, _sellAmount, token.totalSupply());
$ x5 u# b- q( d- d, @    }
1 [" _& b# o+ a, p! d: d# Y/ o/**
& i+ }$ j$ `9 {6 o  H* ^        @dev 工具,基于一个总供应量,返回基于一个连接器代币来卖掉代币的期待返回
( u/ |1 E2 F# e* Y0 K. D        @param _connectorToken  连接器代币协议地址9 s3 H5 J! M8 {% ?/ `) @7 U
        @param _sellAmount      销售的数量4 ~, C2 ?' H3 `9 ~) y# h
        @param _totalSupply     设置总供应量
$ X6 V7 V) ]0 P% W        @return 返回的数量
3 S9 q/ R. L5 S/ b/ w+ s    */
5 V' \( S; {( }. ~# C5 p    function getSaleReturn(IERC20Token _connectorToken, uint256 _sellAmount, uint256 _totalSupply)
2 T! ?. S1 E/ m5 c$ K/ \8 P        private" `& X8 ^7 T- s. ~, Y; _! Z( y
        view( E) w% |- Z* T$ s/ X+ D  d  G: w
        active
, v8 H$ l' [( H. l5 Z        validConnector(_connectorToken)
) k' V$ Y* g9 W# H% v        greaterThanZero(_totalSupply)
! x; F% w6 |( ~7 z9 x        returns (uint256)+ H" Q  [1 Z$ i* T2 Q" ?
    {
$ M5 C5 R7 n( c  W        Connector storage connector = connectors[_connectorToken];9 }9 G6 {' {! q# M
        uint256 connectorBalance = getConnectorBalance(_connectorToken);! h9 E1 B# z- V9 Y3 a
        uint256 amount = extensions.formula().calculateSaleReturn(_totalSupply, connectorBalance, connector.weight, _sellAmount);' z8 @4 L+ {8 i  t
        // 从返回的数量中剪掉费用
& c2 G/ h& ]1 T0 \4 b/ x8 w        uint256 feeAmount = getConversionFeeAmount(amount);
6 g; Z0 u" A7 [% Q! f, p+ z        return safeSub(amount, feeAmount);" y# t3 o/ _: y( v4 o
    }
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14