3. Signing the order

We will resume the example from above, setting the validity (Unix timestamp) to August 4th 2021. We use keccak(GPv2 Place Order Tutorial) as appData (you can use your individual 32 bytes to identify the “source” of your orders).
Our typescript library provides a convenient way to create valid signatures for your order.
import {
} from ""
const [trader] = await ethers.getSigners();
const order = {
sellToken: 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48,
buyToken: 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2,
sellAmount: 10000000000,
buyAmount: 4959721654652700610,
validTo: 1628035200,
appData: 0xf785fae7a7c5abc49f3cd6a61f6df1ff26433392b066ee9ff2240ff1eb7ab6e4,
feeAmount: 14075734,
kind: OrderKind.SELL,
partiallyFillable: false,
receiver: ethers.constants.AddressZero,
const raw_signature = await signOrder(
// Needed to turn the three part object into a single bytestring
const signature = ethers.utils.joinSignature(;
If you are using a different programming language you may have to write your own signing logic. Here are some pointers:
The ultimate source of truth for signature verification is the smart contract’s implementation of the order digest and how it gets verified given different signing schemes.

Security notice:

Do not sign orders with simultaneously sellAmount == 0, buyAmount == 0, and partiallyFillable == false.
Because of a known issue in the contracts, such orders can be settled unlimited times, which means that any solver could take the fee amount multiple times. There is normally no reason to generate such "empty" order. However, you should consider this case if you are signing orders that come from potentially untrusted sources.