Liquidity Module

A Liquidity Module (LM) is a mandatory contract in a Valantis Sovereign Pool construction. LMs handle the underlying pricing logic for swaps. A Liquidity Module can host whatever internal logic it wants for asset pricing and it communicates with the Sovereign Pool by implementing the function getLiquidityQuote. During a swap, a call is made to the LM function getLiquidityQuote which returns an ALMLiquidityQuote struct.

There are two callback functions an LM must implement which allow the contract to update its internal state and execute logic post-swap and post-deposit.

getLiquidityQuote

The Liquidity Module’s getLiquidityQuote function hosts the logic for swap pricing and is defined as follows:

    /** 
        @notice Called by the Sovereign pool to request a liquidity quote from the ALM.
        @param _almLiquidityQuoteInput Contains fundamental data about the swap.
        @param _externalContext Data received by the pool from the user.
        @param _verifierData Verification data received by the pool from the verifier module
        @return almLiquidityQuote Liquidity quote containing tokenIn and tokenOut amounts filled.
    */
    function getLiquidityQuote(
        ALMLiquidityQuoteInput memory _almLiquidityQuoteInput,
        bytes calldata _externalContext,
        bytes calldata _verifierData
    ) external returns (ALMLiquidityQuote memory);

Inputs

Liquidity Quote Struct

This struct contains the user's requested swap along with the fees deducted from the Swap Fee Module.

struct ALMLiquidityQuoteInput {
    bool isZeroToOne;
    uint256 amountInMinusFee;
    uint256 feeInBips;
    address sender;
    address recipient;
    address tokenOutSwap;
}

ALMLiquidityQuoteInput contains the following fields:

  • isZeroToOne Direction of the swap

  • amountInMinusFee Amount of input token that sender intends to swap, excluding the fee.

  • feeInBips Fee in bips, returned by Swap Fee Module. Note: This fee will be applied to ALMLiquidityQuote.amountInFilled

  • sender Address of msg.sender during the swap (the user).

  • recipient Address which is meant to receive output tokens by the end of the swap

  • tokenOutSwap Token which the user is meant to receive. This will not necessarily be one of the tokens in the pool in case the LM contains logic that handles more than 2 tokens.

External Context

Optional context passed by the user initiating the trade. This context is used by the Sovereign Pool to inform the Swap Fee Module, Verifier Module, and/or Liquidity Module about some external conditions that might affect the user's execution. This field allows the LM to directly implement special logic based on external data, such as: Signed Quotes, Oracle Data, Onchain credentials, etc.

Verifier Data

This is optional context produced by the Verifier Module which can be used to inform the Liquidity Module about different swap conditions based on the user's credentials. This allows the Verifier Module to provide the user with different execution based on the external context provided.

Output Struct

The getLiquidityQuote function outputs a quote for the user's trade and returns it to the Sovereign Pool to execute.

struct ALMLiquidityQuote {
    bool isCallbackOnSwap;
    uint256 amountOut;
    uint256 amountInFilled;
}

ALMLiquidityQuote contains the following fields:amountOut worth of them to _almLiquidityQuoteInput.recipient

  • isCallbackOnSwap True if the LM requires a callback at the end of the swap.

  • amountOut Amount of token out which the LM commits to transfer to the user.

  • amountInFilled Amount of input token which the LM expects from the user, excluding the swap fee portion.

Callbacks

The liquidity module contains two functions that can be called if the LM is configured to require callbacks. Arbitrary data can be returned back to the LM to update its internal state upon deposits

Swap Callback

At the end of a swap, the pool can pass data back to the Liquidity Module by calling onSwapCallback. This allows a Liquidity Module to update its internal state post-swap, or execute any other necessary logic. The Liquidity Module can request a callback by specifying isCallbackOnSwap as True when returning from the getLiquidityQuote call. It is important this is set correctly if the LM requires a callback to function properly. The function can execute any logic necessary post-swap.

/**
        @notice Callback to ALM after swap into liquidity pool.
        @dev Only callable by pool.
        @param _isZeroToOne Direction of swap.
        @param _amountIn Amount of tokenIn in swap.
        @param _amountOut Amount of tokenOut in swap. 
     */
    function onSwapCallback(bool _isZeroToOne, uint256 _amountIn, uint256 _amountOut) external;

Deposit Callback

Deposits are initially made directly to the LM, and the LM forwards the funds to the proper reserve address (either directly to the Sovereign Pool or a custom Sovereign Vault). The LM can request a callback from the address where the reserves are held by setting onDepositCallback to true when calling the depositLiquidity on the proper reserve address. The Liquidity Module is responsible for implementing a user-facing deposit function, handling internal accounting/tokenization of LP funds, and forwarding reserves to the proper address.

/**
        @notice Callback function for `depositLiquidity` .
        @param _amount0 Amount of token0 being deposited.
        @param _amount1 Amount of token1 being deposited.
        @param _data Context data passed by the ALM, while calling `depositLiquidity`.
    */
    function onDepositLiquidityCallback(uint256 _amount0, uint256 _amount1, bytes memory _data) external;

Last updated