5/5
## Understanding Delta-Resolving Operations in Uniswap V4 In Uniswap V4, interactions are managed through a central `PoolManager` contract, which tracks the net token balances for any contract that interacts with it. This net balance is called a **delta**. A positive delta means the `PoolManager` owes you tokens, while a negative delta means you owe tokens to the `PoolManager`. Delta-resolving operations are specialized functions designed to efficiently manage these balances, either by settling debts or claiming credits. These operations are typically called within a router contract at the end of a sequence of actions (like swaps or liquidity management) to ensure all token balances are reconciled correctly. Let's explore three key delta-resolving operations: `CLOSE_CURRENCY`, `CLEAR_OR_TAKE`, and `SWEEP`. ### Handling Unknown Balances with `CLOSE_CURRENCY` The `CLOSE_CURRENCY` operation provides a straightforward way to settle a final token balance when you cannot predict whether it will be positive or negative. After a series of complex swaps, the final delta can be difficult to calculate in advance. Instead of implementing complex logic to check the balance and then decide whether to pay or receive tokens, `CLOSE_CURRENCY` handles it for you. This action determines the final state of the currency delta and automatically calls the appropriate function: `_settle` if the contract owes tokens, or `_take` if the contract is owed tokens. #### Code Walkthrough When `CLOSE_CURRENCY` is triggered, it calls the internal `_close` function: ```solidity // From DeltaResolver.sol function _close(Currency currency) internal { /// @dev this address has applied all deltas on behalf of the user/owner /// it is safe to close this entire delta because of slippage checks through the router int256 currencyDelta = poolManager.currencyDelta(address(this), currency); /// the locker is the payer or receiver address caller = msg.sender; if (currencyDelta < 0) { // Casting is safe due to limits on the total supply of a pool _settle(currency, caller, uint256(-currencyDelta)); } else { _take(currency, caller, uint256(currencyDelta)); } } ``` 1. **`poolManager.currencyDelta(address(this), currency)`**: The function first queries the `PoolManager` to get the final delta for the specified `currency`. Note that it checks the balance of the router contract itself (`address(this)`). 2. **`if (currencyDelta < 0)`**: It then checks if the delta is negative. * If **true**, it means the router contract owes tokens to the pool. The `_settle` function is called to pay this debt. The amount is `uint256(-currencyDelta)` to convert the negative integer into a positive unsigned integer. The tokens are paid by the `caller` (`msg.sender`), who initiated the transaction. * If **false** (the delta is positive or zero), the router contract is owed tokens. The `_take` function is called to withdraw this credit and send it to the `caller`. ### Optimizing for Gas with `CLEAR_OR_TAKE` The `CLEAR_OR_TAKE` operation is a powerful gas-saving utility for dealing with "dust"—extremely small token amounts. Sometimes, the value of tokens owed to you is less than the gas cost required to execute the `transfer` to withdraw them. In these cases, it's more economical to simply forfeit the dust than to spend gas claiming it. `CLEAR_OR_TAKE` automates this decision. You provide a threshold, and the function will either withdraw the tokens if their amount exceeds the threshold or clear the credit from the `PoolManager`'s books if it doesn't, saving a costly token transfer. #### Code Walkthrough This operation calls the internal `clearOrTake` function: ```solidity // From DeltaResolver.sol function clearOrTake(Currency currency, uint256 amountMax) internal { uint256 delta = _getFullCredit(currency); if (delta == 0) return; // forfeit the delta if its less than or equal to the user-specified limit if (delta <= amountMax) { poolManager.clear(currency, delta); } else { _take(currency, msg.sender, delta); } } ``` 1. **`_getFullCredit(currency)`**: This helper function retrieves the positive delta (the amount the contract is owed). 2. **`if (delta <= amountMax)`**: The core logic compares this `delta` against `amountMax`, the user-defined threshold for what is considered dust. * If **true**, the amount is considered dust. The function calls `poolManager.clear(currency, delta)`, which effectively nullifies the contract's credit without executing a token transfer. This saves significant gas. * If **false**, the `delta` is valuable enough to be withdrawn. The `_take` function is called to transfer the full amount to `msg.sender`. ### Refunding Excess Tokens with `SWEEP` The `SWEEP` operation is a clean-up utility designed to handle overpayments. When interacting with a decentralized exchange, users often send slightly more tokens than required for a transaction to account for potential slippage. Without a mechanism to reclaim this excess, the funds could remain locked in the router contract. By adding a `SWEEP` action to the end of a transaction, any unused tokens sent by the user for a specific currency can be "swept up" and refunded. This ensures that no funds are accidentally left behind, providing a safer and more user-friendly experience.
In Uniswap V4, interactions are managed through a central PoolManager contract, which tracks the net token balances for any contract that interacts with it. This net balance is called a delta. A positive delta means the PoolManager owes you tokens, while a negative delta means you owe tokens to the PoolManager. Delta-resolving operations are specialized functions designed to efficiently manage these balances, either by settling debts or claiming credits.
These operations are typically called within a router contract at the end of a sequence of actions (like swaps or liquidity management) to ensure all token balances are reconciled correctly. Let's explore three key delta-resolving operations: CLOSE_CURRENCY, CLEAR_OR_TAKE, and SWEEP.
CLOSE_CURRENCYThe CLOSE_CURRENCY operation provides a straightforward way to settle a final token balance when you cannot predict whether it will be positive or negative. After a series of complex swaps, the final delta can be difficult to calculate in advance. Instead of implementing complex logic to check the balance and then decide whether to pay or receive tokens, CLOSE_CURRENCY handles it for you.
This action determines the final state of the currency delta and automatically calls the appropriate function: _settle if the contract owes tokens, or _take if the contract is owed tokens.
When CLOSE_CURRENCY is triggered, it calls the internal _close function:
poolManager.currencyDelta(address(this), currency): The function first queries the PoolManager to get the final delta for the specified currency. Note that it checks the balance of the router contract itself (address(this)).
if (currencyDelta < 0): It then checks if the delta is negative.
If true, it means the router contract owes tokens to the pool. The _settle function is called to pay this debt. The amount is uint256(-currencyDelta) to convert the negative integer into a positive unsigned integer. The tokens are paid by the caller (msg.sender), who initiated the transaction.
If false (the delta is positive or zero), the router contract is owed tokens. The _take function is called to withdraw this credit and send it to the caller.
CLEAR_OR_TAKEThe CLEAR_OR_TAKE operation is a powerful gas-saving utility for dealing with "dust"—extremely small token amounts. Sometimes, the value of tokens owed to you is less than the gas cost required to execute the transfer to withdraw them. In these cases, it's more economical to simply forfeit the dust than to spend gas claiming it.
CLEAR_OR_TAKE automates this decision. You provide a threshold, and the function will either withdraw the tokens if their amount exceeds the threshold or clear the credit from the PoolManager's books if it doesn't, saving a costly token transfer.
This operation calls the internal clearOrTake function:
_getFullCredit(currency): This helper function retrieves the positive delta (the amount the contract is owed).
if (delta <= amountMax): The core logic compares this delta against amountMax, the user-defined threshold for what is considered dust.
If true, the amount is considered dust. The function calls poolManager.clear(currency, delta), which effectively nullifies the contract's credit without executing a token transfer. This saves significant gas.
If false, the delta is valuable enough to be withdrawn. The _take function is called to transfer the full amount to msg.sender.
SWEEPThe SWEEP operation is a clean-up utility designed to handle overpayments. When interacting with a decentralized exchange, users often send slightly more tokens than required for a transaction to account for potential slippage. Without a mechanism to reclaim this excess, the funds could remain locked in the router contract.
By adding a SWEEP action to the end of a transaction, any unused tokens sent by the user for a specific currency can be "swept up" and refunded. This ensures that no funds are accidentally left behind, providing a safer and more user-friendly experience.
A transactional deep-dive to Delta-Resolving Operations in Uniswap v4 - Learn how `CLOSE_CURRENCY`, `CLEAR_OR_TAKE`, and `SWEEP` finalize interactions, managing unpredictable deltas, gas-saving dust, and slippage-related overpayments.
Previous lesson
Previous
Next lesson
Next
Course Overview
About the course
Difference between Uniswap v3 and v4
Uniswap v4 PoolManager
Uniswap v4 Hooks
Uniswap v4 PositionManager
Uniswap v4 Universal Router
Uniswap v4 Singleton architecture and flash accounting
Uniswap v4 operations and lifecycle
Uniswap v4 multihopping and quoting
How to build a Uniswap v4 swap router
How to build a smart contract a liquidation bot executes
Last updated on November 6, 2025
Duration: 5min
Duration: 7min
Duration: 39min
Duration: 35min
Duration: 34min
Duration: 31min
Course Overview
About the course
Difference between Uniswap v3 and v4
Uniswap v4 PoolManager
Uniswap v4 Hooks
Uniswap v4 PositionManager
Uniswap v4 Universal Router
Uniswap v4 Singleton architecture and flash accounting
Uniswap v4 operations and lifecycle
Uniswap v4 multihopping and quoting
How to build a Uniswap v4 swap router
How to build a smart contract a liquidation bot executes
Last updated on November 6, 2025