Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT: CompositeLiquidityRouterV2 #1104

Draft
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

elshan-eth
Copy link
Contributor

Description

The idea behind this refactoring is to use recursion for handling nested pools, as well as to represent the input arguments as a structure. Introducing the structure made it possible to apply the parameters minBptAmountOut, wethIsEth, and userData individually for each operation.

NestedAddPoolOperation is a structure that represents a single liquidity addition operation.

struct NestedAddPoolOperation {
        address prevPool; 
        address pool;
        uint256[] tokensInAmounts;
        uint256 minBptAmountOut;
        bool wethIsEth;
        bytes userData;
}
  • prevPool — if the target pool is nested within another pool, we need to specify this. This allows the same wrapped asset to be used across multiple pools.
  • pool — the target pool.
  • tokensInAmounts — the token amounts we want to use in the operation. If one of the tokens is nested, its amount should be set to 0. If we want to add liquidity to an ERC4626, we need to specify only one element in tokensInAmounts.

Example:

                MAIN_POOL                 
                    │                     
           ─────────┴───────────          
         POOL_A               POOL_B      
          │                    │          
   ───────┴───────     ────────┴───────   
 WETH          wDAI   USDC           USDT 

If we want to wrap ETH -> WETH and DAI -> wDAI, as well as add liquidity to BPT_POOL_B, the nestedPoolOperations array will be populated as follows:

ICompositeLiquidityRouter.NestedPoolOperation[] memory nestedPoolOperations = new ICompositeLiquidityRouter.NestedPoolOperation[](2);
nestedPoolOperations[0] = ICompositeLiquidityRouter.NestedPoolOperation({
            prevPool: POOL_A,
            pool: wETH,
            tokensInAmounts: [ethAmount].toMemoryArray(),
            minBptAmountOut: 0,
            wethIsEth: true,
            userData: new bytes(0)
        });

nestedPoolOperations[1] = ICompositeLiquidityRouter.NestedPoolOperation({
            prevPool: POOL_A,
            pool: wDAI,
            tokensInAmounts: [daiAmount].toMemoryArray(),
            minBptAmountOut: 0,
            wethIsEth: false,
            userData: new bytes(0)
        });
        
nestedPoolOperations[2] = ICompositeLiquidityRouter.NestedPoolOperation({
            prevPool: MAIN_POOL,
            pool: POOL_B,
            tokensInAmounts: [usdcAmount, usdtAmount].toMemoryArray(),
            minBptAmountOut: 0,
            wethIsEth: false,
            userData: new bytes(0)
        });

The order of operations will be as follows:

  1. Wrap ETH → wETH.
  2. Wrap DAI → wDAI.
  3. Add liquidity to POOL_A (this operation is executed automatically, even if it's not in our list of operations, because its children were affected).
  4. Add liquidity to POOL_B.
  5. Add liquidity to MAIN_POOL (this operation is also executed automatically, even if it's not in our list of operations, because its children were affected).

If we want to add wDAI instead of wrapping DAI, then our structure will look like this:

ICompositeLiquidityRouter.NestedPoolOperation[] memory nestedPoolOperations = new ICompositeLiquidityRouter.NestedPoolOperation[](2);
nestedPoolOperations[0] = ICompositeLiquidityRouter.NestedPoolOperation({
            prevPool: POOL_A,
            pool: wETH,
            tokensInAmounts: [ethAmount].toMemoryArray(),
            minBptAmountOut: 0,
            wethIsEth: true,
            userData: new bytes(0)
        });

nestedPoolOperations[1] = ICompositeLiquidityRouter.NestedPoolOperation({
            prevPool: MAIN_POOL,
            pool: POOL_A, // In this case, we are adding liquidity directly to `POOL_A`.
            tokensInAmounts: [0, wDAIAmount].toMemoryArray(), // The first element is set to 0 because the result for this value will be obtained after the `ETH → wETH` operation.
            minBptAmountOut: 0,
            wethIsEth: false,
            userData: new bytes(0)
        });
        
nestedPoolOperations[2] = ICompositeLiquidityRouter.NestedPoolOperation({
            prevPool: MAIN_POOL,
            pool: POOL_B,
            tokensInAmounts: [usdcAmount, usdtAmount].toMemoryArray(),
            minBptAmountOut: 0,
            wethIsEth: false,
            userData: new bytes(0)
        });

The order of operations will be as follows:

  1. Wrap ETH → wETH.
  2. Add liquidity to POOL_A
  3. Add liquidity to POOL_B.
  4. Add liquidity to MAIN_POOL (this operation is also executed automatically, even if it's not in our list of operations, because its children were affected).

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Dependency changes
  • Code refactor / cleanup
  • Optimization: [ ] gas / [ ] bytecode
  • Documentation or wording changes
  • Other

Checklist:

  • The diff is legible and has no extraneous changes
  • Complex code has been commented, including external interfaces
  • Tests have 100% code coverage
  • The base branch is either main, or there's a description of how to merge

Issue Resolution

Closes #1044

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CompositeLiquidityRouter fixes
2 participants