Skip to content

Commit 7dcf3bf

Browse files
fix: support prefix matching in v2 display field validation (#284)
The display field linter was using strict set comparison between format paths and ABI paths. This caused false positives when a descriptor defines a display field for an array root (e.g. `entries.[]`) while the ABI expands to individual leaf paths (e.g. `entries.[].alias`, `entries.[].address`). Use `data_path_starts_with` for prefix matching so that: - A format path is valid if it matches an ABI path or is a prefix of one - An ABI path is considered covered if a format path is a prefix of it Made-with: Cursor
1 parent 294f783 commit 7dcf3bf

1 file changed

Lines changed: 20 additions & 13 deletions

File tree

src/erc7730/lint/v2/lint_validate_display_fields.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from erc7730.lint.v2 import ERC7730Linter
1616
from erc7730.lint.v2.path_schemas import compute_format_schema_paths
1717
from erc7730.model.paths import DataPath
18+
from erc7730.model.paths.path_ops import data_path_starts_with
1819
from erc7730.model.paths.path_schemas import compute_abi_schema_paths
1920
from erc7730.model.resolved.v2.context import ResolvedContractContext, ResolvedEIP712Context
2021
from erc7730.model.resolved.v2.descriptor import ResolvedERC7730Descriptor
@@ -101,21 +102,27 @@ def _validate_contract_display_fields(cls, descriptor: ResolvedERC7730Descriptor
101102
format_paths = compute_format_schema_paths(fmt)
102103
abi_paths = abi_paths_by_selector[selector]
103104

104-
# Check for display fields referencing non-existent ABI paths
105+
# Check for display fields referencing non-existent ABI paths.
106+
# A format path is valid if it matches an ABI path exactly OR is a prefix of one
107+
# (e.g. defining a field for an array root covers all nested elements).
105108
for path in format_paths.data_paths - abi_paths:
106-
out.error(
107-
title="Invalid display field",
108-
message=f"A display field is defined for `{path}`, but it does not exist in function "
109-
f"{selector} ABI (see {explorer_url}). Please check the field path is valid.",
110-
)
111-
112-
# Check for ABI paths without corresponding display fields
109+
if not any(data_path_starts_with(abi_path, path) for abi_path in abi_paths):
110+
out.error(
111+
title="Invalid display field",
112+
message=f"A display field is defined for `{path}`, but it does not exist in function "
113+
f"{selector} ABI (see {explorer_url}). Please check the field path is valid.",
114+
)
115+
116+
# Check for ABI paths without corresponding display fields.
117+
# An ABI path is covered if it matches a format path exactly OR a format path is a prefix of it
118+
# (e.g. a field defined for an array root covers all descendant paths).
113119
for path in abi_paths - format_paths.data_paths:
114-
out.warning(
115-
title="Missing display field",
116-
message=f"No display field is defined for path `{path}` in function {selector} "
117-
f"(see {explorer_url}).",
118-
)
120+
if not any(data_path_starts_with(path, fmt_path) for fmt_path in format_paths.data_paths):
121+
out.warning(
122+
title="Missing display field",
123+
message=f"No display field is defined for path `{path}` in function {selector} "
124+
f"(see {explorer_url}).",
125+
)
119126

120127
# Check selector exhaustiveness: all ABI functions should have display formats
121128
for selector, abi in reference_abis.functions.items():

0 commit comments

Comments
 (0)