Signed data may be usable cross-chain
Signed order data may be re-usable cross-chain as the chain-id is not explicitly part of the signed data.\\nIt is also recommended to further harden the signature verification and validate that `v` and `s` are within expected bounds. `ecrecover()` returns `0x0` to indicate an error condition, therefore, a `signerAddress` or `recovered` address of `0x0` should explicitly be disallowed.\\nThe signed order data currently includes the EIP712 Domain Name `Mai Protocol` and the following information:\\n```\\nstruct Order {\\n    address trader;\\n    address broker;\\n    address perpetual;\\n    uint256 amount;\\n    uint256 price;\\n    /\\*\\*\\n \\* Data contains the following values packed into 32 bytes\\n \\* ╔════════════════════╤═══════════════════════════════════════════════════════════╗\\n \\* ║ │ length(bytes) desc ║\\n \\* ╟────────────────────┼───────────────────────────────────────────────────────────╢\\n \\* ║ version │ 1 order version ║\\n \\* ║ side │ 1 0: buy (long), 1: sell (short) ║\\n \\* ║ isMarketOrder │ 1 0: limitOrder, 1: marketOrder ║\\n \\* ║ expiredAt │ 5 order expiration time in seconds ║\\n \\* ║ asMakerFeeRate │ 2 maker fee rate (base 100,000) ║\\n \\* ║ asTakerFeeRate │ 2 taker fee rate (base 100,000) ║\\n \\* ║ (d) makerRebateRate│ 2 rebate rate for maker (base 100) ║\\n \\* ║ salt │ 8 salt ║\\n \\* ║ isMakerOnly │ 1 is maker only ║\\n \\* ║ isInversed │ 1 is inversed contract ║\\n \\* ║ │ 8 reserved ║\\n \\* ╚════════════════════╧═══════════════════════════════════════════════════════════╝\\n \\*/\\n    bytes32 data;\\n}\\n```\\n\\nSignature verification:\\n```\\nfunction isValidSignature(OrderSignature memory signature, bytes32 hash, address signerAddress)\\n    internal\\n    pure\\n    returns (bool)\\n{\\n    uint8 method = uint8(signature.config[1]);\\n    address recovered;\\n    uint8 v = uint8(signature.config[0]);\\n\\n    if (method == uint8(SignatureMethod.ETH\\_SIGN)) {\\n        recovered = ecrecover(\\n            keccak256(abi.encodePacked("\\x19Ethereum Signed Message:\\n32", hash)),\\n            v,\\n            signature.r,\\n            signature.s\\n        );\\n    } else if (method == uint8(SignatureMethod.EIP712)) {\\n        recovered = ecrecover(hash, v, signature.r, signature.s);\\n    } else {\\n        revert("invalid sign method");\\n    }\\n\\n    return signerAddress == recovered;\\n}\\n```\\n
Include the `chain-id` in the signature to avoid cross-chain validity of signatures\\nverify `s` is within valid bounds to avoid signature malleability\\n```\\nif (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n      revert("ECDSA: invalid signature 's' value");\\n }\\n```\\n\\nverify `v` is within valid bounds\\n```\\nif (v != 27 && v != 28) {\\n     revert("ECDSA: invalid signature 'v' value");\\n}\\n```\\n\\nreturn invalid if the result of `ecrecover()` is `0x0`
```\\nstruct Order {\\n    address trader;\\n    address broker;\\n    address perpetual;\\n    uint256 amount;\\n    uint256 price;\\n    /\\*\\*\\n \\* Data contains the following values packed into 32 bytes\\n \\* ╔════════════════════╤═══════════════════════════════════════════════════════════╗\\n \\* ║ │ length(bytes) desc ║\\n \\* ╟────────────────────┼───────────────────────────────────────────────────────────╢\\n \\* ║ version │ 1 order version ║\\n \\* ║ side │ 1 0: buy (long), 1: sell (short) ║\\n \\* ║ isMarketOrder │ 1 0: limitOrder, 1: marketOrder ║\\n \\* ║ expiredAt │ 5 order expiration time in seconds ║\\n \\* ║ asMakerFeeRate │ 2 maker fee rate (base 100,000) ║\\n \\* ║ asTakerFeeRate │ 2 taker fee rate (base 100,000) ║\\n \\* ║ (d) makerRebateRate│ 2 rebate rate for maker (base 100) ║\\n \\* ║ salt │ 8 salt ║\\n \\* ║ isMakerOnly │ 1 is maker only ║\\n \\* ║ isInversed │ 1 is inversed contract ║\\n \\* ║ │ 8 reserved ║\\n \\* ╚════════════════════╧═══════════════════════════════════════════════════════════╝\\n \\*/\\n    bytes32 data;\\n}\\n```\\n