Invalidators

Invalidators is a SwapVM instruction module that provides order invalidation primitives. It prevents replay, enforces one-time execution, and tracks partial fills against a cap.

Router scope: These instructions belong to the limit-order opcode set, which is compiled into the limit-order router. They are not part of the deployed Aqua router. The Aqua router (AquaSwapVMRouter) inherits the AquaOpcodes set (Controls, XYCSwap, XYCConcentrate, Decay, Fee, PeggedSwap, Extruction) and does not include Invalidators. Both routers are compiled by the same SwapVM engine, so the encoding described here does not appear in an Aqua strategy program.

Source: src/instructions/Invalidators.sol


Public state

Solidity
1
2
3
4
5
6
7
8
9
mapping(address maker => mapping(uint256 slotIndex => uint256 bitmap)) public bitInvalidators;

mapping(address maker =>
    mapping(bytes32 orderHash =>
        mapping(address token => uint256 filled))) public tokenInInvalidators;

mapping(address maker =>
    mapping(bytes32 orderHash =>
        mapping(address token => uint256 filled))) public tokenOutInvalidators;

External invalidation functions

Makers can pre-cancel orders by calling these directly (no program required):

Function Effect
invalidateBit(uint256 bitIndex) Sets bit at bitIndex in bitInvalidators[msg.sender]
invalidateTokenIn(bytes32 orderHash, address tokenIn) Sets tokenInInvalidators[msg.sender][orderHash][tokenIn] = type(uint256).max
invalidateTokenOut(bytes32 orderHash, address tokenOut) Sets tokenOutInvalidators[msg.sender][orderHash][tokenOut] = type(uint256).max

Instructions

_invalidateBit1D

Solidity
1
function _invalidateBit1D(Context memory ctx, bytes calldata args) internal

One-time execution guard. Checks and sets a single bit in a packed 256-bit bitmap keyed by maker.

Field Offset Size Description
bitIndex 0 4 bytes (uint32) Bit index; slot = bitIndex >> 8, bit position = bitIndex & 0xFF

Build with InvalidatorsArgsBuilder.buildInvalidateBit(uint32 bitIndex).

Behavior: If the bit is not set, proceeds and sets it (in swap mode). If the bit is already set, reverts. In quote mode, checks but does not set.

Errors: InvalidatorsBitAlreadySet(maker, bitIndex, bitmap).


_invalidateTokenIn1D

Solidity
1
function _invalidateTokenIn1D(Context memory ctx, bytes calldata /* args */) internal

Partial fill tracking against balanceIn. Accumulates amountIn into tokenInInvalidators[maker][orderHash][tokenIn]. Reverts if the cumulative total would exceed ctx.swap.balanceIn.

Args: none (0 bytes)

Behavior:

  1. If amountIn == 0, calls ctx.runLoop() first (waits for exactOut computation)
  2. Reads prefilled = tokenInInvalidators[maker][orderHash][tokenIn]
  3. Requires prefilled + amountIn <= balanceIn
  4. In swap mode, stores newFilled

Errors

Error Condition
InvalidateTokenInExpectsAmountInToBeComputed() amountIn still zero after runLoop
InvalidatorsTokenInExceeded(prefilled, amountIn, balanceIn) Fill would exceed balance

_invalidateTokenOut1D

Solidity
1
function _invalidateTokenOut1D(Context memory ctx, bytes calldata /* args */) internal

Partial fill tracking against balanceOut. Accumulates amountOut into tokenOutInvalidators[maker][orderHash][tokenOut]. Reverts if cumulative total would exceed ctx.swap.balanceOut.

Args: none (0 bytes)

Behavior: Mirrors _invalidateTokenIn1D but tracks amountOut / tokenOut / balanceOut.

Errors

Error Condition
InvalidateTokenOutExpectsAmountOutToBeComputed() amountOut still zero after runLoop
InvalidatorTokenOutExceeded(prefilled, amountOut, balanceOut) Fill would exceed balance

Quote/swap divergence (all instructions): In quote mode, state is read but not updated. A quote may succeed while the swap reverts if the order was filled between the two calls. Do not use backward jumps to any of these instructions.


  • LimitSwap: sets balanceIn/balanceOut that define fill caps
  • Controls: alternative access guards (deadline, token balance)

Did you find what you need?