Skip to main content
Pre-Release Documentation

This describes a pre-release version of LBAMM. Interfaces and behavior may change.

Verify the exact repository commit before building production integrations.

Execute Swaps

This guide shows how to execute swaps using:

  • singleSwap (one pool)
  • multiSwap (multiple pools)

It assumes:

  • You already understand swap semantics.
  • You are interacting with pools that already exist.
  • The executor (msg.sender) is directly supplying input tokens.
  • No custom transfer handler is used (transferData = "0x").

For deeper semantics, see:

  • Protocol Fundamentals → Swaps
  • Fees & Economics
  • Hooks

Entry Points

singleSwap

function singleSwap(
SwapOrder calldata swapOrder,
bytes32 poolId,
BPSFeeWithRecipient calldata exchangeFee,
FlatFeeWithRecipient calldata feeOnTop,
SwapHooksExtraData calldata swapHooksExtraData,
bytes calldata transferData
) external payable returns (uint256 amountIn, uint256 amountOut);

multiSwap

function multiSwap(
SwapOrder calldata swapOrder,
bytes32[] calldata poolIds,
BPSFeeWithRecipient calldata exchangeFee,
FlatFeeWithRecipient calldata feeOnTop,
SwapHooksExtraData[] calldata swapHooksExtraDatas,
bytes calldata transferData
) external payable returns (uint256 amountIn, uint256 amountOut);

Return values:

  • amountIn — total input collected (including execution-level fees)
  • amountOut — output delivered to swapOrder.recipient

Constructing SwapOrder

struct SwapOrder {
uint256 deadline;
address recipient;
int256 amountSpecified; // >0 swap-by-input, <0 swap-by-output
uint256 minAmountSpecified; // partial fill tolerance
uint256 limitAmount; // min output (input mode) or max input (output mode)
address tokenIn;
address tokenOut;
}

You are responsible for:

  • Setting deadline
  • Encoding swap mode via the sign of amountSpecified
  • Setting limitAmount correctly for your mode
  • Setting minAmountSpecified according to your partial-fill policy

Execution-Level Fees

Swaps accept two fee structs:

struct BPSFeeWithRecipient {
address recipient;
uint256 BPS;
}

struct FlatFeeWithRecipient {
address recipient;
uint256 amount;
}

Rules:

  • If recipient == address(0) → fee value must be 0.
  • BPS bounds depend on swap mode (see Fees & Economics).
  • Fee-on-top constraints depend on swap mode.

Hook Calldata

struct SwapHooksExtraData {
bytes tokenInHook;
bytes tokenOutHook;
bytes poolHook;
bytes poolType;
}

If no hook requires calldata:

SwapHooksExtraData({
tokenInHook: "",
tokenOutHook: "",
poolHook: "",
poolType: ""
})

For multiSwap, provide one SwapHooksExtraData per hop.


Token Approvals

For direct executor settlement:

  • msg.sender supplies tokenIn
  • LBAMM pulls via transferFrom
  • The executor must approve LBAMM beforehand

If using wrapped native input:

  • msg.value may be used
  • Incorrect or unused native value reverts
  • Excess native value is refunded

singleSwap Example (Solidity)

SwapOrder memory order = SwapOrder({
deadline: block.timestamp + 60,
recipient: recipient,
amountSpecified: int256(amountIn), // positive => swap-by-input
minAmountSpecified: amountIn,
limitAmount: minAmountOut,
tokenIn: tokenIn,
tokenOut: tokenOut
});

BPSFeeWithRecipient memory exchangeFee = BPSFeeWithRecipient({
recipient: exchangeFeeRecipient,
BPS: 30
});

FlatFeeWithRecipient memory feeOnTop = FlatFeeWithRecipient({
recipient: executorFeeRecipient,
amount: executorFee
});

SwapHooksExtraData memory hookData = SwapHooksExtraData({
tokenInHook: "",
tokenOutHook: "",
poolHook: "",
poolType: ""
});

(uint256 totalIn, uint256 totalOut) =
amm.singleSwap{ value: nativeAmountIn }(
order,
poolId,
exchangeFee,
feeOnTop,
hookData,
"" // no transfer handler
);

multiSwap Example (Solidity)

SwapHooksExtraData[] memory hookDatas = new SwapHooksExtraData[](poolIds.length);

for (uint256 i = 0; i < poolIds.length; i++) {
hookDatas[i] = SwapHooksExtraData("", "", "", "");
}

(uint256 totalIn, uint256 totalOut) =
amm.multiSwap{ value: msg.value }(
order,
poolIds,
exchangeFee,
feeOnTop,
hookDatas,
""
);

Notes:

  • swapHooksExtraDatas.length must equal poolIds.length.
  • A Swap event is emitted per hop.

TypeScript Example (singleSwap)

const swapOrder = {
deadline: BigInt(Math.floor(Date.now() / 1000) + 60),
recipient,
amountSpecified: amountIn, // >0 => swap-by-input
minAmountSpecified: amountIn,
limitAmount: minAmountOut,
tokenIn,
tokenOut,
};

const exchangeFee = {
recipient: exchangeFeeRecipient,
BPS: 30n,
};

const feeOnTop = {
recipient: executorFeeRecipient,
amount: executorFee,
};

const hookData = {
tokenInHook: "0x",
tokenOutHook: "0x",
poolHook: "0x",
poolType: "0x",
};

const { request } = await publicClient.simulateContract({
address: ammAddress,
abi: ammAbi,
functionName: "singleSwap",
args: [swapOrder, poolId, exchangeFee, feeOnTop, hookData, "0x"],
value: msgValue,
});

await walletClient.writeContract(request);

Common Integration Errors

Most swap failures come from:

  • Expired deadline
  • Incorrect limitAmount for swap mode
  • Fee configuration invalid (recipient zero with non-zero value)
  • Insufficient allowance or balance
  • Route array length mismatch (multiSwap)
  • Hook validation reverts

Limit Break

TwitterLimitBreak.comMedium

© 2026 Limit Break International, Inc. All rights reserved.

Privacy PolicyTerms of ServiceCookie PolicyDo Not Sell My Info