Skip to content
🚧 Under Development! May be incomplete.Some pages/links may be incomplete or subject to change.

Single Swap

A single swap in BeraSwap allows users to exchange one token for another within a single liquidity pool by calling the swap function on the BeraSwap Vault. This function is implemented in the Vault contract, which serves as the main entry point for all BeraSwap operations.

Swap

solidity
function swap(
    SingleSwap memory singleSwap,
    FundManagement memory funds,
    uint256 limit,
    uint256 deadline
) returns (uint256 amountCalculated)

Parameters

NameTypeDescription
singleSwapSingleSwapA definition of the swap to be executed
fundsFundManagementA definition of where funds are going to/from
limituint256The minimum amount to receive (for GIVEN_IN swaps) or the maximum amount to send (for GIVEN_OUT swaps) i.e. slippage tolerance
deadlineuint256The UNIX timestamp by which the swap must be completed

Returns

NameTypeDescription
amountCalculateduint256The amount of tokens sent (for GIVEN_IN swaps) or received (for GIVEN_OUT swaps)

Structs

SingleSwap

solidity
struct SingleSwap {
    bytes32 poolId;
    SwapKind kind;
    IAsset assetIn;
    IAsset assetOut;
    uint256 amount;
    bytes userData;
}
FieldTypeDescription
poolIdbytes32The id of the pool to swap with
kindSwapKindThe type of swap to perform (GIVEN_IN or GIVEN_OUT)
assetInIAssetThe address of the token to swap into the pool
assetOutIAssetThe address of the token to receive in return
amountuint256The amount of tokens being sent (for GIVEN_IN) or received (for GIVEN_OUT)
userDatabytesAny additional data required by the pool for the swap

FundManagement

solidity
struct FundManagement {
    address sender;
    bool fromInternalBalance;
    address payable recipient;
    bool toInternalBalance;
}
FieldTypeDescription
senderaddressThe address from which tokens will be taken to perform the swap
fromInternalBalanceboolWhether to use tokens stored in the Vault
recipientaddress payableThe address to which tokens will be sent after the swap
toInternalBalanceboolWhether to store tokens in the recipient's internal balance

Example

Here's a small example of how to call the swap function in Solidity:

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

import "forge-std/Test.sol";
import "balancer-v2-monorepo/pkg/interfaces/contracts/vault/IVault.sol";
import "balancer-v2-monorepo/pkg/interfaces/contracts/solidity-utils/openzeppelin/IERC20.sol";

contract BalancerExampleTest is Test {
    IVault public vault;
    address public user;

    address constant VAULT_ADDRESS = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
    address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
    bytes32 constant WETH_USDC_POOL_ID = 0x96646936b91d6b9d7d0c47c496afbf3d6ec7b6f8000200000000000000000019;

    function setUp() public {
        vm.createSelectFork("rpc-url");

        vault = IVault(VAULT_ADDRESS);

        user = makeAddr("user");

        deal(WETH, user, 1 ether);

        vm.startPrank(user);
        IERC20(WETH).approve(VAULT_ADDRESS, type(uint256).max);
        vm.stopPrank();
    }

    function testDirectSwap() public {
        uint256 amountIn = 1 ether;
        uint256 minAmountOut = 1000 * 1e6; // 1000 USDC

        uint256 balanceBefore = IERC20(USDC).balanceOf(user);

        IVault.SingleSwap memory singleSwap = IVault.SingleSwap({
            poolId: WETH_USDC_POOL_ID,
            kind: IVault.SwapKind.GIVEN_IN,
            assetIn: IAsset(WETH),
            assetOut: IAsset(USDC),
            amount: amountIn,
            userData: ""
        });

        IVault.FundManagement memory funds = IVault.FundManagement({
            sender: user,
            fromInternalBalance: false,
            recipient: payable(user),
            toInternalBalance: false
        });

        vm.startPrank(user);
        vault.swap(singleSwap, funds, minAmountOut, block.timestamp);
        vm.stopPrank();

        uint256 balanceAfter = IERC20(USDC).balanceOf(user);
        uint256 amountReceived = balanceAfter - balanceBefore;

        assertGe(amountReceived, minAmountOut, "Received less than minimum amount");
        console.log("USDC received:", amountReceived);
    }
}