Algebra Integral
HomepageSocialsIntegrate
  • Overview / FAQ
    • 💡What is Algebra?
    • 🫂The Algebra Ecosystem
    • 🧑‍🔬Algebra Integral
    • 📚Glossary
    • 🪙Tokenomics
    • 📱Social Media & Links
    • 👨‍🎨Brand Assets
    • Partners
      • Algebra V1.0
        • QuickSwap Polygon
        • ZyberSwap
        • Thena
        • StellaSwap
        • QuickSwap Dogechain
        • SkullSwap
        • UbeSwap
        • Litx
      • Algebra V1.9
        • Camelot
        • Lynex
        • Swapbased
        • Synthswap
        • Zyberswap Optimism
        • Hercules
      • Integral 1.0
        • Swapsicle Telos
        • Swapsicle Mantle
        • Kim
        • Fenix
        • Blade
        • SilverSwap Fantom
        • Horizon
        • Glyph Exchange
        • SilverSwap Sonic
        • SwapX
        • Bulla
      • Integral 1.1
        • Scribe
      • Integral 1.2
        • Fibonacci
        • Voltage
        • Henjin
        • Wasabee
        • Holiverse
        • MorFi
        • StellaSwap
        • QuickSwap Soneium
  • Algebra Integral / Technical Reference
    • ℹ️Intro
    • 🔍Audits
    • 🏗️Integration Process
      • Specification and API of contracts
        • Algebra Pool
        • Algebra Factory
        • Swap Router
        • Nonfungible Position Manager
        • Quoter
        • QuoterV2
        • TickLens
      • Interaction with pools
        • Getting data from pools
      • Subgraphs and analytics
        • Examples of queries
      • Technical Guides
        • Intro
        • Swaps
          • Single swaps
          • Multihop swaps
        • Providing liquidity
          • Setting up your contract
          • Mint a new position
          • Collect fees
          • Decrease liquidity
          • Increase liquidity
          • Final Contract
        • Flashloans
          • Setting up your contract
          • Calling flash
          • Flash callback
          • Final contract
      • Migration from UniswapV3
    • 🖲️Core Logic
      • Pool overview
      • Swap calculation
      • Liquidity and positions
      • Ticks
        • Ticks search tree
      • Reserves
      • Flash
      • Plugins
      • AlgebraFactory and roles
    • 🧩Plugins
      • Overview
      • Adaptive Fee
      • Sliding Fee
      • Whitelist Discount Fee
      • Safety Switch
      • Position Limit Orders
      • Managed Swap Fee
      • FAQ
    • 📖Guides
      • 🔨Plugin Development
      • 🔬Plugin Testing
      • ☄️Plugin Deployment
    • ⬆️Changes V1
    • ⬆️Changes V1.1
    • ⬆️Changes v1.2
  • ⬆️Changes v1.2.1
  • Algebra V1 / Technical Reference
    • 🔏Contracts
      • API Reference v1.0
        • V1.0 - Core
          • AlgebraFactory
          • AlgebraPool
          • AlgebraPoolDeployer
          • DataStorage
          • DataStorageOperator
          • IAlgebraFactory
          • IAlgebraFlashCallback
          • IAlgebraMintCallback
          • IAlgebraPoolActions
          • IAlgebraPoolDeployer
          • IAlgebraPoolDerivedState
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraPoolState
          • IAlgebraSwapCallback
          • IAlgebraVirtualPool
          • IDataStorageOperator
          • IERC20Minimal
          • PoolImmutables
          • PoolState
        • V1.0 - Periphery
          • AlgebraInterfaceMulticall
          • ERC20
          • ERC20Permit
          • ERC165
          • ERC721
          • ERC721Permit
          • IAlgebraMintCallback
          • IAlgebraFactory
          • IAlgebraPoolDerivedState
          • IAlgebraPoolActions
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraPoolState
          • IAlgebraSwapCallback
          • IERC20
          • IDataStorageOperator
          • IERC20Metadata
          • IERC20Permit
          • IERC20PermitAllowed
          • IERC165
          • IERC721
          • IERC721Enumerable
          • IERC721Metadata
          • IERC721Permit
          • IERC721Receiver
          • IERC1271
          • IMulticall
          • INonfungiblePositionManager
          • INonfungibleTokenPositionDescriptor
          • IPeripheryImmutableState
          • IPeripheryPayments
          • IPeripheryPaymentsWithFee
          • IPoolInitializer
          • IQuoter
          • IQuoterV2
          • ISelfPermit
          • ISwapRouter
          • ITickLens
          • IUniswapV2Pair
          • IV3Migrator
          • IWNativeToken
          • LiquidityManagement
          • Multicall
          • NFTDescriptor
          • NonfungiblePositionManager
          • NonfungibleTokenPositionDescriptor
          • PeripheryImmutableState
          • PeripheryPayments
          • PeripheryPaymentsWithFee
          • PoolInitializer
          • Quoter
          • QuoterV2
          • SwapRouter
          • SelfPermit
          • TickLens
          • V3Migrator
        • V1.0 - Tokenomics
          • AlgebraEternalFarming
          • AlgebraFarming
          • AlgebraIncentiveFarming
          • AlgebraLimitFarming
          • AlgebraTokenStaking
          • AlgebraVault
          • AlgebraVirtualPoolBase
          • ERC20
          • ERC165
          • ERC721
          • ERC721Permit
          • EternalVirtualPool
          • FarmingCenter
          • FarmingCenterVault
          • FreezableToken
          • IAlgebraEternalFarming
          • IAlgebraEternalVirtualPool
          • IAlgebraFactory
          • IAlgebraFarming
          • IAlgebraIncentiveFarming
          • IAlgebraIncentiveVirtualPool
          • IAlgebraLimitFarming
          • IAlgebraLimitVirtualPool
          • IAlgebraPoolActions
          • IAlgebraPoolDeployer
          • IAlgebraPoolDerivedState
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraPoolState
          • IAlgebraSwapCallback
          • IAlgebraVirtualPool
          • IAlgebraVirtualPoolBase
          • IDataStorageOperator
          • IERC20
          • IERC20Minimal
          • IERC165
          • IERC721
          • IERC721Enumerable
          • IERC721Metadata
          • IERC721Permit
          • IERC721Receiver
          • IERC1271
          • IFarmingCenter
          • IFarmingCenterVault
          • IMulticall
          • IncentiveVirtualPool
          • INonfungiblePositionManager
          • IPeripheryPayments
          • IPeripheryImmutableState
          • IPoolInitializer
          • ISwapRouter
          • IWNativeToken
          • LimitVirtualPool
          • Multicall
          • PeripheryPayments
      • API Reference v1.9
        • V1.9 - Core
          • AlgebraFactory
          • AlgebraPool
          • AlgebraPoolDeployer
          • DataStorage
          • DataStorageOperator
          • IAlgebraFactory
          • IAlgebraFlashCallback
          • IAlgebraMintCallback
          • IAlgebraPoolActions
          • IAlgebraPoolDeployer
          • IAlgebraPoolDerivedState
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraPoolState
          • IAlgebraSwapCallback
          • IAlgebraVirtualPool
          • IDataStorageOperator
          • IERC20Minimal
          • PoolImmutables
          • PoolState
        • V1.9 - Periphery
          • ERC721Permit
          • AlgebraInterfaceMulticall
          • IERC20Metadata
          • IERC20PermitAllowed
          • IERC721Permit
          • IERC1271
          • IMulticall
          • INonfungiblePositionManager
          • INonfungibleTokenPositionDescriptor
          • IPeripheryImmutableState
          • IPeripheryPayments
          • IPeripheryPaymentsWithFee
          • IPoolInitializer
          • IQuoter
          • IQuoterV2
          • ISelfPermit
          • ISwapRouter
          • ITickLens
          • IV3Migrator
          • IWNativeToken
          • LiquidityManagement
          • Multicall
          • NFTDescriptor
          • NonfungiblePositionManager
          • NonfungibleTokenPositionDescriptor
          • PeripheryImmutableState
          • PeripheryPayments
          • PoolInitializer
          • PeripheryPaymentsWithFee
          • Quoter
          • QuoterV2
          • SelfPermit
          • SwapRouter
          • TickLens
          • V3Migrator
        • V1.9 - Tokenomics
          • AlgebraFarming
          • AlgebraEternalFarming
          • AlgebraLimitFarming
          • AlgebraTokenStaking
          • AlgebraVault
          • AlgebraVirtualPoolBase
          • ERC20
          • EternalVirtualPool
          • FarmingCenter
          • FarmingCenterVault
          • FreezableToken
          • IAlgebraEternalFarming
          • IAlgebraEternalVirtualPool
          • IAlgebraFarming
          • IAlgebraLimitFarming
          • IAlgebraLimitVirtualPool
          • IAlgebraVirtualPoolBase
          • IERC20Minimal
          • IFarmingCenter
          • IFarmingCenterVault
          • LimitVirtualPool
          • PeripheryPayments
      • API Reference v1.9 - Directional Fees
        • V1.9 (Directional Fees) - Core
          • AlgebraFactory
          • AlgebraPool
          • AlgebraPoolDeployer
          • DataStorage
          • DataStorageOperator
          • IAlgebraFactory
          • IAlgebraFlashCallback
          • IAlgebraMintCallback
          • IAlgebraPoolActions
          • IAlgebraPoolDeployer
          • IAlgebraPoolDerivedState
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraSwapCallback
          • IAlgebraPoolState
          • IAlgebraVirtualPool
          • IDataStorageOperator
          • IERC20Minimal
          • PoolImmutables
          • PoolState
        • V1.9 (Directional Fees) - Periphery
          • AlgebraInterfaceMulticall
          • ERC721Permit
          • IERC20Metadata
          • IERC20PermitAllowed
          • IERC721Permit
          • IERC1271
          • IMulticall
          • INonfungiblePositionManager
          • INonfungibleTokenPositionDescriptor
          • IPeripheryImmutableState
          • IPeripheryPayments
          • IPeripheryPaymentsWithFee
          • IPoolInitializer
          • IQuoter
          • IQuoterV2
          • ISelfPermit
          • ISwapRouter
          • ITickLens
          • IV3Migrator
          • IWNativeToken
          • LiquidityManagement
          • Multicall
          • NFTDescriptor
          • NonfungiblePositionManager
          • NonfungibleTokenPositionDescriptor
          • PeripheryImmutableState
          • PeripheryPayments
          • PeripheryPaymentsWithFee
          • PoolInitializer
          • Quoter
          • QuoterV2
          • SelfPermit
          • SwapRouter
          • TickLens
          • V3Migrator
        • V1.9 (Directional Fees) - Tokenomics
          • AlgebraFarming
          • AlgebraEternalFarming
          • AlgebraLimitFarming
          • AlgebraTokenStaking
          • AlgebraVault
          • AlgebraVirtualPoolBase
          • ERC20
          • EternalVirtualPool
          • FarmingCenter
          • FarmingCenterVault
          • FreezableToken
          • IAlgebraEternalFarming
          • IAlgebraEternalVirtualPool
          • IAlgebraFarming
          • IAlgebraLimitVirtualPool
          • IAlgebraLimitFarming
          • IAlgebraVirtualPoolBase
          • IERC20Minimal
          • IFarmingCenterVault
          • IFarmingCenter
          • LimitVirtualPool
          • PeripheryPayments
      • API Reference v2.0
        • V2.0 - Core
          • AlgebraCommunityVault
          • AlgebraFactory
          • AlgebraFeeConfiguration
          • AlgebraPool
          • AlgebraPoolBase
          • AlgebraPoolDeployer
          • DataStorage
          • DataStorageOperator
          • DerivedState
          • IAlgebraFactory
          • IAlgebraFlashCallback
          • IAlgebraMintCallback
          • IAlgebraPoolActions
          • IAlgebraPoolDeployer
          • IAlgebraPoolDerivedState
          • IAlgebraPoolErrors
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraPoolState
          • IAlgebraSwapCallback
          • IAlgebraVirtualPool
          • IDataStorageOperator
          • IERC20Minimal
          • Positions
          • ReservesManager
        • V2.0 - Periphery
          • AlgebraInterfaceMulticall
          • ERC721Permit
          • IERC20Metadata
          • IERC20PermitAllowed
          • IERC721Permit
          • IERC1271
          • ILimitOrderManager
          • IMulticall
          • INonfungiblePositionManager
          • INonfungibleTokenPositionDescriptor
          • IPeripheryImmutableState
          • IPeripheryPayments
          • IPeripheryPaymentsWithFee
          • IPoolInitializer
          • IPositionFollower
          • IQuoter
          • IQuoterV2
          • ISelfPermit
          • ISwapRouter
          • ITickLens
          • IV3Migrator
          • IWNativeToken
          • LimitOrderManagement
          • LimitOrderManager
          • LiquidityManagement
          • Multicall
          • NFTDescriptor
          • NonfungiblePositionManager
          • NonfungibleTokenPositionDescriptor
          • PeripheryImmutableState
          • PeripheryPayments
          • PeripheryPaymentsWithFee
          • PoolInitializer
          • Quoter
          • QuoterV2
          • SelfPermit
          • SwapRouter
          • TickLens
          • V3Migrator
        • V2.0 - Tokenomics
          • AlgebraEternalFarming
          • EternalVirtualPool
          • FarmingCenter
          • IAccessControl
          • IAlgebraEternalFarming
          • IAlgebraEternalVirtualPool
          • IFarmingCenter
          • IncentiveKey
          • VirtualTickStructure
      • API Reference v2.0 - Directional Fees
        • V2.0 (Directional Fees) - Core
          • AlgebraCommunityVault
          • AlgebraFactory
          • AlgebraFeeConfiguration
          • AlgebraPool
          • AlgebraPoolBase
          • AlgebraPoolDeployer
          • DataStorage
          • DataStorageOperator
          • DerivedState
          • IAlgebraFactory
          • IAlgebraFlashCallback
          • IAlgebraMintCallback
          • IAlgebraPoolActions
          • IAlgebraPoolDeployer
          • IAlgebraPoolDerivedState
          • IAlgebraPoolErrors
          • IAlgebraPoolEvents
          • IAlgebraPoolImmutables
          • IAlgebraPoolPermissionedActions
          • IAlgebraPoolState
          • IAlgebraSwapCallback
          • IAlgebraVirtualPool
          • IDataStorageOperator
          • IERC20Minimal
          • Positions
          • ReservesManager
        • V2.0 (Directional Fees) - Periphery
          • AlgebraInterfaceMulticall
          • ERC721Permit
          • IERC20Metadata
          • IERC20PermitAllowed
          • IERC721Permit
          • IERC1271
          • ILimitOrderManager
          • IMulticall
          • INonfungiblePositionManager
          • INonfungibleTokenPositionDescriptor
          • IPeripheryImmutableState
          • IPeripheryPayments
          • IPeripheryPaymentsWithFee
          • IPoolInitializer
          • IPositionFollower
          • IQuoter
          • IQuoterV2
          • ISelfPermit
          • ISwapRouter
          • ITickLens
          • IV3Migrator
          • IWNativeToken
          • LimitOrderManagement
          • LimitOrderManager
          • LiquidityManagement
          • Multicall
          • NFTDescriptor
          • NonfungiblePositionManager
          • NonfungibleTokenPositionDescriptor
          • PeripheryImmutableState
          • PeripheryPayments
          • PeripheryPaymentsWithFee
          • PoolInitializer
          • QuoterV2
          • Quoter
          • SelfPermit
          • SwapRouter
          • TickLens
          • V3Migrator
        • V2.0 (Directional Fees) - Tokenomics
          • AlgebraEternalFarming
          • EternalVirtualPool
          • FarmingCenter
          • IAccessControl
          • IAlgebraEternalFarming
          • IAlgebraEternalVirtualPool
          • IFarmingCenter
          • IncentiveKey
          • VirtualTickStructure
      • Adaptive Fee
        • Adaptive Fee
        • How to set up specific formula behaviour
        • How to tweak formula behaviour
      • Contracts Setup
        • Deployment
          • Contracts Deployment
          • Deployment Scripts
        • Misc
          • POOL_INIT_CODE_HASH
          • Code Audits
          • Deployment Addresses
      • The Algebra Guides
        • Flash Integrations
          • The Full Contract
          • Calling Flash
          • Flash Callback
          • Inheritance constructor
        • Liquidity Mining
          • Liquidity Mining Overview
        • Providing Liquidity
          • Collecting fees
          • Decrease liquidity
          • Increase Liquidity Within The Current Range
          • Mint a new position
          • Set up your contract
          • The full contract
        • Swaps
          • Multihop swaps
          • Single swaps
    • 📊Subgraph
      • Query Examples
        • Query Examples
      • GraphQL Schema
        • Farming GraphQL Schema
        • Algebra GraphQL Schema
      • Subgraph Setup
        • Subgraph Settings
        • Subgraph Deployment
    • 🖥️Frontend
      • Admin Panel
        • Contracts
          • Admin Panel
          • Changing Subgraph
        • Eternal Farmings
          • Create Eternal Farming
          • Managing Eternal Farming
        • Limit Farmings
          • Create Limit Farming
    • ⚙️Backend
      • Backend Setup
    • ⛑️Guides
      • Step by Step Deployment
  • Other
    • 📦Archived Documentation
    • ❗Link Awareness Notice
