fix(erc20): gate token metadata calls on bytecode selectors#252
Merged
Conversation
Before calling symbol()/decimals(), confirm the contract bytecode actually dispatches both selectors (95d89b41 / 313ce567). EOAs and non-token contracts are skipped without a blind eth_call, so the AI explainer no longer probes every address in a tx and fails. Proxies delegate via fallback and carry none of the implementation's selectors, so a bare scan would false-negative proxy tokens (USDC etc.). We resolve the implementation via utils.proxy.get_current_implementation and scan its bytecode too. The existing try/except stays as a backstop for exotic dispatch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The AI explainer enriches every address in a transaction (each call target + every address-typed calldata arg) by calling
symbol()/decimals()and catching the failure. Most addresses aren't tokens, so we fire eth_calls we expect to fail. On a MAPLE safe tx this surfaced as repeated:— a non-ERC20 address returning empty data, retried across every RPC.
Fix
Gate the metadata call on positive evidence: only call
symbol()/decimals()when the contract bytecode actually dispatches both selectors (95d89b41/313ce567).utils.proxy.get_current_implementationand scan its bytecode too. Without this, proxy tokens would be false-negatives.try/exceptstays as a backstop for exotic dispatch (metamorphic, unusual proxies).get_coderesults feed the same per-address cache, so a non-token address costs at most oneeth_getCode(+ a proxy-slot read) once, then is cached as a miss.Why not a different check?
There's no reliable static "is ERC20" check — ERC20 has no ERC165
supportsInterface, and many tokens are proxies. Bytecode-selector inspection (with proxy resolution) is the cheapest scheme that gives a positive signal before calling, while staying proxy-safe.Testing
tests/test_erc20_metadata.pyrewritten to mock the bytecode gate: token, EOA-skip, non-token-skip, proxy-resolution, revert-backstop, and cache-miss-no-refetch.ruffclean.Note
This is independent of the related one-line web3 change on PR #251 (treating decode failures as non-retryable). This PR removes the call entirely in the common case; that one quiets the retry storm if a probe still slips through.
🤖 Generated with Claude Code