Single swaps

Swaps are the most common interaction with the Algebra Protocol. The following example displays the way of implementing a single-path swap contract that uses two functions that you create:

  • swapExactInputSingle

  • swapExactOutputSingle

The swapExactOutputSingle function is used for performing exact output swaps, which swap a minimum possible amount of the token 1 for a fixed amount of the token 2. This function uses the ExactOutputSingleParams struct and the exactOutputSingle function from the ISwapRouter interface.

The swapExactOutputSingle function is for performing exact output swaps, which swap a minimum possible amount of one token for a fixed amount of another token. This function uses the ExactOutputSingleParams struct and the exactOutputSingle function from the ISwapRouter interface.

To make it seem more simple, the example hardcodes the token contract addresses, but as explained below the contract could be modified to change pools and tokens on a per-transaction basis.

When trading from a smart contract, the most important thing that you should remember is that access to an external price source is always required. Without that, trades can be frontrun for considerable loss.

Note: As always, the swap examples are not production ready code, and are implemented in a simplistic manner for the learning purposes.

Set Up the Contract

Declare the solidity version 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 both encoded and decoded in calldata, a feature that is used when executing a swap.

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

Import the two relevant 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;

Hardcode the token contract addresses just for the example. In production, you would likely need to 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 a better understanding of the process and conceptual simplicity, we are hardcoding them here.

Exact Input Swaps

The caller must approve the contract to withdraw the tokens from the calling address's account to execute a swap. Keep in mind that because our contract is a contract itself and not an extension of the caller (us); we must also approve the Algebra Protocol router contract to use the tokens that our contract will be in possession of after they have been withdrawn from the calling address (us).

Then, transfer the amount of Dai from the calling address into our contract, and use amount as the value passed to the second approve.

Swap Input Parameters

To execute the swap function, we need to fill the ExactInputSingleParams with the necessary swap data. These parameters are found in the smart contract interfaces, which can be browsed in ISwapRouter.

A little overview of the parameters:

  • tokenIn is the contract address of the inbound token

  • tokenOut is the contract address of the outbound token

  • deployer is the contract address of plugin deployer, zero addres for base pools

  • recipient is the destination address of the outbound token

  • deadline: stands for unix time after which a swap will fail, to protect against long-pending transactions and wild swings in prices

  • amountOutMinimum: is the parameter we are setting to zero, but this is a significant risk in production. For a real deployment, this value should be calculated using our SDK or an onchain price oracle – it’ll help protect against getting an unusually unreasonable price for a trade due to a front running sandwich or another type of price manipulation.

  • sqrtPriceLimitX96: is also a parameter we are setting to zero - which makes it inactive. In production, this value might be used to set the limit for the price the swap will push the pool to – it can help us protect against price impact or for setting up logic in a variety of price-relevant mechanisms.

Call the function

Exact Output Swaps

Exact Output swaps a minimum possible amount of the input token for a fixed amount of the outbound token. It can be seen as a less common swap style – but we find it quite useful in a variety of cases and circumstances.

As this example transfers in the inbound asset in anticipation of the swap, it is possible that some of the inbound tokens will be left over after the swap is executed, which is why we pay it back to the calling address once the swap is completed.

Call the function

A Complete Single Swap Contract

Last updated