Skip to main content
Helpful?

Flash Accounting

In previous versions of Uniswap, every time a swap was made - including multi-hop swap - tokens were transferred between Pool contracts for intermediate steps.

This design incurred inefficiencies because transferring tokens with external calls to their smart contracts - especially in a multi-hop swap - is quite expensive. This design was required since each pool was its own contract and token transfers were required to maintain accounting and solvency

With the singleton architecture, a better design was possible and is referred to as Flash Accounting. The design became practical with gas efficiencies of Transient Storage. Flash Accounting further reduces the gas cost of trades that cross multiple pools and supports more complex integrations with Uniswap v4.

With flash accounting, each balance-changing operation (e.g. swap and liquidity modification) updates an internal net balance known as delta. Only the final balance-changes require token transfers.

Deltas

Locking

To ensure correctness and atomicity in complex operations like a multi-hop swap - v4 uses a locking mechanism. Anytime key actions need to take place within the PoolManager - e.g. swaps and liquidity modification - a periphery contract must unlock the PoolManager first. Then integrators implement the unlockCallback and proceed with any of the following actions on the pools:

  • swap
  • modifyLiquidity
  • donate
  • take
  • settle
  • mint
  • burn
  • sync

Note that pool initialization can happen outside the context of unlocking the PoolManager, as there are no balance-changing operations associated with pool creation.

Balance Delta

Inside unlockCallback, a periphery contract performs balance-changing operations i.e. conduct swaps, modify positions, etc. After returning execution context back to PoolManager, the core contract checks that balances are resolved - nothing is owed to or from the PoolManager.

The balances resolved above is what we refer as the delta, a field held in the transient state. The value(s) represent the debts and credits of assets owed to or from the PoolManager.

Swapping

Multi-hop swaps on V3 vs V4

As shown in the above diagram, for example - let's say you wanted to swap ETH for DAI. Assuming this requires a multi-hop swap going from ETH to USDC and then from USDC to DAI.

Previously on v3

  1. ETH is transferred to ETH <> USDC pool contract

  2. USDC is withdrawn from ETH <> USDC contract and transferred to USDC <> DAI contract

  3. DAI is withdrawn from USDC <> DAI contract and transferred to the user

Now on v4

  1. Call swap() on ETH <> USDC

  2. Call swap() on USDC <> DAI, with the credit of USDC from above being used as the input amount

  3. User resolves deltas by paying ETH and receiving DAI

Therefore we can skip the step of actually calling transfer() on the USDC contract.

The optimization scales infinitely, any number of arbitrary hops only requires two token transfers - input and output tokens.

Liquidity Management

The optimization becomes more evident for complex liquidity operations

For example, a user wanted to add liquidity to ETH <> DAI but does not have DAI. The user can swap some ETH to DAI in order to add liquidity with both tokens. In addition, the user can multi-hop swap going from ETH to USDC to DAI. If properly integrated, the user would only need to transfer ETH once.

Developer resources

To see how unlock callback and delta work in a smart contract read Unlock Callback & Deltas.

Helpful?