Skip to content

fix(engine): match enum keys case-insensitively when no exact key matches - #16

Merged
llbartekll merged 1 commit into
llbartekll:mainfrom
kuzdogan:fix/enum-case-insensitive-lookup
Sep 28, 2026
Merged

llbartekll merged 1 commit into
llbartekll:mainfrom
kuzdogan:fix/enum-case-insensitive-lookup

Conversation

@kuzdogan

Copy link
Copy Markdown
Contributor

Problem

The enum formatter looks up the field value with an exact string match. A bool argument renders as "true" or "false", but a descriptor may spell the enum keys "True" and "False". The lookup then misses and the raw value is shown.

Seen in the ERC-7730 registry CI on the PR that adds two Sourcify-found deployments to the Flying Tulip pFT NFT descriptor, ethereum/clear-signing-erc7730-registry#2926 (job log):

Approve pFT operator — field value at [1] "Access rights": expected "Grant all", got "true"

The descriptor has:

"enums": { "rights": { "True": "Grant all", "False": "Deny all" } }

and formats setApprovalForAll(address operator, bool approved)'s approved with "format": "enum", "$ref": "$.metadata.enums.rights".

The ERC-7730 schema only says that enum keys are "the field values". It does not fix a spelling for booleans, and the registry has both: ekubo/calldata-MEVCaptureRouter.json uses "true"/"false", flyingtulip/calldata-PftNft.json used "True"/"False". @ethereum-sourcify/clear-signing resolves both, because its resolveEnumLabel falls back to a case-insensitive key scan after an exact miss.

Change

  • New lookup_enum_label in engine.rs. It resolves the enum by enumPath (v1) or $ref (v2), tries an exact key match first, and only then compares keys with eq_ignore_ascii_case.
  • format_enum (calldata) and the FieldFormat::Enum arm in eip712.rs both call it. This removes the duplicated lookup code in the two files.
  • Unit tests: bool values match True/False keys, an exact key still wins over a case-insensitive one, enumPath works, and unknown enums or keys still return None so the raw value is rendered as before.

Integer enums are unaffected: their keys are decimal strings, which have no case.

Testing

cargo fmt --check passes and the new unit tests pass:

test engine::tests::bool_argument_renders_as_lowercase_and_still_matches_capitalized_enum_key ... ok
test engine::tests::enum_lookup_prefers_exact_key_and_supports_enum_path ... ok
test engine::tests::enum_lookup_returns_none_for_unknown_enum_or_key ... ok
test engine::tests::enum_lookup_matches_bool_keys_case_insensitively ... ok

I did not run the full suite or clippy locally, so please rely on CI for those.

🤖 Generated with Claude Code

…ches

A bool argument renders as "true"/"false", but descriptors may spell the
enum keys "True"/"False" (e.g. registry/flyingtulip/calldata-PftNft.json
in the ERC-7730 registry). The exact HashMap lookup missed, so the field
showed the raw value "true" instead of "Grant all".

Move the enum lookup into a shared lookup_enum_label helper used by both
the calldata and EIP-712 paths. It still tries an exact match first and
only falls back to an ASCII case-insensitive comparison, which mirrors
what @ethereum-sourcify/clear-signing does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@llbartekll
llbartekll merged commit c62c8ed into llbartekll:main Sep 28, 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.

2 participants