├── .gitignore ├── DexChain-YellowPaper.pdf ├── Fund.md ├── LICENSE ├── README.md ├── YellowPaper.md ├── dexchain ├── CMakeLists.txt ├── dexchain.abi ├── dexchain.cpp ├── dexchain.hpp ├── exchange_state.cpp └── exchange_state.hpp └── tools └── test.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.wast 2 | *.wast.hpp 3 | *.wasm 4 | *.s 5 | *.abi 6 | passwd.txt 7 | nodeos.log 8 | cleos.sh 9 | .* 10 | -------------------------------------------------------------------------------- /DexChain-YellowPaper.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DexChain/eos-dexchain/bfcf2355db3afcf5b9e70a1a913cc6d523be1504/DexChain-YellowPaper.pdf -------------------------------------------------------------------------------- /Fund.md: -------------------------------------------------------------------------------- 1 | # Eos-DexChain Fund Model 2 | # 社区(Contact) 3 |     项目网站:https://github.com/DexChain
4 |     币乎:https://bihu.com/people/224762
5 |     电报:https://t.me/dexchain
6 |     公众号:区块链斜杠青年
7 |     欢迎交流技术及合作,有任何问题请加我微信:itleaks
8 | 9 | # 简介 10 |     上周在我的文章里提到过,去中心化链里的通证的价值锚定在生态成熟之前比较有难度,因而我在是思考一种代码保障的价值通证。目前阶段,要想实现价值通证,必须从EOS内部生态入手,因而我提出了一个基金币模型。
11 |     基金币采用100%的bancor模型,用户使用基金母币(一般是比较稳定的价值币,比如XEOS/EOS)购买基金币(比如VEX,投票代理基金币),基金币可随时按当前市价兑换成母币。基金币分为两类: 12 | * 保本型基金币
13 | 基金币只涨不跌,价格随着基金币的收益增加而上涨,早期购买,可以早点获取收益,任何时候购买都不晚,永不亏本金。此类基金币的经典场景是EOS CPU租赁市场,投票代理市场等。这种市场,基金管理人员(可以是代码)只可把募集到的母币用于出租,投票,是肯定可以回收的(所以不亏本金),同时租金,投票收益记入母币总量,从而基金币价格增长,投资人获取收益。 14 | * 非保本型基金
15 | 基金管理人员可以支配一定比例的母币去投资以获取收益,进而提高了基金总价值,对应的基金币价格上涨。如果亏损,则反之。此类基金币的场景更广泛,比如量化交易团体,传统行业投资团队。 16 | 17 | ## Eos-DexChain FUND API 18 | ### createfund(创建基金币) 19 | #### 介绍 20 | ``` 21 | createfund(account_name creator, account_name fund_account, symbol_name base, symbol_name fund, uint8_t permission) 22 | ``` 23 | * creator
24 | 基金币创建人,任何账号都可调用该接口创建场内币 25 | * fund_account
26 | 基金币管理账号 27 | * base
28 | 基金币 29 | * fund
30 | 母币 31 | * permission
32 | 母币操作权限,比如只能代理,投票等 33 | 34 | ### buyfund(购买基金) 35 | #### 介绍 36 | ``` 37 | void buyfund(account_name payer, account_name receiver, account_name fund_account, asset quantity); 38 | ``` 39 | * player
40 | 购买人 41 | * receiver
42 | 基金币接收账号 43 | * fund_account
44 | 基金管理账号 45 | * quantity
46 | 购买量 47 | 48 | ### sellfund(购买基金) 49 | #### 介绍 50 | ``` 51 | void sellfund(account_name account, account_name receiver, account_name fund_account, asset quantity); 52 | ``` 53 | * account
54 | 出售账号 55 | * fund_account
56 | 基金管理账号 57 | * quantity
58 | 出售量 59 | 60 | ### addfund(增加基金母币) 61 | #### 介绍 62 | ``` 63 | void addfund(account_name account, account_name fund_account, asset quantity); 64 | ``` 65 | * account
66 | 账号 67 | * fund_account
68 | 基金管理账号 69 | * quantity
70 | 增加量 71 | 72 | 比如租赁CPU,投票获得的收益就可以通过这个接口增加基金价值 73 | 74 | ## License 75 |     该项目是一个区块链4.0通证经济去中心化链的试验性探索链,遵循MIT License, 任何企业或个体可在MIT规范下使用本项目的源码。
76 |     由于该项目是一个试验性探索项目,目前该项目已经上线jungle测试网络,智能合约账号dexchaincode, 方便大家测试实践。 77 | 78 | ## Contact 79 |     项目网站:https://github.com/DexChain
80 |     币乎:https://bihu.com/people/224762
81 |     电报:https://t.me/dexchain
82 |     公众号:区块链斜杠青年
83 |     欢迎交流技术及合作,有任何问题请加我微信:itleaks
84 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018, Respective Authors all rights reserved. 2 | 3 | The MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Eos-DexChain 2 | # 社区(Contact) 3 |     项目网站:https://github.com/DexChain
4 |     币乎:https://bihu.com/people/224762
5 |     电报:https://t.me/dexchain
6 |     公众号:区块链斜杠青年
7 |     欢迎交流技术及合作,有任何问题请加我微信:itleaks
8 | 9 | # 简介 10 |     Eos-DexChain是DexChain在EOS生态下的一种试验性实现。更多信息请查看【黄皮书】
11 |     为了更好的理解Eos-DexChain,我们再次重述一下区块链4.0的标准。 12 | ``` 13 | 1)零成本发token 14 | 2) 零成本上交易所流通 15 | 3)去中心化交易所 16 | 去中心化交易所会借助市场机制完成通证token的价格形成及价值交换 17 | 4)高TPS 18 | 5)高安全性 19 | 6)信用体系 20 | 7)可只支持结算层 21 | 8) 高兼容及扩展性,可接入已有主流公链 22 | ``` 23 | ## 高TPS,高安全性 24 |     EOS本身具备高TPS和一定的高安全性,因而在EOS上创建一个智能合约来实现EOS生态的DexChain是最简单最直接的方式了。 25 | ## 零成本发币 26 |     Eos-DexChain实现一个类似eosio.token的智能合约,能够比较便捷的实现该功能。
27 |     Eos-DexChain的币分为两种 28 | ### 场内币(create) 29 |     这种币是给那些大量尾部需求的发币人准备的。通过Eos-DexChain发行场内币,只需消耗很少量的RAM(<1k)即可实现,不再需要部署发币合约而消耗大量的金钱,真正实现了零成本发币。且Eos-DexChain内置推广功能,比如主动领取空投,转账领取空投。同时场内币的交易很简单,非常容易实现流动性,更多信息将在交易一节讲解。 30 | ### 抵押币 (createbystake) 31 |     抵押币是为了给那些已经发行的币准备的,已经发行的币要在DexChain交易流通,必须先通过抵押方式转换为抵押币,场外币和Eos-DexChain的抵押币按1:1的比例发行。抵押一个场外比,Eos-DexChain发行一个抵押币。通过1:1抵押的方法实现了场外币和抵押币的价值绑定,且这个抵押发行过程是完全代码控制的,安全且可靠。 32 | ## 零成本上交易所,去中心化交易所(createdex) 33 |     Eos-DexChain是一个去中心化链,一个币币交易对你可以看成是一个去中心化交易所。 34 | ### 创建交易对 35 |     Eos-DexChain内采用Bancor机制来实现币币交易,Bancor实时交易是目前最好的去中心化交易所的模型。任何用户可以通过抵押交易币对的方式免费自由创建币(场内币,抵押币)交易对。 36 | ### 币币交易对初始价格 37 |     交易对的初始价格由抵押的量的比例决定。比如用户通过抵押1000EETH,10EOS来创建一个交易对EETH/EOS,那么初始的EETH价格是0.01EOS,后续价格由交易对的买卖交易市场形成。由于创建交易对需要抵押,因而是有成本的,如果定价不合理,创建者会损失资产。比如如果EETH抵押价格过高,就会有EETH持有者卖掉EETH获取EOS, 从而创建者的抵押的EOS变少了,总价值也减少了。因而该机制会促使创建者定一个他觉得合理的价格。 38 | ### 代币价格形成机制 39 |     cw=0.5的Bancor交易所初始价格变化比较平缓,后面比较剧烈,一开始的50%的交易量只会导致价格上涨一倍或者下跌一倍左右,因而市场价格形成不够迅速,因此开始可采取少量抵押量的方式先让市场先形成价格。价格形成后,可能会进入曲线的快速变动段,因而少量交易就会导致价格大波动,该阶段比较容易进入投机阶段,即大量买进导致价格飞涨(具体可参考RAM暴涨期)。由于价格急剧飞涨,交易对创建者也有巨额收入,他也应该乐于坐享其成,真相难道真会是这样的吗?非也,不像RAM市场是由BM,BP一小撮人控制的,且变动前必须提前通知,因而不够市场化。Eos-DexChain市场内,交易对是可以任意创建的,且相同的交易对也可以创建多个。如果前面的价格飞涨是因为老的交易所内的容量不够导致的,且超出了合理价格,那么其他人就会重开一个容量更大的相同的交易对来增加交易量,进而抑制了价格的继续上涨。新的交易所对老交易所的竞争会促使老交易所增加bancor的交易容量,进而减少波动。同时为了减少价格波动和抑制老交易所杀熟投机,老交易所必须按照当前价增加容量
40 | ### 币币交易对常见创建者 41 | * 1)代币的发行人或者大户
42 | 交易才能产生价值,才能形成价格,因而代币的发行人是最有动力去做这个事情的。也只有他们最有动力愿意冒着损失一部分抵押币的风险来创建。 43 | * 2)交易所老手
44 | 交易对价格稳定后,就会有成熟的交易所老手开建相同的交易对以更好的服务赚取手续费。 45 | ### 代币(Token通证)的真正价值 46 |     交易形成价格,投机交易也可能导致不合理价格,但是核心的还是代币的真正价值。具体到Eos-DexChain,场内币的价值由该代币所能绑定的实际价值决定。比如小超市的购物券币,就由该购物券所能使用的超市数量,用户量决定。抵押币通过代码1:1绑定后,抵押币的价值就完全和抵押的币的价值一致。比如XEOS(Eos-DexChain抵押币)就和EOS的价值一样。 47 | ### Eos-DexChain交易的各种安全保障 48 | * 抵押币的安全。
49 | 抵押币发行时会有对应量的场外币进入Eos-DexChain合约的抵押账号,因而抵押币是肯定可以提现的。比如1XEOS是肯定可以兑换成1EOS的。由于用作抵押的币的资金操作必须要赋值智能合约eosio.code权限,从而导致用户的场外币长时间可被智能合约操作。EOS-DexChain的抵押币设计了Stake,Unstake操作,只有执行这两个action时才需要eosio.code权限,其他抵押币交易阶段不需要eosio.code权限,大大降低了eosio.code权限的暴露时间。同时对于支持require_receipt的token,可以通过监听transfer事件直接stake而不需要eosio.code权限。 50 | * 交易所的安全
51 | 交易所管理账号的资金都是受合约监管的。EOS-DexChain新建了approve机制,交易所账号的所有资金都approve给了合约,这些资金只有智能合约能够管理。只有在交易所关闭时,才能提取这些资金,且关闭交易所会有延时,从而有足够时间让交易所的用户做出合理的响应,比如及时买卖。 52 | * 合约的安全
53 | DexChain合约推荐使用该文【固化EOS智能合约,监管升级权限,净化EOS DAPP生态】的建议,经过测试周期后,固化移交升级权限,实现合约自身的安全 54 | ## Eos-DexChain API 55 | ### create(创建场内币) 56 | #### 介绍 57 | ``` 58 | void create( account_name issuer, asset maximum_supply) 59 | ``` 60 | * issuer
61 | 场内币发行人,任何账号都可调用该接口创建场内币 62 | * maximum_supply
63 | 最大发行量 64 | 65 | #### 示例 66 | ``` 67 | cleos push action dexchaincode create '["useruseridx1", "100000000.0000 XTEST"]' -p useruseridx1 68 | ``` 69 | 上图就创建了一个XTEST场内币,然后你就可以直接使用这个币宣传运营了 70 | useruseridx1 71 | 72 | ### createbystake(创建抵押币) 73 | #### 介绍 74 | ``` 75 | void createbystake(asset maximum_supply, 76 | asset stake, 77 | account_name stake_contract); 78 | ``` 79 | 和场内币创建不一样,抵押币没有发行账号issuer,抵押一个就发行一个.且只能是抵押的场外币的合约拥有者才可调用 80 | * stake
81 | 抵押的场外币的资金量 82 | * stake_contract
83 | 抵押的场外币的智能合约账号 84 | * maximum_supply
85 | 最大发行量 86 | 87 | #### 示例 88 | ``` 89 | cleos push action dexchaincode createbystake '["1000000.0000 XEETH", "0.0000 EETH", "eosfavorcomm", "create new token XEETH by stake EETH"]' -p eosfavorcomm 90 | ``` 91 | 上图就创建了一个XEETH抵押币,然后任何EETH的持有人都可以通过stake将EETH转化为XEETH抵押币并进行交易 92 | 93 | ### stake(抵押获得抵押币) 94 | #### 介绍 95 | ``` 96 | void stake(account_name player, account_name receiver, 97 | symbol_type token_symbol, asset stake, 98 | account_name stake_contract, 99 | string memo ) 100 | ``` 101 | * player
102 | 抵押的场外币的消耗账号 103 | * receiver
104 | 抵押币的接收账号 105 | * token_symbol
106 | 要获取的抵押币的符号信息 107 | * stake
108 | 抵押的场外币的资金量 109 | * stake_contract
110 | 抵押的场外币的智能合约账号 111 | 112 | #### 示例 113 | ``` 114 | cleos push action dexchaincode stake '["useruseridx2", "useruseridx3", "4,XEETH", "8000.1000 EETH", "eosfavorcomm", "stake EETH to get XEETH"]' -p useruseridx2 115 | ``` 116 | useruseridx3会接收到8000.1000 XEETH 117 | 118 | ### unstake(取消抵押赎回已抵押的场外币) 119 | #### 介绍 120 | ``` 121 | void unstake(account_name player, account_name receiver, 122 | asset quantity, symbol_type stake_symbol, 123 | account_name stake_contract, 124 | string memo ) 125 | ``` 126 | * player
127 | 抵押的场外币的消耗账号 128 | * receiver
129 | 抵押币的接收账号 130 | * quantity
131 | 抵押币的数量 132 | * stake_symbol
133 | 要获取的场外币的符号信息 134 | * stake_contract
135 | 抵押的场外币的智能合约账号 136 | 137 | #### 示例 138 | ``` 139 | cleos push action dexchaincode unstake '["useruseridx3", "useruseridx2", "1.1000 XEETH", "4,EETH", "eosfavorcomm", "unstake XEETH to get EETH"]' -p useruseridx3 140 | ``` 141 | useruseridx2会接收到8000.1000 EETH 142 | 143 | ### createdex(创建交易对交易所) 144 | #### 介绍 145 | ``` 146 | void createdex(account_name creator, account_name dex_account, 147 | asset base, asset quote, uint32_t fee_amount); 148 | ``` 149 | * creator
150 | 交易对的创建者,也是抵押币的消耗者 151 | * dex_account
152 | 交易所管理账号 153 | * base
154 | bancor交易所的base币 155 | * quote
156 | bancor交易所的quote币 157 | * fee_amount
158 | 交易费,= 1/fee_amount, 比如200就是0.5%的手续费 159 | 160 | #### 示例 161 | ``` 162 | cleos push action dexchaincode createdex '["useruseridx3", "onefamousdex", "1000.0000 XTEST", "10.0000 XEOS", 200]' -p useruseridx3 163 | ``` 164 | 创建一个交易所对,管理账号时onefamousdex, 交易对是XTEST/XEOS, XTEST的初始价格是10/1000=0.01 XEOS 165 | 166 | ### buytoken(买base币) 167 | #### 介绍 168 | ``` 169 | void buytoken(account_name owner, account_name receiver, account_name dex_account, asset quat); 170 | 171 | ``` 172 | * owner
173 | 交易者 174 | * receiver
175 | 币的接收账号 176 | * dex_account
177 | 交易对管理账号 178 | * quat
179 | 用来购买base币的quote币量 180 | 181 | #### 示例 182 | ``` 183 | cleos push action dexchaincode buytoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XEOS"]' -p useruseridx3 184 | ``` 185 | useruseridx5将获得XTEST币 186 | 187 | ### selltoken(卖base币) 188 | #### 介绍 189 | ``` 190 | void selltoken(account_name owner, account_name receiver, account_name dex_account, asset quant); 191 | ``` 192 | * owner
193 | 交易者 194 | * receiver
195 | 币的接收账号 196 | * dex_account
197 | 交易对管理账号 198 | * quat
199 | 卖掉的base币的量 200 | 201 | #### 示例 202 | ``` 203 | cleos push action dexchaincode selltoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XTEST"]' -p useruseridx3 204 | ``` 205 | useruseridx5将获得XEOS币 206 | 207 | ### closedex(关闭交易所) 208 | #### 介绍 209 | ``` 210 | void closedex(account_name dex_account) 211 | ``` 212 | * dex_account
213 | 交易对管理账号 214 | 215 | #### 示例 216 | ``` 217 | cleos push action dexchaincode closedex '["onefamousdex"]' -p onefamousdex 218 | ``` 219 | onefamousdex账号对应的交易对关闭 220 | 221 | ### 获取交易所信息 222 | ``` 223 | > cleos get table dexchaincode dexchaincode dexmarkets 224 | { 225 | "rows": [{ 226 | "supply": "100000000000000 DEXCORE", 227 | "base": { 228 | "balance": "980.5879 XTEST", 229 | "weight": "0.50000000000000000" 230 | }, 231 | "quote": { 232 | "balance": "10.1980 XEOS", 233 | "weight": "0.50000000000000000" 234 | }, 235 | "dex_account": "onefamousdex", 236 | "fee_rate": 200 237 | } 238 | ], 239 | "more": false 240 | } 241 | 242 | ``` 243 | 244 | ### 获取代币信息 245 | ``` 246 | > cleos get table dexchaincode XEOS stat 247 | { 248 | "rows": [{ 249 | "supply": "0.0000 XEOS", 250 | "max_supply": "10000000000.0000 XEOS", 251 | "issuer": "dexchaincode", 252 | "stake_symbol": "4,EOS", 253 | "stake_contract": "eosio.token" 254 | } 255 | ], 256 | "more": false 257 | } 258 | ``` 259 | 260 | ### 获取代币持有 261 | ``` 262 | > cleos get currency balance dexchaincode useruseridx3 263 | 7989.0000 XEOS 264 | 4000.1000 XTEST 265 | ``` 266 | ### 汇总 267 |     上面的EOS可以是任意其他已经发行的场外币,XTEST可以是Eos-DexChain合约里的任意币(场内币和抵押币) 268 | 269 | ## 编译部署 270 | ``` 271 | cd dexchain 272 | eosiocpp -o dexchain.wast exchange_state.cpp dexchain.cpp 273 | cleos set contract your_account ./dexchain/ -p your_account 274 | ``` 275 | ## License 276 |     该项目是一个区块链4.0通证经济去中心化链的试验性探索链,遵循MIT License, 任何企业或个体可在MIT规范下使用本项目的源码。
277 |     由于该项目是一个试验性探索项目,目前该项目已经上线jungle测试网络,智能合约账号dexchaincode, 方便大家测试实践。 278 | 279 | ## Contact 280 |     项目网站:https://github.com/DexChain
281 |     币乎:https://bihu.com/people/224762
282 |     电报:https://t.me/dexchain
283 |     公众号:区块链斜杠青年
284 |     欢迎交流技术及合作,有任何问题请加我微信:itleaks
285 | -------------------------------------------------------------------------------- /YellowPaper.md: -------------------------------------------------------------------------------- 1 | # "区块链4.0" DexChain,通证经济及去中心化交易链探索 2 |     首先看到这里,你可能会有点失望,区块链4.0怎么不是新的共识算法,新的记账系统,新的DAPP虚拟机,新的….
3 |     这里的区块链4.0简单来说就是通证经济,价值即token, token呈现价值,去中心化交换价值传递价值。最近币改是区块链非常热门的话题,很多团队都在做通证经济学相关的理论研究,以探索币改生态。其实币改只是区块链4.0的一个落地点,只要你的token(代币)有某种实际价值或权益,你的token就有价值,就会反应到token的价格上,近到你小超市的购物券,大到公司股票权益。 4 | 5 | # 传统交易所 6 |     推广开来的通证在传统交易所是不可能实现的,高企的上币费,高难度的审核,小价值容量的币根本没有露面的机会。再者,目前传统交易所上币高门槛,导致币壳稀缺,币壳比币本身值钱,进而导致区块链代币只注重宣传,而不重视价值,绝大部分不需要token的场景也发币圈钱。因而token价值流动的载体交易所变革才是区块链4.0的基石,这个变革就是去中心化交易所。大家可能会说,去中心化交易所不是早就有了吗?其实不然,传统的去中心化交易所都是撮合型(买单和卖单)的交易所,在总量少,交易不及时的负反馈下,交易量只会更少,更不及时。因而高效实时的去中心化交易所的诞生才是区块链4.0的萌芽。 7 | 8 | # 去中心化交易所 9 |     大家很多人最近可能都在骂BM,其实BM在EOS引入的很多经济模型都是很牛逼的,最简单的就是RAM交易市场引入的Bancor机制,这个是真正意义上的区块链去中心化交易所的鼻祖,当然这个交易所也是有一些问题的,但新鲜事物出来都是需要进化的。
10 |     目前所有号称去中心化的交易所中,只有刚发布的币安去中心化交易所链Binance Chain才是最接近可以承载广义通证经济区块链4.0的,但它也才刚刚发布。 11 | 12 | # 区块链4.0标准 13 | 14 |     区块链4.0标准 15 | ``` 16 | 1)零成本发token 17 | 1) 零成本上交易所流通 18 | 3)去中心化交易所 19 | 去中心化交易所会借助市场机制完成通证token的价格形成及价值交换 20 | 4)高TPS 21 | 5)高安全性 22 | 6)信用体系 23 | 7)可只支持结算层 24 | 8) 高兼容及扩展性,可接入已有主流公链 25 | ``` 26 |     区块链4.0之前,只有大佬们是价值标的物的发球人,我们个体只是价值的传球手。4.0之后,任何有价值有能力的人都可以上球场玩,成为价值的发球人。
27 |     区块链4.0之前,似乎只有和区块链链本身相关的标的物才有价值,可惜的是绝大部分和区块链相关的其实最后也没有真正价值。区块链4.0之后,大量真正能看到价值的标的物上链了,礼品卡,购物券,家政服务,软件外包服务,公司股权,只要市场认可,皆可创币上链,价格形成交给市场。 28 | 29 | # DexChain 30 |     好了,到了介绍项目的时候了。DexChain是一个试验性的去中心化交易所链,是一个以探索去中心交易及通证经济为目标的链。首先DexChain将在EOS生态探索,后面会支持更多生态,合适的时机最后会形成一个统一的公链。
31 |     DexChain免费开源,本身不做任何商业化运作,只是一个实验性的网络,用来学习探索通证经济去中心化交易所,我们力量很微薄,我们也仅在尝试中,欢迎大家一起参与,一起促进区块链行业的发展,大家可以按照MIT License标准自由使用DexChain。 32 | 33 | # Eos-DexChain 34 |     Eos-DexChain是DexChain在EOS生态下的一种试验性实现。为了更好的理解Eos-DexChain,我们再次重述一下区块链4.0的标准。 35 | ``` 36 | 1)零成本发token 37 | 2) 零成本上交易所流通 38 | 3)去中心化交易所 39 | 去中心化交易所会借助市场机制完成通证token的价格形成及价值交换 40 | 4)高TPS 41 | 5)高安全性 42 | 6)信用体系 43 | 7)可只支持结算层 44 | 8) 高兼容及扩展性,可接入已有主流公链 45 | ``` 46 | ## 高TPS,高安全性 47 |     EOS本身具备高TPS和一定的高安全性,因而在EOS上创建一个智能合约来实现EOS生态的DexChain是最简单最直接的方式了。 48 | ## 零成本发币 49 |     Eos-DexChain实现一个增强的eosio.token的智能合约,能够比较便捷的实现该功能。
50 |     Eos-DexChain的币分为两种 51 | ### 场内币(create) 52 |     这种币是给那些大量尾部需求的发币人准备的。通过Eos-DexChain发行场内币,只需消耗很少量的RAM(<1k)即可实现,不再需要部署发币合约而消耗大量的金钱,真正实现了零成本发币。且Eos-DexChain内置推广功能,比如主动领取空投,转账领取空投。同时场内币的交易很简单,非常容易实现流动性,更多信息将在交易一节讲解。 53 | ### 抵押币 (createbystake) 54 |     抵押币是为了给那些已经发行的币准备的,已经发行的币要在DexChain交易流通,必须先通过抵押方式转换为抵押币,场外币和Eos-DexChain的抵押币按1:1的比例发行。抵押一个场外比,Eos-DexChain发行一个抵押币。通过1:1抵押的方法实现了场外币和抵押币的价值绑定,且这个抵押发行过程是完全代码控制的,安全且可靠。 55 | ## 零成本上交易所,去中心化交易所(createdex) 56 |     Eos-DexChain是一个去中心化链,一个币币交易对你可以看成是一个去中心化交易所。 57 | ### 创建交易对 58 |     Eos-DexChain内采用Bancor机制来实现币币交易,Bancor实时交易是目前最好的去中心化交易所的模型。任何用户可以通过抵押交易币对的方式免费自由创建币(场内币,抵押币)交易对。 59 | ### 币币交易对初始价格 60 |     交易对的初始价格由抵押的量的比例决定。比如用户通过抵押1000EETH,10EOS来创建一个交易对EETH/EOS,那么初始的EETH价格是0.01EOS,后续价格由交易对的买卖交易市场形成。由于创建交易对需要抵押,因而是有成本的,如果定价不合理,创建者会损失资产。比如如果EETH抵押价格过高,就会有EETH持有者卖掉EETH获取EOS, 从而创建者的抵押的EOS变少了,总价值也减少了。因而该机制会促使创建者定一个他觉得合理的价格。 61 | ### 代币价格形成机制 62 |     cw=0.5的Bancor交易所初始价格变化比较平缓,后面比较剧烈,一开始的50%的交易量只会导致价格上涨一倍或者下跌一倍左右,因而市场价格形成不够迅速,因此开始可采取少量抵押量的方式先让市场先形成价格。价格形成后,可能会进入曲线的快速变动段,因而少量交易就会导致价格大波动,该阶段比较容易进入投机阶段,即大量买进导致价格飞涨(具体可参考RAM暴涨期)。由于价格急剧飞涨,交易对创建者也有巨额收入,他也应该乐于坐享其成,真相难道真会是这样的吗?非也,不像RAM市场是由BM,BP一小撮人控制的,且变动前必须提前通知,因而不够市场化。Eos-DexChain市场内,交易对是可以任意创建的,且相同的交易对也可以创建多个。如果前面的价格飞涨是因为老的交易所内的容量不够导致的,且超出了合理价格,那么其他人就会重开一个容量更大的相同的交易对来增加交易量,进而抑制了价格的继续上涨。新的交易所对老交易所的竞争会促使老交易所增加bancor的交易容量,进而减少波动。同时为了减少价格波动和抑制老交易所杀熟投机,老交易所必须按照当前价增加容量
63 | ### 币币交易对常见创建者 64 | * 1)代币的发行人或者大户
65 | 交易才能产生价值,才能形成价格,因而代币的发行人是最有动力去做这个事情的。也只有他们最有动力愿意冒着损失一部分抵押币的风险来创建。 66 | * 2)交易所老手
67 | 交易对价格稳定后,就会有成熟的交易所老手开建相同的交易对以更好的服务赚取手续费。 68 | ### 代币(Token通证)的真正价值 69 |     交易形成价格,投机交易也可能导致不合理价格,但是核心的还是代币的真正价值。具体到Eos-DexChain,场内币的价值由该代币所能绑定的实际价值决定。比如小超市的购物券币,就由该购物券所能使用的超市数量,用户量决定。抵押币通过代码1:1绑定后,抵押币的价值就完全和抵押的币的价值一致。比如XEOS(Eos-DexChain抵押币)就和EOS的价值一样。 70 | ### Eos-DexChain交易的各种安全保障 71 | * 抵押币的安全。
72 | 抵押币发行时会有对应量的场外币进入Eos-DexChain合约的抵押账号,因而抵押币是肯定可以提现的。比如1XEOS是肯定可以兑换成1EOS的。由于用作抵押的币的资金操作必须要赋值智能合约eosio.code权限,从而导致用户的场外币长时间可被智能合约操作。EOS-DexChain的抵押币设计了Stake,Unstake操作,只有执行这两个action时才需要eosio.code权限,其他抵押币交易阶段不需要eosio.code权限,大大降低了eosio.code权限的暴露时间。 73 | * 交易所的安全
74 | 交易所管理账号的资金都是受合约监管的。EOS-DexChain新建了approve机制,交易所账号的所有资金都approve给了合约,这些资金只有智能合约能够管理。只有在交易所关闭时,才能提取这些资金,且关闭交易所会有延时,从而有足够时间让交易所的用户做出合理的响应,比如及时买卖。 75 | * 合约的安全
76 | DexChain合约推荐使用该文【固化EOS智能合约,监管升级权限,净化EOS DAPP生态】的建议,经过测试周期后,固化移交升级权限,实现合约自身的安全 77 | ## Eos-DexChain API 78 | ### create(创建场内币) 79 | #### 介绍 80 | ``` 81 | void create( account_name issuer, asset maximum_supply) 82 | ``` 83 | * issuer
84 | 场内币发行人,任何账号都可调用该接口创建场内币 85 | * maximum_supply
86 | 最大发行量 87 | 88 | #### 示例 89 | ``` 90 | cleos push action dexchaincode create '["useruseridx1", "100000000.0000 XTEST"]' -p useruseridx1 91 | ``` 92 | 上图就创建了一个XTEST场内币,然后你就可以直接使用这个币宣传运营了 93 | useruseridx1 94 | 95 | ### createbystake(创建抵押币) 96 | #### 介绍 97 | ``` 98 | void createbystake(asset maximum_supply, 99 | asset stake, 100 | account_name stake_contract); 101 | ``` 102 | 和场内币创建不一样,抵押币没有发行账号issuer,抵押一个就发行一个.且只能是抵押的场外币的合约拥有者才可调用 103 | * stake
104 | 抵押的场外币的资金量 105 | * stake_contract
106 | 抵押的场外币的智能合约账号 107 | * maximum_supply
108 | 最大发行量 109 | 110 | #### 示例 111 | ``` 112 | cleos push action dexchaincode createbystake '["1000000.0000 XEETH", "0.0000 EETH", "eosfavorcomm", "create new token XEETH by stake EETH"]' -p eosfavorcomm 113 | ``` 114 | 上图就创建了一个XEETH抵押币,然后任何EETH的持有人都可以通过stake将EETH转化为XEETH抵押币并进行交易 115 | 116 | ### stake(抵押获得抵押币) 117 | #### 介绍 118 | ``` 119 | void stake(account_name player, account_name receiver, 120 | symbol_type token_symbol, asset stake, 121 | account_name stake_contract, 122 | string memo ) 123 | ``` 124 | * player
125 | 抵押的场外币的消耗账号 126 | * receiver
127 | 抵押币的接收账号 128 | * token_symbol
129 | 要获取的抵押币的符号信息 130 | * stake
131 | 抵押的场外币的资金量 132 | * stake_contract
133 | 抵押的场外币的智能合约账号 134 | 135 | #### 示例 136 | ``` 137 | cleos push action dexchaincode stake '["useruseridx2", "useruseridx3", "4,XEETH", "8000.1000 EETH", "eosfavorcomm", "stake EETH to get XEETH"]' -p useruseridx2 138 | ``` 139 | useruseridx3会接收到8000.1000 XEETH 140 | 141 | ### unstake(取消抵押赎回已抵押的场外币) 142 | #### 介绍 143 | ``` 144 | void unstake(account_name player, account_name receiver, 145 | asset quantity, symbol_type stake_symbol, 146 | account_name stake_contract, 147 | string memo ) 148 | ``` 149 | * player
150 | 抵押的场外币的消耗账号 151 | * receiver
152 | 抵押币的接收账号 153 | * quantity
154 | 抵押币的数量 155 | * stake_symbol
156 | 要获取的场外币的符号信息 157 | * stake_contract
158 | 抵押的场外币的智能合约账号 159 | 160 | #### 示例 161 | ``` 162 | cleos push action dexchaincode unstake '["useruseridx3", "useruseridx2", "1.1000 XEETH", "4,EETH", "eosfavorcomm", "unstake XEETH to get EETH"]' -p useruseridx3 163 | ``` 164 | useruseridx2会接收到8000.1000 EETH 165 | 166 | ### createdex(创建交易对交易所) 167 | #### 介绍 168 | ``` 169 | void createdex(account_name creator, account_name dex_account, 170 | asset base, asset quote, uint32_t fee_amount); 171 | ``` 172 | * creator
173 | 交易对的创建者,也是抵押币的消耗者 174 | * dex_account
175 | 交易所管理账号 176 | * base
177 | bancor交易所的base币 178 | * quote
179 | bancor交易所的quote币 180 | * fee_amount
181 | 交易费,= 1/fee_amount, 比如200就是0.5%的手续费 182 | 183 | #### 示例 184 | ``` 185 | cleos push action dexchaincode createdex '["useruseridx3", "onefamousdex", "1000.0000 XTEST", "10.0000 XEOS", 200]' -p useruseridx3 186 | ``` 187 | 创建一个交易所对,管理账号时onefamousdex, 交易对是XTEST/XEOS, XTEST的初始价格是10/1000=0.01 XEOS 188 | 189 | ### buytoken(买base币) 190 | #### 介绍 191 | ``` 192 | void buytoken(account_name owner, account_name receiver, account_name dex_account, asset quat); 193 | 194 | ``` 195 | * owner
196 | 交易者 197 | * receiver
198 | 币的接收账号 199 | * dex_account
200 | 交易对管理账号 201 | * quat
202 | 用来购买base币的quote币量 203 | 204 | #### 示例 205 | ``` 206 | cleos push action dexchaincode buytoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XEOS"]' -p useruseridx3 207 | ``` 208 | useruseridx5将获得XTEST币 209 | 210 | ### selltoken(卖base币) 211 | #### 介绍 212 | ``` 213 | void selltoken(account_name owner, account_name receiver, account_name dex_account, asset quant); 214 | ``` 215 | * owner
216 | 交易者 217 | * receiver
218 | 币的接收账号 219 | * dex_account
220 | 交易对管理账号 221 | * quat
222 | 卖掉的base币的量 223 | 224 | #### 示例 225 | ``` 226 | cleos push action dexchaincode selltoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XTEST"]' -p useruseridx3 227 | ``` 228 | useruseridx5将获得XEOS币 229 | 230 | ### closedex(关闭交易所) 231 | #### 介绍 232 | ``` 233 | void closedex(account_name dex_account) 234 | ``` 235 | * dex_account
236 | 交易对管理账号 237 | 238 | #### 示例 239 | ``` 240 | cleos push action dexchaincode closedex '["onefamousdex"]' -p onefamousdex 241 | ``` 242 | onefamousdex账号对应的交易对关闭 243 | 244 | ### 获取交易所信息 245 | ``` 246 | > cleos get table dexchaincode dexchaincode dexmarkets 247 | { 248 | "rows": [{ 249 | "supply": "100000000000000 DEXCORE", 250 | "base": { 251 | "balance": "980.5879 XTEST", 252 | "weight": "0.50000000000000000" 253 | }, 254 | "quote": { 255 | "balance": "10.1980 XEOS", 256 | "weight": "0.50000000000000000" 257 | }, 258 | "dex_account": "onefamousdex", 259 | "fee_rate": 200 260 | } 261 | ], 262 | "more": false 263 | } 264 | 265 | ``` 266 | 267 | ### 获取代币信息 268 | ``` 269 | > cleos get table dexchaincode XEOS stat 270 | { 271 | "rows": [{ 272 | "supply": "0.0000 XEOS", 273 | "max_supply": "10000000000.0000 XEOS", 274 | "issuer": "dexchaincode", 275 | "stake_symbol": "4,EOS", 276 | "stake_contract": "eosio.token" 277 | } 278 | ], 279 | "more": false 280 | } 281 | ``` 282 | 283 | ### 获取代币持有 284 | ``` 285 | > cleos get currency balance dexchaincode useruseridx3 286 | 7989.0000 XEOS 287 | 4000.1000 XTEST 288 | ``` 289 | ### 汇总 290 |     上面的EOS可以是任意其他已经发行的场外币,XTEST可以是Eos-DexChain合约里的任意币(场内币和抵押币) 291 | 292 | ## 编译部署 293 | ``` 294 | cd dexchain 295 | eosiocpp -o dexchain.wast exchange_state.cpp dexchain.cpp 296 | cleos set contract your_account ./dexchain/ -p your_account 297 | ``` 298 | ## License 299 |     该项目是一个区块链4.0通证经济去中心化链的试验性探索链,遵循MIT License, 任何企业或个体可在MIT规范下使用本项目的源码。
300 |     该项目是一个试验性探索项目,目前该项目已经上线jungle测试网络,智能合约账号dexchaincode, 方便大家测试实践。 301 | ## 其他生态实现 302 | 以太坊等其他生态的DexChain将视情况适时开发推进 303 | ## Contact 304 |     项目网站:https://github.com/DexChain
305 |     币乎:https://bihu.com/people/224762
306 |     电报:https://t.me/dexchain
307 |     公众号:区块链斜杠青年
308 |     欢迎交流技术及合作,有任何问题请加我微信:itleaks
309 | 310 | -------------------------------------------------------------------------------- /dexchain/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | file(GLOB ABI_FILES "*.abi") 2 | configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY) 3 | 4 | add_wast_executable(TARGET dexchain 5 | INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}" 6 | LIBRARIES libc++ libc eosiolib 7 | DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR} 8 | ) 9 | -------------------------------------------------------------------------------- /dexchain/dexchain.abi: -------------------------------------------------------------------------------- 1 | { 2 | "____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-08-19T00:25:34", 3 | "version": "eosio::abi/1.0", 4 | "types": [{ 5 | "new_type_name": "account_name", 6 | "type": "name" 7 | }], 8 | "structs": [{ 9 | "name": "create", 10 | "base": "", 11 | "fields": [{ 12 | "name": "issuer", 13 | "type": "name" 14 | },{ 15 | "name": "maximum_supply", 16 | "type": "asset" 17 | } 18 | ] 19 | },{ 20 | "name": "issue", 21 | "base": "", 22 | "fields": [{ 23 | "name": "to", 24 | "type": "name" 25 | },{ 26 | "name": "quantity", 27 | "type": "asset" 28 | },{ 29 | "name": "memo", 30 | "type": "string" 31 | } 32 | ] 33 | },{ 34 | "name": "transfer", 35 | "base": "", 36 | "fields": [{ 37 | "name": "from", 38 | "type": "name" 39 | },{ 40 | "name": "to", 41 | "type": "name" 42 | },{ 43 | "name": "quantity", 44 | "type": "asset" 45 | },{ 46 | "name": "memo", 47 | "type": "string" 48 | } 49 | ] 50 | },{ 51 | "name": "approve", 52 | "base": "", 53 | "fields": [{ 54 | "name": "account", 55 | "type": "name" 56 | },{ 57 | "name": "quantity", 58 | "type": "asset" 59 | },{ 60 | "name": "memo", 61 | "type": "string" 62 | } 63 | ] 64 | },{ 65 | "name": "disapprove", 66 | "base": "", 67 | "fields": [{ 68 | "name": "account", 69 | "type": "name" 70 | },{ 71 | "name": "quantity", 72 | "type": "asset" 73 | },{ 74 | "name": "memo", 75 | "type": "string" 76 | } 77 | ] 78 | },{ 79 | "name": "createbystake", 80 | "base": "", 81 | "fields": [{ 82 | "name": "maximum_supply", 83 | "type": "asset" 84 | },{ 85 | "name": "stake", 86 | "type": "asset" 87 | },{ 88 | "name": "stake_contract", 89 | "type": "name" 90 | } 91 | ] 92 | },{ 93 | "name": "stake", 94 | "base": "", 95 | "fields": [{ 96 | "name": "player", 97 | "type": "name" 98 | },{ 99 | "name": "receiver", 100 | "type": "name" 101 | },{ 102 | "name": "token_symbol", 103 | "type": "symbol" 104 | },{ 105 | "name": "stake", 106 | "type": "asset" 107 | },{ 108 | "name": "stakecontract", 109 | "type": "name" 110 | },{ 111 | "name": "memo", 112 | "type": "string" 113 | } 114 | ] 115 | },{ 116 | "name": "unstake", 117 | "base": "", 118 | "fields": [{ 119 | "name": "player", 120 | "type": "name" 121 | },{ 122 | "name": "receiver", 123 | "type": "name" 124 | },{ 125 | "name": "quantity", 126 | "type": "asset" 127 | },{ 128 | "name": "stake_symbol", 129 | "type": "symbol" 130 | },{ 131 | "name": "stakecontract", 132 | "type": "name" 133 | },{ 134 | "name": "memo", 135 | "type": "string" 136 | } 137 | ] 138 | },{ 139 | "name": "createdex", 140 | "base": "", 141 | "fields": [{ 142 | "name": "creator", 143 | "type": "name" 144 | },{ 145 | "name": "dex_account", 146 | "type": "name" 147 | },{ 148 | "name": "base", 149 | "type": "asset" 150 | },{ 151 | "name": "quote", 152 | "type": "asset" 153 | },{ 154 | "name": "fee_amount", 155 | "type": "uint32" 156 | } 157 | ] 158 | },{ 159 | "name": "buytoken", 160 | "base": "", 161 | "fields": [{ 162 | "name": "owner", 163 | "type": "name" 164 | },{ 165 | "name": "receiver", 166 | "type": "name" 167 | },{ 168 | "name": "dex_account", 169 | "type": "name" 170 | },{ 171 | "name": "quat", 172 | "type": "asset" 173 | } 174 | ] 175 | },{ 176 | "name": "selltoken", 177 | "base": "", 178 | "fields": [{ 179 | "name": "owner", 180 | "type": "name" 181 | },{ 182 | "name": "receiver", 183 | "type": "name" 184 | },{ 185 | "name": "dex_account", 186 | "type": "name" 187 | },{ 188 | "name": "quant", 189 | "type": "asset" 190 | } 191 | ] 192 | },{ 193 | "name": "closedex", 194 | "base": "", 195 | "fields": [{ 196 | "name": "dex_account", 197 | "type": "name" 198 | } 199 | ] 200 | },{ 201 | "name": "account", 202 | "base": "", 203 | "fields": [ 204 | {"name":"balance", "type":"asset"} 205 | ] 206 | },{ 207 | "name": "currency_stats", 208 | "base": "", 209 | "fields": [ 210 | {"name":"supply", "type":"asset"}, 211 | {"name":"max_supply", "type":"asset"}, 212 | {"name":"issuer", "type":"account_name"}, 213 | {"name":"stake_symbol", "type":"symbol"}, 214 | {"name":"stake_contract", "type":"account_name"} 215 | ] 216 | 217 | },{ 218 | "name": "connector", 219 | "base": "", 220 | "fields": [ 221 | {"name":"balance", "type":"asset"}, 222 | {"name":"weight", "type":"float64"} 223 | ] 224 | },{ 225 | "name": "dex_state", 226 | "base": "", 227 | "fields": [ 228 | {"name":"supply", "type":"asset"}, 229 | {"name":"base", "type":"connector"}, 230 | {"name":"quote", "type":"connector"}, 231 | {"name":"dex_account", "type":"account_name"}, 232 | {"name":"fee_rate", "type":"uint32"}, 233 | ] 234 | } 235 | ], 236 | "actions": [{ 237 | "name": "create", 238 | "type": "create", 239 | "ricardian_contract": "" 240 | },{ 241 | "name": "issue", 242 | "type": "issue", 243 | "ricardian_contract": "" 244 | },{ 245 | "name": "transfer", 246 | "type": "transfer", 247 | "ricardian_contract": "" 248 | },{ 249 | "name": "approve", 250 | "type": "approve", 251 | "ricardian_contract": "" 252 | },{ 253 | "name": "disapprove", 254 | "type": "disapprove", 255 | "ricardian_contract": "" 256 | },{ 257 | "name": "createbystake", 258 | "type": "createbystake", 259 | "ricardian_contract": "" 260 | },{ 261 | "name": "stake", 262 | "type": "stake", 263 | "ricardian_contract": "" 264 | },{ 265 | "name": "unstake", 266 | "type": "unstake", 267 | "ricardian_contract": "" 268 | },{ 269 | "name": "createdex", 270 | "type": "createdex", 271 | "ricardian_contract": "" 272 | },{ 273 | "name": "buytoken", 274 | "type": "buytoken", 275 | "ricardian_contract": "" 276 | },{ 277 | "name": "selltoken", 278 | "type": "selltoken", 279 | "ricardian_contract": "" 280 | },{ 281 | "name": "closedex", 282 | "type": "closedex", 283 | "ricardian_contract": "" 284 | } 285 | ], 286 | "tables": [{ 287 | "name": "accounts", 288 | "type": "account", 289 | "index_type": "i64", 290 | "key_names" : ["currency"], 291 | "key_types" : ["uint64"] 292 | },{ 293 | "name": "approves", 294 | "type": "account", 295 | "index_type": "i64", 296 | "key_names" : ["currency"], 297 | "key_types" : ["uint64"] 298 | },{ 299 | "name": "stat", 300 | "type": "currency_stats", 301 | "index_type": "i64", 302 | "key_names" : ["currency"], 303 | "key_types" : ["uint64"] 304 | }, 305 | { 306 | "name": "dexmarkets", 307 | "type": "dex_state", 308 | "index_type": "i64", 309 | "key_names" : ["supply"], 310 | "key_types" : ["uint64"] 311 | } 312 | ], 313 | "ricardian_clauses": [], 314 | "error_messages": [], 315 | "abi_extensions": [] 316 | } 317 | -------------------------------------------------------------------------------- /dexchain/dexchain.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in ../LICENSE 4 | */ 5 | 6 | #include 7 | #include 8 | #include "dexchain.hpp" 9 | #include 10 | 11 | namespace dex { 12 | #define NONE_ACCOUNT 0 13 | #define APPROVE_ACCOUNT _self 14 | #define STAKE_ACCOUNT _self 15 | #define DELEGATE_ACCOUNT _self 16 | 17 | #define SYSTEM_CONTRACT N(eosio) 18 | #define EOS_CONTRACT N(eosio.token) 19 | #define EOS_SYM S(4,EOS) 20 | #define DEXCHAIN_EOS_SYM S(4,XEOS) 21 | #define NONE_SYMBOL S(0,NONE) 22 | 23 | #define FUND_PERMISSION_DELEGATE 0x1 24 | #define FUND_PERMISSION_VOTE 0x2 25 | #define FUND_PERMISSION_WITHDRAW 0x4 26 | #define FUND_PERMISSION_FULL 0xff 27 | 28 | #define FUND_USAGE_TYPE_DELEGATEBW 1 29 | #define FUND_USAGE_TYPE_VOTE 2 30 | #define FUND_USAGE_TYPE_WITHDRAW 3 31 | 32 | using namespace eosio; 33 | 34 | dexchain::dexchain( account_name self ):contract(self), _dexmarket(self, self), _fundmarket(self, self) { 35 | auto xeos = eosio::symbol_type(DEXCHAIN_EOS_SYM); 36 | stats statstable( _self, xeos.name() ); 37 | auto existing = statstable.find( xeos.name()); 38 | if ( existing == statstable.end()) { 39 | print("Create EOS with stake asset"); 40 | auto maximum_supply = asset(100000000000000ll, xeos); 41 | statstable.emplace( _self, [&]( auto& s ) { 42 | s.supply.symbol = maximum_supply.symbol; 43 | s.max_supply = maximum_supply; 44 | s.issuer = self; 45 | s.stake_symbol = EOS_SYM; 46 | s.stake_contract = EOS_CONTRACT; 47 | }); 48 | } else { 49 | print("EOS with stake already created"); 50 | } 51 | } 52 | 53 | void dexchain::create( account_name issuer, 54 | asset maximum_supply) 55 | { 56 | require_auth( issuer ); 57 | 58 | auto sym = maximum_supply.symbol; 59 | //TODO:Should inner token begin with "Y"? 60 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 61 | eosio_assert( maximum_supply.is_valid(), "invalid supply"); 62 | eosio_assert( maximum_supply.amount > 0, "max-supply must be positive"); 63 | 64 | stats statstable( _self, sym.name() ); 65 | auto existing = statstable.find( sym.name() ); 66 | eosio_assert( existing == statstable.end(), "token with symbol already exists" ); 67 | 68 | statstable.emplace( issuer, [&]( auto& s ) { 69 | s.supply.symbol = maximum_supply.symbol; 70 | s.max_supply = maximum_supply; 71 | s.issuer = issuer; 72 | s.stake_symbol = NONE_SYMBOL; 73 | s.stake_contract = NONE_ACCOUNT; 74 | }); 75 | } 76 | 77 | void dexchain::createbystake( 78 | asset maximum_supply, 79 | asset stake, 80 | account_name stake_contract) 81 | { 82 | require_auth( stake_contract ); 83 | 84 | auto sym = maximum_supply.symbol; 85 | //TODO:Should token with stake asset begin with "X"? 86 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 87 | eosio_assert( maximum_supply.is_valid(), "invalid supply"); 88 | eosio_assert( maximum_supply.amount > 0, "max-supply must be positive"); 89 | eosio_assert( stake.amount >= 0, "stake amount must >= 0"); 90 | 91 | stats statstable( _self, sym.name() ); 92 | auto existing = statstable.find( sym.name() ); 93 | eosio_assert( existing == statstable.end(), "token with symbol already exists" ); 94 | 95 | statstable.emplace( _self, [&]( auto& s ) { 96 | s.supply.symbol = maximum_supply.symbol; 97 | s.max_supply = maximum_supply; 98 | s.issuer = STAKE_ACCOUNT; 99 | 100 | s.stake_symbol = stake.symbol; 101 | s.stake_contract = stake_contract; 102 | }); 103 | 104 | if (stake.amount > 0) { 105 | auto quantity = asset(stake.amount, sym); 106 | action( 107 | permission_level{ stake_contract, N(active) }, //Must assign eosio.code of creator to this contract 108 | _self, N(stake), 109 | std::make_tuple(stake_contract, stake_contract, quantity, stake, stake_contract, std::string("stake outer token to dex token")) 110 | ).send(); 111 | } 112 | } 113 | 114 | void dexchain::issue( account_name to, asset quantity, string memo ) 115 | { 116 | auto sym = quantity.symbol; 117 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 118 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 119 | 120 | auto sym_name = sym.name(); 121 | stats statstable( _self, sym_name ); 122 | auto existing = statstable.find( sym_name ); 123 | eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); 124 | const auto& st = *existing; 125 | 126 | require_auth( st.issuer ); 127 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 128 | eosio_assert( quantity.amount > 0, "must issue positive quantity" ); 129 | 130 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 131 | eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); 132 | 133 | statstable.modify( st, 0, [&]( auto& s ) { 134 | s.supply += quantity; 135 | }); 136 | 137 | add_balance( st.issuer, quantity, st.issuer ); 138 | 139 | if( to != st.issuer ) { 140 | action( 141 | permission_level{ st.issuer, N(active) }, 142 | _self, N(transfer), 143 | std::make_tuple(st.issuer, to, quantity, memo) 144 | ).send(); 145 | } 146 | } 147 | 148 | void dexchain::approve( account_name account, 149 | asset quantity, 150 | string memo ) 151 | { 152 | require_auth( account ); 153 | auto sym = quantity.symbol.name(); 154 | stats statstable( _self, sym ); 155 | const auto& st = statstable.get( sym ); 156 | require_recipient( account ); 157 | 158 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 159 | eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); 160 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 161 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 162 | 163 | //disapprove may cost ram, so sub must after add 164 | add_balance2( account, quantity, account ); 165 | sub_balance( account, quantity ); 166 | } 167 | 168 | void dexchain::disapprove( account_name account, 169 | asset quantity, 170 | string memo ) 171 | { 172 | require_auth( APPROVE_ACCOUNT ); 173 | auto sym = quantity.symbol.name(); 174 | stats statstable( _self, sym ); 175 | const auto& st = statstable.get( sym ); 176 | require_recipient( account ); 177 | 178 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 179 | eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); 180 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 181 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 182 | 183 | sub_balance2( account, quantity ); 184 | //Approve add 185 | add_balance( account, quantity, account ); 186 | } 187 | 188 | void dexchain::transfer( account_name from, 189 | account_name to, 190 | asset quantity, 191 | string memo ) 192 | { 193 | eosio_assert( from != to, "cannot transfer to self" ); 194 | require_auth( from ); 195 | eosio_assert( is_account( to ), "to account does not exist"); 196 | auto sym = quantity.symbol.name(); 197 | stats statstable( _self, sym ); 198 | const auto& st = statstable.get( sym ); 199 | require_recipient( from ); 200 | require_recipient( to ); 201 | 202 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 203 | eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); 204 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 205 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 206 | 207 | sub_balance( from, quantity ); 208 | add_balance( to, quantity, from ); 209 | } 210 | 211 | void dexchain::burn( account_name owner, asset quantity, string memo ) 212 | { 213 | require_auth( owner ); 214 | sub_balance( owner, quantity ); 215 | auto sym_name = quantity.symbol.name(); 216 | stats statstable( _self, sym_name ); 217 | auto& st = statstable.get( sym_name ); 218 | statstable.modify( st, 0, [&]( auto& s ) { 219 | s.supply -= quantity; 220 | }); 221 | } 222 | 223 | void dexchain::sub_balance( account_name owner, asset value) { 224 | accounts from_acnts( _self, owner ); 225 | 226 | const auto& from = from_acnts.get( value.symbol.name(), "no balance object found" ); 227 | eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); 228 | 229 | 230 | if( from.balance.amount == value.amount ) { 231 | approves acnts( _self, owner ); 232 | const auto existing = acnts.find( value.symbol.name()); 233 | if (existing == acnts.end()) { 234 | from_acnts.erase( from ); 235 | } else { 236 | from_acnts.modify( from, owner, [&]( auto& a ) { 237 | a.balance -= value; 238 | }); 239 | } 240 | } else { 241 | from_acnts.modify( from, owner, [&]( auto& a ) { 242 | a.balance -= value; 243 | }); 244 | } 245 | } 246 | 247 | void dexchain::add_balance( account_name owner, asset value, account_name ram_payer ) 248 | { 249 | accounts to_acnts( _self, owner ); 250 | auto to = to_acnts.find( value.symbol.name() ); 251 | if( to == to_acnts.end() ) { 252 | to_acnts.emplace( ram_payer, [&]( auto& a ){ 253 | a.balance = value; 254 | }); 255 | } else { 256 | to_acnts.modify( to, 0, [&]( auto& a ) { 257 | a.balance += value; 258 | }); 259 | } 260 | } 261 | 262 | void dexchain::sub_balance2( account_name owner, asset value ) { 263 | approves from_acnts( _self, owner ); 264 | 265 | const auto& from = from_acnts.get( value.symbol.name(), "no balance object found" ); 266 | eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); 267 | 268 | 269 | if( from.balance.amount == value.amount ) { 270 | from_acnts.erase( from ); 271 | } else { 272 | from_acnts.modify( from, owner, [&]( auto& a ) { 273 | a.balance -= value; 274 | }); 275 | } 276 | } 277 | 278 | void dexchain::add_balance2( account_name owner, asset value, account_name ram_payer ) 279 | { 280 | approves to_acnts( _self, owner ); 281 | auto to = to_acnts.find( value.symbol.name() ); 282 | if( to == to_acnts.end() ) { 283 | to_acnts.emplace( ram_payer, [&]( auto& a ){ 284 | a.balance = value; 285 | }); 286 | } else { 287 | to_acnts.modify( to, 0, [&]( auto& a ) { 288 | a.balance += value; 289 | }); 290 | } 291 | } 292 | 293 | void dexchain::assertAsset( asset quantity ) { 294 | auto sym = quantity.symbol; 295 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 296 | 297 | auto sym_name = sym.name(); 298 | stats statstable( _self, sym_name ); 299 | auto existing = statstable.find( sym_name ); 300 | eosio_assert( existing != statstable.end(), "token with symbol does not exist" ); 301 | } 302 | 303 | void dexchain::stake( 304 | account_name player, 305 | account_name receiver, 306 | symbol_type token_symbol, 307 | asset stake, 308 | account_name stakecontract, 309 | string memo ) 310 | { 311 | require_auth( player ); 312 | 313 | auto sym = token_symbol; 314 | auto sym_name = sym.name(); 315 | stats statstable( _self, sym_name ); 316 | auto existing = statstable.find( sym_name ); 317 | eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before link" ); 318 | const auto& st = *existing; 319 | eosio_assert( st.stake_contract == stakecontract, "invalid stake contract" ); 320 | eosio_assert( st.stake_symbol == stake.symbol, "invalid stake symbol" ); 321 | 322 | action( 323 | permission_level{ player, N(active) }, //Must assign eosio.code of creator to this contract 324 | stakecontract, N(transfer), 325 | std::make_tuple(player, STAKE_ACCOUNT, stake, std::string("Send stacked outer token to stakeaccount")) 326 | ).send(); 327 | 328 | asset quantity = asset(stake.amount, token_symbol); 329 | action( 330 | permission_level{ STAKE_ACCOUNT, N(active) }, //Must assign eosio.code of creator to this contract 331 | _self, N(issue), 332 | std::make_tuple(STAKE_ACCOUNT, quantity, std::string("Issue inner token for staked outer stoken")) 333 | ).send(); 334 | // add_balance(STAKE_ACCOUNT, quantity, player); 335 | 336 | action( 337 | permission_level{ STAKE_ACCOUNT, N(active) }, //Must assign eosio.code of creator to this contract 338 | _self, N(transfer), 339 | std::make_tuple(STAKE_ACCOUNT, receiver, quantity, std::string("Send inner token to receiver")) 340 | ).send(); 341 | } 342 | 343 | void dexchain::unstake( 344 | account_name player, 345 | account_name receiver, 346 | asset quantity, 347 | symbol_type stake_symbol, 348 | account_name stakecontract, 349 | string memo ) 350 | { 351 | require_auth( player ); 352 | 353 | auto sym = quantity.symbol; 354 | auto sym_name = sym.name(); 355 | stats statstable( _self, sym_name ); 356 | auto existing = statstable.find( sym_name ); 357 | eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before link" ); 358 | const auto& st = *existing; 359 | eosio_assert( st.stake_contract == stakecontract, "invalid stake contract" ); 360 | eosio_assert( st.stake_symbol == stake_symbol, "invalid stake symbol" ); 361 | 362 | action( 363 | permission_level{ player, N(active) }, //Must assign eosio.code of creator to this contract 364 | _self, N(transfer), 365 | std::make_tuple(player, STAKE_ACCOUNT, quantity, std::string("Send dex token to stack account")) 366 | ).send(); 367 | 368 | statstable.modify( st, 0, [&]( auto& s ) { 369 | s.supply.amount -= quantity.amount; 370 | }); 371 | 372 | asset stake = asset(quantity.amount, stake_symbol); 373 | action( 374 | permission_level{ STAKE_ACCOUNT, N(active) }, //Must assign eosio.code of creator to this contract 375 | stakecontract, N(transfer), 376 | std::make_tuple(STAKE_ACCOUNT, receiver, stake, std::string("Send stacked totoken to receive")) 377 | ).send(); 378 | 379 | action( 380 | permission_level{ STAKE_ACCOUNT, N(active) }, //Must assign eosio.code of creator to this contract 381 | stakecontract, N(burn), 382 | std::make_tuple(STAKE_ACCOUNT, quantity, std::string("Burn inner token due to unstake outer token")) 383 | ).send(); 384 | } 385 | 386 | //fee_rate >= 1 387 | void dexchain::createdex(account_name creator, account_name dex_account, asset base, asset quote, uint32_t fee_rate) 388 | { 389 | require_auth( creator ); 390 | eosio_assert( fee_rate > 0, "fee_rate should be larger than 0" ); 391 | assertAsset(base); 392 | assertAsset(quote); 393 | 394 | auto existing = _dexmarket.find( dex_account ); 395 | 396 | eosio_assert(existing == _dexmarket.end(), "dex market already existed"); 397 | 398 | //Send staked base token to dex account 399 | action( 400 | permission_level{ creator, N(active) }, 401 | _self, N(transfer), 402 | std::make_tuple(creator, dex_account, base, std::string("Send base token to dex account")) 403 | ).send(); 404 | 405 | action( 406 | permission_level{ dex_account, N(active) }, //Must assign eosio.code of dex_account to this contract 407 | _self, N(approve), 408 | std::make_tuple(dex_account, base, std::string("approve token")) 409 | ).send(); 410 | 411 | //Send staked quote token to dex account 412 | action( 413 | permission_level{ creator, N(active) }, 414 | _self, N(transfer), 415 | std::make_tuple(creator, dex_account, quote, std::string("Send quote token to dex account")) 416 | ).send(); 417 | 418 | action( 419 | permission_level{ dex_account, N(active) }, 420 | _self, N(approve), 421 | std::make_tuple(dex_account, quote, std::string("approve token")) 422 | ).send(); 423 | 424 | _dexmarket.emplace( _self, [&]( auto& m ) { 425 | m.dex_account = dex_account; 426 | m.fee_rate = fee_rate; 427 | m.supply.amount = 100000000000000ll; 428 | m.supply.symbol = S(0,DEXCORE); 429 | m.base.balance.amount = base.amount; 430 | m.base.balance.symbol = base.symbol; 431 | m.quote.balance.amount = quote.amount; 432 | m.quote.balance.symbol = quote.symbol; 433 | }); 434 | } 435 | 436 | void dexchain::closedex(account_name dex_account) 437 | { 438 | //TODO:Add a delay action to close a dex 439 | //延迟关闭去中心化交易对,以给参与者足够的时间交易token 440 | require_auth( dex_account ); 441 | 442 | auto existing = _dexmarket.find( dex_account ); 443 | 444 | eosio_assert(existing != _dexmarket.end(), "dex market not existed"); 445 | 446 | auto& st = *existing; 447 | _dexmarket.erase( st ); 448 | 449 | auto asset = get_balance2(dex_account, st.base.balance.symbol.name()); 450 | print("base,", asset, "\n"); 451 | action( 452 | permission_level{ APPROVE_ACCOUNT, N(active) }, 453 | _self, N(disapprove), 454 | std::make_tuple(dex_account, asset, std::string("disapprove base token")) 455 | ).send(); 456 | 457 | asset = get_balance2(dex_account, st.quote.balance.symbol.name()); 458 | print("quote,", asset, "\n"); 459 | action( 460 | permission_level{ APPROVE_ACCOUNT, N(active) }, 461 | _self, N(disapprove), 462 | std::make_tuple(dex_account, asset, std::string("disapprove quote token")) 463 | ).send(); 464 | } 465 | 466 | void dexchain::buytoken(account_name owner, account_name receiver, account_name dex_account, asset quant) { 467 | require_auth( owner ); 468 | 469 | auto existing = _dexmarket.find( dex_account ); 470 | eosio_assert(existing != _dexmarket.end(), "dex market not existed"); 471 | 472 | const auto& dex = *existing; 473 | 474 | eosio_assert( quant.amount > 0, "must purchase a positive amount" ); 475 | auto fee = quant; 476 | fee.amount = ( fee.amount + dex.fee_rate - 1 ) / dex.fee_rate; /// fee_rate=200 when .5% fee 477 | auto quant_after_fee = quant; 478 | quant_after_fee.amount -= fee.amount; 479 | 480 | eosio_assert( quant_after_fee.amount > 0, "quant_after_fee must a positive amount" ); 481 | 482 | //Send staked quote token to dex account 483 | action( 484 | permission_level{ owner, N(active) }, 485 | _self, N(transfer), 486 | std::make_tuple(owner, dex_account, quant, std::string("Send quote token to dex account")) 487 | ).send(); 488 | 489 | action( 490 | permission_level{ dex_account, N(active) }, //Must assign eosio.code of creator to this contract 491 | _self, N(approve), 492 | std::make_tuple(dex_account, quant, std::string("approve quote token")) 493 | ).send(); 494 | 495 | asset tokens_out; 496 | _dexmarket.modify( existing, 0, [&]( auto& es ) { 497 | tokens_out = es.convert( quant_after_fee, dex.base.balance.symbol ); 498 | }); 499 | eosio_assert( tokens_out.amount > 0, "must reserve a positive amount" ); 500 | print("token exchange,", quant_after_fee.amount, ":", tokens_out.amount); 501 | 502 | //从交易所转出 503 | action( 504 | permission_level{ APPROVE_ACCOUNT, N(active) }, 505 | _self, N(disapprove), 506 | std::make_tuple(dex_account, tokens_out, std::string("disapprove base token")) 507 | ).send(); 508 | 509 | action( 510 | permission_level{ dex_account, N(active) }, 511 | _self, N(transfer), 512 | std::make_tuple( dex_account, receiver, tokens_out, std::string("Send token to receiver")) 513 | ).send(); 514 | } 515 | 516 | void dexchain::selltoken(account_name owner, account_name receiver, account_name dex_account, asset quant) 517 | { 518 | require_auth( owner ); 519 | 520 | auto existing = _dexmarket.find( dex_account ); 521 | eosio_assert(existing != _dexmarket.end(), "dex market not existed"); 522 | 523 | auto dex = *existing; 524 | 525 | eosio_assert( quant.amount > 0, "must purchase a positive amount" ); 526 | auto fee = quant; 527 | fee.amount = ( fee.amount + dex.fee_rate - 1 ) / dex.fee_rate; /// fee_rate=200 when .5% fee 528 | auto quant_after_fee = quant; 529 | quant_after_fee.amount -= fee.amount; 530 | 531 | eosio_assert( quant_after_fee.amount > 0, "quant_after_fee must a positive amount" ); 532 | 533 | action( 534 | permission_level{ owner, N(active) }, 535 | _self, N(transfer), 536 | std::make_tuple(owner, dex_account, quant, std::string("Send base token to dex account")) 537 | ).send(); 538 | 539 | action( 540 | permission_level{ dex_account, N(active) }, //Must assign eosio.code of dex_account to this contract 541 | _self, N(approve), 542 | std::make_tuple(dex_account, quant, std::string("approve base token")) 543 | ).send(); 544 | 545 | asset tokens_out; 546 | _dexmarket.modify( existing, 0, [&]( auto& es ) { 547 | tokens_out = es.convert( quant_after_fee, dex.quote.balance.symbol ); 548 | }); 549 | eosio_assert( tokens_out.amount > 0, "must reserve a positive amount" ); 550 | 551 | //从交易所转出 552 | action( 553 | permission_level{ APPROVE_ACCOUNT, N(active) }, 554 | _self, N(disapprove), 555 | std::make_tuple(dex_account, tokens_out, std::string("disapprove quote token")) 556 | ).send(); 557 | action( 558 | permission_level{ dex_account, N(active) }, 559 | _self, N(transfer), 560 | std::make_tuple(dex_account, receiver, tokens_out, std::string("Send token to receiver")) 561 | ).send(); 562 | } 563 | 564 | 565 | void dexchain::claim(account_name account){ 566 | //TODO 567 | } 568 | 569 | void refund(account_name dex_account){ 570 | //TODO 571 | } 572 | 573 | void resetDex(account_name dex_account, asset maxBase, asset maxQuote) 574 | { 575 | //TODO:Increase or descrease volume of dex with price keeping same 576 | } 577 | 578 | void dexchain::createfund(account_name creator, account_name fund_account, symbol_name base_symbol, symbol_name fund_symbol, uint8_t permission) 579 | { 580 | require_auth( creator ); 581 | asset base(0, base_symbol); 582 | assertAsset(base); 583 | asset fund(0, fund_symbol); 584 | assertAsset(fund); 585 | 586 | auto existing = _fundmarket.find( fund_account ); 587 | 588 | eosio_assert(existing == _fundmarket.end(), "fund market already existed"); 589 | 590 | _fundmarket.emplace( _self, [&]( auto& m ) { 591 | m.fund_account = fund_account; 592 | m.base_balance = base; 593 | m.fund_balance = fund; 594 | m.permission = permission; 595 | }); 596 | } 597 | 598 | void dexchain::buyfund(account_name payer, account_name receiver, account_name fund_account, asset quantity) 599 | { 600 | require_auth( payer ); 601 | 602 | auto existing = _fundmarket.find( fund_account ); 603 | eosio_assert(existing != _fundmarket.end(), "fund market not existed"); 604 | 605 | const auto& fund = *existing; 606 | 607 | eosio_assert( quantity.amount > 0, "must purchase a positive amount" ); 608 | eosio_assert( fund.fund_balance.symbol == quantity.symbol, "invalid symbol" ); 609 | //Send fund token to fund account 610 | action( 611 | permission_level{ payer, N(active) },//Must assign eosio.code of payer to this contract 612 | _self, N(transfer), 613 | std::make_tuple(payer, fund_account, quantity, std::string("Send fund token to dex account")) 614 | ).send(); 615 | 616 | action( 617 | permission_level{ fund_account, N(active) }, 618 | _self, N(approve), 619 | std::make_tuple(fund_account, quantity, std::string("approve fund token")) 620 | ).send(); 621 | 622 | asset tokens_out; 623 | _fundmarket.modify( existing, 0, [&]( auto& es ) { 624 | tokens_out = es.buy( quantity ); 625 | }); 626 | eosio_assert( tokens_out.amount > 0, "must reserve a positive amount" ); 627 | print("fund price,", quantity.amount, ":", tokens_out.amount); 628 | 629 | //从基金转出 630 | action( 631 | permission_level{ fund_account, N(active) }, 632 | _self, N(issue), 633 | std::make_tuple(fund_account, receiver, tokens_out, std::string("Issue base token")) 634 | ).send(); 635 | } 636 | 637 | void dexchain::sellfund(account_name account, account_name fund_account, asset quantity) 638 | { 639 | require_auth( account ); 640 | 641 | auto existing = _fundmarket.find( fund_account ); 642 | eosio_assert(existing != _fundmarket.end(), "fund market not existed"); 643 | 644 | const auto& fund = *existing; 645 | 646 | eosio_assert( quantity.amount > 0, "must sell a positive amount" ); 647 | eosio_assert( fund.fund_balance.symbol == quantity.symbol, "invalid symbol" ); 648 | //Send fund token to fund account 649 | action( 650 | permission_level{ account, N(active) }, 651 | _self, N(transfer), 652 | std::make_tuple(account, fund_account, quantity, std::string("Send fund token to dex account")) 653 | ).send(); 654 | sub_balance(account, quantity); 655 | 656 | asset tokens_out; 657 | _fundmarket.modify( existing, 0, [&]( auto& es ) { 658 | tokens_out = es.sell( quantity ); 659 | }); 660 | eosio_assert( tokens_out.amount > 0, "must reserve a positive amount" ); 661 | print("fund price,", quantity.amount, ":", tokens_out.amount); 662 | 663 | action( 664 | permission_level{ fund_account, N(active) }, //Must assign eosio.code of creator to this contract 665 | _self, N(disapprove), 666 | std::make_tuple(fund_account, tokens_out, std::string("disapprove fund token")) 667 | ).send(); 668 | //从基金转出 669 | action( 670 | permission_level{ fund_account, N(active) }, //Must assign eosio.code of creator to this contract 671 | _self, N(transfer), 672 | std::make_tuple(fund_account, account, tokens_out, std::string("refund token")) 673 | ).send(); 674 | } 675 | 676 | void dexchain::addfund(account_name account, account_name fund_account, asset quantity) 677 | { 678 | require_auth( account ); 679 | 680 | auto existing = _fundmarket.find( fund_account ); 681 | eosio_assert(existing != _fundmarket.end(), "fund market not existed"); 682 | 683 | const auto& fund = *existing; 684 | 685 | action( 686 | permission_level{ account, N(active) }, 687 | _self, N(transfer), 688 | std::make_tuple(account, fund_account, quantity, std::string("Send fund token to fund account")) 689 | ).send(); 690 | 691 | action( 692 | permission_level{ fund_account, N(active) }, //Must assign eosio.code of creator to this contract 693 | _self, N(approve), 694 | std::make_tuple(fund_account, quantity, std::string("approve fund token")) 695 | ).send(); 696 | 697 | _fundmarket.modify( existing, 0, [&]( auto& es ) { 698 | es.addfund( quantity ); 699 | }); 700 | } 701 | 702 | void dexchain::delegatebw(account_name fund_account, account_name receiver, asset net, asset cpu) 703 | { 704 | require_auth( fund_account ); 705 | 706 | auto existing = _fundmarket.find( fund_account ); 707 | eosio_assert(existing != _fundmarket.end(), "fund market not existed"); 708 | 709 | const auto& fund = *existing; 710 | eosio_assert(fund.fund_balance.symbol == DEXCHAIN_EOS_SYM, "only xeos can be rent"); 711 | eosio_assert((fund.permission & FUND_PERMISSION_DELEGATE) == 1, "no delegate permission"); 712 | 713 | asset all_amount = net + cpu; 714 | 715 | action( 716 | permission_level{ fund_account, N(active) }, 717 | _self, N(disapprove), 718 | std::make_tuple(fund_account, all_amount, std::string("disapprove fund token")) 719 | ).send(); 720 | 721 | action( 722 | permission_level{ fund_account, N(active) }, 723 | _self, N(transfer), 724 | std::make_tuple(fund_account, DELEGATE_ACCOUNT, all_amount, std::string("transfer token to delegate account to delegate")) 725 | ).send(); 726 | 727 | 728 | fundusages _fundusages( _self, fund_account ); 729 | auto id = _fundusages.available_primary_key(); 730 | _fundusages.emplace( _self, [&]( auto& m ) { 731 | m.id = id; 732 | m.amount = net; 733 | m.amount2 = cpu; 734 | m.fund_account = fund_account; 735 | m.type = FUND_USAGE_TYPE_DELEGATEBW; 736 | m.create_time = now(); 737 | }); 738 | 739 | //Delegatebw to receiver 740 | action( 741 | permission_level{ DELEGATE_ACCOUNT, N(active) }, 742 | SYSTEM_CONTRACT, N(delegatebw), 743 | std::make_tuple(DELEGATE_ACCOUNT, receiver, net, cpu, false) 744 | ).send(); 745 | 746 | 747 | //TODO:add delay action to undelegate cpu after one day 748 | 749 | 750 | _fundmarket.modify( existing, 0, [&]( auto& es ) { 751 | es.used_balance.amount += all_amount.amount; 752 | }); 753 | } 754 | 755 | void dexchain::updateusage( account_name fund_account ) { 756 | ///TODO:遍历fund_usages table,找出到期的delegate 757 | } 758 | 759 | //TODO: 760 | void dexchain::voteproducer( account_name fund_account, const account_name voter, const account_name proxy, const std::vector& producers ) { 761 | 762 | } 763 | 764 | //TODO: 765 | void dexchain::withdrawfund( account_name fund_account, const account_name voter, const account_name proxy, const std::vector& producers ) { 766 | 767 | } 768 | 769 | }/// namespace dex 770 | 771 | EOSIO_ABI( dex::dexchain, (create)(createbystake)(issue)(transfer)(approve)(disapprove)(stake)(unstake)(createdex)(closedex)(buytoken)(selltoken)(createfund)(buyfund)(sellfund)(addfund) 772 | ) 773 | -------------------------------------------------------------------------------- /dexchain/dexchain.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in ../LICENSE 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include "exchange_state.hpp" 13 | 14 | namespace dex { 15 | using namespace eosio; 16 | using std::string; 17 | using eosio::asset; 18 | using eosio::symbol_type; 19 | 20 | class dexchain : public contract { 21 | public: 22 | dexchain( account_name self ); 23 | 24 | void create( account_name issuer, 25 | asset maximum_supply); 26 | 27 | void issue( account_name to, asset quantity, string memo ); 28 | 29 | void transfer( account_name from, 30 | account_name to, 31 | asset quantity, 32 | string memo ); 33 | 34 | void approve( account_name account, 35 | asset quantity, 36 | string memo ); 37 | 38 | void disapprove( account_name account, 39 | asset quantity, 40 | string memo ); 41 | 42 | void burn( account_name owner, asset quantity, string memo ); 43 | 44 | void createbystake( 45 | asset maximum_supply, 46 | asset stake, 47 | account_name stake_contract); 48 | 49 | void stake( 50 | account_name player, 51 | account_name receiver, 52 | symbol_type token_symbol, 53 | asset stake, 54 | account_name stakecontract, 55 | string memo ); 56 | 57 | void unstake( 58 | account_name player, 59 | account_name receiver, 60 | asset quantity, 61 | symbol_type stake_symbol, 62 | account_name stakecontract, 63 | string memo ); 64 | 65 | inline asset get_supply( symbol_name sym )const; 66 | 67 | inline asset get_balance( account_name owner, symbol_name sym )const; 68 | 69 | inline asset get_balance2( account_name owner, symbol_name sym )const; 70 | 71 | 72 | // dex functions 73 | void createdex(account_name creator, account_name dex_account, asset base, asset quote, uint32_t fee_amount); 74 | void buytoken(account_name owner, account_name receiver, account_name dex_account, asset quat); 75 | void selltoken(account_name owner, account_name receiver, account_name dex_account, asset quant); 76 | void closedex(account_name dex_account); 77 | 78 | //TODO 79 | void claim(account_name account); 80 | void refund(account_name dex_account); 81 | void resetDex(account_name dex_account, asset maxBase, asset maxQuote); 82 | 83 | // fund functions 84 | void createfund(account_name creator, account_name fund_account, symbol_name base, symbol_name fund, uint8_t permission); 85 | void buyfund(account_name payer, account_name receiver, account_name fund_account, asset quantity); 86 | void sellfund(account_name account, account_name fund_account, asset quantity); 87 | void addfund(account_name account, account_name fund_account, asset quantity); 88 | void rentcpu(account_name account, account_name fund_account, asset quantity); 89 | //使用基金的资金(XEOS/EOS)为账号抵押资源,该类型基金为保本型基金 90 | void delegatebw(account_name fund_account, account_name receiver, asset net, asset cpu); 91 | 92 | //TODO: 93 | //使用基金的资金(XEOS/EOS)投票,该类型基金为保本型基金 94 | void voteproducer( account_name fund_account, const account_name voter, const account_name proxy, const std::vector& producers ); 95 | //提取基金的资金(XEOS/EOS)投资,该类型基金为高风险型基金 96 | void withdrawfund( account_name fund_account, const account_name voter, const account_name proxy, const std::vector& producers ); 97 | 98 | private: 99 | struct account { 100 | asset balance; 101 | 102 | uint64_t primary_key()const { return balance.symbol.name(); } 103 | }; 104 | 105 | struct currency_stats { 106 | asset supply; 107 | asset max_supply; 108 | account_name issuer; 109 | 110 | //Optional 111 | symbol_type stake_symbol; 112 | account_name stake_contract; 113 | 114 | uint64_t primary_key()const { return supply.symbol.name(); } 115 | }; 116 | 117 | struct fund_usage { 118 | uint64_t id; 119 | account_name fund_account; 120 | 121 | asset amount; 122 | asset amount2; 123 | uint8_t type; 124 | time create_time; 125 | uint64_t primary_key()const { return id; } 126 | }; 127 | 128 | typedef eosio::multi_index accounts; 129 | typedef eosio::multi_index approves; 130 | typedef eosio::multi_index fundusages; 131 | typedef eosio::multi_index stats; 132 | dexmarkets _dexmarket; 133 | fundmarkets _fundmarket; 134 | 135 | 136 | void sub_balance( account_name owner, asset value ); 137 | void add_balance( account_name owner, asset value, account_name ram_payer ); 138 | 139 | void sub_balance2( account_name owner, asset value ); 140 | void add_balance2( account_name owner, asset value, account_name ram_payer ); 141 | 142 | void assertAsset( asset quantity ); 143 | void updateusage( account_name fund_account ); 144 | 145 | public: 146 | struct transfer_args { 147 | account_name from; 148 | account_name to; 149 | asset quantity; 150 | string memo; 151 | }; 152 | }; 153 | 154 | asset dexchain::get_supply( symbol_name sym )const 155 | { 156 | stats statstable( _self, sym ); 157 | const auto& st = statstable.get( sym ); 158 | return st.supply; 159 | } 160 | 161 | asset dexchain::get_balance( account_name owner, symbol_name sym )const 162 | { 163 | accounts accountstable( _self, owner ); 164 | const auto& ac = accountstable.get( sym ); 165 | return ac.balance; 166 | } 167 | 168 | asset dexchain::get_balance2( account_name owner, symbol_name sym )const 169 | { 170 | approves accountstable( _self, owner ); 171 | const auto& ac = accountstable.get( sym ); 172 | return ac.balance; 173 | } 174 | 175 | } /// namespace dex 176 | -------------------------------------------------------------------------------- /dexchain/exchange_state.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in ../LICENSE 4 | */ 5 | 6 | #include 7 | #include "exchange_state.hpp" 8 | 9 | namespace dex { 10 | asset dex_state::convert_to_dex( connector& c, asset in ) { 11 | 12 | real_type R(supply.amount); 13 | real_type C(c.balance.amount+in.amount); 14 | real_type F(c.weight/1000.0); 15 | real_type T(in.amount); 16 | real_type ONE(1.0); 17 | 18 | real_type E = -R * (ONE - std::pow( ONE + T / C, F) ); 19 | //print( "E: ", E, "\n"); 20 | int64_t issued = int64_t(E); 21 | 22 | supply.amount += issued; 23 | c.balance.amount += in.amount; 24 | 25 | return asset( issued, supply.symbol ); 26 | } 27 | 28 | asset dex_state::convert_from_dex( connector& c, asset in ) { 29 | eosio_assert( in.symbol== supply.symbol, "unexpected asset symbol input" ); 30 | 31 | real_type R(supply.amount - in.amount); 32 | real_type C(c.balance.amount); 33 | real_type F(1000.0/c.weight); 34 | real_type E(in.amount); 35 | real_type ONE(1.0); 36 | 37 | 38 | // potentially more accurate: 39 | // The functions std::expm1 and std::log1p are useful for financial calculations, for example, 40 | // when calculating small daily interest rates: (1+x)n 41 | // -1 can be expressed as std::expm1(n * std::log1p(x)). 42 | // real_type T = C * std::expm1( F * std::log1p(E/R) ); 43 | 44 | real_type T = C * (std::pow( ONE + E/R, F) - ONE); 45 | //print( "T: ", T, "\n"); 46 | int64_t out = int64_t(T); 47 | 48 | supply.amount -= in.amount; 49 | c.balance.amount -= out; 50 | 51 | return asset( out, c.balance.symbol ); 52 | } 53 | 54 | asset dex_state::convert( asset from, symbol_type to ) { 55 | auto sell_symbol = from.symbol; 56 | auto ex_symbol = supply.symbol; 57 | auto base_symbol = base.balance.symbol; 58 | auto quote_symbol = quote.balance.symbol; 59 | 60 | //print( "From: ", from, " TO ", asset( 0,to), "\n" ); 61 | //print( "base: ", base_symbol, "\n" ); 62 | //print( "quote: ", quote_symbol, "\n" ); 63 | //print( "ex: ", supply.symbol, "\n" ); 64 | 65 | if( sell_symbol != ex_symbol ) { 66 | if( sell_symbol == base_symbol ) { 67 | from = convert_to_dex( base, from ); 68 | } else if( sell_symbol == quote_symbol ) { 69 | from = convert_to_dex( quote, from ); 70 | } else { 71 | eosio_assert( false, "invalid sell" ); 72 | } 73 | } else { 74 | if( to == base_symbol ) { 75 | from = convert_from_dex( base, from ); 76 | } else if( to == quote_symbol ) { 77 | from = convert_from_dex( quote, from ); 78 | } else { 79 | eosio_assert( false, "invalid conversion" ); 80 | } 81 | } 82 | 83 | if( to != from.symbol ) 84 | return convert( from, to ); 85 | 86 | return from; 87 | } 88 | 89 | asset fund_state::buy(asset quantity) { 90 | asset out_asset( 0, base_balance.symbol); 91 | 92 | const auto S0 = fund_balance.amount; 93 | const auto S1 = S0 + quantity.amount; 94 | const auto R0 = base_balance.amount; 95 | 96 | const auto R1 = (uint128_t(S1) * R0) / S0; 97 | 98 | fund_balance.amount = S1; 99 | base_balance.amount = R0; 100 | out_asset.amount = R1 - R0; 101 | return out_asset; 102 | } 103 | 104 | asset fund_state::sell(asset quantity) { 105 | asset out_asset( 0, fund_balance.symbol); 106 | 107 | const auto S0 = fund_balance.amount; 108 | const auto R0 = base_balance.amount; 109 | const auto R1 = R0 - quantity.amount; 110 | const auto S1 = (uint128_t(R1) * S0) / R0; 111 | 112 | fund_balance.amount = S1; 113 | base_balance.amount = R0; 114 | out_asset.amount = R1 - R0; 115 | return out_asset; 116 | } 117 | 118 | void fund_state::addfund(asset quantity) { 119 | fund_balance.amount += quantity.amount; 120 | } 121 | 122 | } /// namespace dex 123 | -------------------------------------------------------------------------------- /dexchain/exchange_state.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @file 3 | * @copyright defined in ../LICENSE 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | 11 | namespace dex { 12 | using namespace eosio; 13 | using eosio::asset; 14 | using eosio::symbol_type; 15 | typedef double real_type; 16 | 17 | 18 | /** 19 | * Uses Bancor math to create a 50/50 relay between two asset types. The state of the 20 | * bancor exchange is entirely contained within this struct. There are no external 21 | * side effects associated with using this API. 22 | */ 23 | struct dex_state { 24 | asset supply; 25 | 26 | struct connector { 27 | asset balance; 28 | double weight = .5; 29 | 30 | EOSLIB_SERIALIZE( connector, (balance)(weight) ) 31 | }; 32 | 33 | connector base; 34 | connector quote; 35 | account_name dex_account; 36 | uint32_t fee_rate; 37 | 38 | uint64_t primary_key()const { return dex_account; } 39 | uint64_t by_base()const {return base.balance.symbol;} 40 | uint64_t by_quote()const {return quote.balance.symbol;} 41 | 42 | asset convert_to_dex( connector& c, asset in ); 43 | asset convert_from_dex( connector& c, asset in ); 44 | asset convert( asset from, symbol_type to ); 45 | 46 | EOSLIB_SERIALIZE( dex_state, (supply)(base)(quote)(dex_account)(fee_rate) ) 47 | }; 48 | 49 | struct fund_state { 50 | asset base_balance; 51 | asset fund_balance; 52 | 53 | asset used_balance; 54 | 55 | account_name fund_account; 56 | uint8_t permission; 57 | 58 | uint64_t primary_key()const { return fund_account; } 59 | 60 | asset buy(asset quantity); 61 | asset sell(asset quantity); 62 | void addfund(asset quantity); 63 | 64 | EOSLIB_SERIALIZE( fund_state, (base_balance)(fund_balance)(used_balance)(fund_account)(permission) ) 65 | }; 66 | 67 | typedef eosio::multi_index >, 69 | indexed_by< N(quote), const_mem_fun > 70 | > dexmarkets; 71 | 72 | typedef eosio::multi_index fundmarkets; 74 | 75 | } /// namespace dex 76 | -------------------------------------------------------------------------------- /tools/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | LOCAL=true 3 | if [ $LOCAL = true ];then 4 | ROOT_ACCOUNT="eosio" 5 | CLEOS="cleos -u http://127.0.0.1:8888" 6 | else 7 | ROOT_ACCOUNT="itleakstoken" 8 | CLEOS="cleos -u xxxxx" 9 | echo "no local" 10 | fi 11 | 12 | echoCmd() { 13 | echo -e "\033[31;46m"$1"\033[0m" 14 | } 15 | 16 | WORK_DIR="$( dirname "$0" )" 17 | cd $WORK_DIR 18 | echo $WORK_DIR 19 | 20 | EOSIO_PRIVATE_KEY=5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3 21 | EOSIO_PUBLIC_KEY=EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV 22 | 23 | #Replace below keys to your keys 24 | KEY_PRIVATE_2=5JsYXh93SPC4qTJRiK6xxxxxxxxxxxxxxx 25 | KEY_PUB_2=EOS5zv6z6r1fmh5Arzzh71iWkxxxxxxxxxxxxxx 26 | 27 | $CLEOS wallet create -n test 28 | echo "import keys...." 29 | $CLEOS wallet import -n test $EOSIO_PRIVATE_KEY 30 | $CLEOS wallet import -n test $KEY_PRIVATE_2 31 | sleep 2 32 | 33 | echo "Some operation may throw some errors" 34 | 35 | if [ $LOCAL = true ];then 36 | $CLEOS create account $ROOT_ACCOUNT dexchaincode $KEY_PUB_2 37 | $CLEOS create account $ROOT_ACCOUNT eosfavoreeth $KEY_PUB_2 38 | $CLEOS create account $ROOT_ACCOUNT useruseridx1 $KEY_PUB_2 39 | $CLEOS create account $ROOT_ACCOUNT useruseridx2 $KEY_PUB_2 40 | $CLEOS create account $ROOT_ACCOUNT useruseridx3 $KEY_PUB_2 41 | $CLEOS create account $ROOT_ACCOUNT useruseridx4 $KEY_PUB_2 42 | $CLEOS create account $ROOT_ACCOUNT useruseridx5 $KEY_PUB_2 43 | $CLEOS create account $ROOT_ACCOUNT onefamousdex $KEY_PUB_2 44 | else 45 | echo "no local" 46 | fi 47 | 48 | echoCmd '$CLEOS set contract dexchaincode ../dexchain/ -p dexchaincode' 49 | $CLEOS set contract dexchaincode ../dexchain/ -p dexchaincode 50 | 51 | #dexchaincode as stake account, need authorize eosio.code permission to contract dexchaincode 52 | $CLEOS set account permission dexchaincode active '{"threshold": 1,"keys": [{"key":"'$KEY_PUB_2'","weight":1}],"accounts": [{"permission":{"actor":"dexchaincode","permission":"eosio.code"},"weight":1}]}' owner -p dexchaincode@owner 53 | 54 | $CLEOS set contract eosfavoreeth ../dexchain/ -p eosfavoreeth 55 | 56 | $CLEOS push action eosfavoreeth create '["useruseridx1", "100000000.0000 EETH"]' -p useruseridx1 57 | $CLEOS get table eosfavoreeth EETH stat 58 | $CLEOS push action eosfavoreeth issue '["useruseridx2", "10000.0000 EETH"]' -p useruseridx1 59 | $CLEOS get currency balance eosfavoreeth useruseridx2 60 | 61 | 62 | $CLEOS push action dexchaincode stake2create '["1000000.0000 XEETH", "0.0000 EETH", "eosfavoreeth", "create new token XEETH by stake EETH"]' -p eosfavoreeth 63 | $CLEOS get table dexchaincode XEETH stat 64 | 65 | $CLEOS set account permission useruseridx2 active '{"threshold": 1,"keys": [{"key":"'$KEY_PUB_2'","weight":1}],"accounts": [{"permission":{"actor":"dexchaincode","permission":"eosio.code"},"weight":1}]}' owner -p useruseridx2@owner 66 | 67 | sleep 3 68 | echoCmd "Stake EETH to get XEETH" 69 | $CLEOS push action dexchaincode stake '["useruseridx2", "useruseridx3", "4,XEETH", "8000.1000 EETH", "eosfavoreeth", "stake EETH to get XEETH"]' -p useruseridx2 70 | exit 71 | 72 | #get useruseridx2 account balance of EETH 73 | echoCmd "$CLEOS get currency balance eosfavoreeth useruseridx2" 74 | $CLEOS get currency balance eosfavoreeth useruseridx2 75 | 76 | #get stake account balance of EETH 77 | echoCmd "$CLEOS get currency balance eosfavoreeth dexchaincode" 78 | $CLEOS get currency balance eosfavoreeth dexchaincode 79 | #get useruseridx3 account balance of XEETH 80 | echoCmd "$CLEOS get currency balance dexchaincode useruseridx3" 81 | $CLEOS get currency balance dexchaincode useruseridx3 82 | echoCmd "$CLEOS get table dexchaincode XEETH stat" 83 | $CLEOS get table dexchaincode XEETH stat 84 | 85 | echoCmd "Unstake XEETH to get EETH" 86 | $CLEOS push action dexchaincode unstake '["useruseridx3", "useruseridx2", "1.1000 XEETH", "4,EETH", "eosfavoreeth", "unstake XEETH to get EETH"]' -p useruseridx3 87 | $CLEOS get currency balance eosfavoreeth useruseridx2 88 | 89 | #get useruseridx2 account balance of EETH 90 | echoCmd "$CLEOS get currency balance eosfavoreeth useruseridx2" 91 | $CLEOS get currency balance eosfavoreeth useruseridx2 92 | #get stake account balance of EETH 93 | echoCmd "$CLEOS get currency balance eosfavoreeth dexchaincode" 94 | $CLEOS get currency balance eosfavoreeth dexchaincode 95 | #get useruseridx3 account balance of XEETH 96 | echoCmd "$CLEOS get currency balance dexchaincode useruseridx3" 97 | $CLEOS get currency balance dexchaincode useruseridx3 98 | echoCmd "$CLEOS get table dexchaincode XEETH stat" 99 | $CLEOS get table dexchaincode XEETH stat 100 | 101 | $CLEOS push action dexchaincode create '["useruseridx4", "1000000.0000 XTEST"]' -p useruseridx4 102 | echoCmd "$CLEOS get table dexchaincode XTEST stat" 103 | $CLEOS get table dexchaincode XTEST stat 104 | echoCmd "$CLEOS push action dexchaincode issue '["useruseridx3", "5000.1000 XTEST"]' -p useruseridx4" 105 | $CLEOS push action dexchaincode issue '["useruseridx3", "5000.1000 XTEST"]' -p useruseridx4 106 | echoCmd "$CLEOS get currency balance dexchaincode useruseridx3" 107 | $CLEOS get currency balance dexchaincode useruseridx3 108 | 109 | $CLEOS push action dexchaincode createdex '["useruseridx3", "onefamousdex", "1000.0000 XTEST", "10.0000 XEETH", 200]' -p useruseridx3 110 | echoCmd "$CLEOS get table dexchaincode onefamousdex approves" 111 | $CLEOS get table dexchaincode onefamousdex approves 112 | $CLEOS set account permission onefamousdex active '{"threshold": 1,"keys": [{"key":"'$KEY_PUB_2'","weight":1}],"accounts": [{"permission":{"actor":"dexchaincode","permission":"eosio.code"},"weight":1}]}' owner -p onefamousdex 113 | echoCmd "$CLEOS get currency balance dexchaincode useruseridx3" 114 | $CLEOS get currency balance dexchaincode useruseridx3 115 | echoCmd "$CLEOS get currency balance dexchaincode ondex" 116 | $CLEOS get currency balance dexchaincode onefamousdex 117 | sleep 1 118 | echoCmd "$CLEOS get table dexchaincode dexchaincode dexmarkets" 119 | $CLEOS get table dexchaincode dexchaincode dexmarkets 120 | 121 | $CLEOS push action dexchaincode buytoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XEETH"]' -p useruseridx3 122 | 123 | $CLEOS get currency balance dexchaincode useruseridx5 124 | sleep 1 125 | $CLEOS push action dexchaincode buytoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XEETH"]' -p useruseridx3 126 | $CLEOS push action dexchaincode selltoken '["useruseridx3", "useruseridx5", "onefamousdex", "0.1000 XTEST"]' -p useruseridx3 127 | 128 | echoCmd "$CLEOS get currency balance dexchaincode useruseridx5" 129 | $CLEOS get currency balance dexchaincode useruseridx5 130 | echoCmd "$CLEOS get currency balance dexchaincode useruseridx3" 131 | $CLEOS get currency balance dexchaincode useruseridx3 132 | echoCmd "$CLEOS get currency balance dexchaincode ondex" 133 | $CLEOS get currency balance dexchaincode onefamousdex 134 | sleep 1 135 | echoCmd "$CLEOS get table dexchaincode dexchaincode dexmarkets" 136 | $CLEOS get table dexchaincode dexchaincode dexmarkets 137 | echoCmd "$CLEOS push action dexchaincode closedex '[\"onefamousdex\"]' -p onefamousdex" 138 | $CLEOS push action dexchaincode closedex '["onefamousdex"]' -p onefamousdex 139 | echoCmd "$CLEOS get currency balance dexchaincode onefamousdex" 140 | $CLEOS get currency balance dexchaincode onefamousdex 141 | echoCmd "$CLEOS get table dexchaincode dexchaincode dexmarkets" 142 | $CLEOS get table dexchaincode dexchaincode dexmarkets 143 | echoCmd "$CLEOS get table dexchaincode XEOS stat" 144 | $CLEOS get table dexchaincode XEOS stat 145 | #$CLEOS push action dexchaincode buytoken '["onefamousdex", "useruseridx3", "useruseridx5", "2.0000 XEETH"]' -p useruseridx3 146 | #$CLEOS get currency balance dexchaincode useruseridx5 147 | --------------------------------------------------------------------------------