Powered by GitBook
On this page
  • Setting up the Contract
  • Exact Input Multi Hop Swaps
  • Exact Output Multihop Swap
  • The Full Contract
  1. Algebra Integral / Technical Reference
  2. Integration Process
  3. Technical Guides
  4. Swaps

Multihop swaps

Setting up the Contract

Declare the solidity version that will be used to compile the contract. If needed (if you are using older versions of solidity) add abicoder v2 to allow arbitrary nested arrays and structs to be encoded and decoded in calldata, a feature that is used when completing a swap.

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.20;

Import the two needed contracts from the npm package installation.

import '@cryptoalgebra/integral-periphery/contracts/interfaces/ISwapRouter.sol';
import '@cryptoalgebra/integral-periphery/contracts/libraries/TransferHelper.sol';

Create a contract called SwapExamples, and declare an immutable public variable swapRouter of type ISwapRouter. This allows us to call functions in the ISwapRouter interface.

contract SwapExamples {
    // For the scope of these swap examples,
    // we will detail the design considerations when using `exactInput`, `exactInputSingle`, `exactOutput`, and  `exactOutputSingle`.
    // It should be noted that for the sake of these examples we pass in the swap router as a constructor argument instead of inheriting it.
    // More advanced example contracts will detail how to inherit the swap router safely.
    // This example swaps DAI/WMATIC for single path swaps and DAI/USDC/WMATIC for multi path swaps.

    ISwapRouter public immutable swapRouter;

Now, hardcode the token contract addresses for the example. In production, you would likely use an input parameter for this and pass the input into a memory variable, allowing the contract to change the pools and tokens it interacts with on a per-transaction basis, but for conceptual simplicity, we are hardcoding them here.

    address public constant DAI = 0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063;
    address public constant WMATIC = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270;
    address public constant USDC = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174;

    constructor(ISwapRouter _swapRouter) {
        swapRouter = _swapRouter;
    }

Exact Input Multi Hop Swaps

Exact input multi hop swaps will swap a fixed amount on a given input token for the maximum amount possible for a given output, and can include an arbitrary number of intermediary swaps.

Input Parameters

  • path: The path is a sequence of (tokenAddress - tokenAddress), which are the variables needed to compute each pool contract address in our sequence of swaps. The multihop swap router code will automatically find the correct pool with these variables, and execute the swap needed within each pool in our sequence.

  • recipient: is the destination address of the outbound asset.

  • deadline: is the unix time after which a transaction will be reverted, in order to protect against long delays and the increased chance of large price swings therein.

  • amountIn: the amount of the inbound asset.

  • amountOutMin: the minimum amount of the outbound asset, less than which will cause the transaction to revert. For this example we will set it to 0, in production one will need to use the SDK to quote an expected price, or an on chain price oracle for more advanced manipulation resistant systems.

Calling the function

    /// @notice swapExactInputMultihop swaps a fixed amount of DAI for a maximum possible amount of WMATIC through an intermediary pool.
    /// For this example, we will swap DAI to USDC, then USDC to WMATIC to achieve our desired output.
    /// @dev The calling address must approve this contract to spend at least `amountIn` worth of its DAI for this function to succeed.
    /// @param amountIn The amount of DAI to be swapped.
    /// @return amountOut The amount of WMATIC received after the swap.
    function swapExactInputMultihop(uint256 amountIn) external returns (uint256 amountOut) {
        // Transfer `amountIn` of DAI to this contract.
        TransferHelper.safeTransferFrom(DAI, msg.sender, address(this), amountIn);

        // Approve the router to spend DAI.
        TransferHelper.safeApprove(DAI, address(swapRouter), amountIn);

        // Multiple pool swaps are encoded through bytes called a `path`. A path is a sequence of token addresses that define the pools used in the swaps.
        // The format for pool encoding is (tokenIn, tokenOut/tokenIn, tokenOut) where tokenIn/tokenOut parameter is the shared token across the pools.
        // Since we are swapping DAI to USDC and then USDC to WMATIC the path encoding is (DAI, USDC, WMATIC).
        ISwapRouter.ExactInputParams memory params =
            ISwapRouter.ExactInputParams({
                path: abi.encodePacked(DAI, USDC, WMATIC),
                recipient: msg.sender,
                deadline: block.timestamp,
                amountIn: amountIn,
                amountOutMinimum: 0
            });

        // Executes the swap.
        amountOut = swapRouter.exactInput(params);
    }

Exact Output Multihop Swap

An exact output swap will trade a variable amount of the input token for a fixed amount of the outbound token. This one can be seen as a less common technique used for multihop swaps. The code for swapping is mostly the same except for one major difference – the Path is encoded backwards, as an exact output swap is executed in reverse order to pass down the necessary variables for the chain of transactions

Input Parameters

  • path: The path is a sequence of tokenAddress tokenAddress, encoded in reverse order, which are the variables needed to compute each pool contract address in our sequence of swaps. This way, the multihop swap router code will automatically find the correct pool with these variables, and execute the swap needed within each pool in our sequence.

  • recipient: the destination address of the outbound asset.

  • deadline: the unix time after which a transaction will be reverted, to protect against long delays and the increased chance of wild price swings therein.

  • amountOut: The desired amount of WMATIC.

  • amountInMaximum: The maximum amount of DAI willing to be swapped for the specified amountOut of WMATIC.

Calling the function

    /// @notice swapExactOutputMultihop swaps a minimum possible amount of DAI for a fixed amount of WMATIC through an intermediary pool.
    /// For this example, we want to swap DAI for WMATIC through a USDC pool but we specify the desired amountOut of WMATIC. Notice how the path encoding is slightly different in for exact output swaps.
    /// @dev The calling address must approve this contract to spend its DAI for this function to succeed. As the amount of input DAI is variable,
    /// the calling address will need to approve for a slightly higher amount, anticipating some variance.
    /// @param amountOut The desired amount of WMATIC.
    /// @param amountInMaximum The maximum amount of DAI willing to be swapped for the specified amountOut of WMATIC.
    /// @return amountIn The amountIn of DAI actually spent to receive the desired amountOut.
    function swapExactOutputMultihop(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) {
        // Transfer the specified `amountInMaximum` to this contract.
        TransferHelper.safeTransferFrom(DAI, msg.sender, address(this), amountInMaximum);
        // Approve the router to spend  `amountInMaximum`.
        TransferHelper.safeApprove(DAI, address(swapRouter), amountInMaximum);

        // The parameter path is encoded as (tokenOut, tokenIn/tokenOut, tokenIn)
        // The tokenIn/tokenOut field is the shared token between the two pools used in the multiple pool swap. In this case USDC is the "shared" token.
        // For an exactOutput swap, the first swap that occurs is the swap which returns the eventual desired token.
        // In this case, our desired output token is WMATIC so that swap happens first, and is encoded in the path accordingly.
        ISwapRouter.ExactOutputParams memory params =
            ISwapRouter.ExactOutputParams({
                path: abi.encodePacked(WMATIC, USDC, DAI),
                recipient: msg.sender,
                deadline: block.timestamp,
                amountOut: amountOut,
                amountInMaximum: amountInMaximum
            });

        // Executes the swap, returning the amountIn actually spent.
        amountIn = swapRouter.exactOutput(params);

        // If the swap did not require the full amountInMaximum to achieve the exact amountOut then we refund msg.sender and approve the router to spend 0.
        if (amountIn < amountInMaximum) {
            TransferHelper.safeApprove(DAI, address(swapRouter), 0);
            TransferHelper.safeTransferFrom(DAI, address(this), msg.sender, amountInMaximum - amountIn);
        }
    }

The Full Contract

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity =0.8.20;

import '@cryptoalgebra/integral-periphery/contracts/libraries/TransferHelper.sol';
import '@cryptoalgebra/integral-periphery/contracts/interfaces/ISwapRouter.sol';

contract SwapExamples {
    // For the scope of these swap examples,
    // we will detail the design considerations when using
    // `exactInput`, `exactInputSingle`, `exactOutput`, and  `exactOutputSingle`.

    // It should be noted that for the sake of these examples, we purposefully pass in the swap router instead of inherit the swap router for simplicity.
    // More advanced example contracts will detail how to inherit the swap router safely.

    ISwapRouter public immutable swapRouter;

    // This example swaps DAI/WMATIC for single path swaps and DAI/USDC/WMATIC for multi path swaps.

    address public constant DAI = 0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063;
    address public constant WMATIC = 0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270;
    address public constant USDC = 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174;

    constructor(ISwapRouter _swapRouter) {
        swapRouter = _swapRouter;
    }

    /// @notice swapInputMultiplePools swaps a fixed amount of DAI for a maximum possible amount of WMATIC through an intermediary pool.
    /// For this example, we will swap DAI to USDC, then USDC to WMATIC to achieve our desired output.
    /// @dev The calling address must approve this contract to spend at least `amountIn` worth of its DAI for this function to succeed.
    /// @param amountIn The amount of DAI to be swapped.
    /// @return amountOut The amount of WMATIC received after the swap.
    function swapExactInputMultihop(uint256 amountIn) external returns (uint256 amountOut) {
        // Transfer `amountIn` of DAI to this contract.
        TransferHelper.safeTransferFrom(DAI, msg.sender, address(this), amountIn);

        // Approve the router to spend DAI.
        TransferHelper.safeApprove(DAI, address(swapRouter), amountIn);

        // Multiple pool swaps are encoded through bytes called a `path`. A path is a sequence of token addresses that define the pools used in the swaps.
        // The format for pool encoding is (tokenIn, tokenOut/tokenIn, tokenOut) where tokenIn/tokenOut parameter is the shared token across the pools.
        // Since we are swapping DAI to USDC and then USDC to WMATIC the path encoding is (DAI, 0.3%, USDC, 0.3%, WMATIC).
        ISwapRouter.ExactInputParams memory params =
            ISwapRouter.ExactInputParams({
                path: abi.encodePacked(DAI, USDC, WMATIC),
                recipient: msg.sender,
                deadline: block.timestamp,
                amountIn: amountIn,
                amountOutMinimum: 0
            });

        // Executes the swap.
        amountOut = swapRouter.exactInput(params);
    }

    /// @notice swapExactOutputMultihop swaps a minimum possible amount of DAI for a fixed amount of WMATIC through an intermediary pool.
    /// For this example, we want to swap DAI for WMATIC through a USDC pool but we specify the desired amountOut of WMATIC. Notice how the path encoding is slightly different in for exact output swaps.
    /// @dev The calling address must approve this contract to spend its DAI for this function to succeed. As the amount of input DAI is variable,
    /// the calling address will need to approve for a slightly higher amount, anticipating some variance.
    /// @param amountOut The desired amount of WMATIC.
    /// @param amountInMaximum The maximum amount of DAI willing to be swapped for the specified amountOut of WMATIC.
    /// @return amountIn The amountIn of DAI actually spent to receive the desired amountOut.
    function swapExactOutputMultihop(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) {
        // Transfer the specified `amountInMaximum` to this contract.
        TransferHelper.safeTransferFrom(DAI, msg.sender, address(this), amountInMaximum);
        // Approve the router to spend  `amountInMaximum`.
        TransferHelper.safeApprove(DAI, address(swapRouter), amountInMaximum);

        // The parameter path is encoded as (tokenOut, tokenIn/tokenOut, tokenIn)
        // The tokenIn/tokenOut field is the shared token between the two pools used in the multiple pool swap. In this case USDC is the "shared" token.
        // For an exactOutput swap, the first swap that occurs is the swap which returns the eventual desired token.
        // In this case, our desired output token is WMATIC so that swap happpens first, and is encoded in the path accordingly.
        ISwapRouter.ExactOutputParams memory params =
            ISwapRouter.ExactOutputParams({
                path: abi.encodePacked(WMATIC, USDC, DAI),
                recipient: msg.sender,
                deadline: block.timestamp,
                amountOut: amountOut,
                amountInMaximum: amountInMaximum
            });

        // Executes the swap, returning the amountIn actually spent.
        amountIn = swapRouter.exactOutput(params);

        // If the swap did not require the full amountInMaximum to achieve the exact amountOut then we refund msg.sender and approve the router to spend 0.
        if (amountIn < amountInMaximum) {
            TransferHelper.safeApprove(DAI, address(swapRouter), 0);
            TransferHelper.safeTransferFrom(DAI, address(this), msg.sender, amountInMaximum - amountIn);
        }
    }
}
PreviousSingle swapsNextProviding liquidity
🏗️