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, handling all buy and sell operations with the n=2 curve and BLV translation.
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 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 amountOut_, uint256 fee_)Returns:
amountOut_: bTokens for_amountInreserve (preview)fee_: Fee portion of the quote
quoteBuyExactOut
function quoteBuyExactOut(BToken _bToken, uint256 _amountOut)
external view returns (uint256 amountIn_, uint256 fee_)Returns:
amountIn_: Reserves required for_amountOutbTokens (preview)fee_: Fee portion of the quote
quoteSellExactIn
function quoteSellExactIn(BToken _bToken, uint256 _amountIn)
external view returns (uint256 amountOut_, uint256 fee_)Returns:
amountOut_: Reserves for_amountInbTokens sold (preview)fee_: Fee portion of the quote
quoteSellExactOut
function quoteSellExactOut(BToken _bToken, uint256 _amountOut)
external view returns (uint256 amountIn_, uint256 fee_)Returns:
amountIn_: bTokens to sell to receive_amountOutreserves (preview)fee_: Fee portion of the quote
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 sender, bool isBuy, uint256 amountIn, uint256 amountOut, uint256 fee);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 → bToken | Cheap | Direct curve computation |
sellTokensExactIn | bToken → reserve | Cheap | Direct curve computation |
buyTokensExactIn | reserve → bToken | Expensive | Binary-searches for amountOut |
sellTokensExactOut | bToken → 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's already the efficient path. - Never call
buyTokensExactInorsellTokensExactOuton-chain unless you can't pre-compute the amounts.
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) = 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": "Component_NotPermitted",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_Insolvent",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_Paused",
"inputs": []
},
{
"type": "error",
"name": "GuardLib_Reentrant",
"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
Contracts
Mercury smart contract reference and Ethereum mainnet addresses for Relay, BSwap, BStaking, BCredit, BFactory, and BLens, plus legacy Baseline deployments and operational multisigs.
BStaking
BStaking stakes bTokens on Ethereum to earn protocol fees, including deposit, withdraw, lock periods, claim, view functions, events, errors, and JSON ABI for integrations.