Hi 游客

更多精彩,请登录!

比特池塘 区块链技术 正文
在以太坊上发行的大量ERC20-Token是没有价值锚定的,其价值完全依赖于项目方的技术与运营能力,若项目失败了,则通证(TOKEN)价值就很可能归零。
0 j: O9 O' t, }) W2 y! y  n6 ?+ M& C8 K& U8 {" E& f) j2 `( z6 c
若利用智能合约的强大而灵活的“资金流转控制”能力,在通证合约中控制着一定量的储备金,让通证与储备金之间拥有一定的兑换能力,那么Token的价值就可以储备金为锚定物,而不完全依赖于项目方。通证持有者也就不用承担项目失败或者项目方可能诈骗跑路的风险。
( n8 G& Z' K: [+ w" E8 L4 ~# G$ q7 P" `6 a6 H4 m( R
若通证与锚定物之间的兑换算法采用了Bancor算法,又符合ERC20标准,则被称为智能通证(Smart-Token) 。为了简单起见,以下的论述以ETH作为锚定物举例说明。购买与售卖Token的过程如下:# k. a" K5 l# G: w$ N3 w9 F% x
“购买者”发送一定量的ETH到Token合约地址,触发了合约代码自动执行"购买功能代码",获得对应数量的Token;“售卖者”发送一定量的Token到Token合约地址,触发了合约代码自动执行“售卖功能代码”,获得对应数量的ETH。: J# Y/ B4 Y$ _
0 o$ D0 n# y0 }
若AToken与BToken都是以ETH为锚定物的智能通证,那么Token持有者无需通过交易所,仅仅凭借智能合约提供的买卖与兑换功能,就能实现AToken与BToken的自由兑换,比如AToken–>ETH–>BToken,多种智能通证之间通过共同的锚定物串接起来,就形成了一个价值网络(Bancor Network)。
9 j" a5 F) F0 L& m* v. M0 n
& i6 r+ x% ]  M# p& T5 T! O【核心智能合约简单描述】% \; T; K) d# J6 G) b9 t. P
1,contract BancorConverter
+ C  B1 o4 U, z% s功能说明:代币转换器,允许一个智能代币和其他代币之间的转换,ERC20连接器的余额可以是虚拟的,从而不需要依赖于真实的余额,这有助于避免在一个协约中有大量金额的风险。转换器可以升级。, `, e/ e$ j( Q; c  l" \5 w
2,ITokenConverter
0 V* M$ r5 H6 k& p功能说明:BancorConverter的父类接口之一,EIP228 Token Converter接口,用于智能代币的买卖和数量计算接口。
& |. |" g# |" t' s# Y1 z3 q3,SmartTokenController  R& d8 E5 k% V& J) }( [
功能说明:BancorConverter的父类接口之一,智能代币管理器。智能代币管理器是一个可以升级的模块,从而允许更多功能和问题修复。当它接受了代币的所有权,它会成为代币的唯一管理器,执行各个功能。# g' ?+ f0 l) l% O' _7 U
4,Managed
; M5 d& @5 o. @功能说明: BancorConverter的父类之一,提供协议管理的支持。
1 z  B7 J5 _, w% l% V' z% h5,IBancorConverterExtensions) G; C( N) q: l3 V! E
功能说明:BancorConverter的公开变量类,bancor converter extensions 协议。能返回formula,gasPriceLimit,quickConverter等3类接口合约。  ~% T  N9 W8 X; _' E! {/ p2 r$ D
#4,核心函数分析
; _& M4 X+ N$ q( p. I0 M& Z& @% T##4.1 convert(…)函数' N3 [$ d% o# ~' g
convert(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256)功能: 将一定数量的_fromToken 转换为 _toToken;源码:, R# e; `: _. b' q. Y  x6 A4 Z

