Skip to content

Make squidRouterApproveHash optional in fundEphemeral verification#1274

Open
ebma wants to merge 1 commit into
stagingfrom
fix/optional-squid-approve-hash
Open

Make squidRouterApproveHash optional in fundEphemeral verification#1274
ebma wants to merge 1 commit into
stagingfrom
fix/optional-squid-approve-hash

Conversation

@ebma

@ebma ebma commented Jul 17, 2026

Copy link
Copy Markdown
Member

Problem

FundEphemeralPhaseHandler.verifyUserSubmittedSquidHashes required both squidRouterApproveHash and squidRouterSwapHash before proceeding. Users whose wallet already holds a sufficient allowance for the squid router never broadcast an approve tx, so they have no approve hash to report — and their ramp parked forever in fundEphemeral even though they had already paid.

Fix

  • The approve hash is now optional: verification is skipped when no hash is reported, but when one is reported it is verified against the blueprint with unchanged rigor (receipt status, from, to, calldata, value).
  • squidRouterSwapHash — the tx that actually delivers funds to our ephemeral — remains mandatory; the phase still parks recoverably until it arrives and still fails unrecoverably on content mismatch.
  • The verification gate now keys on the squidRouterSwap blueprint instead of the squidRouterApprove blueprint (they are always emitted together today, so this is behavior-equivalent, but it matches the new semantics).

Skipping a genuinely-needed approve is safe: the swap's transferFrom reverts on-chain, so the swap hash fails its own receipt-status check.

Note this matches validateRampStateData in ramp.service.ts, which already only hard-requires the swap hash at start.

Tests

New corridor tests in brl-offramp-crosschain.scenario.test.ts:

  • Pre-existing allowance: only the swap hash is reported → ramp completes end to end. Verified to fail without the handler change.
  • Tampered approve hash: a reported approve hash whose calldata differs from the blueprint still fails the ramp unrecoverably with no ephemeral funds spent — relaxing presence must not disable content verification.

Existing suites (brl-offramp-crosschain, brl-offramp, eur-offramp, mxn-offramp, sdk-contract.offramp) pass; lint + typecheck clean.

Docs

  • docs/security-spec/03-ramp-engine/transaction-validation.md (F-041 sections) updated with the optional-approve semantics.
  • OpenAPI: /v1/ramp/update description and the squidRouterApproveHash field description updated in vortex.openapi.json; .d.ts regenerated via bun docs:api:types.

⚠️ The OpenAPI JSON is exported from Apidog — the same wording change should be applied in the Apidog project so the next bun docs:api:export doesn't revert it.

Users whose wallet already holds a sufficient allowance for the squid
router never broadcast the approve tx, so they have no approve hash to
report. fundEphemeral previously parked such ramps forever waiting for
it, even though the user had already paid.

The approve hash is now verified only when reported (with unchanged
rigor); squidRouterSwapHash — the tx that actually delivers funds to the
ephemeral — remains mandatory. Skipping a genuinely-needed approve is
safe: the swap's transferFrom reverts on-chain and the swap hash fails
its receipt check. The verification gate now keys on the squidRouterSwap
blueprint instead of the approve blueprint accordingly.

Also updates the security spec (F-041 notes), the OpenAPI description
of /v1/ramp/update, and adds corridor tests for both the swap-hash-only
happy path and a tampered-but-reported approve hash.
@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy Preview for vortex-sandbox ready!

Name Link
🔨 Latest commit 7a281d8
🔍 Latest deploy log https://app.netlify.com/projects/vortex-sandbox/deploys/6a5a65ea2b2ba30008f94cd4
😎 Deploy Preview https://deploy-preview-1274--vortex-sandbox.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy Preview for vrtx-dashboard ready!

Name Link
🔨 Latest commit 7a281d8
🔍 Latest deploy log https://app.netlify.com/projects/vrtx-dashboard/deploys/6a5a65ea8600520008ffe460
😎 Deploy Preview https://deploy-preview-1274--vrtx-dashboard.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy Preview for vortexfi ready!

Name Link
🔨 Latest commit 7a281d8
🔍 Latest deploy log https://app.netlify.com/projects/vortexfi/deploys/6a5a65eac208ff0008b5057c
😎 Deploy Preview https://deploy-preview-1274--vortexfi.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Updates the SELL/offramp SquidRouter hash-verification flow so ramps no longer get stuck in fundEphemeral when no approval tx was needed (pre-existing allowance), while keeping strict by-hash validation for any hashes that are reported.

Changes:

  • Make squidRouterApproveHash optional in FundEphemeralPhaseHandler.verifyUserSubmittedSquidHashes; still verify it rigorously when provided, and keep squidRouterSwapHash mandatory.
  • Add corridor scenario coverage for “pre-existing allowance” and “tampered approve hash still fails” cases.
  • Update security spec + OpenAPI docs to reflect the optional-approve semantics.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
docs/security-spec/03-ramp-engine/transaction-validation.md Documents optional-approve / mandatory-swap verification semantics for SELL SquidRouter flows.
docs/api/openapi/vortex.openapi.json Updates /v1/ramp/update and squidRouterApproveHash descriptions to reflect optional approve hash.
docs/api/openapi/vortex.openapi.d.ts Regenerates typings/comments to match updated OpenAPI wording.
apps/api/src/tests/corridors/brl-offramp-crosschain.scenario.test.ts Adds scenario tests for missing approve hash (allowance) and for tampered approve hash verification.
apps/api/src/api/services/phases/handlers/fund-ephemeral-handler.ts Implements optional approve-hash verification while keeping swap-hash verification mandatory.
Comments suppressed due to low confidence (1)

docs/api/openapi/vortex.openapi.json:1279

  • squidRouterSwapHash is described as "if applicable", but for EVM-origin offramps it’s mandatory (the endpoint description and update-time validation gate require it). This field description should mention the conditional requirement to avoid integrators assuming it’s optional in the EVM-offramp case.
                "description": "Transaction hash for Squid Router approval. Optional: omit when the wallet already holds a sufficient allowance and no approval transaction was submitted.",
                "type": ["string", "null"]
              },
              "squidRouterSwapHash": {
                "description": "Transaction hash for Squid Router swap, if applicable.",

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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