Web3 App: Universal Base Explained
I recently released the first version of my personally developed app Universal Base (visit the link).
In this article, I would like to give you a brief introduction to the app.
About Uniswap
You may know that Uniswap is one of the most popular Ethereum decentralized exchanges (DEX).
You can swap a variety of tokens, from Ethereum’s native token ETH to popular stable coins such as USDC, USDT, and DAI which are equivalent to 1 dollar, to meme tokens such as SHIB and PEPE.
What Matter has Uniswap Trading?
Uniswap traders use the Uniswap App to swap tokens.
The transparency of transactions, is an advantage of blockchain, however, in regards to Uniswap, it is difficult to observe due to its complex mechanism.
Therefore, many traders have no choice but to trust the Uniswap App to ensure that their swaps are done correctly.
The main reason for this is that tokens are first swapped via a contract called “Universal Router”, for the contract, the contents are encoded.
For information on how it is encoded, please see the original reference here.
The reason above seems to be that this encoding omits the string for reducing gas costs.
Solution: Universal Base
I will briefly explain what was solved below.
Decoding transaction data
First, I created a module called “uniswap-universal-decorder” and decoded almost all Universal Router commands (some rare commands have not been tested as there is no data for tests).
This allows anyone who has an Ethereum node to decode it.
Decode Example
?Encoded data
0x3593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006561d94f00000000000000000000000000000000000000000000000000000000000000040a01050c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003a00000000000000000000000000000000000000000000000000000000000000160000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000ffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000658963f900000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad000000000000000000000000000000000000000000000000000000006561de0100000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000415f0511ba3fa712da37ec36ee9a253b62a633045c94307f1199fbbfbe5208e64e631a4964e505db3f74227bab7d03166084939b2e38ec7a312983cccee3a06fdf1c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000001bcc15e33d1b800000000000000000000000000000000000000000000000000000000000f97ce35a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002bc02aaa39b223fe8d0a0e5c4f27ead9083c756cc20001f4a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000037a8f295612602f2774d331e562be9e61b83a327000000000000000000000000000000000000000000000000000aa87bee538000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000001bc16d674ec80000
?Decoded data
{
contents: [
{
command: '0a',
value: 'PERMIT2_PERMIT',
inputType: [
'tuple((address,uint160,uint48,uint48),address,uint256)',
'bytes'
],
decodedInput: [
[
[
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
1461501637330902918203684832716283019655932542975n,
1703502841n,
0n
],
'0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad',
1700912641n
],
'0x5f0511ba3fa712da37ec36ee9a253b62a633045c94307f1199fbbfbe5208e64e631a4964e505db3f74227bab7d03166084939b2e38ec7a312983cccee3a06fdf1c'
]
},
{
command: '01',
value: 'V3_SWAP_EXACT_OUT',
inputType: [ 'address', 'uint256', 'uint256', 'bytes', 'bool' ],
decodedInput: [
'0x0000000000000000000000000000000000000002',
2003000000000000000n,
4185711450n,
[
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
500n,
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
],
true
]
},
{
command: '05',
value: 'TRANSFER',
inputType: [ 'address', 'address', 'uint256' ],
decodedInput: [
'0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2',
'0x37a8f295612602f2774d331e562be9e61b83a327',
3000000000000000n
]
},
{
command: '0c',
value: 'UNWRAP_WETH',
inputType: [ 'address', 'uint256' ],
decodedInput: [
'0x0000000000000000000000000000000000000001',
2000000000000000000n
]
}
],
deadline: 1700911439n
}
However, it would be a bit burdensome for a common trader to set up an Ethereum node and decode it on their own using this module, so I created a system so that anyone can access it.
Providing an open source DB system that stores Uniswap decoded data
As described, many people find extracting Uniswap data from Etherscan or Ethereum nodes to be burdensome.
“uniswap-universal-base” provides a mechanism for querying using GraphQL and storing data in the DB, including transaction pool data.
Past data, current data, and future data (transaction pool data) are stored in the database, allowing traders to utilize that information in their trading.
This is open source, so anyone can use it equally.
Real-time visualization utilizing directed graphs
The above system is the infrastructure for providing Uniswap transaction data from the past to the present, but the data is stored in JSON format, and it is somewhat difficult to understand for humans to observe the transactions.
Accordingly, I visualized these data in real-time utilizing a directed graph.
A directed graph is an intuitive graph that connects nodes (diagrams) with directional arrows.
I will explain what is possible with real-time visualization of directed graphs as follows.
Observability: Including transaction pool data in blocks
You can see that pending data (transaction pool data that has not been included in the block) is included in the block in real-time.
Observability of what kind of transaction pool data is included in a block will help you understand things like current gas prices.
*If the transaction has not been included in the block, there be no arrow (edge) between the block and the transaction. Also, the block number section be “Pending”.
Observability: Transaction congestion
If there are a lot of transactions, the amount of graph data will quickly increase.
It can also be used to judge whether to refrain from trading because crowded transactions suggest high gas prices.
Or perhaps, an event is occurring that will make a trend.
Observability: Finding out which tokens are hot in trading
If there are many graphs extending to token addresses, there are many addresses that are trading (of course, it is necessary to check the trading amount).
Tokens that are hotly traded have high volatility, which can be a trading opportunity (please note that the figure below is “USDT = Stable Coin”, so the price is almost constant).
Observability: Possible to track with the tracking function
You can track block number, transaction hash, wallet address, contract address, etc. by entering it in the input field.
As particles move along the trading path, it is possible to see what kind of trader is trading, in which block, which token, and in what amount.
Wouldn’t this information be useful in determining trading opportunities?
*The figure below tracks the USDC contract address.
Future implementation plans
In the future, I am considering making transaction data searchable and visualizing it in a directed graph, and also visualizing statistics on Universal Router token transaction volume, and Uniswap command statistics.
In addition, also considering support for other L2 chains and support for Uniswap V4.
Plus, I’m planning to release the visualization of directed graphs as open source (I’m currently organizing the code).
However, it seems that adding more functions will require more server specs than expected, so if you would like to help, please donate to this Ethereum address “0x5bdb6895532099E64C2e0013EB7d0b4A2e35e337”.
There are no financial backgrounds so far.
Also, if you have any questions, ideas that want to be implemented, or bugs, please feel free to contact me by creating an issue on Twitter or GitHub (Considering it positively as we want a variety of people to use it).
I hope that you will use “Universal Base” as a trading tool.