You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix: Import safeKeccak256 from Crypto module instead of redefining it
Risk: Maintenance — if the logic diverges between the two copies
2. Split padHex into padLeft / padRight
Where:Crypto.daml:18-19
Why:padHex always left-pads, which is correct for uint, int, address but wrong for bytes1–bytes31 (must be right-padded per EIP-712 spec [ED-8/ED-8a])
Fix: Rename to padLeft or create both padLeft/padRight. Makes padding direction explicit and prevents silent bugs if bytesN types are added later
3. Validate bytes32 input length
Where:RequestId.daml:62 — padHex requestId 32
Why: A shorter-than-32-byte requestId would be silently left-padded, which is semantically wrong for a bytes32 field (should be right-padded or rejected)
Fix: Add an assertion that byteCount requestId == 32 before use
Test Coverage
4. Add official EIP-712 spec test vectors (Mail/Person example)
Why: Current tests use viem as oracle. The spec includes canonical vectors that prove encoding correctness independent of any library
Why: Type strings are hardcoded. A general function would take type name + fields + referenced types and produce the string with correct alphabetical ordering of referenced types
When: Only needed if you add more struct types beyond the current three
8. Add missing EIP-712 type encodings
bool — false = uint256(0), true = uint256(1)
intN — sign-extend to 256 bits (two's complement)
bytesN (N < 32) — right-pad to 32 bytes
Fixed-size arrays Type[n] — encode like struct with N members, then keccak256
Struct arrays — hashStruct each element, concatenate, keccak256
When: Only needed if your domain types expand to use these
9. Support full domain separator fields
Add optional chainId (uint256), verifyingContract (address), salt (bytes32)
When: Only needed if signature verification moves on-chain or cross-domain
EIP-712 Implementation Improvements
Code Quality
1. Remove duplicated
safeKeccak256RequestId.daml:64redefinessafeKeccak256locally insidecomputeResponseHashsafeKeccak256fromCryptomodule instead of redefining it2. Split
padHexintopadLeft/padRightCrypto.daml:18-19padHexalways left-pads, which is correct foruint,int,addressbut wrong forbytes1–bytes31(must be right-padded per EIP-712 spec [ED-8/ED-8a])padLeftor create bothpadLeft/padRight. Makes padding direction explicit and prevents silent bugs ifbytesNtypes are added later3. Validate
bytes32input lengthRequestId.daml:62—padHex requestId 32requestIdwould be silently left-padded, which is semantically wrong for abytes32field (should be right-padded or rejected)byteCount requestId == 32before useTest Coverage
4. Add official EIP-712 spec test vectors (Mail/Person example)
encodeType('Mail')"Mail(Person from,Person to,string contents)Person(string name,address wallet)"typeHash('Mail')0xa0cedeb2dc280ba39b857546d74f5549c3a1d7bdc2dd96bf881f76108e23dac2hashStruct(mail)0xc52c0ee5d84264471806290a3f2c4cecfc5490626bf912d01f240d7a274b371edomainSeparator0xf2cee375fa42b42143804025fc449deafd50cc031ca257e0b194a650a912090fsignHash0xbe609aee343fb3c4b28e1df9e632fca64fcfaede20f02e86244efddf30957bd2{name: "Ether Mail", version: "1", chainId: 1, verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"}Mail{from: Person{name: "Cow", wallet: 0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826}, to: Person{name: "Bob", wallet: 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB}, contents: "Hello, Bob!"}5. Add vector-based assertions to existing Daml tests
TestRequestId.damltests fortestHashText,testHashBytesList,testHashEvmParams, etc.6. Add empty array vector test
TestRequestId.damlhashBytesList []returnskeccak256Empty— verify this matcheskeccak256("")=c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470explicitlyFuture Generalization (if needed)
7. Build a general
encodeTypefunction8. Add missing EIP-712 type encodings
bool—false=uint256(0),true=uint256(1)intN— sign-extend to 256 bits (two's complement)bytesN(N < 32) — right-pad to 32 bytesType[n]— encode like struct with N members, then keccak256hashStructeach element, concatenate, keccak2569. Support full domain separator fields
chainId(uint256),verifyingContract(address),salt(bytes32)