V4HOOKSCUT SHEET DIRECTORY

Index / Limit order

pattern · UNLICENSED · last updated 2026-08-27

Limit order

Rest liquidity at a tick and fill it in afterSwap when the pool trades through that price.

Uniswap’s LimitOrder example records the last tick on afterInitialize. On afterSwap it walks ticks the swap just crossed and fills any epoch resting at those ticks by removing that one-tick-wide liquidity. Users call place() to add an order; withdraw() after Fill. Flags must be afterInitialize + afterSwap. This is the example-contracts file, UNLICENSED, not a production CLOB. Production forks add cancel, partial fill, and gas accounting. Copy the full Solidity from the permalink. Listing is not an audit.

Permission bits

These bits must match the deployed address. Confirm on-chain before you route.

Initialize
ba
Liquidity
baba
Swap
ba
Donate
ba
Return delta
baaa

afterInitializeafterSwap

Solidity

Excerpt from contracts/hooks/examples/LimitOrder.sol. Copy the full file to implement this. Not an audit.

// SPDX-License-Identifier: UNLICENSED
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
    return Hooks.Permissions({
        beforeInitialize: false,
        afterInitialize: true,
        beforeAddLiquidity: false,
        beforeRemoveLiquidity: false,
        afterAddLiquidity: false,
        afterRemoveLiquidity: false,
        beforeSwap: false,
        afterSwap: true,
        beforeDonate: false,
        afterDonate: false,
        beforeSwapReturnDelta: false,
        afterSwapReturnDelta: false,
        afterAddLiquidityReturnDelta: false,
        afterRemoveLiquidityReturnDelta: false
    });
}

function afterSwap(
    address,
    PoolKey calldata key,
    IPoolManager.SwapParams calldata params,
    BalanceDelta,
    bytes calldata
) external override onlyByManager returns (bytes4, int128) {
    (int24 tickLower, int24 lower, int24 upper) = _getCrossedTicks(key.toId(), key.tickSpacing);
    if (lower > upper) return (LimitOrder.afterSwap.selector, 0);
    bool zeroForOne = !params.zeroForOne;
    for (; lower <= upper; lower += key.tickSpacing) {
        _fillEpoch(key, lower, zeroForOne);
    }
    setTickLowerLast(key.toId(), tickLower);
    return (LimitOrder.afterSwap.selector, 0);
}

Spec

Kindpattern
Statusexperimental
LicenseUNLICENSED
Sourcehttps://github.com/Uniswap/v4-periphery
CategoriesLimit orders
PropertiesVanilla swap
ChainsEthereum
Docshttps://docs.uniswap.org/contracts/v4/concepts/hooks

FAQ

Can I paste this into production? The snippet is an excerpt. Use the full file at the source URL, match flags to the address, and treat this page as a map, not a guarantee.

How do I build this safely? Start with secure v4 hooks and the OpenZeppelin hooks guide.