Batch Swaps

Batch Swaps

Batch Swap Overview

A360 AMM integrates the BalancerV2 architectures which allows for multi-hop swaps, or "batch swaps", which pull the best prices from all the pools registered with the Vault.

The Vault exposes the batchSwap function to allow multi-hop swaps with the the interface below.

batchSwap(SwapKind kind,
          BatchSwapStep[] swaps,
          IAsset[] assets,
          FundManagement funds,
          int256[] limits,
          uint256 deadline) returns (int256[] assetDeltas)

Each struct which is explained below.

BatchSwapStep struct

struct BatchSwapStep {
    bytes32 poolId;
    uint256 assetInIndex;
    uint256 assetOutIndex;
    uint256 amount;
    bytes userData;
}
  • poolId: The id of the pool to swap with.

  • assetInIndex: The index of the token within assets which to use as an input of this step.

  • assetOutIndex: The index of the token within assets which is the output of this step.

  • amount: The meaning of amount depends on the value of kind which passed to the batchSwap function.

    • GIVEN_IN: The amount of tokens swapped into the pool in this step

    • GIVEN_OUT: The amount of tokens received from the pool in this step

  • userData: Any additional data which the pool requires to perform the swap. This allows pools to have more flexible swapping logic in future - for all current Balancer pools this can be left empty.

Amounts for multi-hop swaps

When performing multi-hop swaps, it's not always possible to know the value of amount for a given step.

By setting amount to 0, the vault will interpret this to use the full output of the previous hop.

FundManagement struct

The FundManagement struct defines where the input tokens for the first swap are coming from and where any tokens received from swaps should be sent. The FundManagement struct is defined as below.

struct FundManagement {
    address sender;
    bool fromInternalBalance;
    address payable recipient;
    bool toInternalBalance;
}
  • sender: The address from which tokens will be taken to perform the swap.

  • fromInternalBalance: Whether the swap should use tokens owned by the sender which are already stored in the Vault.

  • recipient: The address to which tokens will be sent to after the swap.

  • toInternalBalance: Whether the tokens should be sent to the recipient or stored within their internal balance within the Vault.

BatchSwap function

batchSwap(SwapKind kind,
          BatchSwapStep[] swaps,
          IAsset[] assets,
          FundManagement funds,
          int256[] limits,
          uint256 deadline) returns (int256[] assetDeltas)
  • kind: The type of batch swap to perform - either "Out Given Exact In" or "In Given Exact Out."

  • assets: An array of tokens which are used in the batch swap. This is referenced from within swaps

  • limits: An array of maximum amounts of each asset to be transferred. For tokens going in to the Vault, the limit shall be a positive number. For tokens going out of the Vault, the limit shall be a negative number. If the amount to be transferred for a given asset is greater than its limit, the swap will fail with error BAL#507: SWAP_LIMIT.

  • deadline: The UNIX timestamp at which our swap must be completed by - if the transaction is confirmed after this time, the transaction will fail.

queryBatchSwap

queryBatchSwap is an extremely useful function in the Vault contract. With queryBatchSwap, you can get the exact amounts for a given swap with the on-chain state. You can use these amounts to calculate input/output limits based on a slippage tolerance.

Warning

You should NOT use queryBatchSwap to calculate limits from a smart contract that is executing a swap. This will leave you vulnerable to sandwich attacks.

You should only use queryBatchSwap before sending a batchSwap transaction, when calculating your batchSwap arguments off-chain.

queryBatchSwap(SwapKind kind,
          BatchSwapStep[] swaps,
          IAsset[] assets,
          FundManagement funds)
          returns (int256[] assetDeltas)

To use queryBatchSwap, you must use eth_call.

You may notice that queryBatchSwap shows up on Etherscan as a write function, but this is simply due to the fact that the function fully executes a batchSwap before reverting.

Adding a Slippage Tolerance

Once you have received your assetDeltas from calling queryBatchSwap, you can calculate limits for a batchSwap by applying your slippage tolerance.

GIVEN_IN

To perform a GIVEN_IN batchSwap and apply a 1% slippage tolerance, multiply the negative assetDeltas by 0.99. Positive amounts do not need to be modified since the amount going into the pool is known.

GIVEN_OUT

To perform a GIVEN_OUT batchSwap and apply a 1% slippage tolerance, multiply the positive assetDeltas by 1.01. Negative amounts do not need to be modified since the amount being received from the pool is known.

Last updated