1 ~2 ^; G$ u0 v- [% i" q  D7 y/**
# J, [1 ]  {/ A# z2 \# ?        @dev 将一定数量的_fromToken 转换为 _toToken
( `* S& Y& t8 U! w- a5 T  Q        @param _fromToken  用来转换ERC20代币
% k* d- S- p5 O+ q( z4 z        @param _toToken    被转换到的ERC20代币2 W: E& R5 l1 d/ U) s
        @param _amount     转换的数量,基于fromToken5 \9 I0 r- W$ U; c6 c# S8 W4 A
        @param _minReturn  限制转换的结果需要高于minReturn,否则取消8 N) O0 d: }( S' ^, p
        @return conversion 返回数量  y( q4 {! {6 E4 `+ D1 q
    */- a, e8 }% F+ @
    function convert(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256) {
6 _  n! d7 e# ^2 [: s9 e( w; O            convertPath = [_fromToken, token, _toToken];
% n* Z4 {0 d! O5 o* o            return quickConvert(convertPath, _amount, _minReturn);
% i- {, G# n. t. L    }
1 M+ A4 N# m! I/**/ t* V( M% h- m8 ~8 J7 \# e  S
        @dev 通过之前定义的转换路径来转换代币# p7 j; M  P" o  q, B0 C; k, o
        注意:当从ERC20代币进行转换,需要提前设置补贴% N& \: u* A- m
        @param _path        转换路径" A2 h% K7 g/ i5 w6 n2 f- ?
        @param _amount      转换的数量' q% R# K4 w* E. a1 `$ d
        @param _minReturn   限制转换的结果需要高于minReturn,否则取消
: y8 K: v8 [0 R6 P        @return 返回数量
' n7 c! @$ x$ T$ N- F& |1 L    */
2 Q# i6 _8 j  G( e# ~    quickConvertfunction quickConvert(IERC20Token[] _path, uint256 _amount, uint256 _minReturn)
% ]8 q' L/ |2 {% `1 P, j        public: D% t. x; A. x; A
        payable# `: `: R  v  ]
        validConversionPath(_path)
, H, ^: i2 }  X, s        returns (uint256)$ `4 s' N6 z9 K  S' z
    {
4 [7 @5 K- l0 V: ]% l        return quickConvertPrioritized(_path, _amount, _minReturn, 0x0, 0x0, 0x0, 0x0, 0x0);
- k0 i- b7 @  I4 U" T& P* }4 R+ R$ P    }
$ x2 u* S' s3 v' I- d/ }/**' q5 n% C. v* B
        @dev 通过之前定义的转换路径来转换代币  G% Z- M3 P1 u3 f5 z$ s
        注意:当从ERC20代币进行转换,需要提前设置补贴
# k% W2 x( D$ \) N7 I$ k, W        @param _path        转换路径
  a3 {5 E# D8 z: p% ]1 j        @param _amount      转换的数量) g% T4 J% @0 H4 E! T
        @param _minReturn   限制转换的结果需要高于minReturn,否则取消
8 X6 q: z  ~* P4 h6 u* ?0 c        @param _block       如果当前的区块超过了参数,则取消
+ O' `, W2 W# O! R        @param _nonce       发送者地址的nonce
5 l8 A, Y3 ]5 K- h( M) p5 j# J        @param _v           通过交易签名提取
2 \  d8 h6 X9 u. _        @param _r           通过交易签名提取
$ ~9 F3 s; [- r% S; {        @param _s           通过交易签名提取4 t: K" Z, M  X% B
        @return 返回数量1 D& d/ W+ p3 |/ }& m8 ], D
    */! ^5 u5 A2 W! E* k/ c; K$ }/ F
    function quickConvertPrioritized(IERC20Token[] _path, uint256 _amount, uint256 _minReturn, uint256 _block, uint256 _nonce, uint8 _v, bytes32 _r, bytes32 _s)
' |$ e% l6 ?  L, {        public' T" [% c! X! Z; D8 M* F- \
        payable
0 d2 h/ ^: b5 N        validConversionPath(_path)2 K2 K' O( A- D  R: O
        returns (uint256)
6 d& z4 ?5 B8 j; ^) F# V& ~( ^/ R    {! m) Z6 N& p$ W5 O5 |1 k
        IERC20Token fromToken = _path[0];: P" y& Y. G; N# s
        IBancorQuickConverter quickConverter = extensions.quickConverter();8 J7 Z, T  E3 P6 a5 c
        // 我们需要从调用者向快速转换着把源代币转化
