@@ -32,9 +32,7 @@ import "./interfaces/IEventForwarder.sol";
3232library EngineBlox {
3333 // ============ VERSION INFORMATION ============
3434 bytes32 public constant PROTOCOL_NAME_HASH = keccak256 ("Bloxchain " );
35- uint8 public constant VERSION_MAJOR = 1 ;
36- uint8 public constant VERSION_MINOR = 0 ;
37- uint8 public constant VERSION_PATCH = 0 ;
35+ string public constant VERSION = "1.0.0 " ;
3836
3937 // ============ SYSTEM SAFETY LIMITS ============
4038 // These constants define the safety range limits for system operations
@@ -206,10 +204,25 @@ library EngineBlox {
206204 bytes32 public constant NATIVE_TRANSFER_OPERATION = keccak256 ("NATIVE_TRANSFER " );
207205
208206 // EIP-712 Type Hashes (selective meta-tx payload: MetaTxRecord = txId + params + payment only)
209- // These follow the standard EIP-712 convention so that eth_signTypedData_v4 and equivalent
207+ // These follow the canonical EIP-712 convention so that eth_signTypedData_v4 and equivalent
210208 // wallet typed-data signers can reproduce the same hashes when given matching type definitions.
211- bytes32 private constant META_TX_TYPE_HASH = keccak256 ("MetaTransaction(MetaTxRecord txRecord,MetaTxParams params,bytes data) " );
212- bytes32 private constant META_TX_RECORD_TYPE_HASH = keccak256 ("MetaTxRecord(uint256 txId,TxParams params,PaymentDetails payment) " );
209+ //
210+ // Canonical primary type string for MetaTransaction (primary type + all referenced types,
211+ // appended in alphabetical order by type name
212+ bytes32 private constant META_TX_TYPE_HASH = keccak256 (
213+ "MetaTransaction(MetaTxRecord txRecord,MetaTxParams params,bytes data) "
214+ "MetaTxParams(uint256 chainId,uint256 nonce,address handlerContract,bytes4 handlerSelector,uint8 action,uint256 deadline,uint256 maxGasPrice,address signer) "
215+ "MetaTxRecord(uint256 txId,TxParams params,PaymentDetails payment) "
216+ "PaymentDetails(address recipient,uint256 nativeTokenAmount,address erc20TokenAddress,uint256 erc20TokenAmount) "
217+ "TxParams(address requester,address target,uint256 value,uint256 gasLimit,bytes32 operationType,bytes4 executionSelector,bytes executionParams) "
218+ );
219+
220+ // Canonical primary type string for MetaTxRecord (primary type + its referenced types).
221+ bytes32 private constant META_TX_RECORD_TYPE_HASH = keccak256 (
222+ "MetaTxRecord(uint256 txId,TxParams params,PaymentDetails payment) "
223+ "PaymentDetails(address recipient,uint256 nativeTokenAmount,address erc20TokenAddress,uint256 erc20TokenAmount) "
224+ "TxParams(address requester,address target,uint256 value,uint256 gasLimit,bytes32 operationType,bytes4 executionSelector,bytes executionParams) "
225+ );
213226 bytes32 private constant TX_PARAMS_TYPE_HASH = keccak256 ("TxParams(address requester,address target,uint256 value,uint256 gasLimit,bytes32 operationType,bytes4 executionSelector,bytes executionParams) " );
214227 bytes32 private constant META_TX_PARAMS_TYPE_HASH = keccak256 ("MetaTxParams(uint256 chainId,uint256 nonce,address handlerContract,bytes4 handlerSelector,uint8 action,uint256 deadline,uint256 maxGasPrice,address signer) " );
215228 bytes32 private constant PAYMENT_DETAILS_TYPE_HASH = keccak256 ("PaymentDetails(address recipient,uint256 nativeTokenAmount,address erc20TokenAddress,uint256 erc20TokenAmount) " );
@@ -1713,13 +1726,15 @@ library EngineBlox {
17131726 * @return The EIP-712 digest (no prefix; use standard recovery)
17141727 */
17151728 function generateMessageHash (MetaTransaction memory metaTx ) private view returns (bytes32 ) {
1716- bytes32 domainSeparator = keccak256 (abi.encode (
1717- DOMAIN_SEPARATOR_TYPE_HASH,
1718- PROTOCOL_NAME_HASH,
1719- keccak256 (abi.encodePacked (VERSION_MAJOR, ". " , VERSION_MINOR, ". " , VERSION_PATCH)),
1720- block .chainid ,
1721- address (this )
1722- ));
1729+ bytes32 domainSeparator = keccak256 (
1730+ abi.encode (
1731+ DOMAIN_SEPARATOR_TYPE_HASH,
1732+ PROTOCOL_NAME_HASH,
1733+ keccak256 (bytes (VERSION)),
1734+ block .chainid ,
1735+ address (this )
1736+ )
1737+ );
17231738
17241739 TxParams memory tp = metaTx.txRecord.params;
17251740 bytes32 txParamsStructHash = keccak256 (abi.encode (
@@ -1778,11 +1793,20 @@ library EngineBlox {
17781793
17791794 /**
17801795 * @dev Recovers the signer from the EIP-712 digest and signature. Uses standard EIP-712 recovery (no message prefix).
1781- * Integrators must sign the digest returned by generateMessageHash as a raw hash—e.g.
1782- * account.sign({ hash: contractDigest }) or equivalent raw-hash signing API—with no
1783- * EIP-191/personal prefix, so signatures match this ecrecover(messageHash, v, r, s) verification.
1784- * Do NOT use personal_sign or generic eth_signTypedData_v4; the contract uses abi.encodePacked
1785- * for the domain version and a custom META_TX_TYPE_HASH, so those produce incompatible hashes.
1796+ *
1797+ * Integrators have two equivalent options:
1798+ * - Use typed-data signing (eth_signTypedData_v4 / signTypedData) with:
1799+ * - primaryType: MetaTransaction
1800+ * - domain: { name: "Bloxchain", version: "1.0.0", chainId, verifyingContract }
1801+ * - types: MetaTransaction, MetaTxRecord, TxParams, MetaTxParams, PaymentDetails
1802+ * In this case the wallet computes the same digest as generateMessageHash and signs it.
1803+ * - Sign the digest returned by generateMessageHash as a raw hash—e.g.
1804+ * account.sign({ hash: contractDigest }) or equivalent raw-hash signing API—with no
1805+ * EIP-191/personal prefix.
1806+ *
1807+ * In all cases, this function applies ecrecover(messageHash, v, r, s) over the raw EIP-712 digest.
1808+ * personal_sign / EIP-191-prefixed signatures remain incompatible.
1809+ *
17861810 * @param messageHash The EIP-712 digest (keccak256("\x19\x01" || domainSeparator || structHash))
17871811 * @param signature The signature (r, s, v)
17881812 * @return The address of the signer
0 commit comments