Skip to content

Common Test Strategy - #2586

Merged
hesterbruikman merged 52 commits into
ethereum:masterfrom
manuelwedler:common-test-strategy
Jul 1, 2026
Merged

hesterbruikman merged 52 commits into
ethereum:masterfrom
manuelwedler:common-test-strategy

Conversation

@manuelwedler

@manuelwedler manuelwedler commented May 21, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Goal: Introduces a multi-runner reference-test pipeline so any conformant clear-signing implementation can be validated against the registry, alongside Ledger's existing tests.
  • Schema: New v2 test schema (specs/erc7730-tests-v2.schema.json) replaces the legacy flat expectedTexts array with a structured { intent, interpolatedIntent?, owner, fields } shape that mirrors what wallets render. Tests live in registry/<entity>/testsv2/ and reference their descriptor explicitly. An optional dataProvider block supplies mock token metadata and address-name lookups so runners don't need network access.
  • Runner output: Unified runner output spec under .github/test-results/ defines the single results.json shape every runner emits (runner, implementation, cases[].{status, rendered|error}), with pass/fail/error/skipped examples.
  • CI: Three composite actions (run-ledger-tests, run-sourcify-tests, run-rust-tests) run in parallel on every PR. Results are collated into a single PR comment with one column per implementation, showing per-case pass/fail and a diff against expected output. The workflow fails when any case fails or when a touched descriptor has no testsv2/ file.
  • Gating: Cross-repo PRs require a maintainer to add a run-tests label before any runner executes; same-repo PRs run automatically. This gating can be removed if the updated Ledger test runner doesn't rely on private repos or secrets anymore.
  • Example: A migration of existing tests to the new schema, exercising the full pipeline, can be seen here: test: migrate v1 .tests.json fixtures to v2 (part 1: all entities except permit & morpho) manuelwedler/clear-signing-erc7730-registry#2 — still in progress; not all tests have been ported to the new format yet.

What's missing

  • Ledger updating their test runner to consume the new testsv2/ input format and emit the unified results.json output format.
  • Migration of all existing test files to the new test file schema.
  • Cleanup of legacy tests/ artifacts once Ledger's runner has migrated and all test files are ported; the testsv2/ folder can then be renamed back to tests/.

llbartekll and others added 20 commits May 11, 2026 10:24
Structured per-field assertions for aave/calldata-lpv2 descriptor (3 cases:
Repay All USDC, Manage collateral, Withdraw Max WETH). New workflow_dispatch
runs the cs-test binary from llbartekll/clear-signing against the file with
hardened token permissions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move all Ledger-specific test steps (DMK + Speculos setup, coin-apps
checkout, descriptor preprocessing, cs-tester invocation, artifact
uploads) from the run-tests job into a composite action at
.github/actions/run-ledger-tests/. The workflow now calls the action
with the matrix values and secrets as inputs.

Prepares the workflow for adding sibling Sourcify TS and Bartek Rust
runner jobs without duplicating the orchestration logic. Behavior of
the Ledger pipeline is unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Define the output contract between clear-signing test runners and the
post-results job: every runner writes a single results.json per
descriptor with a fixed shape (runner, implementation, cases[]).
`rendered` mirrors the test schema's `expected` shape so the two can
be compared structurally; status is pass/fail/error/skipped.

Lives under .github/test-results/ with a README spec and four example
files covering each status value. No CI wiring yet — this just nails
down the contract so the Sourcify TS and Bartek Rust runners can be
implemented against it in parallel.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the @ethereum-sourcify/clear-signing-test-runner alongside the
existing Ledger runner. The new runner consumes the unified results.json
contract; future runners (Bartek Rust) can reuse the same plumbing.

Per-runner: .github/actions/run-sourcify-tests/ — clones and builds
sourcifyeth/clear-signing-test-runner, invokes its CLI against a tests
fixture, writes results.json.

Shared: .github/actions/upload-test-results/ — validates basic
results.json structure with jq and uploads as
results__<slug>__<entity>__<descriptor>. Double-underscore separator
avoids ambiguity with hyphens in slugs/descriptors.

Workflow: adds detect-shared-tests, sourcify-tests, and
post-implementation-results jobs. Sourcify discovers tests in
shared-tests/ (parallel to the existing tests/ path that Ledger still
uses). Post job produces a separate PR comment with a per-case ×
per-implementation column table — Bartek joins later by slotting a
column.

