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_INV3_SWAP_EXACT_OUTV2_SWAP_EXACT_INV2_SWAP_EXACT_OUT
- those often needed before or after:
WRAP_ETHUNWRAP_WETHPERMIT2_PERMIT
- and a couple ones that allow more possibilities:
SWEEPPAY_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 307blocks (from18 473 543to18 687 850) -
2 453 214transactions sent to the UR -
5 435 322commands
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_5with 25 counts - a placeholder with no function yet (8 counts)
-
SUDOSWAPwith 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_INfunction -
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)