Skip to content

PositionDescriptor support; PositionManager read methods support; misc#425

Merged
liquid-8 merged 2 commits intouniswap-python:dev/v4-finfrom
liquid-8:uniswap4_RC
Mar 15, 2026
Merged

PositionDescriptor support; PositionManager read methods support; misc#425
liquid-8 merged 2 commits intouniswap-python:dev/v4-finfrom
liquid-8:uniswap4_RC

Conversation

@liquid-8
Copy link
Member

No description provided.

@greptile-apps
Copy link

greptile-apps bot commented Mar 15, 2026

Greptile Summary

This PR adds support for Uniswap v4 PositionDescriptor and PositionManager contracts — including contract addresses for 16 networks, new ABI files, and ~30 read-only wrapper methods in Uniswap4. It also renames get_position_info to get_position_info_stateview and includes minor cleanup in util.py.

  • Critical: pos_descriptor.abi is a proxy ABI — it contains no function definitions, so all 6 PositionDescriptor wrapper methods (get_currency_ratio_priority, get_flip_ratio, etc.) will fail at runtime. The implementation ABI is needed instead.
  • Critical: get_pool_and_position_info passes the wrong argument — it feeds positionLiquidity(token_id).call() (a liquidity value) into getPoolAndPositionInfo(...) instead of passing token_id directly, and is also missing .call() on the outer invocation.
  • Critical: get_position_liquidity calls positionLiquidity but the ABI defines the function as getPositionLiquidity — this will raise an ABI lookup error.
  • Critical: get_next_token_id calls nonces(token_id) instead of the correct nextTokenId() (which takes no arguments per the ABI).
  • Bug: Avalanche address has a tab character in _position_descriptor_contract_addresses_v4, which will cause _str_to_addr to fail on the avalanche network.

Confidence Score: 1/5

  • This PR has multiple runtime-breaking bugs that will cause failures across all new PositionDescriptor and several PositionManager methods.
  • Score of 1 reflects that the PositionDescriptor ABI is entirely wrong (proxy instead of implementation), at least 3 PositionManager methods call non-existent or wrong contract functions, and one contract address has a tab character. None of the new PositionDescriptor methods or several PositionManager methods will work at runtime.
  • uniswap/assets/uniswap-v4/pos_descriptor.abi (wrong ABI entirely), uniswap/uniswap4.py (multiple function name mismatches and logic errors), uniswap/constants.py (tab character in avalanche address)

Important Files Changed

Filename Overview
uniswap/uniswap4.py Adds PositionDescriptor and PositionManager read methods, but has multiple runtime-breaking bugs: wrong function names vs ABI (positionLiquidity vs getPositionLiquidity), wrong argument to getPoolAndPositionInfo, get_next_token_id calls nonces instead of nextTokenId, and a duplicate assignment.
uniswap/constants.py Adds position descriptor and position manager contract addresses for all supported networks. The avalanche entry in _position_descriptor_contract_addresses_v4 contains a tab character before the 0x prefix, which will cause _str_to_addr to fail.
uniswap/assets/uniswap-v4/pos_descriptor.abi New ABI file for PositionDescriptor, but it's the proxy contract ABI — contains only constructor, errors, events, and fallback. Missing all function definitions needed by the Python wrapper (currencyRatioPriority, flipRatio, etc.), so all PositionDescriptor calls will fail at runtime.
uniswap/assets/uniswap-v4/pos_manager.abi New ABI file for the PositionManager contract. Appears complete and well-formed with all expected function definitions.
uniswap/util.py Minor cleanup: wraps equality comparison in bool() for explicit typing, removes a type-ignore comment. No issues.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Uniswap4.__init__] --> B[Load contract addresses from constants.py]
    B --> C[_str_to_addr for each address]
    C --> D[_load_contract with ABI]
    D --> E[quoter / router / stateview / permit2]
    D --> F[position_descriptor\npos_descriptor.abi]
    D --> G[pool_manager\npoolmanager.abi]
    D --> H[position_manager\npos_manager.abi]

    F -->|"❌ Proxy ABI - no functions"| I[get_currency_ratio_priority\nget_flip_ratio\nget_native_currency_label\nget_pool_manager\nget_token_uri\nget_wrapped_native_address]
    
    H --> J[get_position_liquidity]
    J -->|"❌ calls positionLiquidity\nABI has getPositionLiquidity"| K[Runtime Error]

    H --> L[get_pool_and_position_info]
    L -->|"❌ passes liquidity value\ninstead of token_id"| K

    H --> M[get_next_token_id]
    M -->|"❌ calls nonces\ninstead of nextTokenId"| K

    H --> N[get_balance_of / get_approved\nget_owner_of / get_nonces\nget_name / get_symbol / ...]
    N -->|"✅ Correct"| O[Success]
Loading

Last reviewed commit: feee9d1

"worldchain": "0x7da419153bd420b689f312363756d76836aeace4",
"ink": "0x42e3ccd9b7f67b5b2ee0c12074b84ccf2a8e7f36",
"soneium": "0x42e3ccd9b7f67b5b2ee0c12074b84ccf2a8e7f36",
"avalanche": " 0x2b1aed9445b05ac1a3b203eccc1e25dd9351f0a9",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tab character in address string
The avalanche address contains a leading tab character (\t) before 0x. The _str_to_addr function in util.py checks s.startswith("0x"), so this string will not match and will raise a NameNotFound exception at runtime when initializing on the avalanche network.

Suggested change
"avalanche": " 0x2b1aed9445b05ac1a3b203eccc1e25dd9351f0a9",
"avalanche": "0x2b1aed9445b05ac1a3b203eccc1e25dd9351f0a9",

Comment on lines +702 to +709
def get_next_token_id(self, token_id: int) -> int:
"""
:returns: The ID that will be used for the next minted liquidity position
"""
if self.version == 4:
next_token_id: int = int(
self.position_manager.functions.nonces(token_id).call()
)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong contract function called for nextTokenId
get_next_token_id calls nonces(token_id) but should call nextTokenId(). The ABI defines nextTokenId as a no-argument function that returns the next token ID. Additionally, the nonces function in the ABI expects (address owner, uint256 word) — not a single token_id argument — so this will also fail at the ABI encoding level.

Suggested change
def get_next_token_id(self, token_id: int) -> int:
"""
:returns: The ID that will be used for the next minted liquidity position
"""
if self.version == 4:
next_token_id: int = int(
self.position_manager.functions.nonces(token_id).call()
)
def get_next_token_id(self) -> int:
"""
:returns: The ID that will be used for the next minted liquidity position
"""
if self.version == 4:
next_token_id: int = int(
self.position_manager.functions.nextTokenId().call()
)

else:
raise ValueError("Function is not supported for this version")
pool_key: PoolKey = PoolKey(*pool_key_tuple)
return_value = return_value = {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicate assignment
return_value = return_value = { ... } is a duplicated assignment. While it works, it appears to be a copy-paste error.

Suggested change
return_value = return_value = {
return_value = {

@liquid-8 liquid-8 merged commit 41dbad6 into uniswap-python:dev/v4-fin Mar 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant