AMMs in solana do not happen to support flash swaps natively, this repo implements flash swaps for a constant product AMM for solana, we use pinocchio instead of anchor to reduce bloat, and mollusk_svm for testing.
Flash swaps were first introduced by uniswap v2, its a feature that allows you to receive tokens upfront without paying, and pay back at the end of the transaction, just like a flashloan, but we receive the output token of the swap instead (and not what you flash borrowed).
In traditional AMMs, instruction data carries fields like mint, amount_in, and min_amount_out. Our design adds a single flags byte to that payload, that acts as a bitmask where each bit independently enables a feature. Bit 0 is the flash swap bit: when set, the handler takes the flash swap path; when clear, it takes the normal swap path. This way we don't need a separate instruction to flash swap.
Visualisation
FLAG_FLASH_SWAP = 0b0000_0001
^
bit 0 (LSB) = "flash swap" bit
bits are numbered right to left, 0 = least significant:
position: 7 6 5 4 3 2 1 0
│ │ │ │ │ │ │ │
value: 0 0 0 0 0 0 0 1
^
LSB — this is what & 0b0000_0001 isolates
is_flash_swap() = (flags & 0b0000_0001) != 0
normal swap: flash swap:
0b0000_0000 0b0000_0001
& 0b0000_0001 & 0b0000_0001
───────────── ─────────────
0b0000_0000 0b0000_0001
= 0 → false != 0 → true
If it is a flash swap, the program optimistically transfers output tokens to the user first, then introspects the transaction's instruction list to verify a valid repayment exists.
Then, it scans for an SPL Token Transfer instruction where the user sends
the correct token and the correct amount back to the right source vault — no separate
repay or swap_payback instruction needed.
To build the project run cargo build-sbf at root
To run all tests run cargo test at root
IBRL