Skip to content

Commit

Permalink
init commit for onechain dex
Browse files Browse the repository at this point in the history
  • Loading branch information
threadshare committed Sep 26, 2018
1 parent 85d2fb6 commit 2082399
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 522 deletions.
40 changes: 0 additions & 40 deletions .gitignore

This file was deleted.

8 changes: 8 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
file(GLOB ABI_FILES "*.abi")
configure_file("${ABI_FILES}" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY)

add_wast_executable(TARGET exchange
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}"
LIBRARIES libc libc++ eosiolib
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR}
)
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

4 changes: 0 additions & 4 deletions README.md

This file was deleted.

11 changes: 0 additions & 11 deletions docker-compose.yaml

This file was deleted.

77 changes: 77 additions & 0 deletions exchange.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"____comment": "This file was generated by eosio-abigen. DO NOT EDIT - 2018-09-25T10:15:30",
"version": "eosio::abi/1.0",
"types": [],
"structs": [{
"name": "orders",
"base": "",
"fields": [{
"name": "id",
"type": "uint64"
},{
"name": "price",
"type": "uint64"
},{
"name": "quantity",
"type": "asset"
},{
"name": "maker",
"type": "name"
}
]
},{
"name": "bid",
"base": "",
"fields": [{
"name": "maker",
"type": "name"
},{
"name": "quantity",
"type": "asset"
},{
"name": "price",
"type": "uint64"
}
]
},{
"name": "ask",
"base": "",
"fields": [{
"name": "maker",
"type": "name"
},{
"name": "quantity",
"type": "asset"
},{
"name": "price",
"type": "uint64"
}
]
}
],
"actions": [{
"name": "bid",
"type": "bid",
"ricardian_contract": ""
},{
"name": "ask",
"type": "ask",
"ricardian_contract": ""
}
],
"tables": [{
"name": "orders",
"index_type": "i64",
"key_names": [
"id"
],
"key_types": [
"uint64"
],
"type": "orders"
}
],
"ricardian_clauses": [],
"error_messages": [],
"abi_extensions": []
}
172 changes: 172 additions & 0 deletions exchange.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/**
* simple decentralized exchange
* smart contract on eos
*
*/

#include "exchange.hpp"

using namespace eosio;

void exchange::add_order(uint64_t scope, account_name maker, asset quantity, uint64_t price) {
order_index orders(_self, scope);
print("add order, maker: ", name{maker}, " quantity: ", quantity, " price: ", asset(price, settlement_token_symbol),
"\n");
if (quantity.amount > 0) {
orders.emplace(maker, [&](auto &r) {
r.id = orders.available_primary_key();
r.price = price;
r.quantity = quantity;
r.maker = maker;
});
}
}

void exchange::deposit(account_name contract, account_name user, asset quantity) {
print(name{user}, " deposit ", quantity, "\n");
if (quantity.amount == 0) {
print("amoutn equals to 0 abord\n");
return;
}
action(
permission_level{user, N(active)},
contract, N(transfer),
std::make_tuple(user, _self, quantity, std::string("deposit"))
).send();
}

void exchange::transfer(account_name contract, account_name from, account_name to, asset quantity) {
print(name{from}, " transfer ", quantity, " to ", name{to}, "\n");
action(
permission_level{from, N(active)},
contract, N(transfer),
std::make_tuple(from, to, quantity, std::string("transfer"))
).send();
}

void exchange::withdraw(account_name contract, account_name user, asset quantity) {
print(name{user}, " withdraw ", quantity, "\n");
if (quantity.amount == 0) {
print("amoutn equals to 0 abord\n");
return;
}
action(
permission_level{_self, N(active)},
contract, N(transfer),
std::make_tuple(_self, user, quantity, std::string("withdraw"))
).send();
}

asset exchange::to_settlement_token(asset quantity, uint64_t price, bool floor) {
//this is a simple logic, need to add more rules
uint64_t amt = quantity.amount * price;

int64_t p = (int64_t) quantity.symbol.precision();
int64_t p10 = 1;

while (p > 0) {
p10 *= 10;
--p;
}
// this arithmetician work for eos rule like eos.amount*10000
uint64_t res = amt / p10;

if (!floor && res * p10 != amt)
res++;
return asset(res, settlement_token_symbol);
}

