EIP-712 Signature Validation Failing with viem/wagmi & OZ ECDSA.recover Despite Matching Digests #4653
Unanswered
keplerdigitals-avia
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Hi everyone,
I'm encountering a persistent EIP-712 signature validation issue when trying to deploy an ERC1155 contract using a factory pattern (
ERC1155Factory.sol) and client-side signing.Context:
wagmi(useSignTypedDataAsync) andviem. Signing is handled by MetaMask.ethers.js(v6+). Receives the config data and the user's signature, then calls the factory contract.EIP712andECDSA.recoverfor validation. Deployed on Sepolia.noncefrom the factory contract via API.domain,types, andmessage(usingBigIntfornonce).signTypedDataAsync.name,symbol,baseURI,ownerAddress) and theuserSignatureto the backend API.ERC1155Factory.deploy1155ForUser(name, symbol, baseURI, ownerAddress, userSignature).estimateGaswithexecution reverted: "ERC1155Factory: Invalid signature or owner". This indicates therequire(signer == owner)check inside the contract (usingECDSA.recover) is failing during simulation.Debugging Steps & Findings:
viem), contract (ERC1155Factory.sol), and backend (ethers.js).nonceis fetched correctly and passed asBigInttosignTypedDataAsync.ERC1155Config) in the EIP-712 type. Suspecting encoding differences betweenviemand Solidity, we flattened the structure (DeployERC1155(string name, string symbol, string baseURI, address owner, uint256 nonce)) across the contract, frontend types/message, and backend validation/hashing.viem(hashTypedData) in the frontend exactly matches the digest calculated byethers.js(TypedDataEncoder.hash) in the backend just before the contract call.0xb6172fa3ab619dc3f892b1ebb95361f4b85700e1bdcee9f7a40bca019b975593vm.signon the calculated digest) for the exact same flattened contract logic pass successfully.ECDSA.recovercorrectly validates the signature generated byvm.sign.ecrecoverTest: Temporarily replacingECDSA.recoverwith nativeecrecoverin the contract also failed to recover the correct address from theviem/MetaMask signature, suggesting the issue lies with the signature format/interpretation itself. (We reverted back toECDSA.recoverafterwards).v): Thevvalue in the signature generated by the frontend appears correct (e.g.,0x1c= 28).Core Problem:
Even with matching EIP-712 digests (confirmed across
viemandethers.jswith the flattened structure) and using the standard OpenZeppelinECDSA.recover, the signature generated byviem/wagmi/MetaMask (0x840f...in the last test) is not considered valid by the contract duringestimateGas.Specific Data (from last failing attempt):
0x3360648578FAFB04Eb3B46FdE7A1CF62126B30BD0xBE1D984e4B9d66F4848a23423435762db7eAF1BD{ "name": "ERC1155Factory", "version": "1", "chainId": 11155111, "verifyingContract": "0x3360648578FAFB04Eb3B46FdE7A1CF62126B30BD" }{ "DeployERC1155": [ { "name": "name", "type": "string" }, { "name": "symbol", "type": "string" }, { "name": "baseURI", "type": "string" }, { "name": "owner", "type": "address" }, { "name": "nonce", "type": "uint256" } ] }{ "name": "try token", "symbol": "TRY", "baseURI": "https://mondomaine.xyz/api/nft/metadata/", "owner": "0xBE1D984e4B9d66F4848a23423435762db7eAF1BD", "nonce": "0" // Passed as BigInt(0) to signTypedDataAsync }0xb6172fa3ab619dc3f892b1ebb95361f4b85700e1bdcee9f7a40bca019b975593viem/MetaMask):0x840f97e4b53948734113c668ad6fcc12eca26ec4eb8c3925fe8bc128b6ebf37b4a5f549c75b2d34103c63e3ef3544e8161c9842f9a01734a1544613550739d201cQuestion:
Has anyone encountered similar validation failures with
ECDSA.recoverfor signatures generated byviem/wagmi/MetaMask, specifically when the EIP-712 digest is confirmed to be correct? Are there known subtle incompatibilities, signature formatting issues (beyond the standardvvalue), or encoding nuances that could cause this?Any insights or suggestions on how to further debug the signature interpretation on the EVM side would be greatly appreciated!
Thanks!
Beta Was this translation helpful? Give feedback.
All reactions