BSwap
BSwap is the Mercury AMM for bTokens on Ethereum, with n=2 power-law curve, exact in/out trades, quotes, fees, events, errors, and full JSON ABI for viem, ethers, and integrations.
Overview
The BSwap contract implements Baseline's power-law AMM curve for token trading. It handles exact-in and exact-out buys and sells, plus matching quote functions for off-chain previews.
Functions
Trading Functions
buyTokensExactIn
Buy bTokens with an exact amount of reserves.
function buyTokensExactIn(
BToken _bToken,
uint256 _amountIn,
uint256 _limitAmount
) external returns (uint256 amountOut_, uint256 feesReceived_)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The bToken to buy |
_amountIn | uint256 | Exact reserve amount to spend |
_limitAmount | uint256 | Minimum bTokens to receive (slippage protection) |
Returns:
amountOut_: bTokens receivedfeesReceived_: Fees attributed to the trade
buyTokensExactOut
Buy an exact amount of bTokens.
function buyTokensExactOut(
BToken _bToken,
uint256 _amountOut,
uint256 _limitAmount
) external payable returns (uint256 amountIn_, uint256 feesReceived_)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The bToken to buy |
_amountOut | uint256 | Exact bTokens to receive |
_limitAmount | uint256 | Maximum reserves to spend (slippage protection) |
Returns:
amountIn_: Reserves spentfeesReceived_: Fees attributed to the trade
sellTokensExactIn
Sell an exact amount of bTokens.
function sellTokensExactIn(
BToken _bToken,
uint256 _amountIn,
uint256 _limitAmount
) external returns (uint256 amountOut_, uint256 feesReceived_)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The bToken to sell |
_amountIn | uint256 | Exact bTokens to sell |
_limitAmount | uint256 | Minimum reserves to receive (slippage protection) |
Returns:
amountOut_: Reserves receivedfeesReceived_: Fees attributed to the trade
sellTokensExactOut
Sell bTokens to receive an exact amount of reserves.
function sellTokensExactOut(
BToken _bToken,
uint256 _amountOut,
uint256 _limitAmount
) external returns (uint256 amountIn_, uint256 feesReceived_)| Parameter | Type | Description |
|---|---|---|
_bToken | BToken | The bToken to sell |
_amountOut | uint256 | Exact reserves to receive |
_limitAmount | uint256 | Maximum bTokens to sell (slippage protection) |
Returns:
amountIn_: bTokens soldfeesReceived_: Fees attributed to the trade
Quote Functions
Quote functions return expected trade results without executing.
quoteBuyExactIn
function quoteBuyExactIn(BToken _bToken, uint256 _amountIn)
external view returns (uint256 tokensOut_, uint256 feesReceived_, uint256 slippage_)Returns:
tokensOut_: bTokens for_amountInreserve (preview)feesReceived_: Fee portion of the quoteslippage_: Price impact as a WAD-scaled ratio
quoteBuyExactOut
function quoteBuyExactOut(BToken _bToken, uint256 _amountOut)
external view returns (uint256 amountIn_, uint256 feesReceived_, uint256 slippage_)Returns:
amountIn_: Reserves required for_amountOutbTokens (preview)feesReceived_: Fee portion of the quoteslippage_: Price impact as a WAD-scaled ratio
quoteSellExactIn
function quoteSellExactIn(BToken _bToken, uint256 _amountIn)
external view returns (uint256 amountOut_, uint256 feesReceived_, uint256 slippage_)Returns:
amountOut_: Reserves for_amountInbTokens sold (preview)feesReceived_: Fee portion of the quoteslippage_: Price impact as a WAD-scaled ratio
quoteSellExactOut
function quoteSellExactOut(BToken _bToken, uint256 _amountOut)
external view returns (uint256 tokensIn_, uint256 feesReceived_, uint256 slippage_)Returns:
tokensIn_: bTokens to sell to receive_amountOutreserves (preview)feesReceived_: Fee portion of the quoteslippage_: Price impact as a WAD-scaled ratio
View Functions
getCurveParams
Get current curve parameters for a bToken.
function getCurveParams(BToken _bToken) external view returns (CurveParams memory)Returns: CurveParams (CurveLib, WAD):
BLV,circ,supply,swapFee,reserves,totalSupply,convexityExp,lastInvariant(curve state for pricing and invariant math)
Events
event Swap(
BToken bToken,
address user,
uint256 activePrice,
uint256 blvPrice,
int256 bTokenDelta,
int256 reserveDelta,
uint256 totalFee,
uint256 liquidityFee
);Errors
| Error | Description |
|---|---|
SlippageExceeded | Result would break the min/max slippage bound on the trade (_limitAmount) |
SolverFailed | Numerical solver failed to converge for the trade |
Efficient Swap Paths For Integrators
BSwap exposes 4 swap functions, but only 2 are gas-efficient on-chain:
| Function | Direction | Gas | Reason |
|---|---|---|---|
buyTokensExactOut | reserve to bToken | Cheap | Direct curve computation |
sellTokensExactIn | bToken to reserve | Cheap | Direct curve computation |
buyTokensExactIn | reserve to bToken | Expensive | Binary-searches for amountOut |
sellTokensExactOut | bToken to reserve | Expensive | Binary-searches for amountIn |
The ExactIn/ExactOut naming refers to what's exact from the user's perspective, but the on-chain cost depends on whether the contract receives the natural input to the curve math (direct computation) or the other side (binary search).
Pattern for integrators:
- Buys: Quote off-chain via
quoteBuyExactIn(view call, solver is free), then execute viabuyTokensExactOutwith the quotedamountOut. - Sells: Call
sellTokensExactIndirectly. It is already the efficient path. - Never call
buyTokensExactInorsellTokensExactOuton-chain unless you can't pre-compute the amounts.
The @baseline-markets/sdk exposes the same pattern for TypeScript apps:
const quote = await sdk.quoteBuyExactIn(bToken, reservesIn);
await sdk.buyTokensExactOut(bToken, quote.tokensOut, maxReservesIn, {
confirmations: 1,
});
await sdk.sellTokensExactIn(bToken, amountIn, minReservesOut, {
confirmations: 1,
});Usage Example
Recommended buy flow: quote off-chain, then execute on the cheap path.
// 1. Quote off-chain: how many bTokens does 100 reserves buy?
(uint256 quotedOut, uint256 quotedFee, uint256 slippage) = bswap.quoteBuyExactIn(
bToken,
100e18 // 100 reserves in
);
// 2. Execute via buyTokensExactOut with the quoted amount.
// Apply slippage tolerance to the reserve cap (e.g. +1%).
uint256 maxIn = 101e18;
(uint256 amountIn, uint256 fees) = bswap.buyTokensExactOut(
bToken,
quotedOut,
maxIn
);
// Sells are already on the efficient path. Call directly.
(uint256 amountOut, uint256 sellFees) = bswap.sellTokensExactIn(
bToken,
10e18, // 10 bTokens in
9e18 // min 9 reserves out (slippage)
);ABI
[
{
"type": "function",
"name": "LABEL",
"inputs": [],
"outputs": [
{
"name": "",
"type": "bytes32",
"internalType": "bytes32"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "ROUTES",
"inputs": [],
"outputs": [
{
"name": "routes_",
"type": "bytes4[]",
"internalType": "bytes4[]"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "VERSION",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "pure"
},
{
"type": "function",
"name": "buyTokensExactIn",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_amountIn",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_limitAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "amountOut_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "buyTokensExactOut",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_amountOut",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_limitAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "amountIn_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "payable"
},
{
"type": "function",
"name": "getCurveParams",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"internalType": "struct CurveParams",
"components": [
{
"name": "BLV",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "circ",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "supply",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "swapFee",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "reserves",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "totalSupply",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "convexityExp",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "lastInvariant",
"type": "uint256",
"internalType": "uint256"
}
]
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "quoteBuyExactIn",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_reservesIn",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "tokensOut_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "slippage_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "quoteBuyExactOut",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_amountOut",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "amountIn_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "slippage_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "quoteSellExactIn",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_amountIn",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "amountOut_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "slippage_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "quoteSellExactOut",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_reservesOut",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "tokensIn_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "slippage_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"type": "function",
"name": "sellTokensExactIn",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_amountIn",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_limitAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "amountOut_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "sellTokensExactOut",
"inputs": [
{
"name": "_bToken",
"type": "address",
"internalType": "contract BToken"
},
{
"name": "_amountOut",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "_limitAmount",
"type": "uint256",
"internalType": "uint256"
}
],
"outputs": [
{
"name": "amountIn_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "feesReceived_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "supportsInterface",
"inputs": [
{
"name": "_interfaceId",
"type": "bytes4",
"internalType": "bytes4"
}
],
"outputs": [
{
"name": "",
"type": "bool",
"internalType": "bool"
}
],
"stateMutability": "pure"
},
{
"type": "event",
"name": "Distributed",
"inputs": [
{
"name": "bToken",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "reserve",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "totalAmount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "protocolFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "creatorFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "stakingFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Swap",
"inputs": [
{
"name": "bToken",
"type": "address",
"indexed": false,
"internalType": "contract BToken"
},
{
"name": "user",
"type": "address",
"indexed": false,
"internalType": "address"
},
{
"name": "activePrice",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "blvPrice",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "bTokenDelta",
"type": "int256",
"indexed": false,
"internalType": "int256"
},
{
"name": "reserveDelta",
"type": "int256",
"indexed": false,
"internalType": "int256"
},
{
"name": "totalFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
},
{
"name": "liquidityFee",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "error",
"name": "BlockPricingLib_InvalidDeltaDirection",
"inputs": []
},
{
"type": "error",
"name": "BlockPricingLib_SellExceedsSameBlockCapacity",
"inputs": []
},
{
"type": "error",
"name": "BlockPricingLib_SellFloorExceedsCurveRelease",
"inputs": []
},
{
"type": "error",
"name": "Component_NotPermitted",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_Insolvent",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_InsufficientSettledReserves",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_Paused",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_Reentrant",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_ReserveAccountingMismatch",
"inputs": []
},
{
"type": "error",
"name": "InvalidConvexityExp",
"inputs": []
},
{
"type": "error",
"name": "InvalidOutput",
"inputs": []
},
{
"type": "error",
"name": "InvalidParameters",
"inputs": []
},
{
"type": "error",
"name": "InvalidSwapDirection",
"inputs": []
},
{
"type": "error",
"name": "InvariantDecreased",
"inputs": [
{
"name": "prevInvariant",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "newInvariant",
"type": "uint256",
"internalType": "uint256"
}
]
},
{
"type": "error",
"name": "NativeLib_AmountMismatch",
"inputs": []
},
{
"type": "error",
"name": "NativeLib_NotWrapped",
"inputs": []
},
{
"type": "error",
"name": "PriceMustChange",
"inputs": []
},
{
"type": "error",
"name": "SlippageExceeded",
"inputs": []
},
{
"type": "error",
"name": "SolverFailed",
"inputs": []
},
{
"type": "error",
"name": "TradeExceedsLimit",
"inputs": []
}
]Related
- BMM Mechanics: Power-law curve explanation
- BLens Contract : View functions