Providing Liquidity
Liquidity providers (LPs) deposit tokens into Risk Marketplace pools and receive pool share tokens representing their proportional ownership. LPs earn LP fees generated by trading activity in the pool.
Pool Shares
When providing liquidity, users receive pool shares calculated based on their contribution relative to the existing pool value. These shares:
Represent proportional ownership of all tokens in the pool
Accumulate value as LP fees are retained in the pool
Can be redeemed for underlying tokens at any time (subject to circuit breakers)
Fees
Single-asset joins and exits incur two fees that proportional joins and exits do not. Single-asset exits also incur a third, small fee on the pool shares themselves.
LP Fee (dynamic). Paid on the rebalancing portion of the implicit swap and retained in the pool, accruing to existing LPs. The LP fee is dynamic: each single-asset call must include a feeData payload signed off-chain by an authorized signer. The contract validates:
ECDSA signature against the set of authorized signers
Domain binding (
poolmatches the calling pool,chainIdmatchesblock.chainid)Freshness (
timestampwithin the configuredstalenessThreshold)Bounds (
feelies within the configured[minFee, maxFee])
If validation fails, the call reverts.
Protocol Fee. Taken on the gross input for joins and the gross output for exits. The fee is transferred directly to protocolAddress and is not retained in the pool. The rate is read from bPool.getProtocolFee(). If protocolAddress is unset, the fee is waived for that call and a ProtocolFeeSkipped event is emitted.
Emergency Mode. If signing infrastructure is unavailable, the pool owner can enable emergency mode. While enabled, single-asset joins and exits accept an empty feeData and fall back to a pre-configured emergencyFee. Outside emergency mode, calls with empty feeData revert with BPOOL_Missing_Fee_Data.
1. Joining a Pool
1 a) Proportional Join (Multi-Asset Deposit)
Deposit all pool tokens in their current ratio. This method incurs no LP fees since it maintains the pool balance.
Calculation:
tokenAmountIni=poolSupplypoolAmountOut×Bi
Where:
poolAmountOut = Pool shares to receive
poolSupply = Current total pool shares
Bi = Current balance of token (i)
Key Functions
joinPool Method: Handles depositing multiple tokens proportionally in exchange for the pool shares.
Parameters:
poolAmountOut:The amount of pool shares to receivemaxAmountsIn[]: Maximum amounts of each token willing to deposit (slippage protection)
Process
Ratio Calculation
The system calculates the ratio of requested pool shares to total supply.
This ratio determines how much of each token is required
Token Transfer
For each token in the pool, the required amount is calculated:
tokenAmountIn = ratio × tokenBalance.Tokens are transferred from the user to the pool; If any calculated amount exceeds
maxAmountsIn, the transaction reverts
Share Minting
Pool shares are minted to the user equal to
poolAmountOut
Example: A pool contains 1,000 ETH and 2,000,000 USDC with a total supply of 100 pool share tokens. To receive 10 pool share tokens (10% of supply):
ETH required: 10% × 1,000 = 100 ETH
USDC required: 10% × 2,000,000 = 200,000 USDC
1 b) Single-Asset Join (Single Token Deposit)
Deposit only one token. The pool implicitly swaps part of the deposit into the other pool tokens; the rebalancing portion incurs an LP fee. The protocol fee is taken on the full deposit amount before share math runs.
Where:
‘Ai‘= Amount of token credited to the pool (=
tokenAmountIn − protocolFee)‘Bi‘ = Current balance of deposit token
‘Win‘ = Normalized weight of deposit token
‘LPFee‘= Validated dynamic LP fee from the signed
feeDatapayload
Key Functions
joinswapExternAmountIn Method: Deposit an exact amount of one token, receive calculated pool shares.
tokenIn
address
Address of the token being deposited
tokenAmountIn
uint
Total amount transferred from the LP. The protocol fee is taken out of this amount and the remainder is credited to the pool.
minPoolAmountOut
uint
Minimum pool shares to receive (slippage protection)
feeData
bytes
ABI-encoded (fee, timestamp, pool, chainId) from an authorized signer
signature
bytes
ECDSA signature over feeData
joinswapPoolAmountOut Method: Specify exact pool shares desired; the system calculates the required deposit.
tokenIn
address
Address of the token being deposited
poolAmountOut
uint
Exact amount of pool shares to receive
maxAmountIn
uint
Maximum tokens willing to pay, including the protocol fee (slippage protection)
feeData
bytes
ABI-encoded (fee, timestamp, pool, chainId) from an authorized signer
signature
bytes
ECDSA signature over feeData
Process
Fee Validation -
feeDataandsignatureare verified; the dynamic LP fee is extracted.Protocol Fee - Computed on
tokenAmountIn(or the implied input forjoinswapPoolAmountOut) and routed toprotocolAddress. Pool-share math runs on the post-protocol-fee amount.Pool Shares Calculation - Uses weighted math on the net amount. The LP fee applies only to the portion that "rebalances" the pool.
Execution - Net deposit transferred from the user to the pool. Pool shares minted to the user.
Fee Logic: Only the portion that rebalances the pool pays the LP fee. If a token has 25% weight, depositing that token implicitly trades 75% of it for other tokens — only that 75% incurs the LP fee. The protocol fee, by contrast, is taken on the entire input.
Example: Single-asset join with 1,000 USDC into a pool where USDC has 20% weight, LP fee 0.3%, protocol fee 0.05%:
Protocol fee taken from input: 0.05% × 1,000 = 0.5 USDC → sent to
protocolAddressNet amount credited to pool: 999.5 USDC
Implicit swap portion: 80% × 999.5 ≈ 799.6 USDC
LP fee paid (retained in pool): 0.3% × 799.6 ≈ 2.4 USDC
Net contribution used for share calculation: ~997.1 USDC equivalent
2. Exiting a Pool
2 a) Proportional Exit (Multi-Asset Withdrawal)
Redeem pool shares for all tokens proportionally. This method incurs no LP fees.
Calculation:
tokenAmountOuti=poolSupplypoolAmountIn×Bi
Where:
poolAmountIn = Pool shares being redeemed
poolSupply = Current total pool shares
Bi = Current balance of token (i)
Key Functions
exitPool Method: Burn pool shares and receive all underlying tokens proportionally.
Parameters:
minAmountsOut: Minimum amounts of each token to receive (slippage protection)poolAmountIn: Amount of pool shares to redeem
Process
Ratio Calculation
The system calculates the ratio of redeemed shares to total supply, which determines how much of each token the user receives
Share Burning
Pool shares are pulled from the user's balance and are burned, reducing the total supply
Token Distribution
For each token: tokenAmountOut = ratio × tokenBalance, and if any calculated amount is below minAmountsOut, the transaction reverts
Tokens are transferred from the pool to the user
Example: Redeeming 10 BPT from a pool with 100 BPT supply, 1,000 ETH, and 2,000,000 USDC:
ETH received: 10% × 1,000 = 100 ETH
USDC received: 10% × 2,000,000 = 200,000 USDC
2 b) Single-Asset Exit (Single Token Withdrawal)
Redeem pool shares for only one token. The pool implicitly sells the other tokens for the desired token; the rebalancing portion incurs an LP fee. The protocol fee is taken from the gross output before delivery, and the EXIT_FEE (if set) is taken on pool shares.
Tokens Received (net of protocol fee):
Where:
‘Bo‘ = Current balance of withdrawal token
‘Won‘ = Normalized weight of withdrawal token
‘poolAmountIn‘ = Pool shares being redeemed (before
EXIT_FEEon shares)‘LPFee‘ = Validated dynamic LP fee from the signed
feeDatapayload‘ProtocolFee‘ =
bPool.getProtocolFee()
Key Functions
exitswapPoolAmountIn Method: Burn exact pool shares, receive calculated token amount.
tokenOut
address
Address of the token to receive
poolAmountIn
uint
Exact amount of pool shares to redeem
minAmountOut
uint
Minimum net tokens to receive after the protocol fee (slippage protection)
feeData
bytes
ABI-encoded (fee, timestamp, pool, chainId) from an authorized signer
signature
bytes
ECDSA signature over feeData
exitswapExternAmountOut Method: Specify the exact net token amount desired; the system calculates the shares to burn.
tokenOut
address
Address of the token to receive
tokenAmountOut
uint
Exact net amount of tokens to receive
maxPoolAmountIn
uint
Maximum pool shares willing to burn. Must cover the gross calculation (tokenAmountOut + protocolFee), not just the net.
feeData
bytes
ABI-encoded (fee, timestamp, pool, chainId) from an authorized signer
signature
bytes
ECDSA signature over feeData
Process
Fee Validation -
feeDataandsignatureare verified; the dynamic LP fee is extracted.Output Calculation - Uses weighted math to determine fair gross token output.
Protocol Fee - Protocol fee is computed on the gross output and routed to
protocolAddress. The user receivesgrossAmountOut − protocolFee.Exit Fee on Pool Shares -
EXIT_FEE × poolAmountInof pool shares is sent to the factory. The remainder of the redeemed shares is burned.Execution - Net token amount transferred from the pool to the user.
Fee Logic: The LP fee applies to the portion being implicitly swapped. Withdrawing a 20% weight token means 80% of the value comes from selling other tokens — that portion pays the LP fee. The protocol fee is taken on the entire gross output. The EXIT_FEE is taken on pool shares regardless of which token is withdrawn.
Example: Single-asset exit for 1 BPT from a pool with 100 BPT supply, 1,000 ETH, and 2,000,000 USDC, withdrawing USDC at 80% weight, LP fee 0.3%, protocol fee 0.05%, EXIT_FEE 0%:
Gross USDC released by weighted math: ~25,000 USDC (illustrative)
LP fee retained in pool: 0.3% × (1 − 0.8) × 25,000 = 15 USDC
Net of LP fee: ~24,985 USDC
Protocol fee: 0.05% × 24,985 ≈ 12.5 USDC → sent to
protocolAddressUSDC delivered to LP: ~24,972.5 USDC
Last updated
