
Uniswap Universal Router Decoder
io.github.Elnaril由 GitHub 帳號 Elnaril 發布v4.0.0更新於 Oct 29, 2026
Decode and encode Uniswap Universal Router calldata (V2, V3, V4). Read-only: never signs or sends.
發布方自己的服務:370.ai — AI Gateway: 100+ Chat Models, Image & Speech Generation
概覽
本機 MCP 伺服器,用來解碼與編碼 Uniswap Universal Router 的 V2、V3、V4 呼叫資料,僅供讀取,不簽章也不送出交易。
- 可以做什麼
- 把 Universal Router 交易輸入解碼成指令、參數、截止時間與尾端資料
- 依交易雜湊從 RPC 端點取得並解碼整筆交易
- 編碼與解碼 Uniswap V3 交換路徑,並建立 V4 的 pool key、path key 與 pool id
- 從解碼結果重建呼叫資料,可先解碼、修改路徑再重新編碼
- 編碼可串接的路由指令,例如各種交換、包裝 ETH、Permit2 授權、分帳、sweep 與轉帳
- 適用情境
- 適合需要釐清某筆 Uniswap Universal Router 交易實際做了什麼,或希望助理在你自行簽章之前產生、調整交換、流動性或 Permit2 流程的路由呼叫資料時使用。
- 執行需求
- 以 Python 套件形式在本機執行(可用 uvx 或 pip 安裝)。依雜湊解碼整筆交易需要以太坊 RPC 端點,透過環境變數 RPC_URL 提供;解碼原始呼叫資料與編碼則不需要。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Uniswap Universal Router Decoder,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
Uniswap Universal Router Decoder & Encoder
Many thanks to everyone who has ☕️ offered some coffees! ☕️ or ⭐ starred this project! ⭐
It is greatly appreciated! :)
Project Information
[PyPI - Python Version] [GitHub release (latest by date)] [PyPi Repository] [GitHub] [Uniswap Universal Router Decoder MCP on mcprush]
Code Quality
[Tests & Lint] [CodeQL] [Test Coverage] [Imports: isort] [Type Checker: basedpyright] [Linter: flake8]
Release Notes
See the release notes page
v4.0.0 - breaking changes
- Update COMMAND_TYPE_MASK to 0x7f to match UR
- Add support for the PAY_PORTION_FULL_PRECISION command (0x07)
- Add support for the BALANCE_CHECK_ERC20 command (0x0e)
- Add support for the V3_POSITION_MANAGER_PERMIT command (0x11)
- Add support for the V3_POSITION_MANAGER_CALL command (0x12)
- Add support for the EXECUTE_SUB_PLAN command (0x21)
- Add
revert_on_failto the encoder methods for the commands whose failure the UR can tolerate - Capture the bytes some callers append after the UR arguments as
trailing_data, and re-append them when rebuilding the calldata, so a decoded call can be rebuilt byte-for-byte - Make the chained function builders public and expose the
encoder&decodermodules - Reduce CI time
- Add a
publish.ymlGitHub Actions workflow that automatically publishes the package to PyPI and the MCP Registry with OIDC Trusted Publishing - Agent-friendly changes:
- Add
Encoder.function_input()/AsyncEncoder.function_input()to rebuild the calldata from a decoded call - Add
decoded_input_to_dict()andtransaction_to_dict()to render the decoder output as JSON-friendly dicts - Add the
ur-decodeandur-encodecommand line tools, includingur-encode v3-pathand itsencode_v3_pathMCP counterpart - Add the
ur-mcpMCP server (optionalmcpextra) so AI agents can drive the codec, includingencode_calldatato rebuild the calldata from a decoded call - Annotate the MCP tools as read-only so a host can auto-approve them, and give them human-readable titles
- The command descriptions (
ur-encode list/describeand thelist_commands/describe_commandMCP tools) now describe the decoded call format and its ABI parameters, instead of the encoder methods - Add the MCP Registry metadata (
server.json) to make theur-mcpserver discoverable - Add
AGENTS.mdandllms.txtfor AI agents, plus amcpPyPI keyword - Add
tests/test_version_consistency.pyto keep the packaging version,server.jsonand the READMEmcp-name:marker in sync
- Add
Overview and Points of Attention
The object of this library is to decode & encode transactions sent to the Uniswap Universal Router (UR) on Ethereum Mainnet, though it would work on any compatible chain where the UR is deployed. See Version Mapping below. This Python SDK is based on, and intended to be used with web3.py
The target audience is Python developers who are familiar with the Ethereum blockchain concepts and web3.py, and how DEXes work.
The same codec is also available without Python, through the ur-decode / ur-encode command line tools and the optional
ur-mcp MCP server (see "Command line interface" and "MCP server" below): both print JSON, so shell scripts and AI
agents can drive it too.
⚠ Before using this library, ensure you are familiar with general blockchain concepts. The Python API also expects web3.py knowledge in particular.
⚠ Not all UR functions supported by this SDK are available through the CLI or MCP tools:
run ur-encode list and look for the "rebuildable" flag.
List of supported Uniswap Universal Router Functions
All the ✅ commands can be decoded and encoded. V4_SWAP, V4_POSITION_MANAGER_CALL and EXECUTE_SUB_PLAN can also
be decoded, but they cannot be rebuilt from a decoded call (see "How to rebuild the calldata from a decoded call").
Version Mapping
Here is the mapping between the Universal Router versions and the SDK ones
Installation
A good practice is to use Python virtual environments, here is a tutorial.
The library can be pip installed from pypi.org as usual:
To install it from source:
or for contributors:
Usage
The library exposes 2 classes, RouterCodec and AsyncRouterCodec with several public methods
that can be used to decode or encode UR data and transactions.
Both RouterCodec and AsyncRouterCodec are used the same way but either synchronously
or asynchronously for the relevant parts, ie when doing rpc calls.
How to instantiate the router codec
1/ When no need for rpc calls
2/ Using the URL of an rpc endpoint
Sync code:
Async code:
3/ Using a Web3/AsyncWeb3 instance
Sync code:
Async code:
How to decode a Uniswap Universal Router transaction input
To decode a transaction input, use the decode.function_input() method as follows:
Example of decoded input returned by decode.function_input():
decode.function_input() reports the bytes some callers append after the UR arguments as trailing_data (see the
example above). Pass find_trailing_data=False to ignore them.
Tip: You can format the decoded input like above with this Gedit plugin ;)
How to decode a Uniswap Universal Router transaction
It's also possible to decode the whole transaction, given its hash
and providing the codec has been built with either a valid Web3 instance or the link to a rpc endpoint.
The decoder will get the transaction from the blockchain and decode it, along with its input data:
How to encode/decode a Uniswap V3 swap path
RouterCodec exposes two mirror methods: encode.v3_path() builds a Uniswap V3 path from the ordered tokens and the
pool fees between them, and decode.v3_path() reads one back.
decode.v3_path() returns a tuple, starting with the "in-token" and ending with the "out-token", with the pool fees
between each pair. Both methods use that same order: V3_SWAP_EXACT_OUT reverses the path when encoding, and the
decoder reverses it back.
How to get the decoded data as JSON-friendly dicts
The decoder returns rich Python objects (web3 contract functions, raw bytes, ...) that are not directly serialisable. Two helpers render that output as plain dicts/lists/strings, ready to be printed as JSON or sent to another system:
decoded_input_to_dict()takes the output ofdecode.function_input()transaction_to_dict()takes the output ofdecode.transaction()
Bytes are rendered as "0x"-prefixed hex strings, and each decoded command becomes a dict with a command name,
its params, and a revert_on_fail flag:
How to encode
The Uniswap Universal Router allows the chaining of several functions in the same transaction. This codec supports it (at least for supported functions) and exposes public methods that can be chained.
The chaining starts with the encode.chain() method and ends with the build() one which returns the full encoded data to be included in the transaction.
Below some examples of encoded data for one function and one example for 2 functions.
Starting with v3.0.0, it is possible to start the chaining with encode() instead of encode.chain(), making the code a bit more concise.
Default values for deadlines and expirations can be computed with the static methods get_default_deadline() and get_default_expiration() respectively.
These 2 functions accept a custom duration in seconds as argument.
revert_on_fail can be passed to the methods whose command the UR can tolerate failing: permit2_permit(),
permit2_permit_batch(), balance_check_erc20(), v3_position_manager_permit(), v3_decrease_liquidity(),
v3_collect(), v3_burn(), v4_initialize_pool(), build_v4_posm_call() and execute_sub_plan(). It defaults to
True; set it to False to let the transaction continue if that command fails. The other methods don't accept it,
because the UR ignores that flag for their command.
How to rebuild the calldata from a decoded call
As an alternative to chaining the encoder methods, encode.function_input() builds the calldata from the decoded form
of an execute call. It is the mirror of decode.function_input(): where the decoder turns a function input into
commands, this turns the decoded commands back into a function input, so a route can be decoded, edited, and re-encoded.
The expected shape is the one produced by decoded_input_to_dict() (and by the ur-decode CLI and the MCP server):
its params.inputs hold the commands, using the names and parameters the decoder reports (the Universal Router ABI
names).
The function key is optional and defaults to execute, and the commands bytes are ignored: the command list is
rebuilt from the inputs entries. The deadline key is optional too; when it is absent, the plain
execute(bytes,bytes[]) form is used instead of execute(bytes,bytes[],uint256).
Some callers append a tag after the ABI-encoded arguments, which the UR ignores. The decoder reports it as
params.trailing_data, and encode.function_input() re-appends it, so a decoded call can be rebuilt byte-for-byte.
The chained builders take the same value as an optional trailing_data argument of build(), after deadline.
Commands the decoder expands into structures (V4_SWAP, V4_POSITION_MANAGER_CALL, EXECUTE_SUB_PLAN) cannot be
rebuilt this way and raise a ValueError.
revert_on_fail is honoured only for the commands whose failure the UR can tolerate (PERMIT2_PERMIT,
PERMIT2_PERMIT_BATCH, BALANCE_CHECK_ERC20, V3_POSITION_MANAGER_PERMIT, V3_POSITION_MANAGER_CALL,
V4_INITIALIZE_POOL, V4_POSITION_MANAGER_CALL, EXECUTE_SUB_PLAN). For every other command the UR ignores the
flag, so it is always cleared. The same applies to the encoder methods: those commands take a revert_on_fail
argument (default True), the others do not.
AsyncRouterCodec exposes the same method (encode.function_input()); it is synchronous, so no await is needed.
How to encode a call to the Uniswap Universal Router function WRAP_ETH
This function can be used to convert eth to weth using the UR.
How to encode a call to the Uniswap V2 function V2_SWAP_EXACT_IN
This function can be used to swap tokens on a V2 pool. Correct allowances must have been set before sending such transaction.
For more details, see this tutorial
How to encode a call to the Uniswap V2 function V2_SWAP_EXACT_OUT
This function can be used to swap tokens on a V2 pool. Correct allowances must have been set before sending such transaction.
How to encode a call to the Uniswap V3 function V3_SWAP_EXACT_IN
This function can be used to swap tokens on a V3 pool. Correct allowances must have been set before sending such transaction.
How to encode a call to the Uniswap V3 function V3_SWAP_EXACT_OUT
This function can be used to swap tokens on a V3 pool. Correct allowances must have been set before sending such transaction.
How to encode a call to the Uniswap Universal Router function PERMIT2_PERMIT
This function is used to give an allowance to the universal router via the Permit2 contract (0x000000000022D473030F116dDEE9F6B43aC78BA3).
It is also necessary to approve the Permit2 contract using the token approve function.
See this tutorial
After that, you can swap tokens using the Uniswap universal router.
How to get the current permit2 allowance, expiration and nonce
You can get the nonce you need to build the permit2 signable message like this:
How to chain a call to PERMIT2_PERMIT and V2_SWAP_EXACT_IN in the same transaction
Don't forget to give a token allowance to the Permit2 contract as well.
Uniswap V4 Functions
How to build a Uniswap V4 pool key
PoolKey is used to identify a pool.
How to build a Uniswap V4 path key
PathKey is used to identify pools in a multi-hop swaps.
How to encode a Uniswap V4 pool id
Pool ids are used by V4 contracts to identify pools. For example, you'll need it to request the StateView contract.
How to initialize a Uniswap V4 pool with the Universal Router function V4_INITIALIZE_POOL
How to mint a Uniswap V4 position with the Universal Router function V4_POSITION_MANAGER_CALL
Example where a position on a ETH/TOKEN pool is minted between tick_0 and tick_1
How to perform a Uniswap V4 swap with the Universal Router function V4_SWAP
Example using the V4 SWAP_EXACT_IN_SINGLE function to swap ETH for a token
Example using the V4 SWAP_EXACT_IN function to swap ETH for a token through 2 pools
path: eth -> token a -> token b
Other chainable functions
(See integration tests for full examples)
PAY_PORTION
Example where a recipient is paid 1% of the USDC amount:
PAY_PORTION_FULL_PRECISION
Same as PAY_PORTION but with full precision, where 10**18 represents 100%. Example where a recipient is paid 50% of the USDC amount:
SWEEP
Example where the sender gets back all remaining USDC:
TRANSFER
Example where a USDC amount is sent to a recipient:
BALANCE_CHECK_ERC20
Reverts if the owner's balance of the given ERC20 token is lower than the minimum amount. Example where the router must hold at least 1 USDC:
EXECUTE_SUB_PLAN
Executes a nested plan of commands. The Universal Router calls itself to run the sub-plan, so its commands
are executed in the same transaction and share the same context (recipients, balances, ...).
The sub-plan is built with encode.chain() just like the main plan.
Example where a sub-plan transferring USDC is nested in the main plan:
V3_POSITION_MANAGER_PERMIT
Approves a spender for a specific V3 position (NFT) using an EIP-712 signature instead of a transaction.
The signable message is built with create_v3_position_manager_permit_signable_message(), then signed.
Example where the spender is approved for the position token_id:
V3_POSITION_MANAGER_CALL
Calls one of the 3 V3 position manager functions the UR allows: decreaseLiquidity, collect or burn.
Only one function can be called per V3_POSITION_MANAGER_CALL command: the UR forwards the input as a single
call and rejects anything else (including multicall). To run several of them, chain several commands in the
same transaction (see the integration test).
The UR must be approved for the position first (see V3_POSITION_MANAGER_PERMIT).
decreaseLiquidityremoves liquidity from the position. The freed tokens are NOT sent out: they are recorded astokensOwed0/tokensOwed1on the position, together with ALL the fees earned since the last update (fees are not prorated, even if only part of the liquidity is removed).collectsendsmin(amountMax, tokensOwed)to the recipient.tokensOwedholds both the principal freed bydecreaseLiquidityand the fees, socollectalone harvests the fees without touching the liquidity.burndeletes the position (NFT). It requires the position to be empty (liquidity == 0andtokensOwed0 == tokensOwed1 == 0), hence the usualdecreaseLiquidity->collect->burnorder.
Note: increaseLiquidity and mint are not reachable through the UR (only the 3 functions above are allowed),
they must be called directly on the V3 position manager.
Example where the liquidity of a V3 position is decreased:
Example where the tokens owed to a V3 position are collected:
Example where an empty V3 position is burned:
PERMIT2_TRANSFER_FROM
To use this function, the Universal Router needs to be PERMIT2'ed.
Example where 1 WETH is transferred from the caller address to the v4 position manager
PERMIT2_PERMIT_BATCH & PERMIT2_TRANSFER_FROM_BATCH
Check the corresponding integration tests for an example of how to use these functions.
How to build directly a transaction to the Uniswap Universal Router
The SDK provides a handy method to build very easily the full transaction in addition to the input data. It can compute most of the transaction parameters (if the codec has been instantiated with a valid w3 or rpc url) or you can provide them.
See the corresponding integration tests for an async example
Example where a swap is encoded and a transaction is built automatically:
And that's it! You can now sign and send this transaction. A few other important parameters:
value: the quantity of ETH in wei you send to the Universal Router (for example when you wrap them before a swap)trx_speed: an enum which influences the transaction rank in the block. Values are:TransactionSpeed.SLOWTransactionSpeed.AVERAGETransactionSpeed.FAST(default)TransactionSpeed.FASTER
max_fee_per_gas_limit: if the computedmax_fee_per_gasis greater thanmax_fee_per_gas_limitaValueErrorwill be raised to allow you to stay in control. Default is 100 gwei.
How to use the trx_speed parameter:
Command line interface
The package installs two commands that print JSON to stdout, handy for shell scripts or to let an agent drive the codec:
ur-encode: describe the decoded call format and the commands, rebuild calldata from a decoded call, or encode a V3 pathur-decode: decode a transaction, raw calldata, a custom error or a V3 path
A plan file holds a decoded execute call, exactly as ur-decode calldata prints it:
MCP server
The optional mcp extra installs ur-mcp, a side-effect free Model Context
Protocol server that exposes the codec to AI agents over stdio. Its tools only
inspect or derive Universal Router data: they never sign or broadcast a transaction.
It provides eight tools:
list_commands/describe_command: discover the decoded call format and the commandsdecode_transaction: fetch and decode a transaction sent to the UR (needs an RPC endpoint)decode_calldata,encode_calldata,decode_error,decode_v3_path,encode_v3_path: decode/encode data without an RPC endpoint
encode_calldata is the mirror of decode_calldata: it rebuilds the calldata from a decoded call, so an agent can
decode a route, edit it and re-encode it (the MCP counterpart of ur-encode build).
The tools are annotated as read-only (readOnlyHint), and only decode_transaction as open-world (openWorldHint),
so a host can auto-approve them instead of prompting on every call. Each tool also carries a human-readable title
(title) for the host UI.
decode_transaction uses the rpc_url tool argument, or the RPC_URL / ETH_RPC_URL environment variables, so a
host can be pointed at any chain by configuring the server environment.
To wire it into an MCP host (Zed, Claude Desktop, ...):
Utility functions
How to compute the gas fees
The SDK provides handy methods to compute the current "priority fee" and "max fee per gas":
Sync code:
Async code:
Ticks, sqrtPriceX96 and liquidity
These functions can be useful to estimate the arguments needed to mint positions.
⚠️ The implementation of all tick, sqrtPriceX96, and liquidity related functions differs from the contracts: if you want the exact same results/numbers, do not use them.
They can be imported from uniswap_universal_router_decoder.utils.
For examples, check the integration tests for Uniswap V4.
Tutorials and Recipes on the Uniswap Universal Router:
See the SDK Wiki.
News and Q&A:
See the Discussions and 𝕏
來源:README.md,提交 dc4a725
工具
0版本歷史
1- v4.0.0最新Oct 29, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
其他 Router 整合
370.ai — AI Gateway: 100+ Chat Models, Image & Speech Generation
ai.router官方發布者
遠端 AI 閘道 MCP 伺服器,讓助理用一組 370.ai API 金鑰呼叫 100 多個聊天模型、生成圖片並將文字轉成語音。

AI Media Router
由 GitHub 帳號 jutsuhq 發布
本機 MCP 伺服器,用你自己的 API 金鑰透過 40 多家供應商生成圖片與影片,支援比價與可搜尋的本機素材庫。

Bike Router
由 GitHub 帳號 JonasHeinickeBio 發布
連接自架 pyBikeRouter API 的 MCP 伺服器,可規劃以 OSM 為基礎的單車路線,並附上天氣、景點與 GeoJSON/GPX 匯出。

x402 Router
由 GitHub 帳號 camerxnduff 發布
唯讀 MCP 伺服器,可搜尋經探測的 x402 按次付費端點登錄檔,並為助理路由到評分最高的端點。

GenPark Consistent Hash Ring Router
由 GitHub 帳號 alphaparkinc 發布
一個本機 MCP 伺服器,提供含虛擬節點的一致性雜湊環,用於分散式 LLM 快取路由與代理程式分區。