DEX Aggregators

Last modified:

DEX Aggregators

A DEX aggregator is a blockchain-based routing service that monitors prices and available liquidity across multiple decentralized exchanges and determines how a trade should be executed in order to obtain the best possible outcome. In particular, an aggregator may split a single order across several AMMs rather than route the full order to a single pool. This is often advantageous because the price impact of a trade depends on pool depth, so distributing the trade across multiple venues can improve the effective execution price.

To illustrate this mechanism, consider the following simplified problem. Suppose that a trader wants to sell a total amount TT of token XX across two different constant-product pools in order to receive as much token YY as possible. For j{1,2}j \in \{1,2\}, let

xj,  yjx_j,\; y_j

denote the reserves of tokens XX and YY in pool jj, respectively, and let

ϕj[0,1)\phi_j\in[0,1)

be the trading fee of pool jj. Define, for convenience,

λj:=1ϕj.\lambda_j := 1-\phi_j.

Suppose that the trader sends an amount u[0,T]u\in[0,T] of token XX to pool 1 and the remaining amount TuT-u to pool 2. Then, by the fee-adjusted constant-product formula, the amount of token YY received from pool 1 is

Δy1(u)=y1λ1ux1+λ1u,\Delta y_1(u)=\frac{y_1\lambda_1 u}{x_1+\lambda_1 u},

while the amount received from pool 2 is

Δy2(u)=y2λ2(Tu)x2+λ2(Tu).\Delta y_2(u)=\frac{y_2\lambda_2 (T-u)}{x_2+\lambda_2 (T-u)}.

Hence, the total output of token YY is

F(u)=y1λ1ux1+λ1u+y2λ2(Tu)x2+λ2(Tu),u[0,T].F(u)=\frac{y_1\lambda_1 u}{x_1+\lambda_1 u} + \frac{y_2\lambda_2 (T-u)}{x_2+\lambda_2 (T-u)}, \qquad u\in[0,T].

Therefore, the optimal routing problem reduces to maximizing FF over the interval [0,T][0,T].

It is convenient to rewrite FF as

F(u)=y1x1y1x1+λ1u+y2x2y2x2+λ2(Tu).F(u)= y_1-\frac{x_1y_1}{x_1+\lambda_1u} + y_2-\frac{x_2y_2}{x_2+\lambda_2(T-u)}.

Differentiating, we obtain

F(u)=x1y1λ1(x1+λ1u)2x2y2λ2(x2+λ2(Tu))2.F'(u)= \frac{x_1y_1\lambda_1}{(x_1+\lambda_1u)^2} - \frac{x_2y_2\lambda_2}{(x_2+\lambda_2(T-u))^2}.

Since the denominator is always positive on [0,T][0,T], the sign of F(u)F'(u) is the same as the sign of

g(u):=x1y1λ1(x2+λ2(Tu))2x2y2λ2(x1+λ1u)2.g(u) := x_1y_1\lambda_1\bigl(x_2+\lambda_2(T-u)\bigr)^2 - x_2y_2\lambda_2\bigl(x_1+\lambda_1u\bigr)^2.

Thus, to locate the maximizer of FF, it is sufficient to study the zeros and sign changes of the quadratic polynomial gg.

Example 2.8

Consider two CTN/USDC constant-product pools with the following reserves and fees:

Pool 1Pool 2
CTN reserve7,0009,000
USDC reserve24,500,00028,350,000
Fee0.3%0.3%

Suppose that a trader wants to sell a total amount

T=1500T=1500

of CTN across the two pools in order to maximize the amount of USDC received.

Since both pools charge the same fee, we have

λ1=λ2=0.997.\lambda_1=\lambda_2=0.997.

Therefore, the objective function is

F(u)=24,500,0000.997u7000+0.997u+28,350,0000.997(1500u)9000+0.997(1500u),u[0,1500].F(u)= \frac{24{,}500{,}000\cdot 0.997\,u}{7000+0.997\,u} + \frac{28{,}350{,}000\cdot 0.997\,(1500-u)}{9000+0.997\,(1500-u)}, \qquad u\in[0,1500].

Its derivative has the same sign as

g(u)=700024,500,0000.997(9000+0.997(1500u))2900028,350,0000.997(7000+0.997u)2.g(u)= 7000\cdot 24{,}500{,}000\cdot 0.997\bigl(9000+0.997(1500-u)\bigr)^2 - 9000\cdot 28{,}350{,}000\cdot 0.997\bigl(7000+0.997u\bigr)^2.

Expanding this expression, we obtain

g(u)=83,148,852,850u2+7,150,540,330,500,000u+6,389,321,722,875,000,000.g(u)= -83{,}148{,}852{,}850\,u^2 + 7{,}150{,}540{,}330{,}500{,}000\,u + 6{,}389{,}321{,}722{,}875{,}000{,}000.

Applying the quadratic formula, the roots of gg are

u186881.3085,u2884.4477.u_1 \approx -86881.3085, \qquad u_2 \approx 884.4477.

Since the leading coefficient of gg is negative, it follows that g(u)g(u) is positive on the interval (u1,u2)(u_1,u_2) and negative on (,u1)(u2,)(-\infty,u_1)\cup(u_2,\infty). Because u2[0,1500]u_2\in[0,1500], we conclude that FF is strictly increasing on [0,u2][0,u_2] and strictly decreasing on [u2,1500][u_2,1500]. Hence, the unique maximizer on [0,1500][0,1500] is

u884.4477.u^\star \approx 884.4477.

Therefore, the optimal routing is:

  • send
884.4477 CTN884.4477 \text{ CTN}

to pool 1,

  • send
1500884.4477=615.5523 CTN1500-884.4477 = 615.5523 \text{ CTN}

to pool 2.

The corresponding outputs are

Δy1(u)2,740,995.2719 USDC,\Delta y_1(u^\star)\approx 2{,}740{,}995.2719 \text{ USDC},

and

Δy2(u)1,809,765.8129 USDC.\Delta y_2(u^\star)\approx 1{,}809{,}765.8129 \text{ USDC}.

Thus, the maximum total output is

F(u)4,550,761.0848 USDC.F(u^\star)\approx 4{,}550{,}761.0848 \text{ USDC}.

For comparison, if the entire trade were executed only in pool 1, the trader would receive

F(1500)4,312,842.0929 USDC,F(1500)\approx 4{,}312{,}842.0929 \text{ USDC},

whereas if the entire trade were executed only in pool 2, the trader would receive

F(0)4,039,581.2491 USDC.F(0)\approx 4{,}039{,}581.2491 \text{ USDC}.

Hence, splitting the order optimally across both pools yields a substantially better execution than routing the whole trade to either single pool.

This example makes clear why DEX aggregators are valuable. In order to identify the optimal split, one must know the current state of each pool and perform a nontrivial optimization. Aggregators automate this entire procedure and thereby allow users to obtain better prices without carrying out these computations manually.