Skip to content
🚧 Under Development! May be incomplete.Some pages/links may be incomplete or subject to change.

Pool Joins in BeraSwap

Important: Calls to joinPool() must be made on the BeraSwap Vault contract! You cannot send this command directly to a pool.

To add liquidity to a pool, you must call the joinPool function on the BeraSwap Vault.

JoinPool Function

solidity
joinPool(
    bytes32 poolId,
    address sender,
    address recipient,
    JoinPoolRequest request
)

Arguments Explained

ParameterTypeDescription
poolIdbytes32ID of the pool you're joining
senderaddressAddress sending tokens to the pool
recipientaddressAddress receiving LP tokens (usually the same as sender)
requestJoinPoolRequestStruct containing join details (see below)

JoinPoolRequest Struct

solidity
struct JoinPoolRequest {
    address[] assets,
    uint256[] maxAmountsIn,
    bytes userData,
    bool fromInternalBalance
}
FieldTypeDescription
assetsaddress[]Sorted list of all tokens in pool
maxAmountsInuint256[]Maximum token amounts to send
userDatabytesCustom bytes field for join parameters
fromInternalBalanceboolIf fromInternalBalance is true, the caller's Internal Balance will be preferred: ERC20 transfers will only

Token Ordering

When providing assets, tokens must be sorted numerically by address. The values in maxAmountsIn correspond to the same index in assets, so these arrays must be created in parallel after sorting.

Maximum Amounts

The maxAmountsIn parameter sets upper limits for tokens to send. This protects against price changes between transaction submission and execution.

Best practice:

  1. Use queryJoin to calculate current token amounts needed
  2. Add slippage tolerance (e.g., multiply by 1.01 for 1% slippage)
  3. Use these adjusted amounts as maxAmountsIn

userData Encoding

The userData field encodes the join type and parameters. Different pool types support different join kinds.

JoinKind Enum

solidity
enum JoinKind {
    INIT,
    EXACT_TOKENS_IN_FOR_LP_OUT,
    TOKEN_IN_FOR_EXACT_LP_OUT,
    ALL_TOKENS_IN_FOR_EXACT_LP_OUT
}
JoinKindDescription
INITInitial join to seed a pool (can be done only once)
EXACT_TOKENS_IN_FOR_LP_OUTSend precise token quantities, receive estimated LP tokens
TOKEN_IN_FOR_EXACT_LP_OUTSend estimated single token quantity, receive precise LP tokens
ALL_TOKENS_IN_FOR_EXACT_LP_OUTSend estimated token quantities proportionally, receive precise LP tokens

Note: When encoding userData for pools that include their own LP token, the LP tokens are not included except for INIT joins.

userData Encoding

Join TypeABIuserData
Initial Join['uint256', 'uint256[]'][INIT, amountsIn]
Exact Tokens Join['uint256', 'uint256[]', 'uint256'][EXACT_TOKENS_IN_FOR_LP_OUT, amountsIn, minimumLP]
Single Token Join['uint256', 'uint256', 'uint256'][TOKEN_IN_FOR_EXACT_LP_OUT, lpAmountOut, enterTokenIndex]
Proportional Join['uint256', 'uint256'][ALL_TOKENS_IN_FOR_EXACT_LP_OUT, lpAmountOut]

Examples

Example 1: Initial Join (INIT)

Seeding a new pool with $BERA and $HONEY:

StepJoinKindAssetsAmountsIn
1INIT[BERA, HONEY][100 $BERA, 1000 $HONEY]

Example 2: Exact Tokens Join (EXACT_TOKENS_IN_FOR_LP_OUT)

Joining an existing BERA/HONEY pool:

StepJoinKindAssetsAmountsInMinimumLP
1EXACT_TOKENS_IN_FOR_LP_OUT[$BERA, $HONEY][10 BERA, 100 HONEY]95 LP

Example 3: Single Token Join (TOKEN_IN_FOR_EXACT_LP_OUT)

Joining a $BERA/$HONEY/$DAI pool with only $BERA:

StepJoinKindAssetsLPAmountOutEnterTokenIndex
1TOKEN_IN_FOR_EXACT_LP_OUT[$BERA, $HONEY, $DAI]100 LP0