Context
There are more than 30 functions implemented in the Universal Router (UR) at the moment, in the repository main branch.
As the author of the Python Uniswap Universal Router SDK, I always wonder what should be the next one(s) this library should support.
Until now, I've added the most obvious functions:
- the ones that allow to swap ERC-20 tokens:
V3_SWAP_EXACT_IN
V3_SWAP_EXACT_OUT
V2_SWAP_EXACT_IN
V2_SWAP_EXACT_OUT
- those often needed before or after:
WRAP_ETH
UNWRAP_WETH
PERMIT2_PERMIT
- and a couple ones that allow more possibilities:
SWEEP
PAY_PORTION
But for the next supported functions, I decided to list those that are actually used, and order them from the most to the least called.
Methodology
To reach this goal, I wrote a simple Python script that looks into all blocks included in Mainnet during November 2023, gets all transactions sent to the Universal Router, discards those with a too small input field, and decodes them. And counts how many times each command (function) is used.
This script can be found here, so the results can be reproduced. Just change the RPC providers.
No fancy optimizations were implemented in the script apart from good ol' asyncio
and it does not check whether the transactions were rejected by the EVM or not, to avoid requesting the receipts. This is a bit annoying in terms of clean data, but allowed me to get the results in less than half a day.
Another limitation with this method: it does not take into account transactions using the UR through custom contracts.
Results
The scripts scanned:
-
214 307
blocks (from18 473 543
to18 687 850
) -
2 453 214
transactions sent to the UR -
5 435 322
commands
And the raw results is given in the below dict, with the decimal commands as keys and the number of calls as values:
Results: {11: 1362528, 8: 1886773, 9: 97389, 1: 52226, 12: 856319, 10: 593542, 0: 494207, 5: 8346, 4: 36076, 6: 47881, 16: 25, 25: 2, 14: 8}
There were 32 transactions that could not be decoded, either because they are wrongly formatted and rejected by the EVM, or their format does not respect the specifications (as I understand them) but still were accepted by the EVM (more on them in another post). Anyway they are not statistically relevant, so let's just disregard them for now.
The following table lists the results with the function names, ordered by counts (desc) and whether or not it is already supported by the codec:
Dec - Hex Code | Name | Counts | Supported |
---|---|---|---|
8 - 0x08 | V2_SWAP_EXACT_IN | 1886773 | ✅ |
11 - 0x0b | WRAP_ETH | 1362528 | ✅ |
12 - 0x0c | UNWRAP_WETH | 856319 | ✅ |
10 - 0x0a | PERMIT2_PERMIT | 593542 | ✅ |
0 - 0x00 | V3_SWAP_EXACT_IN | 494207 | ✅ |
9 - 0x09 | V2_SWAP_EXACT_OUT | 97389 | ✅ |
1 - 0x01 | V3_SWAP_EXACT_OUT | 52226 | ✅ |
6 - 0x06 | PAY_PORTION | 47881 | ✅ |
4 - 0x04 | SWEEP | 36076 | ✅ |
5 - 0x05 | TRANSFER | 8346 | ❌ |
16 - 0x10 | SEAPORT_V1_5 | 25 | ❌ |
14 - 0x0e | placeholder | 8 | N/A |
25 - 0x19 | SUDOSWAP | 2 | ❌ |
As a Pie Chart:
So, basically, most of the used commands (99.8% of the calls) are already supported by the Python UR SDK. The only one really missing is TRANSFER
with 8346 counts (< 0.2%), the others are anecdotal:
-
SEAPORT_V1_5
with 25 counts - a placeholder with no function yet (8 counts)
-
SUDOSWAP
with 2 counts
Other interesting results
1/ The 4 swap functions (V2_SWAP_EXACT_IN
, V3_SWAP_EXACT_IN
, V2_SWAP_EXACT_OUT
and V3_SWAP_EXACT_OUT
) were called 2 530 595
times:
-
1 984 162
(78.4%) for a V2 pool, most of it (74.6%) through theV2_SWAP_EXACT_IN
function -
546 433
(21.6%) for a V3 pool
2/ The second most used function is WRAP_ETH
with 1 362 528
calls, which is 53.8% of all swap commands. Knowing that several swap commands can be chained after a single WRAP_ETH
, this suggests that ETH is largely used to initiate a swap.
3/ There are 2.2 commands/functions per transaction on average.
4/ Still on average, each block contains 11.4 transactions sent to the Universal Router!
Conclusion
As expected, the functions related to ERC-20 DeFi are extensively used. But, basically, nothing else is used apart the TRANSFER
function: no batch ones, no permit2 transfers, no NFTs, ...
So, I guess I'll implement TRANSFER
sooner or later, but what about the other ones?
Do you think there is an interest in them? If, yes which ones and why are they not already used?
Top comments (0)