Both detect jobs now also trigger when only a test file changes
(previously only descriptor changes did), deduplicated when a PR
changes both. Required-file existence is still enforced.

Spec note added to .github/test-results/README.md: runners are
responsible for resolving ERC-7730 includes themselves.

Cleanup: hardcode the Ledger DMK repo/ref (removed dmk-repo and
dmk-ref inputs, since neither is meaningful to override per call).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Change notify-missing-tests to gate only on detect-shared-tests rather
than both detect jobs. Every descriptor change should have a matching
shared-tests/ file going forward, regardless of whether an old tests/
file exists for Ledger. Comment already directs contributors at the
shared-tests/ path. Excludes both tests/ and shared-tests/ folders
from the changed-descriptor scan so test files are not misread as
descriptor changes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rename registry/<entity>/shared-tests/ → registry/<entity>/testsv2/
across the codebase. Updates the only existing file under aave (via
git mv to preserve history) and every reference in CI workflows:
job name detect-shared-tests → detect-testsv2, path globs,
files_ignore patterns, downstream needs/if expressions, the
notify-missing-tests comment body, and the validate-rs.yml path.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
check-permissions previously used head.repo.fork to decide whether to
require a maintainer-applied run-tests label. That property is true
for any repo that is itself a fork — even when a PR is intra-fork
(head and base are the same fork). Same-repo PRs are not a security
risk and shouldn't be gated.

Switch to comparing head.repo.full_name vs base.repo.full_name. Cross-
repo PRs (the only case where head SHA is untrusted code with secret
access) still require the label; same-repo PRs run without it. Behavior
on upstream is unchanged for the two scenarios that matter there
(internal PRs run; fork PRs need the label). Intra-fork PRs — used
for CI testing — now work as expected.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The post-results comment was always saying "No implementation test
results found" even though the Sourcify artifact uploaded successfully.
Two root causes, both fixed here:

1. github-script's CWD assumption.
   The script used a relative path `fs.readdirSync('artifacts')` inside
   an empty try/catch. Any failure left artifactDirs = [] silently. Use
   process.env.GITHUB_WORKSPACE for an absolute path and surface
   diagnostics via core.info / core.warning so a future regression
   can't hide.

2. actions/download-artifact@v8 single-artifact extraction.
   When `pattern:` matches exactly one artifact, v8 extracts contents
   directly into `path` instead of creating the documented
   `<artifact-name>/` subdir. That made the per-subdir parsing match
   nothing on a single-runner PR; when a second runner joins the
   resulting `results.json` files would have collided in the same
   directory anyway.

   Fix the layout end-to-end: the upload composite copies the source
   results.json to `<slug>__<entity>__<descriptor>.json` (guaranteed
   unique per matrix entry) before uploading, the download step uses
   `merge-multiple: true` to land all files flat, and the post-results
   script reads every `*.json` in the artifacts root and parses
   entity/descriptor from the filename. This shape works regardless
   of how many runners are present and how v8 chooses to flatten.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
pull_request.yml previously only ignored registry/**/tests/**. The new
testsv2/ folder wasn't excluded, so test files there matched the
calldata-*.json glob (because .tests.json ends in .json) and were
treated as descriptors by erc7730 lint / check-jsonschema, failing
validation.

Add registry/**/testsv2/** and a catch-all registry/**/*.tests.json
to the files_ignore lists in both validate_descriptors and
validate_schemas. Catches future test-format folders too.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous comment was a compact status table only. On a failure
the reviewer had to dig into Actions logs to find out what diverged.
Add a Details section below the table with one <details> block per
non-pass case (collapsed by default). Scales cleanly to N runners.

For fail: expected (loaded from the test file at PR head) vs got
(rendered from the runner) as side-by-side JSON code blocks, plus
the runner's optional message.
For error / skipped: just the message — the only signal those
statuses carry.

The details summary line uses the same left-to-right column order as
the status table: <icon> <entity>/<descriptor> · <case> · <impl>.

