Skip to content

Conversation

@yorhodes
Copy link

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: prefer native property

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

Changes

  • libsolidity/analysis/TypeChecker.cpp: Added disambiguation logic after overload resolution
  • Added 3 syntax tests in test/libsolidity/syntaxTests/memberLookup/:
    • library_function_vs_native_property_with_parens.sol - verifies library function is used with ()
    • library_function_vs_native_property_without_parens.sol - verifies native property is used without ()
    • native_isContract_property.sol - verifies native property still works standalone

Behavior After Fix

Syntax Result
addr.isContract() Library function (OpenZeppelin compatible)
addr.isContract Native Tron property (ISCONTRACT opcode)

Motivation

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

…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.
@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
Copy link
Author

Closing to reopen from hyperlane-xyz org fork

@yorhodes yorhodes closed this Jan 21, 2026
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