Repository navigation
Encode_V3_Position_Manager_Call
The V3_POSITION_MANAGER_CALL command calls one of the 3 V3 position manager functions the UR allows: decreaseLiquidity, collect and burn. Only one function can be called per command (the UR forwards the input as a single call and rejects anything else, including multicall), so several calls must be chained in the same transaction.
⚠ The UR must be approved for the position (NFT) first, with the V3_POSITION_MANAGER_PERMIT command.
No rpc access is required to encode these calls:
from uniswap_universal_router_decoder import RouterCodec
codec = RouterCodec()v3_decrease_liquidity() removes liquidity from a V3 position:
encoded_data = codec.encode.chain().v3_decrease_liquidity(
token_id, # the id of the V3 position (NFT)
liquidity, # the amount of liquidity to remove
amount_0_min, # the minimum amount of token0 the decrease must free
amount_1_min, # the minimum amount of token1 the decrease must free
deadline, # when this call is not valid anymore
).build(codec.get_default_deadline()) # unix timestamp after which the trx is not valid any moreThe freed tokens are not sent out: they are recorded as tokensOwed0/tokensOwed1 on 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). Use v3_collect() to withdraw them.
v3_collect() sends the tokens owed to a V3 position:
encoded_data = codec.encode.chain().v3_collect(
token_id, # the id of the V3 position (NFT)
recipient_address, # the address receiving the collected tokens
amount_0_max, # the maximum amount of token0 to collect
amount_1_max, # the maximum amount of token1 to collect
).build(codec.get_default_deadline()) # unix timestamp after which the trx is not valid any moreIt sends min(amountMax, tokensOwed) to the recipient. As tokensOwed holds both the principal freed by v3_decrease_liquidity() and the fees, v3_collect() alone harvests the fees without touching the liquidity.
v3_burn() deletes a V3 position (NFT):
encoded_data = codec.encode.chain().v3_burn(
token_id, # the id of the V3 position (NFT)
).build(codec.get_default_deadline()) # unix timestamp after which the trx is not valid any moreThe position must be empty (liquidity == 0 and tokensOwed0 == tokensOwed1 == 0), hence the usual decreaseLiquidity -> collect -> burn order.
As only one function can be called per command, several calls are chained in the same transaction. Here is the usual decreaseLiquidity -> collect -> burn sequence:
deadline = codec.get_default_deadline()
encoded_data = (
codec
.encode
.chain()
.v3_decrease_liquidity(token_id, liquidity, 0, 0, deadline)
.v3_collect(token_id, recipient_address, 2 ** 128 - 1, 2 ** 128 - 1) # collect everything owed
.v3_burn(token_id)
.build(deadline)
)The calls can also be split across several transactions if needed.
Note that mint and increaseLiquidity are not reachable through the UR: only the 3 functions above are allowed, the others must be called directly on the V3 position manager.
Only the input data is built here. See How to build a full transaction to the Universal Router ? to build the whole transaction.
If you find this library useful, consider a donation and be part of the Supporter Community! :)
- ☕️☕️☕️ https://www.buymeacoffee.com/elnaril ☕️☕️☕️
- Ethereum compatible: 0xe32A121C89121bF8B829D6d88BBEA89e5d88f002
- Sponsoring: https://github.com/sponsors/Elnaril
Thank you to all supporters!! 🙏
Also, consider ⭐ starring ⭐ the repository and following the GitHub account and/or 𝕏 to get the next lib updates!