-
Notifications
You must be signed in to change notification settings - Fork 5
Home
Raidex tries to bring decentralised ERC20-token exchanges off the chain and implement a more fast and scalable solution with the help of Raidens payment channel technology, without sacrificing too much of the trustlessness that on-chain exchanges offer. The current concept (internally refered to as "Raidex 1.0") still involves some centralisation and trust, that arises from the idea how we solve the problem of the a so called "free option".
Raiden has the possibility to swap tokens of different token networks, without any trust issues involved. The swap uses hash-locks, to guarantee that each participant of the swap can only claim the other's funds when he himself complies to the swap and engages in the agreed on transfer. This makes the Token Swap atomic, but it still involves someone to engage in the swap initially, and the other party to successively comply to the swap or stall the swap by simply not reacting. A not complying participant can therefore only be sensed by unresponsiveness, which has to be defined by an arbitrarily chosen timeout by the other party.
"As the initiator, you only can wait for a successful swap-response, or stop waiting at some point" As always, when timeouts are involved like this, it is hard to separate non-compliancy from latency. In our proposal, it is therefore assumed that latency is relatively small compared to timeouts, and responding to steps in the swap and offer process should be nearly immediate.
For the token swap, maker and taker have to agree on the condictions before initiating the actual swap. This can be done over an arbitrary communication channel: The maker creates and broadcasts some message representing it's conditions for the token-swap (asset-pair, price, etc) - and waits for some taker to send back a confirmation-message. Compliance to a token-swap can not be enforced, so a maker has to trust a takers promise to really engage in the token swap in the end. On-chain, this can be easily solved by bilateral deposits and the trustless business logic of a smart contract. This business logic may be even enforceable in generalised state channels, but since we focus on the existing payment-channel network of Raiden, there is a enforceability problem here.
We want to avoid the existing concept of exchanges, where the exchange acts as the centralised middleman, who not only holds the funds of all traders, but also has total and non-transparent control over the match-making of orders. We therefore need to distribute single exchange-offers over a message-broadcast network, where every participant listens to offers of interest and builds it's own offer-book. There is no party that connects makers of offers with takers of offers, so therefore takers will have to compete in a race for taking a specific, broadcasted offer of a maker. They will have to contact the maker, promise him to engage in a token swap, and then eventually engage in the swap once the maker initiated it.
Note: the order of initiation of the swap is reversed in the implementation, but the problems stay the same. Maker being the initiator and Taker the successor is easier to explain
One can see the problem here: bad actors can very easily stall someone, by only promising to engage in a swap, but not being earnest with it. They could do that for several reasons:
- completely DOS-ing some specific actor,
- harming the network in general
- preemptively taking a lot of offers and deciding later which to actually take
The last one is where the "free option" terminology comes from and this is probably the most significant attack. The possibility of that alone can render the whole exchange unusable, since there are only a few bad actors neccessary to stall the whole network. Nobody wants to trade on an fragile exchange with so much trust involved.
In order to circumvent or at least mitigate the free option, we need to introduce a trusted entity that enforces some penalty when promised swaps will not be executed.
Maker and Taker deposit some collateral (commitment
) at this trusted entity, the so called (commitment service
).
The commitment service will only refund the collateral, once both parties report a successful execution of the swap. Once one of the parties is unresponsive to the commitment service, the funds will be kept by the commitment service.
To incentivise the commitment service also in the happy case of a successful swap, it can deduct a small fee of the commitment.
The collateral is "deposited" as a normal Raiden transfer (direct transfer of a single payment channel in this case). Once the swap was reported successful by both parties, the refunding Raiden transfers will be sent back by the commitment service.
That way, actors of the exchange trust the commitment service with funds amounting to the currently open commitments.
They also have to trust the commitment service with compliance to the business logic of evaluating the transfers, determining the rightful taker and processing the successful swap messages.
- The
Maker
creates an Offer:O
with a chosen IdentifierID
- The
Maker
sends a signed "Maker Commitment" messageMC
toCS
, saying it is committed up to certain timestampT
to the offerO
with arbitrary amountcommitment amount
. - The
Maker
sendscommitment amount
to theCS
in a Raiden transfer. -
CS
confirms a successful commitment by signing a commitment proof messageCP = Signed([Signature(MC)], CS)
. -
Maker
broadcast a proven offerPO = Signed([O, MC, CP], Maker)
over some communication channel to interested takers. - A
Taker
sends a signed "Taker Commitment" messageTC
toCS
, mirroring theMC
's arguments. -
- The
Taker
sends araiden-transfer(identifier=ID)
to theCS
with thecommitment amount
. - The first taker to deliver 6) and 7a) to the
CS
will get declared the actualTaker
ofO
by theCS
- The
-
CS
confirms the commitment to Taker by creating, signing and sendingCP
(analogous to step 4) to Taker. 8a) For every actor carrying out step 6+7: if the offer timed out or was already taken,CS
responds by sending back the commitment in a Raidentransfer(amount=commitment_amount, identifier=ID))
(from a backlog-queue, so maybe not immediately) - here the CS doesn't subtract a fee (in our implementation) -
CS
broadcasts a Offer Taken messageOT = Signed([ID], CS)
to all actors in order to stop unsuccessful Taker tries. - Taker creates a Proven Commitment message
PC = Signed([TC, CP], Taker)
- Taker contacts Maker proofing commitment by showing
PC
. Maker and Taker eventually swap the tokens. - Maker and Taker can create and send Swap Execution messages
SWE = Signed([ID, execution_timestamp], Maker/Taker)
to theCS
, whenever they are happy with the swap (the swap was successful)
-
a) Taker and Maker notify of successful execution of the swap before the timeout
T
:-
CS
refunds the commitments through Raiden transfers (minus some fee) to each of the parties -
CS
sends a signed Swap Completed messageSWC= Signed([ID, completion_timestamp], CS)
indicating that the deal completed to the broadcast channel (this is used by the clients to learn which of the orders was executed, so they can deduct last prices).
-
-
b) Only one or none of the parties report execution of the swap before the timeout
T
-
CS
keeps the commitments of both parties.
-
Notes:
- 1:
O = [bid_token, bid_amount, ask_token, ask_amount, offer_id, timeout]
- 12b there is no trust-less Proof of Swap mechanism available; someone can decide to not send the
SWE
, although the swap went through. The other party cannot do anything about the fact, that both parties lose the commitment.
The nature of the offers and the token swap is that you only can specify discrete amounts of tokens you want to swap. The price is calculated implicitly from the token amount ratios. Since the swap is atomic, it is not possible as a taker to try to split an offer or just take a fractional portion of it. The matchmaking is not handled by a centralised entity, so there is no easy way to handle classical order types like limit orders, stop-loss-take-profit etc. etc. The only building block we have available for emulating this kind of behaviour is the how we create and take multiple of those atomic offers.
Offer
is defined here as an offer to engage in a swap with discrete, unalterable conditions - it is atomic
Disclaimer: This algorithm is a naive implementation. It will not find a global maximum and is to some extend only a brute force search of all the available offers that match a specific amount/price. Also, our implementation has some undefined behaviour, that probably stems from a race condition (not tested/solved yet)
Rundown of how a limit order will be emulated on Raidex:
Preconditions/Arguments:
- Arguments:
type
,amount
,price
-
type
: SELL/BUY - defines if a fixed asset pair should be bought or sold -
amount
: the (maximum) amount to sell/buy until the order is finished -
price
:- when
type
is SELL: minimum price at which to sell the tokens - when
type
is BUY: maximum price at which to buy the tokens
- when
The algorithm will do:
- act as a taker: look in the offer book for the best matching offers available
- if offers available with specified price (or better) or less then specified amount, fill the total amount with multiple of those offers
- if no more offers available - act as maker: spawn multiple, small-amount offers with the defined price and wait for takers
Note that offers have a timeout/time-to-live. Once the algorithm the algorithm decides to commit to some offer (as maker or taker), we have to consider this offer as incomplete. We are waiting on it to eventually be successful and we cannot cancel the offer during it's lifetime.
Apart from that, the "high level" limit order can be cancelled anytime. When cancelled, every offer that has been committed to still has to be waited on. Therefore, cancelling simply means that no more additional offers will be taken or spawned. It is therefore possible, that a limit order will not get filled 100%, either because we simply don't find matching offers or takers for our offers, or because we decide to cancel the order at some point before completion.
Limit orders are not atomic - they are just an algorithmic scheme to reach a specific price/amount goal. Limit orders like this can take a lot of time to be nearly filled - the market price can have moved significantly in this time. Note huge differences to classical limit orders.