Skip to content

fix(erc4626): accept Sky/Spark referral deposit/mint overloads (ENG-3841)#31

Open
ajag408 wants to merge 2 commits into
mainfrom
feat/eng-3841-erc4626-referral-deposit
Open

fix(erc4626): accept Sky/Spark referral deposit/mint overloads (ENG-3841)#31
ajag408 wants to merge 2 commits into
mainfrom
feat/eng-3841-erc4626-referral-deposit

Conversation

@ajag408

@ajag408 ajag408 commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes a production false block reported by DFNS: entering the sUSDS vault
(ethereum-usds-susds-0xa3931d71877c0e7a3148cb7eb4463524fec27fbd-4626-vault)
failed on the SUPPLY step with No matching operation pattern found.

The monorepo recently switched sUSDS deposit construction to Sky's referral
overload — deposit(uint256 assets, address receiver, uint16 referral),
selector 0x9b8d6d38 — which the ERC-4626 validator's ABI didn't register, so
the calldata failed to parse. Same overload exists on Spark Savings vaults
(referral 200 on L2s vs 3008 on Ethereum).

Changes:

  • erc4626.validator.ts — add deposit/mint (…, uint16 referral)
    overloads to ERC4626_ABI. All existing SUPPLY checks (receiver == user,
    amount > 0, no ETH value, vault whitelist, calldata integrity) run unchanged
    on the 3-arg path since assets/receiver keep their positions.
  • base.validator.ts — tamper check now re-encodes with
    parsedTx.fragment instead of parsedTx.name. ethers v6 throws on
    name-based lookups for overloaded functions, so without this the overloaded
    ABI would block all deposits/mints (2-arg included) with
    "Failed to validate calldata integrity". Behavior-neutral for every other
    validator — the fragment is always the one the calldata parsed as.
  • Testserc4626.validator.test.ts: 3-arg deposit passes for referral
    3008 / 200 / 0 / 65535 (accept-any), 3-arg mint passes, receiver tampering /
    appended-bytes tampering / zero amount / non-whitelisted vault all still
    block. handler.test.ts: end-to-end repro of the client's exact rejected
    transaction against the real vault registry → SAFE, plus a receiver-redirect
    variant → blocked.

Decisions (per ops context):

  • Referral value is intentionally unconstrained. Ref codes are ops-only
    attribution (they emit a Referral event, never route funds) and vary by
    chain/project (3008 Ethereum, 200 L2s, per-project dynamic codes planned).
  • No per-vault gating. OAV-routed deposits are unaffected — the wrapper
    injects the ref code internally, so Shield only ever sees 2-arg calldata on
    that path.
  • Declared-amount (ENG-2418) coverage for the 3-arg path is added after this
    branch rebases onto the 1.4.0 amount-validation PR currently in review.

Version: 1.4.0 → 1.4.1 (patch — restores validation of a legitimate,
already-whitelisted flow).

QA Proof

Local E2E via the built CLI (dist/cli.js, same handleJsonRequest entry npm
and binary consumers hit), driven by scripts/qa-eng-3841.mjs:

Screen Shot 2026-07-03 at 12 13 40 AM

Cases covered: client's exact rejected transaction → SAFE / SUPPLY;
receiver-tampered word → blocked; non-whitelisted tx.to → blocked; plain
2-arg deposit (selector 0x6e553f65) → SAFE (regression); ticket's USDS
APPROVAL tx → SAFE / APPROVAL (regression). Full unit + handler suites green.

What Needs to Be QA'd in Staging

  • sUSDS enter (base yield path, referral 3008) passes Shield validation — no SUPPLY blocks
  • Spark Savings enter on an L2 (referral 200) passes
  • Existing 2-arg ERC-4626 enters unchanged
  • Tamper smoke tests still block (mutated receiver, mutated vault address,
    appended calldata bytes)
  • Lido / RocketPool / LI.FI validations unaffected (shared
    base.validator.ts tamper-check change)

QA Team Notification

  • QA team has been notified to test in staging

Note

Medium Risk
Touches shared calldata integrity logic in BaseEVMValidator and expands which SUPPLY calldata is accepted, though referral values are unconstrained and existing receiver/amount/vault checks remain.

Overview
Fixes false SUPPLY blocks for Sky/Spark savings vaults that call deposit/mint with a uint16 referral (e.g. sUSDS selector 0x9b8d6d38), which the ERC-4626 validator could not parse before.

The ERC-4626 ABI now includes the 3-argument deposit/mint referral overloads; existing SUPPLY rules (receiver, amount, vault whitelist, no ETH) still apply because assets and receiver stay in the same argument positions. Referral codes are not constrained.

Calldata tamper re-encoding in BaseEVMValidator now uses parsedTx.fragment instead of the function name so ethers v6 can distinguish overloaded signatures without breaking integrity checks for all EVM validators.

Adds unit coverage for referral deposits/mints and an end-to-end JSON handler repro of the client’s rejected sUSDS transaction. Version 1.4.0 → 1.4.1.

Reviewed by Cursor Bugbot for commit eca2a8f. Configure here.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Risk: medium. Cursor Bugbot and Cursor Security Agent completed successfully with no reported findings. Risk exceeds the low approval threshold due to shared base-validator calldata integrity changes and expanded SUPPLY acceptance, so I am not approving; human reviewers are already assigned.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

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.

1 participant