Skip to content
LogoLogo

AsyncFiller

Git Source

Title: AsyncFiller

Author: @msakiart

Stores open async orders and settles fills against them.

Authorization model: the maker authorizes a Router/executor at order-creation time (setExecutor[owner][executor] = true). All subsequent fill / cancel / updatePrice calls on the hook must come from that registered executor. The hook forwards its immediate caller (msg.sender) and the resolved end-actor address (filler / canceller) into this library; the executor is checked here, and PM settlement targets the actor.

Constants

MAX_PRIORITY_FEE

uint64 internal constant MAX_PRIORITY_FEE = type(uint64).max;

MIN_PRIORITY_FEE

Default $0.10 cap for six-decimal numeraires. A pool may override this for other decimals.

uint64 internal constant MIN_PRIORITY_FEE = 100_000;

PRIORITY_FEE_BPS

Below a $100 order the least bid is 10 bps of the order instead: min($0.10, 0.1% of it).

uint256 internal constant PRIORITY_FEE_BPS = 10;

TRADE_FEE_BPS

Protocol fee on what each side of a book match or filler fill receives: 0.02%.

uint256 internal constant TRADE_FEE_BPS = 2;

Functions

addOrder

function addOrder(
        State storage self,
        Book storage book,
        bytes32 id,
        address owner,
        uint256 amountIn,
        uint256 amountOutMin,
        bool isBuy,
        bool zeroForOne,
        uint256 priorityFee
    ) internal;

Parameters

NameTypeDescription
selfState
bookBook
idbytes32
owneraddress
amountInuint256
amountOutMinuint256
isBuybool
zeroForOnebool
priorityFeeuint256

tradeFee

The protocol's 0.02% of a payment, rounded up. Each side of a trade receives its proceeds less this fee, so a maker receives at least amountOutMin minus 0.02%.

function tradeFee(uint256 amount) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256

Returns

NameTypeDescription
<none>uint256

minPriorityFee

The least bid for an order worth notional numeraire units: $0.10, or 0.1% of the order when that is less (orders under $100).

function minPriorityFee(uint256 notional) internal pure returns (uint256);

Parameters

NameTypeDescription
notionaluint256

Returns

NameTypeDescription
<none>uint256

minPriorityFee

function minPriorityFee(uint256 notional, uint64 cap) internal pure returns (uint256);

Parameters

NameTypeDescription
notionaluint256
capuint64

Returns

NameTypeDescription
<none>uint256

checkMinimum

Reverts unless the order's numeraire leg is at least the pool's minimum (a buy's input, a sell's minimum output) and its asset leg at least the pool's asset floor (a sell's input, a buy's minimum output). Neither reads the pool price, which whoever initializes the pool sets.

function checkMinimum(Book storage book, bool isBuy, uint256 amountIn, uint256 amountOutMin) internal view;

Parameters

NameTypeDescription
bookBook
isBuybool
amountInuint256
amountOutMinuint256

settlePriorityFee

function settlePriorityFee(
        State storage self,
        PoolKey memory key,
        bytes32 id,
        address maker,
        uint256 amount,
        address hook
    ) internal;

Parameters

NameTypeDescription
selfState
keyPoolKey
idbytes32
makeraddress
amountuint256
hookaddress

bestOrder

function bestOrder(State storage self, Book storage book, bool isBuy)
        internal
        view
        returns (bool found, uint128 price, bytes32 orderId, address owner);

Parameters

NameTypeDescription
selfState
bookBook
isBuybool

Returns

NameTypeDescription
foundbool
priceuint128
orderIdbytes32
owneraddress

level

function level(Book storage book, bool isBuy, uint128 price)
        internal
        view
        returns (bytes32 head, bytes32 tail, uint32 orderCount);

Parameters

NameTypeDescription
bookBook
isBuybool
priceuint128

Returns

NameTypeDescription
headbytes32
tailbytes32
orderCountuint32

bestAtPrice

function bestAtPrice(Book storage book, bool isBuy, uint128 price) internal view returns (bytes32 id);

Parameters

NameTypeDescription
bookBook
isBuybool
priceuint128

Returns

NameTypeDescription
idbytes32

updatePrice

Maker-only price update: caller must equal order.owner (the maker directly, or the owner whose signature updatePriceWithSig verified). No executor is involved.

function updatePrice(
        State storage self,
        Book storage book,
        AsyncOrder memory order,
        bytes32 id,
        uint256 newAmountOutMin,
        address caller
    ) internal;

Parameters

NameTypeDescription
selfState
bookBook
orderAsyncOrder
idbytes32
newAmountOutMinuint256
calleraddress

fill

Full-fill. The caller (the hook contract) must be an authorized executor of the order owner; filler is the actual end-user paying the output and receiving the input. Must be invoked from inside an IPoolManager.unlock context.

Settle gross output (native only; ERC20 is pre-settled), pay the signed minimum less the trade fee to the maker, and mint fee claims to the vault. Burn input claims and pay the input less the trade fee to the filler. Both currency deltas net to zero. A failed fill reverts all legs.

