Overview
How Socket works
A pool, the hook plugged into it, the permissions that bound the hook, and the order a swap runs in.
A pool#
A Socket pool is a concentrated-liquidity market for two classic SPL tokens, called A and B. The mints are sorted by their public-key bytes, so every pair has exactly one order. The pool's price is the amount of B one A buys, in atomic units, stored as a Q64.64 square root. Liquidity providers deposit into a price range; their liquidity only trades, and only earns fees, while the price is inside that range.
Each pool has its own two vaults. Tokens never pool across markets, and no account outside the program can move them.
What a pool fixes at creation and keeps forever:
| Setting | What it is |
|---|---|
| Tokens | Mint A and mint B, sorted. |
| Starting price | The first square-root price. Liquidity added afterwards sets where it trades. |
| Tick spacing | The grid positions must sit on, from 1 to 32,768 ticks. |
| Base fee | The fee a swap pays when no hook sets one, in parts per million. |
| Max fee | The highest fee a hook may set, at most 100,000 ppm (10%). |
| Hook program | One executable, or none. |
| Permissions | Which hook points the hook runs at and what it may change. |
| Surcharge cap | The largest input surcharge a hook may add, at most 1,000 bps (10%) of the swap's input. |
| Hook compute | The most compute one hook call may use before Socket rejects its result. |
| Hook accounts | Up to eight extra accounts the hook needs, with their owners and write access. |
A hook#
A hook is any Solana program that answers Socket's callback. Socket calls it by cross-program invocation at fixed points:
- Before swap, before any pool math runs.
- After swap, after the math and before tokens move.
- Before liquidity and after liquidity, around every deposit and withdrawal.
The hook receives the pool account read-only, a signer that proves the call came from Socket for this pool, and its own extra accounts. It never receives a vault, a position account or the user's signature. It answers with a small reply: an optional fee for this swap, and an optional input surcharge.
Permissions#
The permission mask is six bits. The first four choose the hook points, the last two grant powers:
| Bit | Name | Effect |
|---|---|---|
| 1 | Before swap | The hook is called before each swap. |
| 2 | After swap | The hook is called after each swap. |
| 4 | Before liquidity | The hook is called before each deposit and withdrawal. |
| 8 | After liquidity | The hook is called after each deposit and withdrawal. |
| 16 | Fee override | The before-swap reply may set this swap's fee, up to the pool's max fee. |
| 32 | Input surcharge | The after-swap reply may add a charge, up to the pool's surcharge cap. |
Points the mask leaves out are never called. A reply that uses a power the mask doesn't grant fails the transaction.
The order a swap runs in#
A swap is one Solana instruction and one transaction. Every hook call happens inside it, so a hook that fails, overspends its compute or replies out of bounds reverts the whole swap. Nothing is charged and nothing moves. Routers rely on that: a failed simulation simply means the route goes elsewhere.
Liquidity#
Positions are program accounts derived from the pool, the owner and a nonce. A position holds one range and its liquidity, and accrues its share of the LP fee in both tokens. Adding and removing liquidity run the before- and after-liquidity hooks when the mask wires them, which is how a hook can enforce a lockup, admit only certain ranges or track incentives.
Deposits round up and withdrawals round down, so rounding never takes value from the pool. The few atomic units of dust that rounding leaves stay in the vaults.
What a hook can't do#
The bounds are enforced by Socket, not by the hook's good behavior:
- It can't move tokens: it never sees a vault or the user's signature.
- It can't set a fee above the pool's max fee, or add a surcharge above the cap.
- It can't run past the pool's hook compute without the swap being rejected.
- It can't call back into the pool: the pool is locked while the hook runs.
- It can't change its own permissions, caps or accounts after creation.
What it can do inside those bounds is the reason to check a pool's hook before you trade in it. See Bounds for each limit in detail.