Decentralized exchange built on Ethereum.
This repository contains the source code that runs the exchange on Ethereum as a set of contracts, along with the UI, tests, tools and documentation.
- Serpent compiler by Vitalik Buterin
- cpp-ethereum node by Gavin Wood
- go-ethereum browser by Jeffrey Wilcke
- pyethereum Python Ethereum client (tests only)
- PyEPM for deployment
- node and grunt for UI development
Start by cloning this repository.
git clone https://github.com/etherex/etherex.git
This will install pyethereum
and ethereum-serpent
if you don't already have those installed.
pip install -r dev_requirements.txt
py.test -vvrs
Refer to Serpent and pyethereum for their respective usage.
You will need a working node.js setup (instructions) and globally installed grunt-cli
(instructions).
cd frontend
npm install
grunt
Requires a working cpp-ethereum client with JSONRPC, Serpent and PyEPM
cd contracts
pyepm EtherEx.yaml
- The API is the format of the data field for the Ethereum transactions.
- Subcurrencies need to support the Subcurrency API.
- You only need an Ethereum client to use the API.
Methods (with serpent type definitions):
price:i:i
buy:iii:i
sell:iii:i
trade:ia:i
deposit:iii:i
withdraw:ii:i
cancel:i:i
add_market:iiiii:i
get_market:i:a
get_trade_ids:i:a
get_trade:i:a
get_sub_balance:ii:a
<method> <market_id>
<method> <amount> <price> <market ID>
<method> <max amount> <trade IDs>
Deposit (subcurrency contracts only, see below)
<method> <address> <amount> <market ID>
<method> <amount> <market ID>
<method> <trade ID>
<method> <currency name> <contract address> <decimal precision> <price denominator> <minimum total>
Market names follow the "/ETH" convention. When registering a new market, submit the currency name as a three or four letter uppercase identifier, ex.: "BOB" for BobCoin.
The subcurrency contract address.
The subcurrency's decimal precision as an integer.
- Denominator for price precision, ex. 10000 (10000 => 1 / 10000 => 0.0001)
When adding a subcurrency, set the minimum trade total high enough to make economic sense. A minimum of 10 ETH (1000000000000000000000 wei) is recommended.
1 = ETX/ETH
New market IDs will be created as DAO creators add their subcurrency to the exchange.
Subcurrency contracts need to support the deposit
ABI call.
It is a different approach than the MetaCoin API which will not be used, as the Approve API
is all-or-nothing and gives too much permissions to the exchange. The new procedure is explained below, and the sample ETX contract can be used as an example.
Each subcurrency has to notify the exchange of each asset transfer from a user's address to the exchange's address. The amount of extra code necessary to support this feature is comparable if not smaller than with the other approach.
The first step a subcurrency has to take is to store the exchange's address for future comparison of recipients. This can be done during the initialization of the contract, however, adding an ABI call to update the address and market_id
is highly recommended.
data owner
data exchange
data market_id
def init():
self.owner = msg.sender
...
def set_exchange(addr, market_id):
if msg.sender == self.owner:
self.exchange = addr
self.market_id = market_id
return(1)
return(0)
After registering the subcurrency using the add_market
ABI call, the subcurrency will receive a market_id
. Since there are currently no return values to actual transactions, this market_id
will need to be inspected from the exchange's contract storage or from the UI.
The second step has to be executed on each asset transfer. The gas costs of comparing the recipient to the exchange's address are minimal but a separate ABI call might be used later on, depending on how this approach will play out on the testnet. The relevant part below is the one under Notify exchange of deposit
, the top part being what can be considered standard subcurrency functionality. Notice the extern
definition that will be used for the deposit
method.
extern exchange: [deposit:iii:i]
def send(recipient, amount):
# Get user balance
balance = self.storage[msg.sender]
# Make sure balance is above or equal to amount
if balance >= amount:
# Update balances
self.storage[msg.sender] = balance - amount
self.storage[recipient] += amount
# Notify exchange of deposit
if recipient == self.exchange:
ret = self.exchange.deposit(msg.sender, amount, self.market_id, datasz=3)
# Exchange returns our new balance as confirmation
if ret >= amount:
return(1)
# We return 2 as error code for notification failure
return(2)
return(1)
return(0)
TODO: Solidity examples.
- Your Ethereum address is used as your identity
- Document error codes of return values
- Implement Wallet section (transactions, balances, etc.) (in progress)
- Re-implement NameReg support and integration
- Start the Tools section, find and list ideas
- subcurrency registration (in progress)
- subcurrency creation tools/wizard
- raw transact (?)
- trading tools (...)
- ...
- Use NatSpec
- Look into how Whisper and Swarm could be used and integrated
- Start working on X-Chain
- Update this TODO more frequently
- Start using GitHub issues instead
- Better, rock solid tests, and way more of them
- Total unilateral world takeover
- Graphs, beautiful graphs
- Advanced trading features (stoploss, etc.)
- Animations/transitions
- Check/clear buttons
- Wallet design and theming
- More/new mockups / wireframes
- More/new design elements
- Implement new mockups / design elements
Released under the MIT License, see LICENSE file.