Repository navigation
perf(svm): reuse the validated Gateway vault for in-place fills #1570
Description
Problem and expected improvement
V5TokenAccounts::load derives the canonical Gateway vault ATA and validates its token program, mint, and current token authority, then parses its balance.
V5FillAccounts::load subsequently derives and parses the recipient ATA before detecting that it is the same Gateway vault. An in-place fill therefore repeats the derivation, lookup, and parsing of an already validated account, with no intervening CPI.
Across benchmark samples 0–4, the vault ATA bumps are 253, 255, 254, 250, and 255. Eliminating the duplicate derivation targets 4,500 / 1,500 / 3,000 / 9,000 / 1,500 CU, respectively (median 3,000), plus unquantified lookup/parsing savings. PDA-work estimates use Solana's documented 1,500 CU per derivation attempt. Actual deltas must be measured on the same runtime.
This bump-dependent work contributes to external/in-place ordering differences. It is not the sole cause: the two paths also have distinct fill-status/buffer PDA bumps.
Proposed scope
When the authenticated fill recipient equals GATEWAY_VAULT_AUTHORITY, reuse the shared loader's validated vault account and parsed token state. Preserve normal recipient derivation/validation for external fills. Keep the change local to the account-loading phase; do not cache live balances or authority fields across arbitrary CPIs.
Retain all initial mint/extension/token-program checks, serialized token authority checks, writable-account requirements, the source.amount >= output_amount condition, canonical fill-status/replay checks, and events. ATA address equality alone is not sufficient token-authority validation.
In-place means recording a fill without transferring inside Spoke. The committed Gateway route must still enforce its balance floor and fully deliver/consume the applicable funds. Preserve the supported aggregate-floor rules for multiple fills; this issue does not change delivery semantics.
Acceptance criteria
- Compare external and in-place success paths and assert the same delivery classification, events, fill status, balances, and rent accounting.
- Cover insufficient balance, wrong mint/program/authority, and malformed/missing account rejection, including a canonical ATA whose serialized authority is wrong.
- Retain downstream-failure rollback and committed balance-requirement/full-consumption coverage.
- Run relevant Rust tests,
yarn test-svm-gateway, and guarded SBF builds. - Publish isolated before/after CU for all fixed fixtures, including sample 3's low vault bump, and verify repeatability before updating the CU snapshot/docs.
- No public ABI/account-order or Gateway program change.
Benchmark context and reproduction
This is a potential optimization, not a confirmed patched-binary saving. The reproducible harness is in contracts PR #1568, benchmark commit e80949f92c0a8cd1fcf17191691bd0bcaa10b479. If the harness has not merged when starting work, use that branch/commit as the measurement reference and refresh the implementation base.
The checked-in baseline measures V5 Spoke source 81a2211c27d9107a0835280d3437c05624275a20, Gateway e2b91eb0454136773728f941b33163346e039aa4, and legacy Spoke 7445f72de17900544605c7e6706c5fb3b3784738. V5 execution medians are 73,530 CU for deposit, 84,660 for external fill, and 77,369 for in-place fill followed by balance requirement and full recipient transfer. Buffer preparation is measured separately.
Run from a contracts checkout containing the harness, with installed Yarn dependencies and the documented toolchain:
SVM_SPOKE_ANCHOR="$HOME/.avm/bin/anchor-0.31.1" \
SVM_GATEWAY_ANCHOR="$HOME/.avm/bin/anchor-1.1.2" \
SVM_GATEWAY_CHECKOUT=/path/to/clean/pinned/solana-v5 \
SVM_CU_OUTPUT=target/cu-before \
yarn bench-svm-cuRepeat after the change into target/cu-after. Compare every fixed fixture, not only aggregate medians; preserve source revisions, compiler/runtime metadata, binary/IDL hashes, and raw receipts. The runner rebuilds programs. Use fresh outputs to check repeatability before deliberately updating the baseline.
The reference used Agave 4.1.2, cargo-build-sbf 4.1.0, platform-tools 1.44/1.52/1.54 for legacy/Spoke/Gateway, and Node 24.14.1. These are consumed-CU measurements using Spoke's test feature, existing ATAs, and the validator's bundled token programs, not a production CU budget. Five fixtures expose PDA-bump variation but are not a worst-case bound.
Sent from Reinis Martinsons's Codex CLI Agent using gpt-6-astra 🤖
Activity