Skip to main content

Developing with the Uniswap v3 Engine

Developing on the Uniswap v3 Engines

Here at Steer Protocol, we have produced a suite of contracts that enable the most flexible liquidity provisioning on Uniswap's v3 pools in the world. We currently offer 4 managers:

  • Multi Position
  • Whitelisted Multi Position
  • Single Position
  • Whitelisted Single Position

What do these liquidity managers do?

Steer Protocol's UNISWAP liquidity managers allow LPs to deposit funds into a vault, where they will be used by the manager to create liquidity positions on UNISWAP v3 pools. As these positions collect fees, the LPs shares of the vault increase in value, which can be redeemed for the principle and fees generated.

Benefits of using a liquidity manager?

Liquidity managers running successful strategies will offer the best returns available via liquidity providing on Uniswap v3, active and automated management means your liquidity will consistently be active therefore earning more fees. Shared vaults means that gas costs are minimal, and we have some whitelisting features if you need to adhere to regulations.

How are Steer Protocol's liquidity managers better?

Steer Protocol's infrastructure allows for logic to be run off chain, with both on and off chain data available to use. Vaults will typically have an associated execution bundle which contains this logic and runs routinely. This bundle of logic can process trading data, market KPIs, or anything you might want to factor into where the best positions might be.

How does whitelisting work?

The whitelisted versions of the contracts exist for those wanting to run apps in compliance with regulation of securities and gives control to the owner of who can invest in the app. This comes at higher operational gas costs. A permissions manager is assigned at vault creation who sets the permissions.

The non-whitelisted counterparts allow anyone to deposit funds to be invested.

What do I get for creating strategies for the liquidity manager app?

Some of Steer Protocol's apps are designed to generate yield. To incentivize developers to create optimal strategies we have implemented a 5% performance fee on profits. Published execution bundles (strategies for the liquidity manager) are registered as NFTs. Anyone can use existing bundles with different parameters but the performance fees will go to the owner of the NFT.

So how do I make strategies for the Uniswap liquidity managers?

First, understand how concentrated liquidity works:

Video on Uniswap v3

Uniswap v3 Whitepaper

tip

The whitepaper is a great resource for understanding how Uniswap v3 works, but it is a bit dense. We recommend watching the video first, then reading the whitepaper.

Ticks

The tick index represents a price ratio of the two assets on a logarithmic scale. The max and min tick values practically cover any price that could exist ( ±887272 ). You can calculate the price at a tick with:

p(i)=1.0001ip(i) = 1.0001^i

Positions have an upper and lower tick where the liquidity will be available in between, and not every tick is viable to use. Each Uniswap pool has a specific tick spacing tied to its fee tier.

Pool Fee TierTick Spacing
0.01%1
0.05%10
0.3%60
1%200

Rebalancing

There may come a time when all of your holdings are in one asset when you need a specific ratio of the two or all of the assets to be in the other. The Liquidity Managers will automatically balance the assets into the right ratio, but be careful as this is one of the few ways to recognize losses providing liquidity.

Multi Position Uniswap Liquidity Manager

This contract allows for the most flexible liquidity positioning in the world. As many positions as you'd like to make to achieve the desired liquidity depth:

Custom Positions Possible Image From Uniswapv3 Whitepaper

Multi Position Interface

When making the execution bundle, format your transaction request like so:

{
functionName: "tend(uint256,(int24[],int24[],uint16[]),bytes)",
typesArray: ["uint256","tuple(int24[],int24[],uint16[])","bytes"],
valuesArray: [totalWeight, [[LowerTickValues],[UpperTickValues],[RelativeWeight]], '0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000ffffffffffffffffffffffffffffffffffffffff']
}

Reference the following table to understand these values:

NameDescription
Total WeightThe share of liquidity we want deposited, multiplied by 10,000. A value of 10,000 means we want to deposit all tokens into Uniswap. A value of 0 means we just want all the liquidity out. Do not enter values above 10,000.
Lower Tick ValuesAn array of lower ticks, which will relate by index to the upper tick and weight of the following arrays.
Upper Tick ValuesArray of upper ticks.
Relative WeightAll of these values will be summed to find the right amount of liquidity that should be delegated to this position. The sum of these numbers should not exceed 65535.
'0xffff….ffff' – Time Sensitive DataPlaceholder data. This is replaced data on how much should be swapped to achieve the correct ratio at time of execution to ensure accurate results. The length is what is important about this placeholder, not the contents.

For further information about the interface reference the documentation for the Multi UniLiquidity Manager.

For further information on writing execution bundles see the 'writing-an-app' documentation.

Single Position Manager

The single position manager is designed to only create and tend one liquidity position for a pool. This limits you to only one position but does save on gas.

The interface for tending the single position manager is a little different to the Multi Position Manager:

{
functionName: "tend(uint256,int24,int24,int256,uint160) ",
typesArray: ["uint256", "int24", "int24", "int256", "uint160"],
valuesArray: [totalWeight, newLowerTick, newUpperTick, swapAmount, sqrtPriceLimitX96]
}

Once again, reference the contracts documentation for more information.

NameDescription
Total WeightThe share of liquidity we want deposited, multiplied by 10,000. A value of 10,000 means we want to deposit all tokens into Uniswap. A value of 0 means we just want all the liquidity out. Do not enter values above 10,000.
New Lower TickThe lower tick of the new position to be created.
New Upper TickThe upper tick of the new position to be created.
Swap AmountThe amount to be swapped from one token to another this tend. zeroForOne if positive, oneForZero if negative.
Sqrt Price Limit X96The slippage limit of the swap. Protections elsewhere prevent extreme slippage if the keeper calling this function is malicious, but this is the first line of defense against MEV attacks.

Backtesting

While developing bundles, use the backtesting-toolset when applicable to test performance. Note that currently the toolset only supports the multi position manager with swap candle data as the only data provided from the data-connector unless configured differently.

Conclusion

Creating liquidity provision strategies for concentrated liquidity AMMs is a very new area. The potential gains are immense, and we are working to provide the tooling to make the most effective strategies. If you need more information the docs are always the best place to start, and reach out if you have any further questions.