For the complete documentation index, see llms.txt. This page is also available as Markdown.

Making a Swap with POE

Error
Cause

InvalidCallback

Callback didn't return correct selector 0xfa483e72

ZeroTokenReceived

Callback didn't transfer any tokens to the pool

InsufficientTokenReceived

Callback transferred less than required

OraclePool__OracleNotSet

Pool's oracle is not configured

OracleData__Expired

Oracle data has expired, operator needs to update

This guide explains how to integrate with OraclePool to execute token swaps. The pool uses a callback pattern similar to Uniswap V3 - you call swap(), receive tokens optimistically, then must pay via a callback.

Getting a Quote

Before executing a swap, you can preview the expected output using getQuote():

function getQuote(bool swapXtoY, uint256 amountIn)
    external view
    returns (uint256 amountOut, uint256 actualAmountIn, uint256 feeIn, uint256 feeOut);

Parameters:

  • swapXtoY - Direction of the swap. true = sell tokenX for tokenY, false = sell tokenY for tokenX

  • amountIn - The amount of input token you want to swap (fee-inclusive)

Returns:

  • amountOut - Amount of output token the recipient will receive (after feeOut, if any)

  • actualAmountIn - Gross input amount the pool will consume (fee-inclusive). May be less than amountIn if the curve would otherwise drain the pool.

  • feeIn - Fee charged in the input token. Non-zero only for Y → X swaps.

  • feeOut - Fee charged in the output token. Non-zero only for X → Y swaps.

Exactly one of feeIn / feeOut is non-zero. Both fees are denominated in tokenY (the pool's quote token), since X → Y fees come out of the output side and Y → X fees come out of the input side.

Example:

Reading Pool Info

To understand what tokens are involved:

Executing a Swap

The swap function uses an optimistic transfer pattern with a callback:

Parameters:

  • recipient - Address that receives the output tokens

  • swapXtoY - Direction: true = tokenX → tokenY, false = tokenY → tokenX

  • amountIn - Amount of input token to swap

  • data - Arbitrary data passed through to the callback

Returns:

  • deltaX - Change in tokenX from pool's perspective (positive = pool received, negative = pool sent)

  • deltaY - Change in tokenY from pool's perspective

Swap Flow

1

Call swap()

Your contract calls pool.swap(recipient, swapXtoY, amountIn, data).

2

Pool transfers output

Pool calculates amountOut and transfers tokenOut to recipient.

3

Pool calls back

Pool calls swapCallback(deltaX, deltaY, data) on msg.sender (your contract).

4

Your callback pays

Your callback must push tokenIn to the pool (msg.sender inside the callback) via transfer / safeTransfer. The pool checks its own balanceOf delta — it never calls transferFrom on your behalf.

5

Callback returns selector

Your callback must return 0xfa483e72 (the function selector).

6

Pool verifies payment

Pool verifies it received enough tokens (≥ actualAmountIn). Overpayment is kept by the pool as a donation to LPs.

7

swap() returns

swap() returns with the final deltas (from the pool's perspective).

Implementing the Callback

Your contract must implement the ISwapCallback interface:

The callback must:

1

Transfer the required input tokens to the pool (msg.sender in the callback).

2

Return the selector 0xfa483e72 (which is ISwapCallback.swapCallback.selector).

Important: The callback is called with deltaX and deltaY from the pool's perspective:

  • Positive delta = pool expects to receive that token

  • Negative delta = pool has sent that token

Solidity Example: Router Contract

Here's a complete example of a router contract that can swap through OraclePool:

Usage Example

TypeScript Example: Reading Quotes

Error Handling

Selected reverts you may encounter on the swap path:

Error
Source
Cause

Callback__InvalidCallback()

Callback library

Callback didn't return the selector 0xfa483e72, or the call reverted.

Callback__ZeroTokenReceived(address token)

Callback library

Pool's balance of token did not increase during the callback.

Callback__InsufficientTokenReceived(address, uint256, uint256)

Callback library

Pool received some token but less than amountIn.

Callback__Overflow()

Callback library

amountIn or amountOut ≥ 2^255 (would overflow signed delta).

OraclePool__OracleNotSet()

OraclePool

Pool's oracle is address(0).

OraclePool__ZeroAmount()

OraclePool

Quote produced amountOut == 0.

OracleData__Expired()

OracleData library

Oracle data for this pair has expired; operator must call setData again.

OracleData__InvalidPrice()

OracleData library

Oracle has no data (or price == 0) for this pair.

Security Considerations

  1. Callback Verification: Always verify that the callback caller is the expected pool to prevent malicious contracts from draining your tokens.

  2. Slippage Protection: Always use minAmountOut checks to protect against price movement between quote and execution.

  3. Reentrancy: The callback pattern can be vulnerable to reentrancy. Use reentrancy guards if your callback does anything complex.

  4. Token Approvals: Be careful with token approvals. Only approve what's needed for the specific swap.


Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the ask query parameter:

The question should be specific, self-contained, and written in natural language. The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.

Last updated