I've skimmed through other similar topics but couldn't figure out a solution.
I'm getting the error 'MinimalForwarder': signature does not match request. This happens when I send my transaction without verifying signature.
It's worth noting that when I use
// const signature = await signer._signTypedData(TypedData.domain, types, request);
ethers.utils.verifyTypedData returns correct address, however the valid check(verify) returns false.
On the contrary if I use
const signature = await signer.provider.send('eth_signTypedData_v4',
[address, JSON.stringify(toSign)]);
ethers.utils.verifyTypedData returns wrong address and valid returns true.
Can someone point to me where I'm messing up?
const EIP712DomainType = [
{ name: 'name', type: 'string' },
{ name: 'version', type: 'string' },
{ name: 'chainId', type: 'uint256' },
{ name: 'verifyingContract', type: 'address' }
]
const ForwardRequestType = [
{ name: 'from', type: 'address' },
{ name: 'to', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'gas', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'data', type: 'bytes' }
]
const types = { ForwardRequestType };
const provider= new ethers.providers.Web3Provider(window.ethereum)
// Forwarder Contract
const forwarderContract = new ethers.Contract(forwarder, Forwarder.ForwarderAbi,
provider);
// gets nonce and chainID
const nonce = await forwarderContract.getNonce(address).then(nonce => nonce.toString());
const chainId = await forwarderContract.provider.getNetwork().then(n => n.chainId);
// Encode meta-tx request
const boxesInterface = new ethers.utils.Interface(PayFactory.abi);
const data = boxesInterface.encodeFunctionData('RedeemPayment', [code]);
const request = {
from: address, // current user address
to: contractAddress,
value: 0,
gas: 1e6,
nonce,
data
};
const TypedData = {
domain: {
name: 'MinimalForwarder',
version: '0.0.1',
chainId: chainId,
verifyingContract: forwarder,
},
primaryType: 'ForwardRequest',
types: {
EIP712Domain: EIP712DomainType,
ForwardRequest: ForwardRequestType
},
message: {
request
}
};
const toSign = { ...TypedData, message: request };
const signature = await signer._signTypedData(TypedData.domain, types, request);
const valid = await forwarderContract.verify(request, signature);
console.log("valid:", valid)
let recovered = await ethers.utils.verifyTypedData(TypedData.domain, types, request, signature);
console.log("recoveredAddress:", recovered)
if (recovered == address) {
console.log('verified TypedData ');
// Call server endpoint.
}
else {
console.log("Wrong recovered Addy")
}