Pool Joins

Calls to joinPool() are made on the Vault, not directly on the pool. To identify the pool targeted for deposit you must pass the poolId as a parameter on the JoinPool Function

API

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

struct JoinPoolRequest {
    address[] assets,
    uint256[] maxAmountsIn,
    bytes userData,
    bool fromInternalBalance
}

Arguments Explained

  • poolId - ID of the pool you're interacting with

  • sender - Address sending tokens to the pool

  • recipient - Address receiving BPT (usually the same as sender)

  • request - JoinPoolRequest tuple made up of the following:

    • assets - Sorted list of all tokens in pool (see below)

    • maxAmountsIn - Maximum token send amounts (see below)

    • userData - Custom bytes field (see below)

    • fromInternalBalance - True if sending from internal token balances. False if sending ERC20.

Token Ordering

When providing your assets, you must ensure that the tokens are sorted numerically by token address. It's also important to note that the values in maxAmountsIn correspond to the same index value in assets, so these arrays must be made in parallel after sorting.

maxAmountsIn

In the joinPool call, you have to provide maxAmountsIn, which represents the maximum amount of tokens you are willing to transfer

Let's say that you want to allow a 1% slippage. After computing how many tokens you expect to provide for a given amount of BPT, you'd apply a factor of 1.01 to all the amounts.

userData

userData is a field which can be used for a variety of different purposes, for joins, userData encodes a JoinKind to tell the pool what style of join you're performing. Not every pool uses every JoinKind, so it's important to keep track of what each pool type can handle.

When encoding userData for pools that include their own BPT as part of the pool's tokens, the BPT are not included in the userData, except for INIT joins where they need to be included.

WeightedPool JoinKinds

enum JoinKind {
    INIT,
    EXACT_TOKENS_IN_FOR_BPT_OUT,
    ALL_TOKENS_IN_FOR_EXACT_BPT_OUT
}

JoinKinds Explained

The A360 AMM leverages three different types of Joins. Initial Join, Exact Tokens Join and Proportional Joins, the team has removed Single Token Joins typically present in the BalancerV2 Framework for security and compliance reasons to prevent users which do not fulfill the necessary compliance requirements from gaining exposure to equity tokens by depositing a single sided digital asset.

  • Initial Join (INIT)

    • User sends the precise initial tokens to seed a pool. This can be done only once.

  • Exact Tokens Join (EXACT_TOKENS_IN_FOR_BPT_OUT)

    • User sends precise quantities of tokens, and receives an estimated but unknown (computed at run time) quantity of BPT.

  • Proportional Join (ALL_TOKENS_IN_FOR_EXACT_BPT_OUT)

    • User sends estimated but unknown (computed at run time) quantities of tokens, and receives precise quantity of BPT.

Encoding

  • Initial Join

    • userData ABI

      • ['uint256', 'uint256[]']

    • userData

      • [INIT, amountsIn]

  • Exact Tokens Join

    • userData ABI

      • ['uint256', 'uint256[]', 'uint256']

    • userData

      • [EXACT_TOKENS_IN_FOR_BPT_OUT, amountsIn, minimumBPT]

  • Proportional Join

    • userData ABI

      • ['uint256', 'uint256']

    • userData

      • [ALL_TOKENS_IN_FOR_EXACT_BPT_OUT, bptAmountOut]

Last updated