1 \9 u  [7 ~- U: t/ j6 j5 H        // 因此他能基于调用者进行转换% c2 E2 u4 p  \% n" F0 D7 ^
        if (msg.value == 0) {
9 ?; ]: c' \: |/ C# X+ t            // 如果不是ETH,把源代币发给快速调用者
/ }2 y8 ^# M: \            // 如果是智能代币,不需要补贴 —— 销毁代币,然后发给快速转换者
" I- X2 A; J( h5 t6 z. K0 T            if (fromToken == token) {
' U# p" n0 n+ f# D. ~                token.destroy(msg.sender, _amount); // 销毁调用者的_amount代币, c8 j0 m/ C7 z" J( D: u2 X5 a
                token.issue(quickConverter, _amount); // 把_amount的新代币发给快速转换者$ L4 b# ^* F9 h1 v* {" D! x
            } else {
% Q( {% R  x! X- a0 A                // 否则,我们假设有了补贴,发给快速转换者
8 r) X* l" t7 j  o+ n9 a                assert(fromToken.transferFrom(msg.sender, quickConverter, _amount));
% s3 {- W( D9 A* z- Q. }. V; I            }) \' _- {, t& U2 i( I* x0 w3 D
        }' j. A/ E+ o0 t( Z* H" c
        // 执行转换,把ETH转回
  _$ E- X4 w6 f( }6 j: }4 |        return quickConverter.convertForPrioritized.value(msg.value)(_path, _amount, _minReturn, msg.sender, _block, _nonce, _v, _r, _s);2 L% w" }5 B7 e6 H2 Y  K6 ^
    }# I6 ^# T7 Y8 ?; G! e

8 h6 j$ e. s1 Y& f6 z1 L, G9 A: D3 n##4.2 change(…)函数7 V2 I( M3 w# T" W! D
** function change**(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256)功能: 将一定数量的_fromToken 转换为 _toToken。弃用了,向后兼容。设计思路和源码结构挺好的代码:/ g, l, b; c6 L6 c1 A! @! U

$ v! Z& a% F  y5 n既然是过期代码,源代码就不放了。
9 a/ {5 `  L2 ]. ~) v8 ?4 s##4.3 getReturn(…)函数  R3 O: H3 B; v7 D2 h  p

6 \: B: F" f9 a) W4 I+ x. K# r% hfunction getReturn(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount) public view returns (uint256)4 K: I! C+ p% l$ F' C% W- n
3 O7 ^! L! R$ F, X8 W) J
功能
' c) E2 W  P7 e返回从一个代币转换为另一个代币的预期数
源码:. H, T0 E" Y+ g. H6 ]9 y& u

) g) t( z1 g; A0 O9 i5 j/**
. s1 {9 b6 O* O% \0 j& O        @dev 返回从一个代币转换为另一个代币的预期数量) S  ]* m! ?; |: ^: g! g
        @param _fromToken  ERC20 被转换的代币
5 i2 n) _( ~& w! V6 `% @+ |0 B        @param _toToken    ERC20 转换成的代币
2 {+ [' e9 ^5 K7 h; c# P        @param _amount     转换的数量( h$ f  v* @, i- V
        @return 与其转换的数量) L- I/ C' P3 U6 a  [
    */
0 ^) r  l" F7 s4 E  E    function getReturn(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount) public view returns (uint256) {
( @8 l% J* @9 E$ v  O5 x        require(_fromToken != _toToken); // 验证输入+ \* o; [7 Q/ A- q/ S
        // 基于当前代币转换
! V  x. v8 W& N) [& {4 d        if (_toToken == token)" f1 B( c# k9 V
            return getPurchaseReturn(_fromToken, _amount);8 d" l( }9 B5 V' o/ z) E
        else if (_fromToken == token)
, {. l! @% x& N+ B* f+ z" d            return getSaleReturn(_toToken, _amount);
& \- L+ P2 ~: n# \5 y        // 在两个连接器之间转换
0 U: ~* ]+ S4 n" o. A        uint256 purchaseReturnAmount = getPurchaseReturn(_fromToken, _amount);, I" t+ H' |3 X1 h7 {% G
        return getSaleReturn(_toToken, purchaseReturnAmount, safeAdd(token.totalSupply(), purchaseReturnAmount));4 Y: n4 x; R; D7 s
    }
- u& a2 D9 K3 z/**- t5 y3 J2 o9 f. A5 \7 U
        @dev 返回通过一个连接器代币购买代币的预期结果, F  R  L, D, O" q
        @param _connectorToken  连接器代币协约地址0 i/ v4 w0 U. [$ J% |4 W8 `/ I( R# }
        @param _depositAmount   买入的数量
' n# i9 m" ^  W& c1 n        @return 预期的数量
+ ~0 |" V% W/ c6 @* Z. `    */
5 k5 I  f9 z/ q9 R) J: Y- M    function getPurchaseReturn(IERC20Token _connectorToken, uint256 _depositAmount)
/ S% b; l# \, Y. C8 j* u8 w" |        public
' c. t& I7 P( N& q* m6 w        view- Z9 f$ v& P- s# a. g
        active
/ k2 i; \3 G$ }5 x: z& ]        validConnector(_connectorToken)' K4 q8 G8 ~; G# t0 b( I
        returns (uint256). ?' V$ L5 T; ]+ y/ S: n
    {5 B9 t2 M0 G0 U  i
        Connector storage connector = connectors[_connectorToken];
  \# K6 v( t' s  l0 v1 u        require(connector.isPurchaseEnabled); // validate input2 A" V! t* ^2 c5 i$ A; H. ?% M
        uint256 tokenSupply = token.totalSupply();
. L' Y* p- V) W. `        uint256 connectorBalance = getConnectorBalance(_connectorToken);. ?% ~% F3 b# ~* y9 e0 W  u5 }. n
        uint256 amount = extensions.formula().calculatePurchaseReturn(tokenSupply, connectorBalance, connector.weight, _depositAmount);
0 r, o) d) `5 P) u$ ~$ l        // 扣除费用2 z3 w& z- m- u6 ?  V' u1 E
        uint256 feeAmount = getConversionFeeAmount(amount);
5 a8 X# K8 t7 D2 Z* y        return safeSub(amount, feeAmount);
0 p- t1 `# Q& q8 p0 r$ N) o    }
2 w6 J5 e. k) b8 Y/**
4 Z; ]- z9 T( n6 Z9 ]" p        @dev 返回通过一个连接器代币卖出代币的预期结果! E& T. M- L- [# A- I7 G
        @param _connectorToken  连接器代币协约地址0 A' f! w* L! @+ H) K- e( A
        @param _sellAmount      卖出的数量
% L% a" r% L& O! n        @return 预期得到的数量! i4 P. y6 V0 K+ E2 U
    */. O# A7 t+ U4 b: \4 B, ^5 _& t$ h9 _
    function getSaleReturn(IERC20Token _connectorToken, uint256 _sellAmount) public view returns (uint256) {5 F- M& ]0 d6 ?: K  I9 u
        return getSaleReturn(_connectorToken, _sellAmount, token.totalSupply());: n, t  K, p- v! M3 y7 B
    }
