Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

SwapPool

Vault + swap engine. ERC-20 metadata (name/symbol/decimals) but no LP tokens.

Proxy: yes. Implementation 0x9e694D34…4160D.

Injected deps

Set in initialize or later via setters, until sealed.

SlotInterfaceIf unset
tokenRegistryhave(address)any token allowed
tokenLimiterlimitOf(token, pool)uncapped
quoterIQuoter1:1
feePolicygetFeepool fee 0
feeAddressn/afees not accrued
protocolFeeControllergetProtocolFee + recipientno protocol fee
feesDecoupledn/afees stay in inventory

Swap

Prefer the bounded form:

withdraw(tokenOut, tokenIn, value, recipient, minAmountOut, deadline)

Shorter overloads send to msg.sender and skip slippage/deadline.

Flow (nonReentrant):

  1. tokenIn == tokenOutInvalidToken.
  2. Deposit tokenIn. Registry + limiter apply. received is the balance delta (fee-on-transfer safe). Zero delta → TransferFailed. Emits Deposit.
  3. quotedValue = quoter.valueFor(tokenOut, tokenIn, received) (or received if no quoter).
  4. Pool fee: quotedValue * feePpm / PPM.
  5. Protocol fee on top (see Fees).
  6. Recipient gets quotedValue - poolFee - protocolFee. Protocol cut is transferred in the same call.
  7. Pool fee recorded in fees[tokenOut] if feeAddress != 0.
  8. Swap + SwapSettlement events.

Swap.initiator is always msg.sender. Expect a Deposit immediately before each Swap.

getAmountOut / getAmountIn revert instead of returning 0 (FeeTooHigh, InsufficientOutput). Do not treat a revert as a zero quote.

Seal

Bits can only be set, never cleared.

ConstantValueLocks
FEE_STATE1feePolicy
FEEADDRESS_STATE2feeAddress
QUOTER_STATE4quoter
REGISTRY_STATE8tokenRegistry
LIMITER_STATE16tokenLimiter
maxSealState31all five

Sealing an unset required slot reverts InvalidState. Seal locks the slot, not the callee. A sealed quoter can still change its own rates.

isSealed(0) compares against the mask stored at init (fullSealMask), so adding a bit in a later implementation does not silently unseal old pools.

Fees in inventory

  • feesDecoupled = false (default): accrued fees count as liquidity.
  • true: available = balance - fees[token]. withdrawLiquidity cannot take the reserved fees.

Owner collects with withdraw(tokenOut) / withdraw(tokenOut, value) to feeAddress.

Owner emergency: withdrawLiquidity(token, to, amount).

Constants

DEFAULT_FEE_PPM = 10_000 (1%). Floor used when computing the protocol cut, so a pool cannot shrink the protocol's share by setting a tiny pool fee.