Order digest
The order digest is abytes32 that uniquely describes the parameters of an order. It is used as the input to the signing schemes. The digest is computed as described in the EIP-712.
Replay protection
Replay protection for the signing schemes is achieved by using anEIP-712 domain separator. This domain separator is unique to each deployment of the CoW Protocol settlement contract on a particular chain.
When computing the domain separator, the following parameters are used:
CoW Protocol was formerly known as Gnosis Protocol v2. The domain separator is still named
Gnosis Protocol as the change would have required a new deployment of the settlement contract.EIP712Domain struct with the EIP-712 defined hashStruct function.
Encoding
To encode the order into the order digest, theEIP-712 specification is used:
keccak256, the standard unpadded Ethereum hashing function"\x19\x01", two bytes‖, the byte-concatenation functiondomainSeparator, the domain separator as mentioned in the previous sectionhashStruct, the identically named function in the EIP-712 standard
hashStruct pseudocode
hashStruct pseudocode
keccak256, the standard unpadded Ethereum hashing function‖, the byte-concatenation functiontypeHash, the hash of the struct typeencodeData, the identically named function in the EIP-712 standard
bytes32 value that is used as the input to the signing schemes.
JavaScript example
Phew, that was a lot of hashing! Feeling dizzy? Don’t worry, we got you covered. The@cowprotocol/contracts package provides a function to compute the order digest for you:
Etherscan Example
For convenience, we also deployed a small helper contract that makes it easy to compute order uids as well as their full encoding for each chain using the Etherscan UI:- Ethereum
- Gnosis
- Base N/A
- Arbitrum N/A
- Avalanche N/A
- Polygon N/A
- Lens N/A
- BNB N/A
- Linea N/A
- Plasma N/A
- Ink N/A
- Sepolia
Supported schemes
CoW Protocol supports four different signing schemes. These signing schemes are summarized in the following table: Except for thePreSign scheme, all signing schemes involve signing an order digest that is based on the message structure of EIP-712.
In the expanded detail sections below,
signature refers to the value passed to signature in the Order book API.eth_sign
This signature type is the most commonly supported signing mechanism for EOAs.
The signature is computed as:
ethSign, using the user’s private key to ECDSA-sign a message prefixed with"\x19Ethereum signed message:\n"and its lengthorderDigest, the order digest
ethSign signatures (ethers-js, web3py).
EIP-712
This signing method, also known as typed structured data signing, is the recommended signing method for EOAs, since the user will be able to see the full order data that is being signed in most wallet implementations.
The signature is computed as:
ecdsaSign, using the user’s private key to ECDSA-sign the messageorderDigest, the order digest
ERC-1271
This signing mechanism is the only option that can be used by smart contracts to provide off-chain signatures for orders.
In order to support smart-contract orders, the trading smart contract (the user) must implement the EIP-1271 interface.
When submitting an
ERC-1271 order to the API, the from field MUST be set to the address of the smart contract that will be signing the order. This is because the ERC-1271 signature is not an Ethereum signature, and thus the from field cannot be inferred from the signature.eip1271Signature, anybytesthat is a valid signature for the contract for the order. This signature is contract specific.
eip1271Signature must be valid for the orderDigest message, that is in Solidity:
PreSign
This is the only signing method that supports both EOA and smart-contract traders.
Together with submitting a PreSign order, the user must submit the order on-chain. This is done by calling the settlement contract setPreSignature function:
orderUid, the unique identifier of the ordertrue, whether the order is pre-signed or not (allows for cancelling pre-signed orders)
bytes string:
When submitting a
PreSign order to the API, the from field MUST be set to the address of the order owner. This is because the PreSign signature is not an Ethereum signature, and thus the from field cannot be inferred from the signature.If an order was already filled, then pre-signing it does not make it tradable again.