武侠小说中的群豪们似乎总不缺钱,经常有台词就是小二来两斤熟牛肉、两斤烧酒,不用找了,难道他们都这么有钱的么?熟悉金庸小说《鹿鼎记》的朋友应该对狗官吴之荣还有些印象,庄允城在书中给他夹了若干金叶子。金叶子直接花出去不太方便,需要兑换成银子再进行消费,那么,这个用金叶子换碎银的过程是怎么实现的呢,兑换的比例又有谁来决定呢,兑换的过程中收不收手续费呢,今天我们就以eos智能合约的方式来简单的介绍下金叶子换碎银的一个过程。
eso的合约中包含有一个名为exchange的智能合约,关于该合约的功能及实现,在/contracts/exchange的exchange.hpp注释中都有简单的说明:
本合约可以让用户在任意对标准货币形式间进行交换。交易创建完成之后,创建人有一个初始份额,且交换双方是进行等值交换的。为了防止因四舍五入造成的误差,在创建的时候初始化金额中应该包含有相当数量的基础货币和报价货币,且交易所应持有最大初始存款数量的100倍。用户若要进行交易,必须先抵押一部分自己的资产在这个合约中,一旦这个交易执行,一种新的货币就创建了且对应的货币交易商也会产生。被创建的货币符号应该是唯一的,我们使用货币管理表来管理这些货币符号。
在eos提供的exchange智能合约中提供了一个测试的例子test_exchange.cpp,下面我们就根据这个例子来实现金叶子兑换碎银。Exchange智能合约中包含有exchange_accounts、exchange_state、market_state、exchange四个类,分别实现了关于交易账户、交易状态、市场状态以及交易的过程。其中exchange依赖于market_state,而market_state又依赖于前面两个类。我们从main入手,可以看到首先定义了一个Exchange_state类型的state变量,那么这个结构体是做什么用的包含了哪些内容呢?
state中包含了发行量,本次交易碎银发行量为10000。Symbol即货币类型,本次交易的类型中包含了GL(金叶子)和BS(碎银)两种类型。以及两个连接器类型的基础账户和报价账户,一个交易函数transfer,一个存放了货币类型及余额的key值的map表,同时存放了利润相关的容器。
这两个连接器类型的结构体变量包含了账户的余额,账户中货币类型的权重(初始化为50%),发行商提供的发型金额、已贷金额、剩余可贷金额、利息池等。在convert结构体重实现了以下三个函数:
初始化state的时候,将发行量设置为10000,GL和BS的初始化金额分别为100,同时设置两种货币的权重,初始化完成之后,打印出这个state如下图
官方给test_exchange中做了诸多对convert函数的操作,具体如下:
咱们化繁为简,只对state进行一次convert操作(其实,源码中是有只进行一次的操作,只不过注释掉了,我们就使用注释掉的代码),执行如下操作:
这个convert进行了什么操作呢?就是吴之荣这个狗官去拿着金叶子去兑换碎银子去了,在convert这个函数中首先对传入的各个参数进行和合法性的判断,如传入金额,账户类型的判断等,在这些判断完成之后开始进行convert_to_exchange的操作.
这里,系统设置了一个默认的货币类型"EXC",当你要操作的货币类型不是这个默认货币类型EXC的时候,要么是base账户的货币类型,要么是quote的货币类型,也就是非这两种货币类型的,我们不再继续进行处理.当传入货币类型为其中之一的时候,执行convert_to_exchange的操作.现在我们传入的是金叶子的货币类型:
在convert_to_exchange中进行了一系列的数学计算,具体计算过程及结果不再赘述,各位方便的话可以边调试边看这些数学计算分别实现了什么(同样的适用于convert_from_exhcange也是如此):
调试过程中,各个变量的变化如下:
所有的这些都执行完成之后,我们new_state的结果就会打印出来:
通过对比,我们知道吴之荣这个狗官拿着10个金叶子换了21.3696个碎银,从图中也可以看到base账户上多了10个金叶子,而吴之荣的账户上少了十个金叶子而多了相应的碎银.至此,一个通过eos智能合约的方式完成了吴之荣拿金叶子换碎银的整个过程实现了.
另外,exchange.cpp中实现了一部分通过一种货币兑换另一种货币的方式,包括借贷/还贷等内容,但在这个test_exchange中并未被调用,因此不做展开分析,有需要的同学,可以加我微信一起来讨论.