Hard Cancel

Overview

In cases where a Maker's orders have been requested as part of a Taker's potential fill order, Makers will have to wait for the Operator signature to lapse before their order can be gaslessly cancelled. As long as the Taker's fill order is not executed, Makers still have the option to immediately cancel their orders by paying a gas fee to prioritize their cancellation on-chain. Usage of this Hard Cancel option is expected to be minimal unless the Maker's orders are consistently close to the market price.

Please refer to Decentralized Limit Orders for more details regarding this design.

Sequence Diagram

KyberSwap exposes 2 API options for Makers who wish to cancel their orders on-chain:

  • /read-ks/api/v1/encode/cancel-batch-orders: Encode the batch cancellation data to be sent on-chain. This API can be used to cancel a single orderId or multiple orders by specifying the target orderIds.

  • /read-ks/api/v1/encode/increase-nonce: Encode the increase nonce data to be sent on-chain. By increasing the LO contract nonce tied to the Maker, the LO contract is able to nullify all existing orders.

In addition to the above, Makers are also able to query their active order(s) to aid with filtering orders to cancel:

TypeScript Example

Limit Order API Demo

The code snippets in the guide below have been extracted from our demo GitHub repo which showcases the full end-to-end Limit Order operations in a TypeScript environment.

Step 1: Get Maker orders

Active/Open Orders

To proceed with this guide, users must have created an Active or Open Limit Order. Please refer to the Create Limit Order developer guide for instructions on how to achieve this programmatically.

We can use the /read-ks/api/v1/orders to get the list of "active" or "open" Maker orders:

const targetPathConfig = {
    params: {
        chainId: ChainId.MATIC,
        maker: signerAddress,
        status: "active"
    }
};

getMakerOrders.ts

In this case, the above query will return all of the Maker active orders from which we can then filter for our target order to cancel.

Step 2: Get the target orderId to cancel

Cancel All Orders

If you would like to cancel all orders instead, you can call /read-ks/api/v1/encode/increase-nonce which will return the encoded increase nonce data. This can be used in place of the encoded data from step 5 onwards.

Please refer to postCancelAllOrders.ts for a Cancel All example.

For our purposes, we will just take the first order which matches our makerAsset and takerAsset pair:

const orders = await getMakerOrders();
const targetOrders = orders.filter(order => 
    order.makerAsset.toLowerCase() == makerAsset.address.toLowerCase() &&
    order.takerAsset.toLowerCase() == takerAsset.address.toLowerCase()
);
const targetOrderId = Number(targetOrders[targetOrders.length-1].id);

postCancelBatchOrder.ts

Step 3: Format the cancel order request body

The orderId will be included as part of the orderIds array:

const requestBody: CancelBatchOrdersBody = {
    orderIds: [targetOrderId]
};

postCancelBatchOrder.ts

Note that you can include multiple orderIds to be encoded in the same transaction so that you will only have to pay gas once to hard cancel all the included orders.

Step 4: Post the encode data request

With the orderIds prepared, we can then request the encoded data via /read-ks/api/v1/encode/cancel-batch-orders:

const {data} = await axios.post(
    LimitOrderDomain+targetPath,
    requestBody
);

This will return the batch cancel encoded data which will be used as the calldata when executing the transaction on-chain.

Step 5: Execute the batch cancel transaction on-chain

To execute the transaction, we can use our ethers.js signer instance to send the transaction with the required gas fees:

const cancelOrderTx = await signer.sendTransaction({
    data: data.data.encodedData,
    to: limitOrderContract,
    from: signerAddress,
    maxFeePerGas: 100000000000,
    maxPriorityFeePerGas: 100000000000
});

postCancelBatchOrders.ts

A transaction hash will be returned once the cancel order has been executed. You can copy this hash into a scanner (i.e. PolygonScan) and see that your transaction has been successfully completed by the network.

Last updated