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
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
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
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:
- If
amountIn == 0, callsctx.runLoop()first (waits for exactOut computation) - Reads
prefilled = tokenInInvalidators[maker][orderHash][tokenIn] - Requires
prefilled + amountIn <= balanceIn - In swap mode, stores
newFilled
Errors
| Error | Condition |
|---|---|
InvalidateTokenInExpectsAmountInToBeComputed() |
amountIn still zero after runLoop |
InvalidatorsTokenInExceeded(prefilled, amountIn, balanceIn) |
Fill would exceed balance |
_invalidateTokenOut1D
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.
Related
- LimitSwap: sets
balanceIn/balanceOutthat define fill caps - Controls: alternative access guards (deadline, token balance)