储蓄分成合约指的是项目方发起了一个锁仓计划(即储蓄合约和取现合约),用户能够在准备期自由选择锁仓金额参与该计划,等到锁仓到期以后还能够自动获取锁仓的利润。用户能够在准备期内(dueBlockHeight
)参与储蓄,按照合约规定能够 1:1
获取同等数量的储蓄票据资产,同时用户锁仓的资产(deposit
)将放到取现合约中,而且项目方是没法动用的,等到锁仓期限(expireBlockHeight
)一到,用户即可以调用取现合约将本身储蓄的资产连本待息一同取出来。其示意图以下:html
从上图中能够看出,项目方发布了一个利润为20%
的锁仓项目,其中储蓄合约FixedLimitCollect
锁定了1000
个票据资产(bill
),同时项目方将200
个储蓄资产(deposit
)锁定到利息合约中。待项目方发布完合约以后,全部用户即可以参与了。例如上图中user1
调用合约储蓄了500
,这500
个储蓄资产将被锁定在取现合约FixedLimitProfit
中,同时user1
得到了500
个票据资产,剩余找零的资产将继续锁定在储蓄合约FixedLimitCollect
中,以此类推,user2
和user3
也是相同的流程,直到储蓄合约没有资产为止。取现合约FixedLimitProfit
跟储蓄合约的模型大体相同,只是取现合约是由多个UTXO
组成的,用户在取现的时候能够并行操做。可是若是合约中的面值不能支持用户一次性取现的话,须要分屡次提取。例如user1
拥有500
个票据资产,而能够得到的本息总额为600
,可是取现的UTXO
面值为500
,那么user1
一次最多只能取500
,剩下的100
须要再构造一笔交易来提现。前端
// 储蓄合约 import "./FixedLimitProfit" contract FixedLimitCollect(assetDeposited: Asset, totalAmountBill: Amount, totalAmountCapital: Amount, dueBlockHeight: Integer, expireBlockHeight: Integer, additionalBlockHeight: Integer, banker: Program, bankerKey: PublicKey) locks billAmount of billAsset { clause collect(amountDeposited: Amount, saver: Program) { verify below(dueBlockHeight) verify amountDeposited <= billAmount && totalAmountBill <= totalAmountCapital define sAmountDeposited: Integer = amountDeposited/100000000 define sTotalAmountBill: Integer = totalAmountBill/100000000 verify sAmountDeposited > 0 && sTotalAmountBill > 0 if amountDeposited < billAmount { lock amountDeposited of assetDeposited with FixedLimitProfit(billAsset, totalAmountBill, totalAmountCapital, expireBlockHeight, additionalBlockHeight, banker, bankerKey) lock amountDeposited of billAsset with saver lock billAmount-amountDeposited of billAsset with FixedLimitCollect(assetDeposited, totalAmountBill, totalAmountCapital, dueBlockHeight, expireBlockHeight, additionalBlockHeight, banker, bankerKey) } else { lock amountDeposited of assetDeposited with FixedLimitProfit(billAsset, totalAmountBill, totalAmountCapital, expireBlockHeight, additionalBlockHeight, banker, bankerKey) lock billAmount of billAsset with saver } } clause cancel(bankerSig: Signature) { verify above(dueBlockHeight) verify checkTxSig(bankerKey, bankerSig) unlock billAmount of billAsset } }
// 取现合约(本金加利息) contract FixedLimitProfit(assetBill: Asset, totalAmountBill: Amount, totalAmountCapital: Amount, expireBlockHeight: Integer, additionalBlockHeight: Integer, banker: Program, bankerKey: PublicKey) locks capitalAmount of capitalAsset { clause profit(amountBill: Amount, saver: Program) { verify above(expireBlockHeight) define sAmountBill: Integer = amountBill/100000000 define sTotalAmountBill: Integer = totalAmountBill/100000000 verify sAmountBill > 0 && sTotalAmountBill > 0 && amountBill < totalAmountBill define gain: Integer = totalAmountCapital*sAmountBill/sTotalAmountBill verify gain > 0 && gain <= capitalAmount if gain < capitalAmount { lock amountBill of assetBill with banker lock gain of capitalAsset with saver lock capitalAmount - gain of capitalAsset with FixedLimitProfit(assetBill, totalAmountBill, totalAmountCapital, expireBlockHeight, additionalBlockHeight, banker, bankerKey) } else { lock amountBill of assetBill with banker lock capitalAmount of capitalAsset with saver } } clause cancel(bankerSig: Signature) { verify above(additionalBlockHeight) verify checkTxSig(bankerKey, bankerSig) unlock capitalAmount of capitalAsset } }
合约的源代码说明能够具体参考Equity合约介绍
.git
2.5
分钟)8
, 即 1BTM = 100000000 neu
,正常状况下参与计算都是以neu
为单位的,然而虚拟机的int64
类型的最大值是9223372036854775807
,为了不数值太大致使计算溢出,因此对计算的金额提出了金额限制(即amountBill/100000000
)clause cancel
是项目方的管理方法,若是储蓄或者取现没有满额,项目方也能够回收剩余的资产编译Equity
合约能够参考一下Equity
编译器的介绍说明。假如储蓄合约FixedLimitCollect
的参数以下:github
assetDeposited :c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee totalAmountBill :10000000000 totalAmountCapital :20000000000 dueBlockHeight :1070 expireBlockHeight :1090 additionalBlockHeight :1100 banker :0014dedfd406c591aa221a047a260107f877da92fec5 bankerKey :055539eb36abcaaf127c63ae20e3d049cd28d0f1fe569df84da3aedb018ca1bf
其中bankerKey
是管理员的publicKey
,能够经过比原链的接口list-pubkeys
来获取,注意管理员须要保存一下对应的rootXpub
和Path
,不然没法正确调用clause cancel
。api
实例化合约命令以下:服务器
// 储蓄合约 ./equity FixedLimitCollect --instance c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee 10000000000 20000000000 1070 1090 1100 0014dedfd406c591aa221a047a260107f877da92fec5 055539eb36abcaaf127c63ae20e3d049cd28d0f1fe569df84da3aedb018ca1bf // 取现合约 ./equity FixedLimitProfit --instance c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee 10000000000 20000000000 1090 1100 0014dedfd406c591aa221a047a260107f877da92fec5 055539eb36abcaaf127c63ae20e3d049cd28d0f1fe569df84da3aedb018ca1bf
发布合约交易即将资产锁定到合约中。因为目前没法在比原的dashboard
上构造合约交易,因此须要借助外部工具来发送合约交易,好比postman
。按照上述示意图所示,项目方须要发布1000
个储蓄资产的储蓄合约和200
个利息资产取现合约。假设项目方须要发布1000
个储蓄资产(假如精度为8
,那么1000
个在比原链中表示为100000000000
)的锁仓合约,那么他须要将对应数量的票据锁定在储蓄合约中,其交易模板以下:app
{ "base_transaction": null, "actions": [ { "account_id": "0ILGLSTC00A02", "amount": 20000000, "asset_id": "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", "type": "spend_account" }, { "account_id": "0ILGLSTC00A02", "amount": 100000000000, "asset_id": "13016eff73ffb7539a69e122f80f5c1cc94446773ac3f64dec290429f87e73b3", "type": "spend_account" }, { "amount": 100000000000, "asset_id": "13016eff73ffb7539a69e122f80f5c1cc94446773ac3f64dec290429f87e73b3", "control_program": "20055539eb36abcaaf127c63ae20e3d049cd28d0f1fe569df84da3aedb018ca1bf160014dedfd406c591aa221a047a260107f877da92fec5024c04024204022e040500c817a8040500e40b540220c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee4d3b02597a642f0200005479cda069c35b797ca153795579a19a695a790400e1f5059653790400e1f505967c00a07c00a09a69c35b797c9f9161644d010000005b79c2547951005e79895d79895c79895b7989597989587989537a894caa587a649e0000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c96c37800a052797ba19a69c3787c9f91616487000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696399000000005b795479515b79c16951c3c2515d79c16963aa000000557acd9f69577a577aae7cac890274787e008901c07ec169515b79c2515d79c16952c35c7994c251005d79895c79895b79895a79895979895879895779895679895579890274787e008901c07ec169632a020000005b79c2547951005e79895d79895c79895b7989597989587989537a894caa587a649e0000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c96c37800a052797ba19a69c3787c9f91616487000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696399000000005b795479515b79c16951c3c2515d79c16963aa000000557acd9f69577a577aae7cac890274787e008901c07ec16951c3c2515d79c169633b020000547acd9f69587a587aae7cac747800c0", "type": "control_program" } ], "ttl": 0, "time_range": 1521625823 }
合约交易成功后,合约control_program
对应的UTXO
将会被全部用户查询到,使用比原链的接口list-unspent-outputs
便可查询。工具
此外,开发者须要存储一下合约UTXO
的assetID
和program
,以便在DAPP
的前端页面的config
配置文件和bufferserver
缓冲服务器中调用。如上所示:post
// 储蓄合约 assetID:13016eff73ffb7539a69e122f80f5c1cc94446773ac3f64dec290429f87e73b3 program:20055539eb36abcaaf127c63ae20e3d049cd28d0f1fe569df84da3aedb018ca1bf160014dedfd406c591aa221a047a260107f877da92fec5024c04024204022e040500c817a8040500e40b540220c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee4d3b02597a642f0200005479cda069c35b797ca153795579a19a695a790400e1f5059653790400e1f505967c00a07c00a09a69c35b797c9f9161644d010000005b79c2547951005e79895d79895c79895b7989597989587989537a894caa587a649e0000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c96c37800a052797ba19a69c3787c9f91616487000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696399000000005b795479515b79c16951c3c2515d79c16963aa000000557acd9f69577a577aae7cac890274787e008901c07ec169515b79c2515d79c16952c35c7994c251005d79895c79895b79895a79895979895879895779895679895579890274787e008901c07ec169632a020000005b79c2547951005e79895d79895c79895b7989597989587989537a894caa587a649e0000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c96c37800a052797ba19a69c3787c9f91616487000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696399000000005b795479515b79c16951c3c2515d79c16963aa000000557acd9f69577a577aae7cac890274787e008901c07ec16951c3c2515d79c169633b020000547acd9f69587a587aae7cac747800c0 // 取现合约 assetID:c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee program:20055539eb36abcaaf127c63ae20e3d049cd28d0f1fe569df84da3aedb018ca1bf160014dedfd406c591aa221a047a260107f877da92fec5024c040242040500c817a8040500e40b540220c6b12af8326df37b8d77c77bfa2547e083cbacde15cc48da56d4aa4e4235a3ee4caa587a649e0000005479cd9f6959790400e1f5059653790400e1f505967800a07800a09a5c7956799f9a6955797b957c96c37800a052797ba19a69c3787c9f91616487000000005b795479515b79c1695178c2515d79c16952c3527994c251005d79895c79895b79895a79895979895879895779895679890274787e008901c07ec1696399000000005b795479515b79c16951c3c2515d79c16963aa000000557acd9f69577a577aae7cac747800c0
本期的比原储蓄分成合约就介绍在这里,下一期咱们将详细介绍如何基于该合约开发dapp应用ui