Cancel Order Signature Structure
To authorize order cancellation operations, users must generate a cryptographic signature compliant with the EIP-191 standard using the Ethereum Signed Message format.
The signature verification process uses the SignatureRecover library which implements the standard Ethereum message signing protocol. The message is constructed by concatenating the EVVM ID, action type, and parameters, then wrapped with the EIP-191 prefix.
Signed Message Format
The signature verification uses the SignatureRecover.signatureVerification function with the following structure:
SignatureRecover.signatureVerification(
Strings.toString(evvmID), // EVVM ID as string
"cancelOrder", // Action type
string.concat( // Concatenated parameters
Strings.toString(_nonce),
",",
AdvancedStrings.addressToString(_tokenA),
",",
AdvancedStrings.addressToString(_tokenB),
",",
Strings.toString(_orderId)
),
signature,
signer
);
Internal Message Construction
Internally, the SignatureRecover.signatureVerification function constructs the final message by concatenating:
string.concat(evvmID, ",", functionName, ",", inputs)
This results in a message format:
"{evvmID},cancelOrder,{nonce},{tokenA},{tokenB},{orderId}"
EIP-191 Message Hashing
The message is then hashed according to EIP-191 standard:
bytes32 messageHash = keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n",
Strings.toString(bytes(message).length),
message
)
);
This creates the final hash that the user must sign with their private key.
Message Components
The signature verification takes three main parameters:
1. EVVM ID (String):
- The result of
Strings.toString(evvmID) - Purpose: Identifies the specific EVVM instance
2. Action Type (String):
- Fixed value:
"cancelOrder" - Purpose: Identifies this as an order cancellation operation
3. Concatenated Parameters (String): The parameters are concatenated with comma separators:
3.1. Nonce (String):
- The result of
Strings.toString(_nonce) - Purpose: Provides replay protection for the P2P Swap transaction
3.2. Token A Address (String):
- The result of
AdvancedStrings.addressToString(_tokenA) - Purpose: Identifies the token that was offered in the original order
3.3. Token B Address (String):
- The result of
AdvancedStrings.addressToString(_tokenB) - Purpose: Identifies the token that was requested in the original order
3.4. Order ID (String):
- The result of
Strings.toString(_orderId) - Purpose: Specifies the unique ID of the order to be cancelled
Example
Here's a practical example of constructing a signature message for cancelling a swap order:
Scenario: User wants to cancel their order #3 in the USDC/ETH market
Parameters:
evvmID:1(EVVM instance ID)_nonce:25_tokenA:0xA0b86a33E6441e6e80D0c4C6C7527d72E1d00000(USDC)_tokenB:0x0000000000000000000000000000000000000000(ETH)_orderId:3
Signature verification call:
SignatureRecover.signatureVerification(
"1", // evvmID as string
"cancelOrder", // action type
"25,0xa0b86a33e6441e6e80d0c4c6c7527d72e1d00000,0x0000000000000000000000000000000000000000,3",
signature,
signer
);
Final message to be signed (after internal concatenation):
1,cancelOrder,25,0xa0b86a33e6441e6e80d0c4c6c7527d72e1d00000,0x0000000000000000000000000000000000000000,3
EIP-191 formatted message hash:
keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n134",
"1,cancelOrder,25,0xa0b86a33e6441e6e80d0c4c6c7527d72e1d00000,0x0000000000000000000000000000000000000000,3"
))
Concatenated parameters breakdown:
25- P2P Swap nonce for replay protection0xa0b86a33e6441e6e80d0c4c6c7527d72e1d00000- USDC token address (tokenA from original order)0x0000000000000000000000000000000000000000- ETH address (tokenB from original order)3- Order ID to be cancelled
Example with Different Token Pair
Scenario: User wants to cancel their order #7 in the MATE/USDC market
Parameters:
evvmID:1_nonce:42_tokenA:0x0000000000000000000000000000000000000001(MATE)_tokenB:0xA0b86a33E6441e6e80D0c4C6C7527d72E1d00000(USDC)_orderId:7
Final message to be signed:
1,cancelOrder,42,0x0000000000000000000000000000000000000001,0xa0b86a33e6441e6e80d0c4c6c7527d72e1d00000,7
Concatenated parameters breakdown:
42- P2P Swap nonce0x0000000000000000000000000000000000000001- MATE token address0xa0b86a33e6441e6e80d0c4c6c7527d72e1d00000- USDC token address7- Order ID to cancel
Signature Implementation Details
The SignatureRecover library performs signature verification in the following steps:
- Message Construction: Concatenates
evvmID,functionName, andinputswith commas - EIP-191 Formatting: Prepends
"\x19Ethereum Signed Message:\n"+ message length - Hashing: Applies
keccak256to the formatted message - Signature Parsing: Splits the 65-byte signature into
r,s, andvcomponents - Recovery: Uses
ecrecoverto recover the signer's address - Verification: Compares recovered address with expected signer
Signature Format Requirements
- Length: Exactly 65 bytes
- Structure:
[r (32 bytes)][s (32 bytes)][v (1 byte)] - V Value: Must be 27 or 28 (automatically adjusted if < 27)
Security Considerations
Order Ownership Validation
The signature alone does not prove order ownership. The contract performs additional validation:
- Signature Verification: Confirms the user signed the cancellation request
- Order Existence: Verifies the order exists in the specified market
- Ownership Check: Confirms the signer is the original order creator
- Nonce Validation: Ensures the nonce hasn't been used before
Market Identification
The token pair (tokenA, tokenB) must match the original order exactly:
- Token Addresses: Must be identical to the original order
- Market Resolution: Used to find the correct market for the order
- Order Lookup: Combined with orderId to locate the specific order
- Message Format: The final message follows the pattern
"{evvmID},{functionName},{parameters}" - EIP-191 Compliance: Uses
"\x19Ethereum Signed Message:\n"prefix with message length - Hash Function:
keccak256is used for the final message hash before signing - Signature Recovery: Uses
ecrecoverto verify the signature against the expected signer - String Conversion:
AdvancedStrings.addressToStringconverts addresses to lowercase hex with "0x" prefixStrings.toStringconverts numbers to decimal strings
- Order Identification: Requires both token pair and order ID to uniquely identify the order
- Nonce Independence: P2P Swap nonces are separate from EVVM payment nonces