We have been working on various scaling solutions for batch auctions. To test the concept of batch auctions we want to start with a minimal viable product with that purely allows multi-token batch auctions. As a recap: a batch auction is different from a “normal order book exchange” aka “continuous double auction” in that orders are not executed continuously but only periodically (in batches) at a single clearing price per batch. In a multi-token batch auctions trades between n tokens can happen and it is possible to settle “ring-trades” (A->B, B->C and C-A) atomically.
Here is a rough specification:
Batches
1) Batches run for 5 minutes. The timestep of a block defines implicitly the current batch number
2) During the current batch (n), the previous batch (n-1) can be solved. The n-1 is finalized once n+1 started.
Deposit and Withdrawl
2) Any user can deposit tokens any time. A deposit needs to only increase the balance for the current batch and not for the previous one that is currently in "solution submission period". This is implemented with a "pending amount" that is only valid from block "current". If there is a write access to balance in a batch n+1 "pending amount" is summed into the regular balance.
3) A withdrawal can be requested anytime. An amount and a "withdrawal batch" needs to be specified. Withdrawal batch number needs to be >= current. If the amount is accessed any time at or after "withdrawal batch" the withdrawal amount is deducted from the amount.
3a) A withdrawal request can be directly canceled/ reduced as long it is in the future or current block. Otherwise, it needs to create a new deposit (amount still pending)
4) A withdrawal settlement can be made if n is > "withdrawal batch" (this can be done by any account)
Orders
5) Users can submit orders any time and specify from when till when they are valid. (can not be from previous batches)
6) Orders can be canceled by setting valid till to "n-1"
Solution Submission
7) A solution can be submitted any time for batch n-1
8) A solution can first change prices of tokens and after that settle trades at those prices.
9) If a solution is already submitted the previous solution will be rolled back if the new solution generates higher trade volume == overall fees
Executing a solution:
10) potentially rollback of the previous solution
11) set all prices of tokens touched denominated in the reference/fee token
For each order
12) check that prices (after fees) are honored. Execute order at clearing prices - fee
13) check that never a token is used that was not in the list of tokens that got a new price
13b) check that every token that was used also got a new price
14) update balances, reduce "volume left" of orders, store those deltas to enable rollback
15) track for each token the total "delta" (sum of sold and bought)
After order execution
16) Check that after all trades are executed deltas for all tokens = 0 and for fee token = claimed total fee
17) credit half the fee to solution submitter, burn half
Some implicit consequences of this specification.
a) No “islands”. All settled trades need to have a trading path to the fee token. This is because fees are taken in each token and the only way to create a valid solution is to trade all those surplusses into the fee token. If “island” would be allowed this auction could not serve as a price oracle because prices could be set arbitrarily by the solver.
b) Solution submissions are attackable by frontrunners and most so by miners. To reduce the “miner extractable value” and to create adoption incentives for the GNO community half of the fees are burned.
c) The number of trades that can be touched is implicitly limited by the block gas limit. We expect this number to be around 20-35.
d) Given a 0.1% total fee, a solver would get 0.05% of the fee. Given marginal gas costs of ~150k per trade and assuming a gas price of 10 GWEI this would mean a 0.0015ETH gas costs. To cover this for the solver the trade size needs to be at least 3 ETH.
e) A consequence of d) is that larger trades will be given preference. There might be pooling contracts where different users aggregate common trades (e.g market order to convert DAI to ETH) to create larger orders and increase overall efficiency.
Code here:
https://github.com/gnosis/dex-contracts/blob/master/contracts/StablecoinConverter.sol