Skip to content

propagate the IDescribedByMetaV1 probe error out of implements_i_described_by_meta_v1 - #271

Open
thedavidmeister wants to merge 1 commit into
mainfrom
2026-08-25-issue-175
Open

propagate the IDescribedByMetaV1 probe error out of implements_i_described_by_meta_v1#271
thedavidmeister wants to merge 1 commit into
mainfrom
2026-08-25-issue-175

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Closes #175.

The IDescribedByMetaV1 supportsInterface call in
implements_i_described_by_meta_v1 folded every failure into false:

match provider.call(tx).await {
    Ok(bytes) => IERC165::supportsInterfaceCall::abi_decode_returns(&bytes).unwrap_or(false),
    Err(_) => false,
}

so a transport outage, a rate limit, or a malformed node response rendered as
the definitive "this contract does not implement IDescribedByMetaV1", and
fetch_for_contract turned that into HasNoWords — indistinguishable from a
contract that genuinely lacks the interface.

  • The call now goes through rain-erc's own IERC165 rpc binding
    (IERC165::new(addr, provider).supportsInterface(..).call()) and reuses that
    crate's classification rather than a second, looser one: revert data or empty
    calldata stay Ok(false) per ERC-165, anything else — transport failure,
    decode failure — surfaces as Erc165Error, rain-erc's documented "answer
    unknown". The manual TransactionRequest + abi_decode_returns round trip
    goes away with it.
  • AuthoringMetaV2Error gains a transparent Erc165Error variant, and
    fetch_for_contract maps the probe error into it rather than HasNoWords.

Relationship to #243

implements_i_described_by_meta_v1 folds twice, and the two folds are filed as
two issues. PR #243, filed against issue #154, fixes the first fold — supports_erc165(..) .unwrap_or(false) at the top of the function. This PR fixes the second
the IDescribedByMetaV1 supportsInterface call at the bottom — and
deliberately leaves the first unwrap_or(false) untouched, so the two changes
are complementary rather than overlapping.

Both must change the signature to Result<bool, Erc165Error> to carry an error
out at all, and both add the same AuthoringMetaV2Error::Erc165Error variant
and the same fetch_for_contract call-site shape; that shared part is written
identically to #243 here to keep the merge trivial. Merge order does not
matter, but whichever lands second needs a rebase
whose only real conflicts
are one line in the function head (take #243's .await?) and the match block at
the tail (take this PR's). Merging only one of them leaves the other fold in
place.

QA

  • Discriminating tests: meta::tests::test_implements_described_by_call_error_is_unknown (erc165 gate passes, the IDescribedByMetaV1 probe answers a JSON-RPC rate-limit error with no revert data, the gate must return Err), meta::tests::test_implements_undecodable_response_is_unknown (the probe answers 0xdeadbeef, not a decodable bool, so a decode failure must be Err not false), meta::types::authoring::v2::tests::test_fetch_for_contract_described_by_probe_error_is_not_has_no_words (the RPC answers the supportsInterface(IDescribedByMetaV1) call with HTTP 500; fetch_for_contract must surface Erc165Error, not HasNoWords) — each fails on base behaviour, verified by reinstating the pre-change expression under the new signature, see the mutation line below.
  • Mutations applied: crates/cli/src/meta/mod.rs:463-470, the whole match tail replaced by the literal pre-change semantics Ok(supported) => Ok(supported), Err(_) => Ok(false), — one edit reinstates both halves of the old fold, since the contract binding surfaces the decode failure as Err too. Result: 11 passed; 3 failed; killed by exactly the three discriminating tests above. The tests pinning behaviour this PR does not change survived, as intended: test_implements_i_describe_by_meta_v1 (revert → Ok(false)), test_implements_empty_response_is_false (0xOk(false)) and test_implements_erc165_gate_short_circuits (the erc165-probe fold, propagate the erc165 probe error out of fetch_for_contract #243's half). Mutation reverted, filtered suite re-run green — 14 passed.
  • Oracle: rain-erc v0.1.1's own documented contract for supports_erc165 — "Err if a non-revert failure (transport or decode) prevented us from finishing the probe — callers can treat that as 'answer unknown' rather than silently reading 'no support'" — plus the rule its Erc165Error doc and private is_revert_like state (revert data or ZeroData fold to Ok(false), everything else is Err), read from ~/.cargo/registry/.../rain-erc-0.1.1/src/erc165/mod.rs, i.e. from the dependency rather than from this repo's implementation. The fetch-level expectation follows from the issue's own framing: transport failures after the gate already surface as RpcError, so the gate's must surface too.
  • Category check: the issue asks for one thing — the IDescribedByMetaV1 probe's transport/decode failures must stop reading as "does not implement". Covered at both levels (the gate returns Err; fetch_for_contract renders it as Erc165Error), for transport and for decode, which the issue names together. The issue's alternative branch — keep bool and document that errors read as false — is not taken; the Result branch it offers is. test_implements_undecodable_response_is_false is renamed to test_implements_empty_response_is_false because "undecodable" now names the opposite outcome; the response it pushes and the answer it asserts are unchanged. The first fold in the same function belongs to issue fetch_for_contract reports transient RPC/transport failures during the erc165 probe as HasNoWords #154 / PR propagate the erc165 probe error out of fetch_for_contract #243 and is deliberately out of scope here.

Local: cargo fmt --check, cargo check --all-targets and
cargo clippy --all-targets -- -D warnings clean. Test runs were filtered to
the affected tests rather than the whole suite.

🤖 Generated with Claude Code

The IDescribedByMetaV1 `supportsInterface` call folded every failure into
`false` with `Err(_) => false` plus `abi_decode_returns(..).unwrap_or(false)`,
so a transport outage, a rate limit or a malformed node response rendered as
the definitive "this contract does not implement IDescribedByMetaV1".

The call now goes through rain-erc's own `IERC165` rpc binding and reuses its
classification: revert data or empty calldata stay `Ok(false)` per ERC-165,
anything else surfaces as `Erc165Error`. `fetch_for_contract` renders that as
a new transparent `AuthoringMetaV2Error::Erc165Error` rather than `HasNoWords`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 22 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 29faac6a-8bbd-4c02-8d8d-5895e00b549e

📥 Commits

Reviewing files that changed from the base of the PR and between 45ca96c and 3194f89.

📒 Files selected for processing (2)
  • crates/cli/src/meta/mod.rs
  • crates/cli/src/meta/types/authoring/v2.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

implements_i_described_by_meta_v1 reports transport/decode errors as 'does not implement', erasing rain-erc's documented 'answer unknown' distinction

1 participant