Skip to content

fix: F-2026-18815 | follow the gateway recipient ATA creation on SVM revert and rescue - #361

Merged
Aman035 merged 7 commits into
audit-fixesfrom
F-2026-18815-gateway-ata
Sep 2, 2026
Merged

fix: F-2026-18815 | follow the gateway recipient ATA creation on SVM revert and rescue#361
Aman035 merged 7 commits into
audit-fixesfrom
F-2026-18815-gateway-ata

Conversation

@Aman035

@Aman035 Aman035 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Follows the gateway update in pc20-3rd-iteration (92a3bbe, da6cca5). Built on current audit-fixes. Replaces #355.

Gateway now creates the recipient ATA everywhere

  • Dropped the client-side prepend and buildCreateATAIdempotentInstruction. Creating it here makes the gateway see the account already present, leaving the rent outside gas_used, which is the original F-2026-18815 leak.
  • buildRevertAccounts gained the two slots the gateway needs to do the create: associated_token_program at 12 and rent at 13. Native passes six None sentinels instead of four. Rescue shares the builder.
  • This also closes the liveness bug the gateway fixed: revert and rescue used to require the recipient ATA to already exist, so a signed recipient without one stranded the funds.

Revert no longer reports a gas fee

  • RevertUniversalTx dropped gas_used. Offset 144 now holds revert_instruction, so the old read reported pubkey bytes as lamports.
  • Nothing needs the value: applyGasRefund returns early for INBOUND_REVERT, and it is the only outbound type whose event lacks it. Rescue still carries it in FundsRescued, withdraw and execute in UniversalTxFinalized, and both of those do refund.
  • The vote still reports "0" rather than empty. Core rejects an empty gas_fee_used and the value feeds the outbound ballot key, so it has to be present and identical across validators.

Tests

  • No client-side ATA create on any of the six withdraw/revert/rescue by native/SPL combinations.
  • On SPL revert and rescue the gateway gets the canonical recipient ATA plus the ATA program and rent sysvar, account list pinned at 14.
  • A revert votes "0", reaches quorum and refunds nothing, end to end across three validators.
  • Mutation: dropping the two new slots, reverting the sentinel count, deriving the recipient ATA from the vault, and removing the empty-to-zero default each fail the suite.

Note for whoever sizes gas_fee

gas_fee is now a ceiling and must cover ATA rent (~2,039,280 lamports) when the recipient's canonical ATA does not exist, or the gateway trips InsufficientGasBudget before any lamport moves. The client does not choose this value; it comes from the outbound event.

@Aman035
Aman035 merged commit 05996bb into audit-fixes Sep 2, 2026
8 checks passed
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