Swap
The swap module provides utilities for encoding Balancer swap requests within CoW Protocol. It enables direct order settlement against Balancer pools via the swap() function on the GPv2Settlement contract.
Interfaces
Swap
Represents a single Balancer pool interaction:
interface Swap {
poolId: string;
assetInIndex: number;
assetOutIndex: number;
amount: BigNumberish;
userData?: string;
}
BatchSwapStep
The encoded form passed to the settlement contract, using token array indices rather than addresses for gas efficiency:
interface BatchSwapStep {
poolId: string;
assetInIndex: number;
assetOutIndex: number;
amount: BigNumberish;
userData: string;
}
SwapExecution
Provides limitAmount for solvers to enforce stricter slippage protection than the original order:
interface SwapExecution {
limitAmount: BigNumberish;
}
EncodedSwap
A three-element tuple:
type EncodedSwap = [BatchSwapStep[], string[], Trade];
SwapEncoder Class
Builder class that constructs encoded swap calldata progressively.
Methods
encodeSwapStep
Appends one or more swaps to the encoder’s internal state:
encoder.encodeSwapStep(swap: Swap | Swap[]): void;
encodeTrade
Incorporates a pre-signed order into the encoding:
encoder.encodeTrade(order: Order, signature: Signature, execution?: SwapExecution): void;
signEncodeTrade
Signs an order and encodes it simultaneously:
await encoder.signEncodeTrade(
order: Order,
signer: Signer,
scheme: SigningScheme,
execution?: SwapExecution
): Promise<void>;
encodedSwap
Returns the finalized tuple:
encoder.encodedSwap(): EncodedSwap;
encodeSwap (static)
One-shot utility method with multiple overloads for convenience:
static SwapEncoder.encodeSwap(swap: Swap, order: Order, signature: Signature): EncodedSwap;
Examples
Single-Pool Swap
import { SwapEncoder } from "@cowprotocol/contracts";
const encoder = new SwapEncoder(domain);
encoder.encodeSwapStep({
poolId: "0x...",
assetInIndex: 0, // WETH
assetOutIndex: 1, // DAI
amount: ethers.utils.parseEther("1"),
});
await encoder.signEncodeTrade(order, wallet, SigningScheme.EIP712);
const encoded = encoder.encodedSwap();
Multi-Hop Swap
encoder.encodeSwapStep([
{
poolId: "0xPoolA...",
assetInIndex: 0, // WETH
assetOutIndex: 1, // USDC
amount: ethers.utils.parseEther("1"),
},
{
poolId: "0xPoolB...",
assetInIndex: 1, // USDC
assetOutIndex: 2, // DAI
amount: 0, // determined by first swap output
},
]);
MEV Mitigation
encoder.encodeTrade(order, signature, {
limitAmount: ethers.utils.parseEther("1990"), // Tighter than order's buyAmount
});
This module specifically handles direct Balancer settlement. For complex scenarios involving multiple orders and contract interactions, use the SettlementEncoder class instead. Most standard Balancer pools omit the userData field.