function fill(
        State storage self,
        Book storage book,
        AsyncOrder memory order,
        bytes32 id,
        address hook,
        address executor,
        address filler,
        address feeVault,
        uint256 fee
    ) internal;

Parameters

NameTypeDescription
selfState
bookBook
orderAsyncOrder
idbytes32
hookaddress
executoraddress
filleraddress
feeVaultaddress
feeuint256

_payFiller

Burn the order's input claims and pay the filler all but the trade fee, which goes to the vault.

function _payFiller(
        State storage self,
        Currency input,
        address hook,
        address filler,
        address feeVault,
        uint256 amountIn
    ) private returns (uint256 tradeFeeIn);

Parameters

NameTypeDescription
selfState
inputCurrency
hookaddress
filleraddress
feeVaultaddress
amountInuint256

Returns

NameTypeDescription
tradeFeeInuint256

_closeOrder

Remove and delete an order, then settle its bid.

function _closeOrder(State storage self, Book storage book, PoolKey memory key, bytes32 id, address hook) private;

Parameters

NameTypeDescription
selfState
bookBook
keyPoolKey
idbytes32
hookaddress

settleOrderPriorityFee

function settleOrderPriorityFee(State storage self, PoolKey memory key, bytes32 id, address hook) internal;

Parameters

NameTypeDescription
selfState
keyPoolKey
idbytes32
hookaddress

cancel

Cancel an unfilled order. Must be called inside an unlock context. Auth: executor must be either the order owner themselves (smart-contract makers calling the hook directly from their own unlock) or an executor the maker authorised via setExecutor. Funds always return to order.owner.

function cancel(
        State storage self,
        Book storage book,
        AsyncOrder memory order,
        bytes32 id,
        address hook,
        address executor
    ) internal;

Parameters

NameTypeDescription
selfState
bookBook
orderAsyncOrder
idbytes32
hookaddress
executoraddress

_append

function _append(State storage self, Book storage book, bytes32 id) internal;

Parameters

NameTypeDescription
selfState
bookBook
idbytes32

_remove

function _remove(State storage self, Book storage book, bytes32 id) internal;

Parameters

NameTypeDescription
selfState
bookBook
idbytes32

_priorityKey

function _priorityKey(uint64 priorityFee, uint64 sequence) private pure returns (uint128);

Parameters

NameTypeDescription
priorityFeeuint64
sequenceuint64

Returns

NameTypeDescription
<none>uint128

refreshExactPrice

Refresh even when a partial fill changes neither the price key nor remaining bid.

function refreshExactPrice(State storage self, Book storage book, bytes32 id) internal;

Parameters

NameTypeDescription
selfState
bookBook
idbytes32

exactPrice

function exactPrice(OrderInfo storage order) internal view returns (EligiblePrice.Ratio memory);

Parameters

NameTypeDescription
orderOrderInfo

Returns

NameTypeDescription
<none>EligiblePrice.Ratio

eligibleAtPrice

function eligibleAtPrice(Book storage book, bool isBuy, uint128 price, EligiblePrice.Ratio memory limit)
        internal
        view
        returns (bytes32);

Parameters

NameTypeDescription
bookBook
isBuybool
priceuint128
limitEligiblePrice.Ratio

Returns

NameTypeDescription
<none>bytes32

mostPermissiveAtPrice

function mostPermissiveAtPrice(Book storage book, bool isBuy, uint128 price)
        internal
        view
        returns (EligiblePrice.Ratio memory);

Parameters

NameTypeDescription
bookBook
isBuybool
priceuint128

Returns

NameTypeDescription
<none>EligiblePrice.Ratio

_priceKey

The order's book level: the v4 tick of its exact limit, ordered by numeraire per asset (see TickPrice.key). The exact limit is kept on the order and decides crossing.

function _priceKey(bool isBuy, bool zeroForOne, uint256 amountIn, uint256 amountOut)
        internal
        pure
        returns (uint128);

Parameters

NameTypeDescription
isBuybool
zeroForOnebool
amountInuint256
amountOutuint256

Returns

NameTypeDescription
<none>uint128

Events

AsyncOrderCreated

event AsyncOrderCreated(
        PoolId indexed poolId,
        bytes32 indexed orderId,
        address indexed owner,
        bool zeroForOne,
        uint256 amountIn,
        uint256 amountOutMin,
        bytes32 salt
    );

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
owneraddress
zeroForOnebool
amountInuint256
amountOutMinuint256
saltbytes32

AsyncOrderPriceUpdated

event AsyncOrderPriceUpdated(
        PoolId indexed poolId, bytes32 indexed orderId, uint256 oldAmountOutMin, uint256 newAmountOutMin
    );

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
oldAmountOutMinuint256
newAmountOutMinuint256

AsyncOrderFilled

event AsyncOrderFilled(
        PoolId indexed poolId, bytes32 indexed orderId, address indexed filler, uint256 amountIn, uint256 amountOutMin
    );

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
filleraddress
amountInuint256
amountOutMinuint256

AsyncOrderCancelled

event AsyncOrderCancelled(PoolId indexed poolId, bytes32 indexed orderId, address indexed owner, uint256 amountIn);

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
owneraddress
amountInuint256

