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 (pool matches the calling pool, chainId matches block.chainid)

  • Freshness (timestamp within the configured stalenessThreshold)

  • Bounds (fee lies 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=poolAmountOutpoolSupply×BitokenAmountIn_i = \frac{poolAmountOut}{poolSupply} \times B_i

Where:

  • poolAmountOutpoolAmountOut = Pool shares to receive

  • poolSupplypoolSupply = Current total pool shares

  • BiB_i = Current balance of token (i)

Key Functions

  • joinPool Method: Handles depositing multiple tokens proportionally in exchange for the pool shares.

    • Parameters:

      1. poolAmountOut: The amount of pool shares to receive

      2. maxAmountsIn[]: Maximum amounts of each token willing to deposit (slippage protection)

Process

  1. Ratio Calculation

    • The system calculates the ratio of requested pool shares to total supply.

    • This ratio determines how much of each token is required

  2. 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

  3. 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.

poolAmountOut=((Bi+Ai×(1(1Win)×LPFee)Bi)Win1)×poolSupplypoolAmountOut = \left( \left( \frac{B_i + A_i \times (1 - (1 - W_i^n) \times LPFee)}{B_i} \right)^{W_i^n} - 1 \right) \times poolSupply

Where:

  • Ai`A_i`= Amount of token credited to the pool (= tokenAmountIn − protocolFee)

  • Bi`B_i` = Current balance of deposit token

  • Win`W_i^n` = Normalized weight of deposit token

  • LPFee`LPFee`= Validated dynamic LP fee from the signed feeData payload

Key Functions

joinswapExternAmountIn Method: Deposit an exact amount of one token, receive calculated pool shares.

Parameter
Type
Description

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.

Parameter
Type
Description

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

  1. Fee Validation - feeData and signature are verified; the dynamic LP fee is extracted.

  2. Protocol Fee - Computed on tokenAmountIn (or the implied input for joinswapPoolAmountOut) and routed to protocolAddress. Pool-share math runs on the post-protocol-fee amount.

  3. Pool Shares Calculation - Uses weighted math on the net amount. The LP fee applies only to the portion that "rebalances" the pool.

  4. Execution - Net deposit transferred from the user to the pool. Pool shares minted to the user.

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 protocolAddress

  • Net 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=poolAmountInpoolSupply×BitokenAmountOut_i = \frac{poolAmountIn}{poolSupply} \times B_i

Where:

  • poolAmountInpoolAmountIn = Pool shares being redeemed

  • poolSupplypoolSupply = Current total pool shares

  • BiB_i = Current balance of token (i)

Key Functions

  • exitPool Method: Burn pool shares and receive all underlying tokens proportionally.

    • Parameters:

      1. minAmountsOut: Minimum amounts of each token to receive (slippage protection)

      2. poolAmountIn: Amount of pool shares to redeem

Process

  1. Ratio Calculation

    • The system calculates the ratio of redeemed shares to total supply, which determines how much of each token the user receives

  2. Share Burning

    • Pool shares are pulled from the user's balance and are burned, reducing the total supply

  3. 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):

tokenAmountOut=Bo×(1(poolSupplypoolAmountInpoolSupply)1Won)×(1(1Won)×LPFee)×(1ProtocolFee)tokenAmountOut = B_o \times \left( 1 - \left( \frac{poolSupply - poolAmountIn}{poolSupply} \right)^{\frac{1}{W_o^n}} \right) \times \left( 1 - (1 - W_o^n) \times LPFee \right) \times \left( 1 - ProtocolFee \right)

Where:

  • Bo`B_o` = Current balance of withdrawal token

  • Won`W_o^n` = Normalized weight of withdrawal token

  • poolAmountIn`poolAmountIn` = Pool shares being redeemed (before EXIT_FEE on shares)

  • LPFee`LPFee` = Validated dynamic LP fee from the signed feeData payload

  • ProtocolFee`ProtocolFee` = bPool.getProtocolFee()

Key Functions

exitswapPoolAmountIn Method: Burn exact pool shares, receive calculated token amount.

Parameter
Type
Description

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.

Parameter
Type
Description

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

  1. Fee Validation - feeData and signature are verified; the dynamic LP fee is extracted.

  2. Output Calculation - Uses weighted math to determine fair gross token output.

  3. Protocol Fee - Protocol fee is computed on the gross output and routed to protocolAddress. The user receives grossAmountOut − protocolFee.

  4. Exit Fee on Pool Shares - EXIT_FEE × poolAmountIn of pool shares is sent to the factory. The remainder of the redeemed shares is burned.

  5. Execution - Net token amount transferred from the pool to the user.

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 protocolAddress

  • USDC delivered to LP: ~24,972.5 USDC

Last updated