第二十四课 基于以太坊的去中心化交易所BANCOR算法实现-框架
1,摘要
EOS带火了Bancor算法。其实BANCOR算法是解决长尾通证流通的最好方式之一。鉴于目前通证大部分是基于ERC20的,辉哥正在尝试实现一个使用SOLIDITY语言实现的去中心化交易所,把项目信息整理分享出来。
【本文目标】
(1)学习BANCOR通证转换合约的类图
(2)学习BANCOR通证核心函数
(3)获取源码和注释
2,BANCOR算法功能描述
在以太坊上发行的大量ERC20-Token是没有价值锚定的,其价值完全依赖于项目方的技术与运营能力,若项目失败了,则通证(TOKEN)价值就很可能归零。
若利用智能合约的强大而灵活的“资金流转控制”能力,在通证合约中控制着一定量的储备金,让通证与储备金之间拥有一定的兑换能力,那么Token的价值就可以储备金为锚定物,而不完全依赖于项目方。通证持有者也就不用承担项目失败或者项目方可能诈骗跑路的风险。
若通证与锚定物之间的兑换算法采用了Bancor算法,又符合ERC20标准,则被称为智能通证(Smart-Token) 。为了简单起见,以下的论述以ETH作为锚定物举例说明。购买与售卖Token的过程如下:
“购买者”发送一定量的ETH到Token合约地址,触发了合约代码自动执行”购买功能代码”,获得对应数量的Token;“售卖者”发送一定量的Token到Token合约地址,触发了合约代码自动执行“售卖功能代码”,获得对应数量的ETH。若AToken与BToken都是以ETH为锚定物的智能通证,那么Token持有者无需通过交易所,仅仅凭借智能合约提供的买卖与兑换功能,就能实现AToken与BToken的自由兑换,比如AToken–>ETH–>BToken,多种智能通证之间通过共同的锚定物串接起来,就形成了一个价值网络(Bancor Network)。
鉴于篇幅限制,本文不准备上传完整源码文件,有需要的同学可加入知识星球下载。
https://t.zsxq.com/ZFaaYVF
【备注】 加入辉哥知识星球可申请加入区块链交流专项微信群,及时交流各种区块链技术问题。3,类图分析
BANCOR转换算法框架类图.png
【核心智能合约简单描述】
1,contract BancorConverter
功能说明:代币转换器,允许一个智能代币和其他代币之间的转换,ERC20连接器的余额可以是虚拟的,从而不需要依赖于真实的余额,这有助于避免在一个协约中有大量金额的风险。转换器可以升级。
2,ITokenConverter
功能说明:BancorConverter的父类接口之一,EIP228 Token Converter接口,用于智能代币的买卖和数量计算接口。
3,SmartTokenController
功能说明:BancorConverter的父类接口之一,智能代币管理器。智能代币管理器是一个可以升级的模块,从而允许更多功能和问题修复。当它接受了代币的所有权,它会成为代币的唯一管理器,执行各个功能。
4,Managed
功能说明: BancorConverter的父类之一,提供协议管理的支持。
5,IBancorConverterExtensions
功能说明:BancorConverter的公开变量类,bancor converter extensions 协议。能返回formula,gasPriceLimit,quickConverter等3类接口合约。4,核心函数分析
4.1 convert(…)函数
convert(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256)功能: 将一定数量的_fromToken 转换为 _toToken;流程图:4.2 change(…)函数
** function change**(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount, uint256 _minReturn) public returns (uint256)功能: 将一定数量的_fromToken 转换为 _toToken。弃用了,向后兼容。设计思路和源码结构挺好的,我画了流程图。流程图:4.3 getReturn(…)函数
function getReturn(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount) public view returns (uint256)功能:返回从一个代币转换为另一个代币的预期数量流程图:getPurchaseReturn
getSaleReturn
源码:/** @dev 返回从一个代币转换为另一个代币的预期数量 @param _fromToken ERC20 被转换的代币 @param _toToken ERC20 转换成的代币 @param _amount 转换的数量 @return 与其转换的数量 */ function getReturn(IERC20Token _fromToken, IERC20Token _toToken, uint256 _amount) public view returns (uint256) { require(_fromToken != _toToken); // 验证输入 // 基于当前代币转换 if (_toToken == token) return getPurchaseReturn(_fromToken, _amount); else if (_fromToken == token) return getSaleReturn(_toToken, _amount); // 在两个连接器之间转换 uint256 purchaseReturnAmount = getPurchaseReturn(_fromToken, _amount); return getSaleReturn(_toToken, purchaseReturnAmount, safeAdd(token.totalSupply(), purchaseReturnAmount)); } /** @dev 返回通过一个连接器代币购买代币的预期结果 @param _connectorToken 连接器代币协约地址 @param _depositAmount 买入的数量 @return 预期的数量 */ function getPurchaseReturn(IERC20Token _connectorToken, uint256 _depositAmount) public view active validConnector(_connectorToken) returns (uint256) { Connector storage connector = connectors[_connectorToken]; require(connector.isPurchaseEnabled); // validate input uint256 tokenSupply = token.totalSupply(); uint256 connectorBalance = getConnectorBalance(_connectorToken); uint256 amount = extensions.formula().calculatePurchaseReturn(tokenSupply, connectorBalance, connector.weight, _depositAmount); // 扣除费用 uint256 feeAmount = getConversionFeeAmount(amount); return safeSub(amount, feeAmount); } /** @dev 返回通过一个连接器代币卖出代币的预期结果 @param _connectorToken 连接器代币协约地址 @param _sellAmount 卖出的数量 @return 预期得到的数量 */ function getSaleReturn(IERC20Token _connectorToken, uint256 _sellAmount) public view returns (uint256) { return getSaleReturn(_connectorToken, _sellAmount, token.totalSupply()); } /** @dev 工具,基于一个总供应量,返回基于一个连接器代币来卖掉代币的期待返回 @param _connectorToken 连接器代币协议地址 @param _sellAmount 销售的数量 @param _totalSupply 设置总供应量 @return 返回的数量 */ function getSaleReturn(IERC20Token _connectorToken, uint256 _sellAmount, uint256 _totalSupply) private view active validConnector(_connectorToken) greaterThanZero(_totalSupply) returns (uint256) { Connector storage connector = connectors[_connectorToken]; uint256 connectorBalance = getConnectorBalance(_connectorToken); uint256 amount = extensions.formula().calculateSaleReturn(_totalSupply, connectorBalance, connector.weight, _sellAmount); // 从返回的数量中剪掉费用 uint256 feeAmount = getConversionFeeAmount(amount); return safeSub(amount, feeAmount); }5,未完待续
上述代码完成了智能代币和连接代币转化的关系,但是没有涉及核心互换及计算代码,而是通过interface类的方式进行隔离。这个在另外一个课程进行讲解。
辉哥整理了BANCOR的系列课程,列表如下:
(1)【白皮书】Bancor协议:通过智能合约为加密货币提供持续流动性(附PDF下载)
(2)【易错概念】以实例形式深入浅出讲透BANCOR算法
(3)第二十四课 基于以太坊的交易所BANCOR算法实现-转换算法框架
发表回复