OrderFeeAccrued

event OrderFeeAccrued(PoolId indexed poolId, bytes32 indexed orderId, Currency indexed currency, uint256 amount);

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
currencyCurrency
amountuint256

PriorityFeeDonated

event PriorityFeeDonated(PoolId indexed poolId, bytes32 indexed orderId, address indexed maker, uint256 amount);

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
makeraddress
amountuint256

PriorityFeeForfeited

event PriorityFeeForfeited(PoolId indexed poolId, bytes32 indexed orderId, address indexed maker, uint256 amount);

Parameters

NameTypeDescription
poolIdPoolId
orderIdbytes32
makeraddress
amountuint256

Errors

OrderAlreadyExists

error OrderAlreadyExists();

OrderNotFound

error OrderNotFound();

NotOrderOwner

error NotOrderOwner();

NotAuthorizedExecutor

error NotAuthorizedExecutor();

ZeroAmount

error ZeroAmount();

PriorityFeeTooLarge

error PriorityFeeTooLarge();

PriorityFeeTooSmall

error PriorityFeeTooSmall();

BelowMinimumOrder

error BelowMinimumOrder();

BelowMinimumAssetAmount

error BelowMinimumAssetAmount();

Structs

OrderInfo

Open-order record. Filler fills are full-order; direct matches can reduce it partially while keeping the remaining input in escrow.

struct OrderInfo {
        address owner;
        uint256 amountIn;
        uint256 amountOutMin;
        uint128 price;
        bool isBuy;
        bool zeroForOne;
        uint64 sequence;
        /// @dev Maker reprices so far; signed reprices commit to it (`OrderSignatures.hashUpdatePrice`).
        uint32 reprices;
        /// @dev The bid, escrowed as hook claims since the order was created.
        uint64 priorityFee;
        uint128 priorityKey;
        /// @dev Immutable settlement age; repricing only resets queue sequence.
        uint64 createdSequence;
    }

Properties

NameTypeDescription
owneraddress
amountInuint256
amountOutMinuint256
priceuint128
isBuybool
zeroForOnebool
sequenceuint64
repricesuint32
priorityFeeuint64
priorityKeyuint128
createdSequenceuint64

PriceLevel

Orders at one price, highest bid first, then earliest.

struct PriceLevel {
        uint32 orderCount;
        RadixPriceTree.Tree priorityOrders;
        mapping(uint128 priorityKey => bytes32 orderId) priorityOrderIds;
        mapping(uint32 nodeId => EligiblePrice.Ratio) exactBounds;
    }

Properties

NameTypeDescription
orderCountuint32
priorityOrdersRadixPriceTree.Tree
priorityOrderIdsmapping(uint128 priorityKey => bytes32 orderId)
exactBoundsmapping(uint32 nodeId => EligiblePrice.Ratio)

MatchAmounts

struct MatchAmounts {
        uint256 assetAmount;
        uint256 quoteAmount;
    }

Properties

NameTypeDescription
assetAmountuint256
quoteAmountuint256

NewOrder

struct NewOrder {
        bytes32 id;
        address owner;
        uint256 amountIn;
        uint256 amountOutMin;
        bool isBuy;
        bool zeroForOne;
        uint256 priorityFee;
        PoolId poolId;
    }

Properties

NameTypeDescription
idbytes32
owneraddress
amountInuint256
amountOutMinuint256
isBuybool
zeroForOnebool
priorityFeeuint256
poolIdPoolId

State

struct State {
        IPoolManager poolManager;
        Currency numeraire;
        address feeVault;
        mapping(bytes32 orderId => OrderInfo) orders;
        mapping(address owner => mapping(address executor => bool)) isExecutor;
        /// @dev Pool tick before the first pool fill of the current backrun window, and that fill's block.
        int24 refTick;
        uint64 refBlock;
    }

Properties

NameTypeDescription
poolManagerIPoolManager
numeraireCurrency
feeVaultaddress
ordersmapping(bytes32 orderId => OrderInfo)
isExecutormapping(address owner => mapping(address executor => bool))
refTickint24
refBlockuint64

Book

struct Book {
        uint64 nextSequence;
        uint64 openOrderCount;
        /// @dev $0.10 in this pool's numeraire base units. Zero uses the six-decimal default.
        uint64 priorityFeeCap;
        TickBitmap.Tree bids;
        TickBitmap.Tree asks;
        mapping(uint128 price => PriceLevel) bidLevels;
        mapping(uint128 price => PriceLevel) askLevels;
        /// @dev Least order size in numeraire base units (0: none); see `checkMinimum`.
        uint256 minOrder;
        /// @dev Least asset amount an order may trade, from the asset's decimals and the hook's precision.
        uint256 minAssetAmount;
    }

Properties

NameTypeDescription
nextSequenceuint64
openOrderCountuint64
priorityFeeCapuint64
bidsTickBitmap.Tree
asksTickBitmap.Tree
bidLevelsmapping(uint128 price => PriceLevel)
askLevelsmapping(uint128 price => PriceLevel)
minOrderuint256
minAssetAmountuint256