You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(v2): support map references in field parameters - #351
Map references ({"map": "$.metadata.maps.X", "keyPath": "..."}) in v2 field parameters were previously dropped with an "Unresolved map reference" warning. They are now resolved:
Constant key (keyPath is a $.… descriptor path): the map value is selected at conversion time and emitted as a plain constant. Hex keys (addresses) match case-insensitively.
Data / container key (#.…, @.…): kept as a new ResolvedValueMap (key path + encoded constant values) in the resolved model. Supported on token, chainId (tokenAmount / tokenTicker), senderAddress (addressName / interoperableAddressName), callee, selector, amount, spender (calldata) and collection (nftName).
Deployment validation: maps keyed on @.chainId or @.to are checked against every deployment, and a missing value is an error (the spec says a wallet MUST treat the descriptor as invalid in that case).
Calldata descriptors: generated per deployment, so @.chainId / @.to maps resolve to constants; other keys are emitted as device side maps (MAP_REF + MAP_ENTRY). PARAM_TOKEN_AMOUNT / PARAM_TOKEN cannot encode a chain id: a tokenAmountchainId (plain or from a map) is ignored with a warning when it may differ from the deployment chain (tokenTicker already warned whenever a chain id is set).
Map validation: hex keys are matched case-insensitively, so maps with keys only differing by case are rejected. Hex values must have an even number of digits.
Legacy EIP-712: map lookups are reported as unsupported.
Lint: map key paths are included in v2 schema path checks.
Test plan
New resolved-conversion fixtures: data key, constant key, missing key (token amount + other parameters)
New calldata conversion tests for deployment-keyed maps
Regression tests for review findings: map keys linter on fixed point ABI types, odd-length hex map values, keys only differing by case, ignored tokenAmountchainId warning
prek run --all-files (ruff, mypy, bandit, codespell, …) passes
Map references ({"map": ..., "keyPath": ...}) in v2 field parameters were
dropped with a warning. They are now resolved:
- a constant key ($.…) selects the map value at conversion time
- a data/container key is kept as a ResolvedValueMap lookup in the
resolved model (token, chainId, senderAddress, callee, selector, amount,
spender, collection)
- maps keyed on @.chainId / @.to are checked against every deployment, and
resolved per deployment when generating calldata descriptors
- legacy EIP-712 conversion reports map lookups as unsupported
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Map lookups keyed on calldata (#.…) or on @.from / @.value were rejected
by the calldata converter. They are now looked up by the device, as
specified in app-ethereum doc/tlv_structs.md#map_entry:
- add a MAP_REF value source (VALUE tag 0x06: version, map id, key as a
nested VALUE with a data or container path)
- emit one MAP_ENTRY instruction per map key (version 0x01, chain id,
contract address, selector, id, key, value) in a new "maps" list next
to "enums", for CAL to sign with the calldata key and serve
- encode keys exactly as the device reads them: 32 bytes ABI word for
static values, raw content for dynamic ones, the slice for sliced
paths, 20 bytes for @.from, 32 bytes for @.value
- allocate map ids per descriptor, sharing them between lookups with the
same key and value encodings
- reject keys / values the device cannot store or match (empty or over
32 bytes, not fitting the key type, duplicate encodings, multi-valued
key paths, key VALUE over 48 bytes)
- keep folding @.chainId / @.to maps into constants, as a descriptor is
bound to a single deployment
- keep the referenced map path in ResolvedValueMap to identify entries
Note MAP_ENTRY version is 0x01 as enforced by map_entry.c, the doc still
states 0x0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- map keys linter: only build the ABI tree for formats with map lookups keyed
on transaction data, so formats using fixed point types still lint
- reject hex constants with an odd number of digits, which could not be
decoded when serializing map values and constants
- reject maps with hex keys only differing by case, since hex keys are matched
case-insensitively
- calldata: warn when a tokenAmount chainId differs from the deployment chain,
as PARAM_TOKEN_AMOUNT cannot encode it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A format such as deposit(uint256 assets, uint32 marketId, fixed128x18 rate) fails linting when a token map uses #.marketId or even @.from. function_to_abi_tree() visits every argument and raises NotImplementedError for fixed/ufixed (convert/calldata/v1/abi.py:189–190). The exception escapes this linter, marks the descriptor as invalid, and skips subsequent checks, although the fixed-point argument is unrelated to the lookup. Avoid ABI-tree construction for container keys and handle unsupported unrelated ABI types without aborting linting. Extend the fixed-point regression test to cover both data-keyed and container-keyed maps; it currently covers only formats without maps.
- reject a tokenAmount chainId that differs from the deployment chain
(plain value or map lookup): PARAM_TOKEN_AMOUNT cannot encode it, and
the device would display the token with a wrong ticker and decimals
- reuse the values encoded at resolution for MAP_ENTRY structs
- share is_deployment_key between the converter and the map keys linter
- use a single pattern to reject optional parameters failing to convert
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The new chain check ignores chainIdPath. A chain-1 deployment using chainIdPath: "#.targetChainId" still produces a tokenAmount descriptor when the transaction selects chain 8453. The device then resolves ticker and decimals on chain 1, potentially displaying an incorrect amount. Reject chain paths that cannot be proven equivalent to @.chainId, just as this check rejects unsupported chainId values.
Unsupported ABI argument blocks token map validation
A valid signature such as deposit(uint256 assets, fixed128x18 rate) with a token map keyed on @.from fails here: function_to_abi_tree visits every argument and raises NotImplementedError for rate. This prevents map validation and subsequent linters from running, even though a container key needs no ABI. Validate container keys without building the tree, and avoid making unrelated unsupported ABI types fatal for data-key validation. Add a regression test combining a map lookup with an unrelated fixed-point argument.
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
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.
Summary
Map references (
{"map": "$.metadata.maps.X", "keyPath": "..."}) in v2 field parameters were previously dropped with an "Unresolved map reference" warning. They are now resolved:keyPathis a$.…descriptor path): the map value is selected at conversion time and emitted as a plain constant. Hex keys (addresses) match case-insensitively.#.…,@.…): kept as a newResolvedValueMap(key path + encoded constant values) in the resolved model. Supported ontoken,chainId(tokenAmount / tokenTicker),senderAddress(addressName / interoperableAddressName),callee,selector,amount,spender(calldata) andcollection(nftName).@.chainIdor@.toare checked against every deployment, and a missing value is an error (the spec says a wallet MUST treat the descriptor as invalid in that case).@.chainId/@.tomaps resolve to constants; other keys are emitted as device side maps (MAP_REF+MAP_ENTRY).PARAM_TOKEN_AMOUNT/PARAM_TOKENcannot encode a chain id: atokenAmountchainId(plain or from a map) is ignored with a warning when it may differ from the deployment chain (tokenTickeralready warned whenever a chain id is set).Test plan
tokenAmountchainIdwarningprek run --all-files(ruff, mypy, bandit, codespell, …) passespytest tests: 327 passed, 2308 skipped (registry integration tests, not run)🤖 Generated with Claude Code