asset exchange::asset_min(asset a, asset b) {
if (a > b) return b;
else return a;
}

//sell
void exchange::ask(account_name maker, asset quantity, uint64_t price) {
//充值其他代币,卖
//deposit(exchange_token_contract, maker, quantity);

//查找所有的买单
order_index bid_orders(_self, N(bid));
//查找所有买价高于price的买方按照价格时间排序
auto bid_orders_by_price = bid_orders.get_index<N(byprice)>();
//买单不存在的表示
auto bid_it = bid_orders_by_price.end();
//获取符合条件的买单的迭代器
auto bid_end = bid_orders_by_price.lower_bound(price);

auto left = quantity;
asset maker_receive(0, settlement_token_symbol);

while (left.amount > 0 && bid_it != bid_end) {
bid_it--;
print("bid order id: ", bid_it->id, " price: ", bid_it->price, "\n");

auto exchange_quantity = asset_min(bid_it->quantity, left);

auto settlement_token_quantity = to_settlement_token(exchange_quantity, price, true);

maker_receive += settlement_token_quantity;
//withdraw(exchange_token_contract, bid_it->maker, exchange_quantity);
transfer(exchange_token_contract, maker, bid_it->maker, exchange_quantity);

left -= exchange_quantity;

if (bid_it->quantity == exchange_quantity) {
bid_it = bid_orders_by_price.erase(bid_it);
} else {
bid_orders_by_price.modify(bid_it, maker, [&](auto &r) {
r.quantity -= exchange_quantity;
});
}
}
deposit(exchange_token_contract, maker, left);
add_order(N(ask), maker, left, price);

withdraw(settlement_token_contract, maker, maker_receive);
}

//buy
void exchange::bid(account_name maker, asset quantity, uint64_t price) {
//充值eos
//deposit(settlement_token_contract, maker, to_settlement_token(quantity, price, false));

//查找对手
order_index ask_orders(_self, N(ask));
//查找所有卖价低于price的卖方按照价格时间排序
auto ask_orders_by_price = ask_orders.get_index<N(byprice)>();
auto ask_it = ask_orders_by_price.begin();
auto ask_end = ask_orders_by_price.upper_bound(price);

auto left = quantity;
asset maker_receive(0, exchange_token_symbol);

while (left.amount > 0 && ask_it != ask_end) {
print("ask order id: ", ask_it->id, " price: ", ask_it->price, "\n");

auto exchange_quantity = asset_min(ask_it->quantity, left);

auto settlement_token_quantity = to_settlement_token(exchange_quantity, ask_it->price, false);

maker_receive += exchange_quantity;
//withdraw(settlement_token_contract, ask_it->maker, settlement_token_quantity);
transfer(settlement_token_contract, maker, ask_it->maker, settlement_token_quantity);

left -= exchange_quantity;

if (ask_it->quantity == exchange_quantity) {
ask_it = ask_orders_by_price.erase(ask_it);
} else {
ask_orders_by_price.modify(ask_it, maker, [&](auto &r) {
r.quantity -= exchange_quantity;
});
ask_it++;
}
}
deposit(settlement_token_contract, maker, to_settlement_token(left, price, false));
add_order(N(bid), maker, left, price);

withdraw(exchange_token_contract, maker, maker_receive);
}

EOSIO_ABI(exchange, (bid)(ask))
7 changes: 5 additions & 2 deletions src/exchange.hpp → exchange.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ class exchange : public contract {
void ask(account_name maker, asset quantity, uint64_t price);

//token contract is not eosio.token it is the op
account_name settlement_token_contract = N(eosio.token);
// account_name settlement_token_contract = N(eosio.token);
account_name settlement_token_contract = N(onedexchange);
symbol_type settlement_token_symbol = S(4, EOS);

account_name exchange_token_contract = N(eosio.token);
account_name exchange_token_contract = N(onedechange);
// account_name exchange_token_contract = N(eosio.token);
symbol_type exchange_token_symbol = S(3, SYS);

private:
Expand Down Expand Up @@ -54,3 +56,4 @@ class exchange : public contract {
asset to_settlement_token(asset quantity, uint64_t price, bool floor);
asset asset_min(asset a, asset b);
};

Loading

0 comments on commit 2082399

Please sign in to comment.