Skip to content

Conversation

@yorhodes
Copy link

@yorhodes yorhodes commented Jan 21, 2026

Summary

This PR fixes an issue where using OpenZeppelin's Address.isContract() library function on Tron causes a compilation error:

Error: Member "isContract" not unique after argument-dependent lookup in address.

This happens because Tron's native address.isContract property (added in TIP-44) conflicts with library functions attached via using Address for address;.

Problem

When code uses:

using Address for address;
// ...
return a.isContract();  // Error: not unique

The compiler finds two members named isContract:

  1. Tron's native property: address.isContract (boolean, uses ISCONTRACT opcode)
  2. Library function: Address.isContract(address) attached via using for

Solution

Disambiguate based on call syntax:

  • With parentheses a.isContract(): prefer library function

Without parentheses (a.isContract) remains unchanged and will still error with "not unique" when both a native property and library function exist.

Changes

  • libsolidity/analysis/TypeChecker.cpp: Added disambiguation logic to filter out non-functions when called with parentheses
  • Added 2 syntax tests in test/libsolidity/syntaxTests/memberLookup/:
    • library_function_vs_native_property_with_parens.sol - verifies library function is used with ()
    • native_isContract_property.sol - verifies native property still works standalone

Behavior After Fix

Syntax Result
addr.isContract() ✅ Library function (OpenZeppelin compatible)
addr.isContract (no using for) ✅ Native Tron property (unchanged)
addr.isContract (with using for) ❌ "not unique" error (unchanged)

Motivation

This enables Hyperlane and other protocols using OpenZeppelin contracts to deploy on Tron without modification.

@github-actions
Copy link

Thank you for your contribution to the Solidity compiler! A team member will follow up shortly.

If you haven't read our contributing guidelines and our review checklist before, please do it now, this makes the reviewing process and accepting your contribution smoother.

If you have any questions or need our help, feel free to post them in the PR or talk to us directly on the #solidity-dev channel on Matrix.

@yorhodes yorhodes force-pushed the fix/member-access-disambiguation branch 2 times, most recently from 8c5fea7 to 0b189a4 Compare January 21, 2026 18:55
…cess

When both a native property (e.g., address.isContract) and a library
function with the same name are available via 'using for', disambiguate
based on call syntax:

- With parentheses: prefer library function (e.g., a.isContract())
- Without parentheses: prefer native property (e.g., a.isContract)

This allows OpenZeppelin's Address.isContract() library function to work
alongside Tron's native address.isContract property without conflict.

The fix mirrors the identifier resolution pattern in visit(Identifier)
where VariableDeclarations are preferred without parentheses (lines
3693-3745 in TypeChecker.cpp).

Fixes the error: 'Member "isContract" not unique after argument-dependent
lookup in address' when using OpenZeppelin contracts on Tron.
@yorhodes yorhodes force-pushed the fix/member-access-disambiguation branch from 0b189a4 to 6847d0c Compare January 21, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant