From ad7b1d6650916a0ed43df5d90e90db574e49027c Mon Sep 17 00:00:00 2001 From: mfw78 <53399572+mfw78@users.noreply.github.com> Date: Fri, 15 Dec 2023 09:06:25 +0000 Subject: [PATCH] chore: sanity check orders (#124) # Description Reduces pressure on the API by doing some sanity checks on orders from contracts. # Changes - [x] Filters out invalid orders that will be rejected by the API ## How to test 1. Run on staging 2. Observe no API errors for orders that are filtered ## Related Issues Fixes #122 --- src/domain/checkForAndPlaceOrder.ts | 5 ++++ src/utils/filterOrder.ts | 37 +++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/utils/filterOrder.ts diff --git a/src/domain/checkForAndPlaceOrder.ts b/src/domain/checkForAndPlaceOrder.ts index 9be3956..36250cb 100644 --- a/src/domain/checkForAndPlaceOrder.ts +++ b/src/domain/checkForAndPlaceOrder.ts @@ -43,6 +43,7 @@ import { measureTime, } from "../utils/metrics"; import { FilterAction } from "../utils/filterPolicy"; +import { validateOrder } from "../utils/filterOrder"; const GPV2SETTLEMENT = "0x9008D19f58AAbD9eD0D60971565AA8510560ab41"; @@ -345,6 +346,10 @@ async function _processConditionalOrder( validTo: Number(order.validTo), }; + // We now have the order, so we can validate it. This will throw if the order is invalid + // and we will catch it below. + validateOrder(orderToSubmit); + // calculate the orderUid const orderUid = _getOrderUid(chainId, orderToSubmit, owner); diff --git a/src/utils/filterOrder.ts b/src/utils/filterOrder.ts new file mode 100644 index 0000000..1053b0e --- /dev/null +++ b/src/utils/filterOrder.ts @@ -0,0 +1,37 @@ +import { Order } from "@cowprotocol/contracts"; +import { BigNumber, ethers } from "ethers"; + +/** + * Process an order to determine if it is valid + * @param order The GPv2.Order data struct to validate + * @throws Error if the order is invalid + */ +export function validateOrder(order: Order) { + // amounts must be non-zero + if (BigNumber.from(order.sellAmount).isZero()) { + throw new Error("Order has zero sell amount"); + } + + if (BigNumber.from(order.buyAmount).isZero()) { + throw new Error("Order has zero buy amount"); + } + + // token addresses must not be the ZeroAddress + if (order.sellToken === ethers.constants.AddressZero) { + throw new Error("Order has zero sell token address"); + } + + if (order.buyToken === ethers.constants.AddressZero) { + throw new Error("Order has zero buy token address"); + } + + // tokens must not be the same + if (order.sellToken === order.buyToken) { + throw new Error("Order has identical sell and buy token addresses"); + } + + // Check to make sure that the order has at least 120s of validity + if (Math.floor(Date.now() / 1000) + 60 > Number(order.validTo)) { + throw new Error("Order expires too soon"); + } +}