+ P7 P" _% W/ k2 S/**
6 C4 `( M' y$ b' d        @dev 工具,基于一个总供应量,返回基于一个连接器代币来卖掉代币的期待返回
# y0 Z5 w3 ]; H& |* C) m6 z        @param _connectorToken  连接器代币协议地址
9 J6 M7 k" D4 B& }( Z5 i0 N- u        @param _sellAmount      销售的数量
) |6 z- x/ ?% k2 V: }& T% Y/ t        @param _totalSupply     设置总供应量
0 S5 W9 g4 x1 J6 o5 n        @return 返回的数量) {8 S1 W9 M7 K! X/ j
    */2 `- p! u/ [5 ~6 i0 n1 u( s
    function getSaleReturn(IERC20Token _connectorToken, uint256 _sellAmount, uint256 _totalSupply)
, b# I1 ]& R% g! U5 u* N        private
) N9 D4 ?/ x! e        view
# Y' U) w# u9 k+ O6 o+ o        active! T2 U* W# b+ F+ M% F+ u" i
        validConnector(_connectorToken)1 m0 n; _' }9 I. M- P/ E* b' u
        greaterThanZero(_totalSupply)
- q) k' _1 K/ N) f0 k) G/ N        returns (uint256)
) l% k; q* c7 y& n" [    {
% u4 g# M- z4 B# v        Connector storage connector = connectors[_connectorToken];
/ N: _. v# |. m0 f        uint256 connectorBalance = getConnectorBalance(_connectorToken);, O3 r( N2 c+ ?& j
        uint256 amount = extensions.formula().calculateSaleReturn(_totalSupply, connectorBalance, connector.weight, _sellAmount);$ D  `4 V, ?8 F+ m1 }3 K
        // 从返回的数量中剪掉费用
$ Z  j2 ?4 S- z, {. S        uint256 feeAmount = getConversionFeeAmount(amount);! ?2 r; S$ p+ d9 w
        return safeSub(amount, feeAmount);
$ V% `' O. `8 V% \: D    }
BitMere.com 比特池塘系信息发布平台,比特池塘仅提供信息存储空间服务。
声明:该文观点仅代表作者本人,本文不代表比特池塘立场,且不构成建议,请谨慎对待。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

成为第一个吐槽的人

V刘晨曦 初中生
  • 粉丝

    0

  • 关注

    3

  • 主题

    14