Transaction

0ce61a1b8934766ab13349785c0a0c71045ad3a8a570367962fbeb6cce298ac2
( - )
181,513
2020-11-27 06:55:45
2
8,438 B

2 Outputs

Total Output:
  • jmetaB02216a2db4d39e49ffa1b6eb7f573b754852f293259b644fbd8f7b33f6b7b1ebb2@2d22f90167c4644830c409217df8551b61606db38d5e1b9434b548917d598455metaidmetanote-02216a2db4d3Ma{"isPrivate":0,"title":"在BSV链上建立带有互换(swap)功能的token合约","content":"我们可以仿照以太坊上的账号模式,在bsv的链上使用scrypt语言建立一个带有与bsv进行互换(swap)功能的token合约。\n\n**实现方式**\n\n我们在合约里面建立两个账户表:\n\ntoken账户表,用于保存每个用户的token数量。\n流动池lptoken账户表,用于保存用户为流动池(swap pool)增加流动性而获得的lptoken数量。\n账户表的保存方式,参考这篇文章中提出的使用merkle tree保存数据的方法, 只将merkle tree root保存在合约里面,以控制合约的数据大小,具体账户信息则保存在链外。每次合约调用后,数据如果有修改,则更新merkle tree,将新的tree root保存到新的合约tx中。\n\n在建立token账户表是,默认维护一个流动池(pool)的账户,用于保存注入到流动池里面的token数量,而注入到流动池里面的bsv数量则保存在合约的utxo里面。通过流动池的token账户与其他用户的token账户交互,来实现流动池的各种功能。\n\n合约实现的具体代码有两个文件tokenSwap.scrypt和merkleTree2.scrypt,部署合约的测试代码在此。\n\n下面依次介绍下合约的各个功能。\n\n**建立合约**\n\n合约的创建需要提供以下参数:\n\n1. 合约utxo初始bsv的数量。\n2. 首次注入流动性所要求的bsv数量。\n3. 首次注入流动性所要求的token数量。\n4. 流动池swap的费率,具体值为实际费率 \\* 1000的整数。\n5. 流动池token账户的pubkey。\n6. 管理员的pubkey。\n\n通过链下生成初始的账户信息,包括token账户的和流动池lptoken。其中token的账户信息,需要至少包括一个初始用户A的账户以及流动池对应的账户pool,lptoken的账户信息包括一个初始用户A的账户信息。然后合约的opreturn中写入三个数据:\n\n1. token账户的merkle tree root。\n2. lptoken账户的merkle tree root。\n3. lptoken的总量。\n\n这里是测试网上生成的的一个合约tx。这个合约里面建立的token和lptoken的merkle tree分别如图1和图2所示。\n![image](https://pic2.zhimg.com/v2-e952466ce77ec432d4118316722c3081_r.jpg)\n图1 token merkle tree\n![image](https://pic4.zhimg.com/80/v2-e14994538ddd7a135c5735f5a74d1c2b_720w.jpg)\n图2 lptoken merkle tree\n\n**增加新的token账户**\n\n合约管理员在token merkle tree上新添加一个叶节点,更新token merkle tree,将新的tree root写入到新合约中去。这个操作只能管理员实施。\n\n构造有两个input和两个output的tx:\n\n1. input 0:最新的合约utxo,调用合约的addTokenUser函数生成解锁脚本。\n2. input 1:有一定数量bsv的utxo,用来提供tx上链手续费。\n3. output 0:合约代码+新的合约数据。\n4. output 1:bsv的找零输出。\n\n这里是测试网上的一个增加token用户的tx。\n\n在加入新的用户后,新的token merkle tree如下图3所示:\n![image](https://pic3.zhimg.com/80/v2-2491a0cc8044672c4ed65d44b7370696_720w.jpg)\n图3 增加用户B后的token merkle tree\n\n**token转账**\n\n发送者发起转账,合约将发送者的token账户减去转账数量,接受者的账户加上相应的转账数量。最后更新token merkle tree,将新的tree root写入到合约里面。\n\n构造有两个input和两个output的tx:\n\n1. input 0:最新的合约utxo,调用合约的transfer函数生成解锁脚本。\n2. input 1:有一定数量bsv的utxo,用来提供tx上链手续费。\n3. output 0:合约代码+新的合约数据。\n4. output 1:bsv的找零输出。\n\n这里是测试网上的一个转账token的tx。\n\n**为流动池注入流动性**\n\n用户转账token给流动池账户,同时输入bsv到合约中。其中token和bsv要按照当前流动池中的比例存入。然后合约会根据用户提供的流动性给其在lptoken账户中增加一定数量的lptoken,同时lptoken的总量也要相应的增加。最后合约更新token merkle tree,lptoken merkle tree和lptoken总量。\n\n构造有两个input和两个output的tx:\n\n1. input 0:最新的合约utxo,调用合约的addLiquidity函数生成解锁脚本。\n2. input 1:有一定数量bsv的utxo,用来提供tx上链手续费以及注入到流动池中的bsv。\n3. output 0:合约代码+新的合约数据。\n4. output 1:bsv的找零输出。\n\n这里是测试网上的增加流动性的tx。\n\n**用bsv交换token**\n\n用户输入bsv到合约里面,然后合约在收取一定手续费后,从pool的token账户转账给用户的token账户一定数量的token,然后合约更新token merkle tree。\n\n构造有两个input和两个output的tx:\n\ninput 0:最新的合约utxo,调用合约的swapBsvToToken函数生成解锁脚本。\ninput 1:有一定数量bsv的utxo,用来提供tx上链手续费以及用来交换token的bsv。\noutput 0:合约代码+新的合约数据。\noutput 1:bsv的找零输出。\n这里是测试网上的bsv交换token的tx。\n\n用token交换bsv\n\n用户将自己的token转账给流动池的token账户,然后合约收取交换手续费后,从合约的utxo上提取相应数量的bsv,减去上链手续费后转账给用户。然后更新token merkle tree。\n\n构造有一个input和两个output的tx:\n\n1. input 0:最新的合约utxo,调用合约的swapTokenToBsv函数生成解锁脚本。\n2. output 0:合约代码+新的合约数据。\n3. output 1:发送给交换用户的bsv。\n\n这里是测试网上的token交换bsv的tx。\n\n**提取流动性**\n\n用户从自己的lptoken账户中销毁一定数量的lptoken,然后合约会依照比例返回用户相应数量的token和bsv。最后更新token merkle tree和lptoken merkle tree。同时lptoken的总量也要相应的减少。\n\n构造有一个input和两个output的tx:\n\n1. input 0:最新的合约utxo,调用合约的removeLiquidity函数生成解锁脚本。\n2. input 1:有一定数量bsv的utxo,用来提供tx上链手续费。\n3. output 0:合约代码+新的合约数据。\n4. output 1:bsv的找零输出,包括流动性提取返回的bsv。\n\n这里是测试网上的提取流动性的tx\n\n**一些限制**\n\n1. 由于合约里面所有的操作需要依赖最新的合约tx然后生成新的合约tx,所以此合约上的所有操作都是需要串行的。但是不同的token合约是完全并行的,性能上的问题应该不是很大。最佳的实践应该是由一个服务商来提供合约的调用和上链服务。此外目前bsv上还存在未确认链长度的限制,需要后续解除这个限制才能无限制使用。\n2. 合约长度较大,上面提到的测试网上的几个合约调用tx,每个tx长度大概在66000字节左右,即使以0.1sat/byte价格来计算,也需要6600sat的手续费,还是比较高的。不过合约代码应该还有进一步的优化空间,以减少合约长度。\n3. 合约代码merkleTree2.scrypt里面计算merkle tree root使用到了循环(loop),由于bitcoin script不支持跳转,循环只能预先确定loop次数,然后展开代码。因此loop次数n决定了树的最大高度也为n。按满二叉树来算,其支持的最大账号的数量为2^n。如图4所示的示例代码中n等于5,则其最多支持32个账户。因此在生成合约时就需要考虑支持的账号数量。需要支持更多的账户数量,则提高n的数值,相应的会使得合约的长度变得更大,调用合约时则需要更多的手续费。\n\n![](https://pic1.zhimg.com/80/v2-475afbbdba3da2b373376b9d2b6caa9c_720w.jpg)\n图4 loop代码\n\n转自知乎 王彼特 [查看原文](https://zhuanlan.zhihu.com/p/312024053?utm_source=wechat_session&utm_medium=social&utm_oi=756624861303934976&utm_content=group3_article&utm_campaign=shareopn)","contentType":"text/markdown","createTime":1606458824501,"isTop":0,"folderID":"","tags":[],"attachments":[]}00.0.9applicaition/jsonUTF-8
    https://whatsonchain.com/tx/0ce61a1b8934766ab13349785c0a0c71045ad3a8a570367962fbeb6cce298ac2