Exact input and exact output swaps
Choose which amount to fix, protect the other amount, and account for fees on both sides.
grapl exposes two swap instructions over the same pool, hook interface, and settlement checks. Both operate on integer token atoms and enforce a square-root price limit.
| Mode | You choose | Your protection | Result |
|---|---|---|---|
swap / ExactIn | Input budget amount_in | minimum_out and price limit | Actual consumed input and net output |
swap_exact_out / ExactOut | Exact net amount_out | maximum_in and price limit | Required input, bounded by your maximum |
Use the instruction reference to match each mode to its account and argument contract.
ExactIn: start from a budget
For an A→B swap, the program validates accounts and asks BeforeSwap for approval and any permitted fees. It applies the input fee, walks the curve or CLMM segments, then settles actual input and net output. AfterSwap sees the settled amounts.
On the direct CLMM instruction, a price limit can leave input unspent. SwapOutcome.amount_unspent is explicit; do not assume the full budget moved. The standard Metis adapter requires a complete ExactIn fill and rejects an incomplete quote.
ExactOut: start from what the recipient receives
An ExactOut request for 10,000 B atoms means 10,000 atoms after a configured hook output deduction. The program solves for sufficient gross output, then sufficient input including the input fee. It rounds costs upward and enforces maximum_in before committing settlement.
required net output
→ gross output sufficient for the output fee
→ net input sufficient for the curve traversal
→ gross input sufficient for the input fee
→ require gross input ≤ maximum_inInsufficient liquidity, an unreachable price limit, or a maximum input that is too small fails the transaction. ExactOut does not silently downgrade to a partial delivery.
The output fee is separate
For gross output g and output rate r in ppm:
output_fee = floor(g × r / 1,000,000)
net_output = g − output_feeFor example, at 5,000 ppm (0.5%), gross output 10,050 gives an output fee of 50 and a net output of 10,000. The inverse calculation must respect integer rounding; dividing a human decimal by 1 − rate and truncating is unsafe.
The input fee remains in the input asset. The output fee is in the output asset and sent by the core to the declared recipient. Adding those atom counts together would mix units.
Hooks receive the swap mode
ABI 4 adds HookSwapDetails.exact_output. A hook can distinguish an input budget from an output target rather than inferring intent from the quantity alone. The snapshot also contains pool_mode, so the same policy can handle a virtual-reserve curve and its graduated CLMM.
Rewards should use HookSettledSwap.actual_output or the relevant actual input, rather than the user's requested budget. The core validates the lifecycle envelope and the hook's account permissions in both modes.
Transaction construction and quotes
Use the current generated IDL for account order. A CLMM trade supplies canonical tick pages followed by hook extras; each operation validates its own account list. The native Metis encoder supports both modes. Public routing availability depends on the routing provider’s integration.
Read instructions, hook authentication, and Jupiter integration for their separate contracts.