> ## Documentation Index
> Fetch the complete documentation index at: https://docs.panofx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How it works

> One swap from request to settlement, and why nobody's funds are ever held.

## Three ideas

**A signed promise.** A resolver does not send tokens when it quotes. It signs a message that says: "I will
give 15,508.06 USDC to whoever hands me 25,000,000 cNGN, if it happens before 12:00:30 and only if the
person executing is wallet 0xTaker." That message costs nothing to make and is worthless to anyone except
that taker.

**Pull by signature.** Permit2 is a contract, deployed by Uniswap at the same address on every EVM chain,
that lets a token holder authorize a transfer with a signature instead of a transaction. The resolver
approves Permit2 once. From then on Permit2 moves the resolver's USDC only when shown a valid resolver
signature naming the exact amount, the exact spender, a one-time nonce and a deadline. The USDC stays in
the resolver's wallet until the moment it is pulled.

**One transaction.** The settlement transaction checks the resolver's signature, pulls the resolver's USDC
to the taker, then pulls the taker's cNGN to the resolver and the fee to the treasury. All of that is one
atomic unit. There is no moment where one side has paid and the other has not.

## One swap on Base

A taker sells 25,000,000 cNGN. Mid is 1,612. A resolver quotes 1,612.05, which is 15,508.06 USDC. The
protocol fee is 5 bps of the USDC, 7.754030 USDC. The keeper's gas for this fill is quoted at 0.10 USDC.
The taker nets 15,500.21 USDC and never touches ETH.

```mermaid theme={null}
sequenceDiagram
    autonumber
    participant T as Taker
    participant R as Relay
    participant N as Resolver nodes
    participant K as Keeper
    participant C as Base contracts
    participant I as Indexer

    T->>R: POST /v1/quotes (25,000,000 cNGN → USDC)
    R->>N: RFQ over WebSocket, 1.5 s window
    N-->>R: Signed offers (Permit2 limit orders)
    R->>R: Validate, rank, simulate the best
    R-->>T: Firm quote: proceeds, fee line, gas line, typed data
    T->>T: Sign TakerAuth (EIP-712, no gas)
    T->>R: POST /v1/executions (signature)
    R->>K: Hand to the keeper leader
    K->>C: PanofxExecutor.execute(...) and pay gas
    C->>C: Reactor pulls USDC from resolver, executor pulls cNGN from taker, pays proceeds, fee and gas
    C-->>I: Fill event
    I-->>T: GET /v1/quotes/:id shows settled, then final
```

| Step | Who      | What happens                                                                                                                                                                                                                                                                                   |
| ---- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1    | Taker    | Types the size and requests a quote from the web app or the API                                                                                                                                                                                                                                |
| 2    | Relay    | Broadcasts the request to every online node on the corridor: pair, side, size, the taker's address and a short reply window                                                                                                                                                                    |
| 3    | Node     | Prices it from its rate and spread, checks its USDC balance and Permit2 allowance, and signs a limit order: input 15,508.06 USDC from itself, output 25,000,000 cNGN to itself, deadline in 90 seconds, validation contract `PanofxValidation` naming the executor and this taker, fresh nonce |
| 4    | Relay    | Collects offers, ranks by USDC out, checks the best against what the chain will enforce, simulates it end to end, and returns a firm quote with the fee and gas as separate lines                                                                                                              |
| 5    | Taker    | Signs one EIP-712 message: a Permit2 authorization with a `TakerAuth` witness. "The executor may pull 25,000,000 cNGN from me for exactly these offers, must deliver at least 15,500.21 USDC to my address, may charge at most 0.12 USDC of gas, before 12:00:30." No transaction, no gas      |
| 6    | Keeper   | Submits `PanofxExecutor.execute(offers, takerPermit, takerAuth, takerSig, gasFee)` and pays the gas                                                                                                                                                                                            |
| 7    | Executor | Checks the offers hash matches the taker's signed authorization and that every offer names this executor and this taker, then calls the reactor                                                                                                                                                |
| 8    | Reactor  | Decodes each order, asks the fee controller for the fee output, checks the deadline, calls `PanofxValidation`, and has Permit2 burn the resolver's nonce and move 15,508.06 USDC from the resolver to the executor                                                                             |
| 9    | Executor | Inside the reactor's callback: pulls 25,000,000 cNGN from the taker through Permit2, sends 15,500.21 USDC to the taker's recipient and 0.10 USDC to the keeper, and reverts if the net is below the taker's minimum                                                                            |
| 10   | Reactor  | Pulls each output from the executor: 25,000,000 cNGN to the resolver, 7.754030 USDC to the treasury. Emits `Fill`. The executor's balance of both tokens is now zero                                                                                                                           |
| 11   | Indexer  | Sees `Fill`, writes the settlement, the lifecycle page flips to "settled", the receipt is generated                                                                                                                                                                                            |

If anything in steps 8 to 10 fails, the transaction reverts at that point and everything before it is
undone. The keeper paid gas and nothing else. There is nothing to refund.

<Info>
  **First-time approvals.** Permit2 can only pull a token the taker has approved to it once. USDC implements
  EIP-2612, so that approval is a signature the executor submits inside the same transaction. cNGN does not,
  so a first-time cNGN seller sends one small approval transaction. After that every swap is gasless.
</Info>

## On Solana

Solana settles through a vendored copy of Jupiter's audited order-engine program. The resolver signs the
settlement transaction as maker when it answers the request. The taker co-signs. The relay's keeper signs
last as fee payer and submits, so the taker needs no SOL. The taker repays the keeper in the pair's dollar
token inside the same transaction. See [Solana settlement](/protocol/settlement-solana).

## Why funds are safe

* **Nothing is prefunded.** Both sides' tokens sit in their own wallets until a valid signature pulls them.
* **The taker's signature is a contract.** It names the exact offers, recipient, minimum proceeds, maximum gas fee and deadline. The executor reverts if any of those is not met.
* **An offer is useless to anyone but its taker.** Front-running an offer is impossible.
* **An offer dies at its deadline, and a signature can be used once.** Permit2 enforces both.
* **Neither the reactor nor the executor keeps tokens.** Both end every call with a zero balance, enforced by a fork test on every commit.
* **The fee can never exceed 5 bps.** The reactor rejects any fee output above that.
* **The keeper is a convenience, not a gate.** Anyone holding the offers and the taker's authorization can submit. The taker can submit it themselves with a zero gas fee.

The full list of invariants is under [Security model](/protocol/security).
