Swapping

Execute swaps against Rapiddex v3 pools directly from your smart contracts using the SwapRouter.

This guide explains how to integrate token swaps on Rapiddex v3 into your smart contracts. It covers interacting with the ISwapRouter contract for single-hop swaps using both exact input (known amount of input tokens) and exact output (known amount of desired output tokens).

The Swap Router

The SwapRouter contract executes token swaps on Rapiddex v3. It acts as the periphery wrapper around pools, ensuring safe execution, transfer of tokens, and slippage verification. Smart contracts call the router by passing parameters packed into structs.

Exact Input Single Hop

An exact input swap trades a fixed amount of tokenIn for the maximum possible amount of tokenOut. A single-hop swap routes trades through a single pool identified by its fee tier.

Exact Output Single Hop

An exact output swap trades a minimum possible amount of tokenIn for a fixed target amount of tokenOut. If the trade requires fewer tokens than the maximum allowed, the unused input tokens must be refunded to the caller.

Solidity Implementation Examples

The following Solidity contract shows how to set up token approvals, transfer tokens from the user, and execute single-hop swaps via the SwapRouter:

solidity// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import "@rapiddex/v3-periphery/contracts/interfaces/ISwapRouter.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract SwapExamples {
    ISwapRouter public immutable swapRouter;

    // The SwapRouter is deployed at a fixed address on each chain (see Deployments)
    constructor(ISwapRouter _swapRouter) {
        swapRouter = _swapRouter;
    }

    /// @notice Swap a fixed amount of tokenIn for tokenOut
    function swapExactInputSingle(
        address tokenIn,
        address tokenOut,
        uint24 fee,
        uint256 amountIn,
        uint256 amountOutMinimum
    ) external returns (uint256 amountOut) {
        // Pull tokenIn from the sender to this contract
        IERC20(tokenIn).transferFrom(msg.sender, address(this), amountIn);

        // Approve the SwapRouter to spend tokenIn from this contract
        IERC20(tokenIn).approve(address(swapRouter), amountIn);

        ISwapRouter.ExactInputSingleParams memory params =
            ISwapRouter.ExactInputSingleParams({
                tokenIn: tokenIn,
                tokenOut: tokenOut,
                fee: fee,
                recipient: msg.sender,
                deadline: block.timestamp,
                amountIn: amountIn,
                amountOutMinimum: amountOutMinimum,
                sqrtPriceLimitX96: 0
            });

        // Execute the swap
        amountOut = swapRouter.exactInputSingle(params);
    }

    /// @notice Swap tokenIn for a fixed amount of tokenOut
    function swapExactOutputSingle(
        address tokenIn,
        address tokenOut,
        uint24 fee,
        uint256 amountOut,
        uint256 amountInMaximum
    ) external returns (uint256 amountIn) {
        // Transfer max possible tokenIn from the sender
        IERC20(tokenIn).transferFrom(msg.sender, address(this), amountInMaximum);

        // Approve the router to spend tokenIn
        IERC20(tokenIn).approve(address(swapRouter), amountInMaximum);

        ISwapRouter.ExactOutputSingleParams memory params =
            ISwapRouter.ExactOutputSingleParams({
                tokenIn: tokenIn,
                tokenOut: tokenOut,
                fee: fee,
                recipient: msg.sender,
                deadline: block.timestamp,
                amountOut: amountOut,
                amountInMaximum: amountInMaximum,
                sqrtPriceLimitX96: 0
            });

        // Execute the swap
        amountIn = swapRouter.exactOutputSingle(params);

        // Refund any leftover tokenIn to the caller
        if (amountIn < amountInMaximum) {
            IERC20(tokenIn).approve(address(swapRouter), 0);
            IERC20(tokenIn).transfer(msg.sender, amountInMaximum - amountIn);
        }
    }
}
Leftover Approvals When performing exact output swaps, always reset the router's approval to 0 if there are unused tokens, and refund the remaining tokens to the caller to avoid locking user funds.

Parameters and Outputs Reference

1. exactInputSingle

Executes a swap to trade a fixed input amount of one token for as many output tokens as possible.

Struct Field (ExactInputSingleParams) Type Description
tokenIn address The contract address of the input token (token to spend).
tokenOut address The contract address of the output token (token to receive).
fee uint24 The fee tier of the pool (500 for 0.05%, 3000 for 0.30%, 10000 for 1.00%).
recipient address The destination address that will receive the output tokens.
deadline uint256 The Unix timestamp after which the transaction will revert if not processed.
amountIn uint256 The exact amount of input tokens to send for the swap.
amountOutMinimum uint256 The minimum amount of output tokens expected. Reverts if slippage exceeds this bounds.
sqrtPriceLimitX96 uint160 The square root price limit. Set to 0 to bypass price limiting.

Output: amountOut (uint256) - The actual amount of output tokens sent to the recipient.

2. exactOutputSingle

Executes a swap to trade as few input tokens as possible for an exact target amount of output tokens.

Struct Field (ExactOutputSingleParams) Type Description
tokenIn address The contract address of the input token (token to spend).
tokenOut address The contract address of the output token (token to receive).
fee uint24 The fee tier of the pool (500 for 0.05%, 3000 for 0.30%, 10000 for 1.00%).
recipient address The destination address that will receive the output tokens.
deadline uint256 The Unix timestamp after which the transaction will revert if not processed.
amountOut uint256 The exact amount of output tokens to receive.
amountInMaximum uint256 The maximum amount of input tokens allowed to be spent. Reverts if swap costs more.
sqrtPriceLimitX96 uint160 The square root price limit. Set to 0 to bypass price limiting.

Output: amountIn (uint256) - The actual amount of input tokens spent in the swap.