Implementation: post-implementation-results now also checks out the
PR head registry tree so it can load the expected block from
registry/<entity>/testsv2/<descriptor>.tests.json. Read-only access
to test data — no execution of PR code, so safe under
pull_request_target.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Test files in testsv2/ follow a different shape than the original
tests/ files: top-level descriptor + dataProvider fields, every test
has a required description and a structured expected block
({intent, owner, fields}) instead of a flat expectedTexts array.
Field values are strings or — for calldata-formatted fields —
nested {intent, owner, fields} objects (recursive). See
.github/test-results/README.md for the matching results format.

Copied erc7730-tests.schema.json as the starting point and adapted.
The v1 schema stays in place to validate legacy tests/ files
during the migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
validate_schemas previously ignored all test files (kept them out of
the changed-files glob entirely). Now it includes them and dispatches
the schema by folder:

  registry/**/tests/*.tests.json   → specs/erc7730-tests.schema.json
  registry/**/testsv2/*.tests.json → specs/erc7730-tests-v2.schema.json

For everything else (descriptors, common-* files, ercs/*) the previous
$schema-field-based logic stays unchanged.

Folder-based dispatch is used because legacy v1 test files lack a
$schema field and we don't want to require contributors to add it
during the migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Point at testsv2/ as the new folder, describe the descriptor +
dataProvider top-level wrapper, replace expectedTexts arrays with
the structured expected.{intent, owner, fields} block. Updated
calldata and EIP-712 examples and field tables to match.

The registry structure diagram earlier in the README still points at
the legacy tests/ folder; that one will move with the broader test
file migration.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The example in the spec uses a calldata case; a reader could
plausibly wonder whether EIP-712 produces a different shape. It
doesn't — both calldata and EIP-712 test cases use the same
{intent, owner, fields} expected/rendered block. Add a single line
to make that explicit.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add a third implementation runner alongside Ledger and Sourcify. The
runner builds llbartekll/clear-signing's cs-test binary from source and
invokes it with the new --output flag so it emits a spec-conforming
results.json (per .github/test-results/).

Composite action: .github/actions/run-rust-tests/. Hardcoded to
manuelwedler/llbartekll-clear-signing@cs-test-results-json for now;
will switch to upstream llbartekll/clear-signing once the contract
adaptation is merged there.

Workflow: new rust-tests job mirrors sourcify-tests (matrix on
detect-testsv2, calls run-rust-tests then upload-test-results with
slug rust-clear-signing). post-implementation-results now also needs
rust-tests so the PR comment table includes its column.

The legacy validate-rs.yml workflow stays in place for now and will be
deleted in a follow-up commit once this path is verified.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The Rust composite was failing at the checkout step because the
cs-test-results-json branch in manuelwedler/llbartekll-clear-signing
contains a stray .claude/worktrees/competent-joliot-876b10/ directory
(leftover from a Claude Code subagent worktree that got committed by
mistake). actions/checkout's post-step runs `git submodule foreach`
unconditionally to clean up auth, and that fails with exit 128 since
the directory looks like a submodule but isn't in .gitmodules. The
checkout step then reports failure even though the files are on disk,
and the rest of the composite (cargo build, cs-test run) is skipped.

Replace actions/checkout with a plain `git clone` for that one repo
and `rm -rf rust-test-runner/.claude` so cargo doesn't see anything
weird either.

Temporary — drop this once the source branch is cleaned up.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Superseded by the run-rust-tests composite + rust-tests job in
clear-signing-tests.yml, which produces results.json conforming to
.github/test-results/ and feeds into the unified PR comment.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ment

Previously the PR could end up with two separate bot comments — one
"## Clear Signing Implementation Results" (per-runner status table)
and one "## Clear Signing Tests" (missing-tests warning) — and the
warning wouldn't go away once tests were added.

Unify under a single "## Clear Signing Tests" comment that both jobs
update via startsWith('## Clear Signing Tests') matcher:

- post-implementation-results (runs when has_tests=true) writes the
  status table.
- notify-missing-tests (runs when has_tests=false) writes the warning,
  or deletes the existing comment if no descriptors changed either
  (handles the case where the user reverts a descriptor change after
  the warning had been posted).

Mutually exclusive on has_tests, so no race between the two jobs.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The runner composite actions exit 0 when they ran cleanly even if
some test cases failed (per the runner contract — non-zero is reserved
for runner-level failures). Until now nothing aggregated that
information into a failed status check, so PRs with failing tests
showed an all-green CI.

Have the two summary jobs set the job as failed where it matters:

- post-implementation-results sets failed if any case has a non-pass
  status (fail / error / skipped), or if no result artifacts were
  uploaded at all when we expected them.
- notify-missing-tests sets failed when it posts the warning
  (a descriptor changed without a matching testsv2 file).

setFailed runs AFTER the comment is posted so the PR comment still
shows the table or the warning even when the check goes red.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ples

For descriptors that use a templated intent (placeholders against
transaction data), tests should be able to assert both the literal
action label and the fully-rendered string separately. Adds an
optional `interpolatedIntent` string to the renderedOutput shape
that both `expected` (in test files) and `rendered` (in results.json)
can carry.

Updates:
- specs/erc7730-tests-v2.schema.json: add interpolatedIntent (optional)
- .github/test-results/README.md: field table + example shape
- .github/test-results/pass.example.json: example with both fields
- README.md: dedicated 'The expected block' field table

Runner-side support is a separate todo — once runners emit
interpolatedIntent the migration script will pick up matching
expected values, and tests can opt in by including the field.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation ci Changes to continuous integration descriptors Changes to clear signing descriptors specifications Changes to ERC-7730 specifications labels May 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Clear Signing Tests

⏳ Waiting for maintainer approval to run tests.

This PR is from a fork. A maintainer needs to add the run-tests label to trigger the clear signing tests.

Once approved, the tests will run automatically and post screenshots here.

Renames .github/test-results/ to .github/test-runner-docs/ and rewrites
the README as a general guideline for implementing a clear-signing test
runner: declares the input contract (pointing to the v2 tests schema and
the contributor-facing Reference test cases section in the main README),
keeps the results.json output spec, and links to run-sourcify-tests as a
reference implementation. Updates path references in composite actions
and the v2 tests schema description.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@manuelwedler
manuelwedler marked this pull request as ready for review May 22, 2026 06:15
…ept permit & morpho)

Migrates 108 v1 fixtures across 34 entities (1inch, aave, benqi, circle,
consensus-specs, degate, dispatch, ethena, figment, hyperliquid, kiln,
ledgerquest, lens, lido, lifi, lombard, midas, okx, opensea, p2p, paraswap,
poap, rarible, safe, serenita, smartcredit, starkgate, swell, swissborg,
tally, uniswap, walletconnect, weth, yieldxyz) to the v2 schema.

Each fixture restructures v1's flat expectedTexts into v2's
{intent, owner, fields} and adds a dataProvider block with tokens/
addressNames/ensNames populated by Etherscan v2 + on-chain RPC lookups
(symbol/decimals/name). Addresses normalized to EIP-55; deadlines/
expirations converted to 24h UTC with Z suffix. Test descriptions
made unique within each file (required as join key by the runners).

Hand-fixed test-data bugs surfaced by Sourcify:
- 1inch: V3 rawTxs signed so the runner can recover Beneficiary
- circle: addresses, dataProvider, RFC-3339-ish timestamps
- kiln Vault-EURC: dataProvider symbol EURC (not Ledger CAL's EUROC)
- kiln Vault-{RLUSD,USDC,USDT,USDe}-Euler-Yield: added vault address to
  dataProvider with vaultTicker symbol; updated Redeem amounts from
  Ledger-truncated keey* to canonical kEuler*
- kiln batch-deposit-v2: replaced OCR-truncated Signatures with full hex
- kiln fee-splitter-factory: dropped Transaction:"signed" placeholder
- lens lenshub: 8 IPFS-URI cases were OCR-split with spaces; Comment/mint
  had sibling labels leaking into values; Follow/Unfollow array fields
  now use the last element (runner's behavior)
- lens token-handle-registry unlink_with_sig: typed-data domain corrected
  from {name:"Example",version:"1"} → Lens Protocol Profiles v2
- lifi LIFIDiamond: added XPR/XEN/TRX/DEVVE to dataProvider; signed
  unsigned rawTxs; fixed Swap (2)/(5) expected
- midas: switched to dataProvider.addressNames for token-name lookup
- paraswap V6.2: added the missing dataProvider.tokens block; added
  Beneficiary to 8 cases; matched runner's "Sender" literal
- uniswap UniswapV3Router02: removed spurious space in "0.3 %" unit
Migrates 131 v1 fixtures:
- permit: 74 EIP-712 ERC-2612 Permit messages across 12 chains. V1 had no
  field values (only labels); rebuilt expected.fields from data.message:
  Spender (EIP-55 checksum), Max spending amount (formatted via
  verifyingContract symbol/decimals), Valid until (24h UTC + Z).
  Each test's dataProvider.tokens[verifyingContract] is populated via
  on-chain symbol()/decimals()/name() lookups — Etherscan v2 for the
  chains they cover for free, public RPC for Avalanche/Optimism/Base/
  BSC/Fantom/Linea.
- morpho: 57 ERC-4626 vault fixtures. Each test's dataProvider.tokens
  was populated for the vault address itself plus the underlying token
  (RPC lookup for symbol/decimals/name). For calldata-MorphoBlue, rawTx
  is decoded and the full nested marketParams (Loan Token, Collateral
  Token, Oracle, Irm, Lltv) are emitted — the migration script only
  inferred top-level fields.

calldata-MorphoBundlerV3 is intentionally omitted — the v1 fixture only
labeled "Action" with no expected value (multicall calldata rendering);
leaving it out until a runner can verify the nested render.

Note: most of these will currently fail on Sourcify because the
test-runner library doesn't follow `includes` when building the format
index (permit's formats live in ercs/eip712-erc2612-permit.json; morpho
vaults' formats live in ercs/calldata-erc4626-vaults.json). Tracked
separately; PR brings the test data into v2 so it's ready when the
library lands the fix.
Migrates 30 v1 fixtures across 5 entities upstream added (ethereum#2542+):
- flyingtulip (14)
- kyberswap (1)
- layerswap (1)
- ondo-finance (4)
- threshold (10)

Test data is the initial migration script output; TODO placeholders in
expected.fields will be backfilled from runner artifacts in a follow-up
based on the deterministic rendered values from the Sourcify runner.
test: migrate v1 .tests.json fixtures to v2 (part 1: all entities except permit & morpho)
test: migrate v1 .tests.json fixtures to v2 (part 2: permit & morpho)
test: migrate v1 .tests.json fixtures to v2 (part 3: 5 new entities)
@manuelwedler

Copy link
Copy Markdown
Collaborator Author

I migrated all existing test data to the new format and fixed the Sourcify implementation to fully match the expectations. Test results can be seen in these PRs:

manuelwedler#2
manuelwedler#3
manuelwedler#4

There is only one case left failing on the Sourcify library because it is expected that it is not supported at the moment.

Temporarily mutes the per-case mismatch gate while test data and the
runners stabilise. The "N case/runner combination(s) did not pass"
finding still posts to the PR comment table and emits a yellow
::warning:: annotation in the run UI, but the step no longer fails the
workflow.

Other gates (JSON schema validation in pull_request.yml, the
notify-missing-tests guard, and the upload-test-results structural
check) are unchanged — broken test files, missing testsv2 fixtures,
and missing or malformed results.json files still fail the run.

Revert by un-commenting the core.setFailed(failureReason) call.
…<id>" form

The Sourcify and Rust runners currently disagree on how to render
nftName-format fields: Sourcify emits
  "Collection Name: pFT NFT - Token ID: 141"
while the Rust (llbartekll/clear-signing) cs-test fork emits the
shorter
  "pFT NFT ethereum#141"

We're aligning the test fixtures to the shorter form because it's the
better display for wallets. Sourcify will fail until its library
adopts the same shape; that's tracked separately.

Affects three flyingtulip fixtures (PftMarketplace, PftNft,
PutManager) covering 16 places — both expected.fields[].value entries
for Position fields and the interpolatedIntent strings that embed the
same rendering.
…lver API

Bumps sourcifyeth/clear-signing-test-runner from c48d3c3f to 9de9e288 —
"Switch to library 0.2.0's filesystem resolver". The library dropped
the embedded resolver in favour of a custom-resolver API plus a
filesystem helper; this bump aligns the runner with the new shape.
Runners don't verify signatures, so signed rawTx hex was just noise in
the fixtures (plus it leaked the test signer's address into every diff
when we re-signed during migration). This switches the convention:
rawTx is now the unsigned canonical pre-signing form, and the
recovered signer — when the test needs one for `@.from` references —
is stored in a new optional `from` field beside rawTx and txHash.

Schema:
- specs/erc7730-tests-v2.schema.json — rawTx description updated to
  "unsigned"; new optional `from` field defined (EIP-55 checksummed
  string, only required when the descriptor uses `@.from`).

Docs:
- README.md — calldata reference table updated to match.

Test data:
- 103 cases across 32 testsv2 files (1inch, aave, flyingtulip, kyberswap,
  layerswap, lido, ondo-finance, paraswap, poap, safe, threshold) had
  their signed rawTx replaced with the canonical unsigned form for the
  same envelope:
    - EIP-1559 / EIP-2930: RLP payload's last 3 elements (yParity,r,s)
      dropped.
    - Legacy: re-emitted in EIP-155 unsigned shape [..., chainId, 0, 0].
  The signer was recovered from the original signed bytes via
  Account.recover_transaction and written to the new `from` field
  (omitted if recovery failed — e.g. already-unsigned or non-tx blobs
  like kyberswap's raw-calldata fixture).
…-field

Bumps sourcifyeth/clear-signing-test-runner from 9de9e288 to 3006d68e —
"Drop rawTx ecrecovery; take signer from the new optional `from` field".
Aligns the runner with the schema change in 1504f20 that switched
rawTx to always-unsigned and added a separate `from` field.
@manuelwedler
manuelwedler force-pushed the common-test-strategy branch from 9e94a12 to ff115fb Compare June 8, 2026 13:47
manuelwedler and others added 3 commits June 9, 2026 15:44
The submit() and stakeETH() formats had `interpolatedIntent: "Stake
{@.value} ETH"`. The runner formats `{@.value}` with the native unit
(e.g. "1.078608424000534547 ETH"), so the template rendered as
"Stake 1.078608424000534547 ETH ETH" — the unit appears twice.

Drops the literal trailing " ETH" from both descriptor templates and
updates the two affected testsv2 fixtures' expected.interpolatedIntent
to match the cleaner render.
Bumps llbartekll/clear-signing from 22196d32 to 0809971c —
"fix(types): accept formats that omit `intent` (optional per spec)".
#8)

The Rust runner resolves nested-call inner descriptors (e.g. the Safe inner call,
the kiln inner deposit) only from directories it's told about. Without --registry
it sees just the test file's own dir, so nested cases (kiln fee-splitter,
Safe 1.4.1, SafeProxyFactory) can't find their inner descriptors and fail. Pass
the registry root (derived from the test-file path) so callees resolve tree-wide.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@manuelwedler

Copy link
Copy Markdown
Collaborator Author

Update: I worked together with @llbartekll to fix any issues on the Rust library too. Both libraries run all tests successfully now (only one expected failure as stated above). See the latest runs here:

…o warning"

This reverts commit 9d6ccb2.

Per-case mismatches once again fail the workflow (core.setFailed
instead of core.warning). Now that the test data and runners have
stabilised, the original "red on any unmet expectation" gate is back.
@hesterbruikman
hesterbruikman self-requested a review June 22, 2026 16:24

@hesterbruikman hesterbruikman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving based on successful test runs against React and Rust library shared

manuelwedler#5
manuelwedler#6
manuelwedler#7

@elasticroentgen there are open change requests by you. Could you please give these another review to keep if blocking, dismiss if not?

@hesterbruikman
hesterbruikman dismissed elasticroentgen’s stale review July 1, 2026 11:08

Discussed offline that comments are non-blocking

@hesterbruikman
hesterbruikman enabled auto-merge (squash) July 1, 2026 11:09
@hesterbruikman
hesterbruikman merged commit a2b33ff into ethereum:master Jul 1, 2026
13 checks passed
@manuelwedler
manuelwedler deleted the common-test-strategy branch July 1, 2026 12:12
@Rafazzzz

Rafazzzz commented Jul 3, 2026

Copy link
Copy Markdown

ab8c3b8

betocattani added a commit to betocattani/clear-signing-erc7730-registry that referenced this pull request Jul 6, 2026
Adopts the new test format introduced in ethereum#2586 (Common Test Strategy). The v2 shape lets the CI run the same fixture against multiple test runners (Ledger cs-tester, Sourcify's TypeScript runner, and the upcoming Rust runner) by declaring the rendered output structurally rather than as a loose list of expected strings.

Changes per test file:

- Moved from registry/figment/tests/ to registry/figment/testsv2/

- Points at specs/erc7730-tests-v2.schema.json

- Adds a top-level descriptor field pointing at the .json under test

- Adds a dataProvider block with token metadata (USDC/MUSDC as underlyings; xSOLY/xFIGSOL as vault share tokens) so runners execute without hitting a live RPC

- Converts rawTx from the signed form to the unsigned EIP-1559 form required by v2

- Replaces the flat expectedTexts array with a structured expected block (intent, owner, fields[]) matching the descriptor's own field order

Old-format tests under registry/figment/tests/ removed to avoid duplicate coverage; the pre-existing calldata-figment-batch-deposit.tests.json is untouched and remains under the old path since it belongs to a separate descriptor.
hesterbruikman added a commit that referenced this pull request Aug 19, 2026
* feat(figment): add Stablecoin Staking Yield clear signing descriptors

Adds ERC-7730 descriptors so wallets supporting the ERC-7730 standard render Figment's Stablecoin Staking Yield product transactions with human-readable intents instead of opaque calldata.

Three descriptor files under registry/figment/ using the includes + metadata.constants convention:

- common-figment-pool-dynamic.json — shared display formats for deposit and requestRedeem, parameterized over the underlying token

- calldata-PoolDynamic-USDC.json — mainnet USDC vault (0xe1b1252652A2FF0CC3A4214eE73d9FeD1FEa5b4f)

- calldata-PoolDynamic-MUSDC-sepolia.json — Sepolia vault (0xD1f0774ccff0CE4F36DeA57b6a28aB7FeB0a01B0); underlying is a Mock USDC (MUSDC) at 0xfd4f11A2aaE86165050688c85eC9ED6210C427A9

Two test files under registry/figment/tests/ with real on-chain deposit + requestRedeem transactions for both mainnet and Sepolia.

On-device labels (all within the 30-char display limit):

- Mainnet $id: "Stablecoin Staking Yield USDC" (29)

- Sepolia $id: "Stablecoin Staking Yield MUSDC" (30)

- deposit intent: "Deposit into Stablecoin Vault" (29)

- requestRedeem intent: "Redeem from Stablecoin Vault" (28)

Scope is customer-only: deposit + requestRedeem. Operator functions (acceptRedemption, repayRedemption, setExchangeRate, depositOffChain, changeRedemptionDestination, etc.) are signed by Figment's settlement infrastructure (HSM/MPC), never by end users. Mainnet and Sepolia are separate descriptors because metadata.constants is flat per descriptor and the underlying tokens differ across chains (USDC vs MUSDC at different addresses); both reference the same common-*.json so display logic stays single-sourced.

* chore(figment): migrate tests to v2 format

Adopts the new test format introduced in #2586 (Common Test Strategy). The v2 shape lets the CI run the same fixture against multiple test runners (Ledger cs-tester, Sourcify's TypeScript runner, and the upcoming Rust runner) by declaring the rendered output structurally rather than as a loose list of expected strings.

Changes per test file:

- Moved from registry/figment/tests/ to registry/figment/testsv2/

- Points at specs/erc7730-tests-v2.schema.json

- Adds a top-level descriptor field pointing at the .json under test

- Adds a dataProvider block with token metadata (USDC/MUSDC as underlyings; xSOLY/xFIGSOL as vault share tokens) so runners execute without hitting a live RPC

- Converts rawTx from the signed form to the unsigned EIP-1559 form required by v2

- Replaces the flat expectedTexts array with a structured expected block (intent, owner, fields[]) matching the descriptor's own field order

Old-format tests under registry/figment/tests/ removed to avoid duplicate coverage; the pre-existing calldata-figment-batch-deposit.tests.json is untouched and remains under the old path since it belongs to a separate descriptor.

---------

Co-authored-by: hesterbruikman <hester.bruikman@ethereum.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Changes to continuous integration descriptors Changes to clear signing descriptors documentation Improvements or additions to documentation specifications Changes to ERC-7730 specifications

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants