Skip to content

fix: F-2026-18815 | restore recipient ATA create on SVM revert and rescue - #355

Closed
Aman035 wants to merge 2 commits into
audit-fixesfrom
F-2026-18815-followup
Closed

fix: F-2026-18815 | restore recipient ATA create on SVM revert and rescue#355
Aman035 wants to merge 2 commits into
audit-fixesfrom
F-2026-18815-followup

Conversation

@Aman035

@Aman035 Aman035 commented Sep 1, 2026

Copy link
Copy Markdown
Member

Follow-up to #338. That PR dropped the client-side recipient ATA create on every path, but the gateway only creates it on withdraw.

The regression

The gateway's revert and rescue take their legacy SPL branch, which does a bare pda_spl_transfer into recipient_token_account and never creates it. Only the is_pc20 branch calls ensure_associated_token_account, and buildRevertAccounts passes no remaining accounts, so is_pc20 is always false for us.

So after #338 an SPL revert or rescue whose recipient has no ATA for that mint fails on chain. It is reachable in normal use: the recipient is RevertInstructions.FundRecipient, any address the user picks, falling back to the inbound sender.

Fix

  • Restore buildCreateATAIdempotentInstruction, scoped to instruction ids 3 and 4. Withdraw (1) stays untouched since the gateway creates and meters it.
  • Test now asserts per path instead of blanket-asserting no ATA instruction. The old test had an SPL revert case pinning the broken behaviour.

Tests

  • All six combinations of withdraw, revert and rescue against native and SPL.
  • On the two paths that create it: instruction data is CreateIdempotent not Create, the account list is the canonical ATA for the recipient and mint, and the created ATA is the same account the gateway is handed in its recipient_token_account slot.
  • New TestBuildWithdrawAndExecuteAccounts_SPLSlots pins the eight SPL slots the gateway needs to create the withdraw ATA itself. Nothing covered them before, so a regression there would only surface on chain.
  • Mutation: 8 run, 8 caught, including reintroducing this exact regression.

Rent accounting

Revert reimburses the relayer the full signed gas_fee, so the rent is covered there. Rescue reimburses measured gas_used, which excludes a client-created ATA, so ~0.00204 SOL per fresh recipient stays on the relayer for that path. Closing it needs the gateway to create and meter the ATA on its legacy SPL branch, the same change it just made for withdraw in 524ae41.

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