Skip to main content
This guide walks you through cancelling a pending withdrawal order by calling cancelOrder() on the WithdrawQueue contract directly. It covers both direct cancellation (you submit the transaction) and meta-transaction cancellation (a relayer submits on your behalf).

How Cancellations Work

When you submitted a withdrawal order, the WithdrawQueue locked your vault shares and minted an ERC-721 NFT to your address representing ownership of the order. To cancel:
1

Find your pending orders

Enumerate your order NFTs using the ERC-721 enumerable interface, then filter by PENDING status.
2

Cancel the order

Call cancelOrder(orderIndex). The contract verifies you own the order NFT, then returns your vault shares to the refundReceiver address.
There is no approval step — the only requirement is that msg.sender holds the NFT for the given order.
Only orders with PENDING status (value 1) can be cancelled. Once an order has been fulfilled or is being processed, it cannot be cancelled.

What You’ll Need

RequirementDescription
Contract addresswithdrawQueueAddress — see Vault Discovery
ABIProvided below
RPC endpointAn Ethereum node URL
Private key or walletThe same wallet that submitted the withdrawal order
Order indexFrom the OrderSubmitted event or NFT enumeration (shown below)

ABI Reference

[
  {
    "inputs": [{ "name": "orderIndex", "type": "uint256" }],
    "name": "cancelOrder",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      { "name": "orderIndex", "type": "uint256" },
      { "name": "deadline", "type": "uint256" },
      { "name": "cancelSignature", "type": "bytes" }
    ],
    "name": "cancelOrderWithSignature",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [{ "name": "orderIndex", "type": "uint256" }],
    "name": "getOrderStatus",
    "outputs": [{ "name": "", "type": "uint8" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [{ "name": "tokenId", "type": "uint256" }],
    "name": "ownerOf",
    "outputs": [{ "name": "", "type": "address" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [{ "name": "owner", "type": "address" }],
    "name": "balanceOf",
    "outputs": [{ "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      { "name": "owner", "type": "address" },
      { "name": "index", "type": "uint256" }
    ],
    "name": "tokenOfOwnerByIndex",
    "outputs": [{ "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  }
]

Contract Method Reference

cancelOrder(orderIndex)

ParameterTypeDescription
orderIndexuint256Index of the order to cancel. Get this from the OrderSubmitted event or by enumerating order NFTs.

cancelOrderWithSignature(orderIndex, deadline, cancelSignature)

For meta-transaction support — a relayer can cancel on behalf of the order owner.
ParameterTypeDescription
orderIndexuint256Index of the order to cancel
deadlineuint256Unix timestamp after which the signature expires
cancelSignaturebytesEIP-712 signature from the order owner (see Meta-Transaction Cancellation below)

ERC-721 Enumeration (finding your orders)

The WithdrawQueue is an ERC-721 contract. Each withdrawal order is represented by an NFT.
MethodReturnsDescription
balanceOf(owner)uint256Number of order NFTs held by the address
tokenOfOwnerByIndex(owner, index)uint256The order index (token ID) at the given position
ownerOf(tokenId)addressThe current owner of a specific order NFT
getOrderStatus(orderIndex)uint8The order’s current status (see status table below)

Order Statuses

ValueStatusCancellable?
0NOT_FOUNDNo
1PENDINGYes
2COMPLETENo
3COMPLETE_PRE_FILLEDNo
4PENDING_REFUNDNo
5COMPLETE_REFUNDEDNo
6FAILED_TRANSFER_REFUNDEDNo

Direct Cancellation Walkthrough

1

Find your order NFTs (read)

Get the number of order NFTs held by your address.
WithdrawQueue.balanceOf(yourAddress) → uint256 orderCount
If orderCount is 0, you have no orders to cancel.
2

Enumerate and filter pending orders (read)

Loop through your NFTs and check each order’s status.For each i from 0 to orderCount - 1:
WithdrawQueue.tokenOfOwnerByIndex(yourAddress, i) → uint256 orderIndex
WithdrawQueue.getOrderStatus(orderIndex) → uint8 status
Only orders with status == 1 (PENDING) can be cancelled.
3

Cancel the order (transaction)

Call cancelOrder() for each pending order you want to cancel.
WithdrawQueue.cancelOrder(orderIndex)
The contract:
  1. Verifies that msg.sender owns the order NFT
  2. Returns the locked vault shares to the refundReceiver address (set during order submission)
  3. Burns the order NFT
Wait for the transaction to be mined. Your vault shares are now unlocked and available.
4

Verify cancellation (read, optional)

Confirm the order status changed.
WithdrawQueue.getOrderStatus(orderIndex) → uint8 status
Expected: 5 (COMPLETE_REFUNDED)
If you already know the orderIndex (e.g., you saved it from the OrderSubmitted event when you submitted the withdrawal), you can skip Steps 1–2 and go directly to cancellation. Just verify the order is still PENDING first.

Meta-Transaction Cancellation

For relayer or gasless cancellation, the order owner signs an EIP-712 message off-chain and anyone can submit the transaction.

EIP-712 Type

Cancel(uint256 orderIndex, uint256 deadline, address queueAddress, uint256 chainId)

Walkthrough

1

Build the EIP-712 typed data (off-chain)

EIP-712 Domain:
FieldValue
name"WithdrawQueue"
chainIdChain ID (e.g., 1)
verifyingContractWithdrawQueue address
Cancel message:
FieldValue
orderIndexThe order to cancel
deadlineUnix timestamp (e.g., now + 1 hour)
queueAddressWithdrawQueue address
chainIdChain ID (e.g., 1)
2

Sign the typed data (off-chain)

The order owner signs the EIP-712 typed data using their wallet’s signTypedData method. This produces a 65-byte signature.
3

Submit via relayer (transaction)

Anyone can submit the cancellation using the owner’s signature:
WithdrawQueue.cancelOrderWithSignature(
  orderIndex,        // the order to cancel
  deadline,          // from the signed message
  cancelSignature    // 65-byte EIP-712 signature
)
The contract verifies the signature came from the order NFT owner and that the deadline hasn’t passed.
The deadline in the signed message and the deadline passed to cancelOrderWithSignature() must match exactly. If the current block timestamp exceeds the deadline, the transaction will revert with SignatureExpired.

Troubleshooting

Your wallet doesn’t own this order’s NFT. Only the original submitter (or whoever holds the NFT) can cancel.
The order isn’t in PENDING status. Check getOrderStatus() — only status 1 is cancellable.
The order index doesn’t exist. Verify it from the OrderSubmitted event or NFT enumeration.
The deadline in cancelOrderWithSignature has passed. Generate a fresh signature with a future deadline.

Next Steps