Skip to main content
Helpful?

Unlock Callback & Deltas

Refresher

In order to have access to the liquidity inside the PoolManager, it needs to be unlocked to begin with. After being unlocked, any number of operations can be executed, which at the end of must be locked again. At this point, if there are any non-zero deltas, meaning the PoolManager is owed or owes tokens back to some address, the whole execution reverts. Otherwise, both parties have paid or received the right amount of tokens and the operations have successfully carried out.

Unlocking the PoolManager

Implementing the unlock callback

Prior to unlocking the PoolManager, the integrating contract must implement the unlockCallback function. This function will be called by the PoolManager after being unlocked. An easy way to do this is to inherit the SafeCallback abstract contract.

import {SafeCallback} from "v4-periphery/src/base/SafeCallback.sol";

contract IntegratingContract is SafeCallback {
constructor(IPoolManager _poolManager) SafeCallback(_poolManager) {}
}

Calling the unlock function

After implementing the callback, the integrating contract can now invoke the unlock() function. It receives a bytes parameter that is further passed to your callback function as an argument. This parameter is used to encode the sequence of operations to be executed in the context of the PoolManager.

bytes memory unlockData = abi.encode(encode_operations_here);
bytes memory unlockResultData = poolManager.unlock(unlockData);

Next, we must override the _unlockCallback function inherited from the SafeCallback contract. In your implementation, you should decode your operations and continue with the desired logic.

function _unlockCallback(bytes calldata data) internal override returns (bytes memory) {
(...) = abi.decode(data, (...));
}

Operations

There are 9 operations that can be done in the PoolManager which fall in two categories: liquidity-accessing and delta-resolving.

Deltas

Deltas are the PoolManager's method to keep track of token amounts it needs to receive, respectively to distribute. A negative delta signals that the PoolManager is owed tokens, while a positive one expresses a token balance that needs to be paid to its user.

Liquidity-accessing

Liquidity-accessing operations will create non-zero deltas and produce a state transition of the selected pool. They are the following:

  • modify liquidity - used to increase or decrease liquidity; increasing liquidity will result in a negative token delta, while decreasing yields a positive one
  • swap - used to trade one token for another; will result in a negative tokenA delta and a positive tokenB delta
  • donate - used to provide direct token revenue to positions in range; will result in a negative delta for the pool's tokens the user wishes to provide

Delta-resolving

Delta-resolving operations are used to even out the deltas created by the liquidity-accessing operations. They are the following:

  • settle - used following token transfers to the manager or burning of ERC6909 claims to resolve negative deltas
  • take - transfer tokens from the manager, used to resolve positive deltas but also provide token loans, producing negative deltas
  • mint - used to create ERC6909 claims, creating a negative delta that needs to be resolved by transferring the corresponding token and settling afterwards
  • burn - removes ERC6909 claims, creating a positive delta for tokens to be transferred back to the owner or used in settling negative balances
  • clear - used to zero out positive token deltas, helpful to forfeit insignificant token amounts in order to avoid paying further transfer costs
Helpful?