Skip to main content
The swap module provides utilities for encoding orders that are settled directly against Balancer pools using the swap() function on the GPv2Settlement contract.

Interfaces

Swap

Represents a Balancer swap used for settling a single order against Balancer pools.
poolId
BytesLike
required
The ID of the Balancer pool to swap against
assetIn
string
required
Address of the input token
assetOut
string
required
Address of the output token
amount
BigNumberish
required
The amount to swap. For sell orders, this is the input amount. For buy orders, this is the output amount.
userData
BytesLike
Optional pool-specific user data required for certain pool types

BatchSwapStep

An encoded Balancer swap step that can be passed to the settlement contract.
poolId
BytesLike
required
The ID of the Balancer pool
assetInIndex
number
required
Index of the input token in the tokens array
assetOutIndex
number
required
Index of the output token in the tokens array
amount
BigNumberish
required
The swap amount
userData
BytesLike
required
Pool-specific user data (empty if not needed)

SwapExecution

Parameters for swap execution that allow tighter slippage control.
limitAmount
BigNumberish
required
The limit amount for the swap. This allows solvers to specify tighter slippage than the order’s limit to reduce MEV.

EncodedSwap

A tuple representing a fully encoded swap ready for the settlement contract.
type EncodedSwap = [
  BatchSwapStep[],  // Swap requests
  string[],         // Token addresses
  Trade,            // Encoded trade
];

SwapEncoder Class

A builder class for encoding swap calldata step-by-step.

Constructor

constructor(domain: TypedDataDomain)
domain
TypedDataDomain
required
The EIP-712 domain for signing orders

Properties

tokens
string[]
Array of token addresses used in the encoded swaps (read-only)
swaps
BatchSwapStep[]
Array of encoded swap steps (read-only)
trade
Trade
The encoded trade (throws if not yet encoded)

Methods

encodeSwapStep

Encodes swap steps and appends them to the encoder.
encodeSwapStep(...swaps: Swap[]): void
swaps
Swap[]
required
One or more swaps to encode

encodeTrade

Encodes a trade from a signed order.
encodeTrade(
  order: Order,
  signature: Signature,
  swapExecution?: Partial<SwapExecution>
): void
order
Order
required
The order to encode
signature
Signature
required
The signature for the order
swapExecution
Partial<SwapExecution>
Optional execution parameters for tighter limits

signEncodeTrade

Signs an order and encodes a trade in one step.
async signEncodeTrade(
  order: Order,
  owner: Signer,
  scheme: EcdsaSigningScheme,
  swapExecution?: Partial<SwapExecution>
): Promise<void>
order
Order
required
The order to sign and encode
owner
Signer
required
The signer for the order
scheme
EcdsaSigningScheme
required
The signing scheme to use (EIP712 or ETHSIGN)
swapExecution
Partial<SwapExecution>
Optional execution parameters

encodedSwap

Returns the complete encoded swap data.
encodedSwap(): EncodedSwap
result
EncodedSwap
Tuple of [swaps, tokens, trade] ready for the settlement contract

encodeSwap (static)

Utility method for encoding a swap in one call. Has multiple overloads:
// With pre-signed order
static encodeSwap(
  swaps: Swap[],
  order: Order,
  signature: Signature,
  swapExecution?: Partial<SwapExecution>
): EncodedSwap

// With signing
static encodeSwap(
  domain: TypedDataDomain,
  swaps: Swap[],
  order: Order,
  owner: Signer,
  scheme: EcdsaSigningScheme,
  swapExecution?: Partial<SwapExecution>
): Promise<EncodedSwap>

Usage Examples

Encode a Direct Balancer Swap

import { SwapEncoder, domain, Order, OrderKind } from "@cowprotocol/contracts";
import { ethers } from "ethers";

const chainId = 1;
const settlementContract = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41";
const domainSeparator = domain(chainId, settlementContract);

// Create the order
const order: Order = {
  sellToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", // WETH
  buyToken: "0x6B175474E89094C44Da98b954EedeAC495271d0F",  // DAI
  sellAmount: ethers.utils.parseEther("1.0"),
  buyAmount: ethers.utils.parseEther("2000"),
  validTo: Math.floor(Date.now() / 1000) + 3600,
  appData: ethers.constants.HashZero,
  feeAmount: ethers.utils.parseEther("0.01"),
  kind: OrderKind.SELL,
  partiallyFillable: false,
};

// Define Balancer pool swap
const swap = {
  poolId: "0x...", // Balancer pool ID
  assetIn: order.sellToken,
  assetOut: order.buyToken,
  amount: order.sellAmount,
};

// Encode the swap with signing
const signer = new ethers.Wallet("0x...");
const encodedSwap = await SwapEncoder.encodeSwap(
  domainSeparator,
  [swap],
  order,
  signer,
  "eip712"
);

const [swaps, tokens, trade] = encodedSwap;
console.log("Encoded swap ready for settlement");

Multi-Hop Swap Through Multiple Pools

import { SwapEncoder } from "@cowprotocol/contracts";

const encoder = new SwapEncoder(domainSeparator);

// Add multiple swap steps for routing through pools
encoder.encodeSwapStep(
  {
    poolId: "0xPoolId1...",
    assetIn: "0xWETH...",
    assetOut: "0xUSDC...",
    amount: ethers.utils.parseEther("1.0"),
  },
  {
    poolId: "0xPoolId2...",
    assetIn: "0xUSDC...",
    assetOut: "0xDAI...",
    amount: 0, // Amount computed from previous swap
  }
);

// Sign and encode the trade
await encoder.signEncodeTrade(order, signer, "eip712");

// Get the complete encoding
const [swaps, tokens, trade] = encoder.encodedSwap();

Tighter Slippage Control

import { SwapEncoder } from "@cowprotocol/contracts";

const encoder = new SwapEncoder(domainSeparator);
encoder.encodeSwapStep(swap);

// Encode with tighter limit than order specified
await encoder.signEncodeTrade(
  order,
  signer,
  "eip712",
  {
    limitAmount: ethers.utils.parseEther("2100"), // Tighter than order's 2000
  }
);

const encoded = encoder.encodedSwap();

Functions

encodeSwapStep

Standalone function to encode a single swap step.
function encodeSwapStep(
  tokens: TokenRegistry,
  swap: Swap
): BatchSwapStep
tokens
TokenRegistry
required
Token registry for mapping addresses to indices
swap
Swap
required
The swap to encode
batchSwapStep
BatchSwapStep
Encoded swap step with token indices

Notes

The swap module is specifically for direct settlement against Balancer pools using the swap() function. For settlements with multiple orders and interactions, use the SettlementEncoder class instead.
The userData field in swaps is pool-implementation specific. Most standard Balancer pools don’t require it, but specialized pools might use it for additional parameters.

Settlement Encoding

Full settlement encoding with multiple trades

Vault Module

Balancer Vault integration utilities

Build docs developers (and LLMs) love