Skip to main content
Helpful?

Swap - Step by Step

The swap happens in a loop until the specified amount has been completely used or the price limit has been reached. In each iteration, the code calculates how much of the tokens can be swapped at the current price level.

The swap keeps iterating until either the specified amount is fully used or the square root of the price hits the defined limit (sqrtPriceLimitX96).

Here is the SwapParams struct, Swap event and swap function from IPoolManager which is used to swap tokens:

/// @notice Emitted for swaps between currency0 and currency1
/// @param id The abi encoded hash of the pool key struct for the pool that was modified
/// @param sender The address that initiated the swap call, and that received the callback
/// @param amount0 The delta of the currency0 balance of the pool
/// @param amount1 The delta of the currency1 balance of the pool
/// @param sqrtPriceX96 The sqrt(price) of the pool after the swap, as a Q64.96
/// @param liquidity The liquidity of the pool after the swap
/// @param tick The log base 1.0001 of the price of the pool after the swap
event Swap(
PoolId indexed id,
address indexed sender,
int128 amount0,
int128 amount1,
uint160 sqrtPriceX96,
uint128 liquidity,
int24 tick,
uint24 fee
);

struct SwapParams {
bool zeroForOne;
int256 amountSpecified;
uint160 sqrtPriceLimitX96;
}

/// @notice Swap against the given pool
function swap(PoolKey memory key, SwapParams memory params, bytes calldata hookData)
external
returns (BalanceDelta);

Example

Here is an example of how to swap tokens by calling the swap function:

PoolSwapTest swapRouter = new PoolSwapTest(IPoolManager(address(manager)));

PoolSwapTest.TestSettings memory testSettings =
PoolSwapTest.TestSettings({withdrawTokens: true, settleUsingTransfer: true});

swapRouter.swap(key, params, testSettings, hookData);

Note: PoolSwapTest implements the ILockCallback interface and adds the lockAcquired function, which in turn calls the manager.swap function.

Acquiring Lock

Full detail about the locking mechanism is explained in the Locking Mechanism section.

The contract that calls the swap must implement ILockCallback interface.

PoolSwapTest.sol has some examples of how to acquire lock and some basic checks in place. https://github.com/Uniswap/v4-core/blob/main/src/test/PoolSwapTest.sol

In PoolSwapTest, the lockAcquired function is triggered when a certain "lock" is acquired in the context of swapping assets or tokens. Once this lock is confirmed, the function handles the settlement based on the result of the swap. It decodes the data provided to understand the context, asks the manager to perform the swap, and then either transfers, withdraws, or mints tokens based on the balance changes resulting from the swap.

To ensure secure operations, the function checks that it's only being called by the intended manager contract. Depending on the type of swap and settings, it handles the balance adjustments for two types of currencies: currency0 and currency1. After settling all balances, it returns the balance changes to the caller.

Helpful?