Protocol
Guides
Providing liquidity

# Providing liquidity

Anyone can add liquidity to a pool, as long as the expiry has not been reached yet. Portfolio provides some utility functions that can help liquidity providers calculate the optimal amounts they need to provide to the `allocate` function:

• `getMaxLiquidity` calculates the exact amount of liquidity that can be provided from an amount of asset and quote tokens.
• `getLiquidityDeltas` calculates the exact amount of asset and quote tokens that are required to provide an exact amount of liquidity.

Together both functions can be used to calculate exactly how much asset and quote tokens need to be provided for a given amount of liquidity.

``````// Assuming we want to allocate into the pool `1099511627777`:
uint64 poolId = 1099511627777;

// Let's check how many tokens we have.

// Now we check the maximum amount of liquidity we can get from both amounts
uint128 maxLiquidity = portfolio.getMaxLiquidity(poolId, assetBalance, quoteBalance);

// Let's use this liquidity amount to get some more precise deltas.
(uint128 deltaAsset, uint128 deltaQuote) = portfolio.getLiquidityDeltas(poolId, int128(maxLiquidity));``````
ℹ️

Note that using `getMaxLiquidity` and `getLiquidityDeltas` onchain is not ideal because pools can be manipulated to alter the results.

Once we calculate all of these amounts, we can simply call the `allocate` function by providing the following parameters:

NameTypeDescription
`useMax``bool`Passing `true` will use the asset and quote amounts of the transient balance.
`poolId``uint64`Id of the pool where the liquidity will be allocated into.
`deltaLiquidity``uint128`Quantity of liquidity to mint in WAD units.
`maxDeltaAsset``uint128`Maximum quantity of asset tokens paid in WAD units.
`maxDeltaQuote``uint128`Maximum quantity of quote tokens paid in WAD units.
ℹ️

Passing `0` as a `poolId` will act as a magic value and will use the `poolId` from `_getLastPoolId`. Note that this feature should only be used with `multicall` to avoid being tricked into allocating into the wrong pool.

This is what a complete allocation looks like:

``````// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "portfolio/interfaces/IPortfolio.sol";
import "portfolio/interfaces/IERC20.sol";

contract AllocateExample {
IPortfolio public portfolio;

portfolio = IPortfolio(portfolio_);
asset = asset_;
quote = quote_;
}

function allocate() external {
// Assuming we want to allocate into the pool `1099511627777`:
uint64 poolId = 1099511627777;

// Let's check how many tokens we have.

// Now we check the maximum amount of liquidity we can get from our
// current token balances.
uint128 maxLiquidity =
portfolio.getMaxLiquidity(poolId, assetBalance, quoteBalance);

// Let's use this liquidity amount to get some more precise deltas.
(uint128 deltaAsset, uint128 deltaQuote) =
portfolio.getLiquidityDeltas(poolId, int128(maxLiquidity));

// We allow the portfolio contract to move our tokens.

// Finally, we call the `allocate` function.
portfolio.allocate(false, poolId, maxLiquidity, deltaAsset, deltaQuote);
}
}``````

You can check out the full code source here (opens in a new tab).

## Removing liquidity

Removing liquidity is as simple as calling the `deallocate` function and passing the right parameters:

NameTypeDescription
`useMax``bool`Pass `true` to remove all the liquidity of the position.
`poolId``uint64`Id of the pool to remove the liquidity from.
`deltaLiquidity``uint128`Quantity of liquidity to burn in WAD units.
`minDeltaAsset``uint128`Minimum quantity of asset tokens to receive in WAD units.
`minDeltaQuote``uint128`Minimum quantity of quote tokens to receive in WAD units.

Using the `positions` function, we can check how much liquidity a user owns:

``uint128 liquidity = portfolio.positions(user, poolId);``

Alternatively, the same functions that we used to `allocate` can be used again to calculate how much liquidity we might want to deallocate and how much asset and quote tokens we will receive:

``(uint128 minDeltaAsset, uint128 minDeltaQuote) = portfolio.getLiquidityDeltas(poolId, int128(liquidity));``

The following example shows how to `allocate` and `deallocate` funds:

``````// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "portfolio/interfaces/IPortfolio.sol";
import "portfolio/interfaces/IERC20.sol";

contract DeallocateExample {
IPortfolio public portfolio;

portfolio = IPortfolio(portfolio_);
asset = asset_;
quote = quote_;
}

function deallocate() external {
// Assuming we want to allocate into the pool `1099511627777`:
uint64 poolId = 1099511627777;

// Let's check how many tokens we have.

// Now we check the maximum amount of liquidity we can get from our
// current token balances.
uint128 maxLiquidity =
portfolio.getMaxLiquidity(poolId, assetBalance, quoteBalance);

// Let's use this liquidity amount to get some more precise deltas.
(uint128 deltaAsset, uint128 deltaQuote) =
portfolio.getLiquidityDeltas(poolId, int128(maxLiquidity));

// We allow the portfolio contract to move our tokens.

// Finally, we call the `allocate` function.
portfolio.allocate(false, poolId, maxLiquidity, deltaAsset, deltaQuote);

// Since we were the first liquidity provider, a part of our liquidity
// was burnt, we need to remove that from our calculations:
uint128 liquidity = maxLiquidity - uint128(1e9);

// To avoid being sandwiched, we can check the minimum amount of
// tokens that we can expect from our liquidity balance.
(uint128 minDeltaAsset, uint128 minDeltaQuote) =
portfolio.getLiquidityDeltas(poolId, int128(liquidity));

// We can now deallocate the liquidity we just allocated.
// Note that we have to remove the burnt liquidity (1e9), since we were
// the first to provide liquidity in this pool.
portfolio.deallocate(false, poolId, liquidity, 0, 0);
}
}``````

You can check out the full code source here (opens in a new tab).