Flash Accounting System Development (Uniswap v4)

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Flash Accounting System Development (Uniswap v4)
Complex
~1-2 weeks
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1238
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1167
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    867
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1084
  • image_logo-advance_0.png
    B2B Advance company logo design
    563
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    829

Development of Flash Accounting System (Uniswap v4)

Uniswap v4 changed fundamental accounting: instead of immediate token transfers on each operation, "debts" and "credits" accumulate within a single lock session. This is flash accounting. The system opens possibilities that never existed in v3: multi-step operations across pools without intermediate token exits, built-in flash loans without a separate protocol, composing any DeFi actions into one transaction. But implementing this correctly means understanding how PoolManager manages currency deltas and why incorrect settle/take order causes revert instead of profit.

How Flash Accounting Works at EVM Level

Currency Delta and Lock Mechanics

The key structure: mapping(address locker => mapping(Currency currency => int256 delta)) in PoolManager. When your contract calls swap(), modifyLiquidity(), or donate(), PoolManager doesn't transfer tokens—it only updates the delta mapping.

Positive delta means PoolManager "owes" your contract tokens. Negative means you owe PoolManager. By the time unlock() completes the lock session, each currency's delta sum must be exactly 0. If any currency isn't zeroed—transaction reverts with CurrencyNotSettled.

This is what makes flash accounting "flash": you can take tokens before returning equivalent value—within a single lock. The difference from flash loans is you don't need a separate callback; all accounting lives in your unlockCallback.

UnlockCallback Pattern

function unlockCallback(bytes calldata data) external returns (bytes memory) {
    // Decode operations from data
    (SwapParams[] memory swaps, SettleParams memory settle) = abi.decode(data, (...));
    
    // Accumulate delta through swap/modifyLiquidity
    for (uint i = 0; i < swaps.length; i++) {
        poolManager.swap(swaps[i].poolKey, swaps[i].params, "");
    }
    
    // Zero delta through settle/take
    // ORDER IS CRITICAL: take first (claim what's owed), then settle (pay debt)
    poolManager.take(currencyOut, address(this), amountOut);
    poolManager.settle{value: msg.value}(currencyIn);
    
    return "";
}

Typical mistake: calling settle before take, trying to "prepay." This works but creates unnecessary intermediate transfer. In multi-pool scenarios, correct order is critical for proper settlement—otherwise intermediate currency won't zero.

Multipool Flash Accounting: Where Real Value Lies

Suppose you need to arbitrage: buy TOKEN_A for USDC in pool A/USDC, sell TOKEN_A for ETH in pool A/ETH, sell ETH for USDC in pool ETH/USDC. In Uniswap v3, these are three separate calls, each with real transfers—significant gas overhead. In v4 with flash accounting:

  1. swap(A/USDC, buy A) → delta: -USDC, +A
  2. swap(A/ETH, sell A) → delta: -USDC, 0 (A zeroed), +ETH
  3. swap(ETH/USDC, sell ETH) → delta: 0 (all zeroed, profit in USDC)
  4. take(USDC, profit)
  5. settle(USDC, initial capital)

Intermediate tokens (TOKEN_A, ETH) never physically leave PoolManager. Gas savings on transfers: 20-40% depending on step count.

Hooks as Flash Accounting Extension Points

In v4, each pool can have a hook—a contract invoked before/after each operation. This opens a new class of logic: the hook can modify swap parameters (dynamic fee), add custom collateral checks, or embed oracle updates in every swap.

Hook address encodes its rights—last 12 bits determine which callbacks are activated. This isn't convention; it's technically enforced: PoolManager reads these bits and only calls allowed methods. Deploying a hook with a random address without vanity mining is a common mistake. You need CREATE2 with a precalculated salt to get an address with the required bits.

// Hook address bits (LSB)
// bit 0:  beforeInitialize
// bit 1:  afterInitialize
// bit 2:  beforeAddLiquidity
// bit 3:  afterAddLiquidity
// bit 4:  beforeRemoveLiquidity
// bit 5:  afterRemoveLiquidity
// bit 6:  beforeSwap
// bit 7:  afterSwap
// bit 8:  beforeDonate
// bit 9:  afterDonate

We use the HookMiner library (from Uniswap v4 periphery) to compute the correct salt via Foundry script.

V4-Specific Hook Vulnerabilities

Reentrancy through hook callback. The hook is called from PoolManager mid-lock session. If the hook makes an external call to a contract that also interacts with PoolManager—this is nested lock. PoolManager v4 supports nested locks, but careless hook logic corrupts delta state.

Delta manipulation. A malicious hook in beforeSwap can modify amountSpecified through the returned BeforeSwapDelta—this is a legitimate capability, but with weak input validation, the hook becomes a vector for price manipulation in the pool.

Our Stack for Uniswap v4 Development

Foundry with fork-tests on Ethereum mainnet—the only adequate choice for v4 development today. V4 PoolManager is deployed on mainnet; forking lets you test with real pools and real liquidity.

Fuzz-tests on unlockCallback with arbitrary delta combinations—the standard. We've found edge cases where intermediate currency doesn't zero with specific swap direction and amount == 0 combinations.

For math verification, we use invariant tests: after each operation, sum of all delta = 0. If a Foundry invariant test fails, we've found a state where the contract broke before PoolManager noticed it.

Work Process

Analytics (2-3 days). Describe the operations graph: which pools, which tokens, what order of settle/take. Determine if a hook is needed and what bits it requires.

Development (5-8 days). Implement IUnlockCallback, hook if needed, vanity mine the address via Foundry script. Fork-tests on mainnet, fuzz-tests on edge cases.

Audit and Deployment (2-3 days). Manual review of delta flow, Slither for static analysis, deployment via Foundry script with Etherscan verification.

Basic flash accounting system without hook: 1 week. With custom hook and extended logic: 2 weeks. Cost calculated after analyzing the operation graph.