I use ERC20Permit token extension contract from openzeppelin for approval via signatures. In tests (hardhat testnet), I use ethers and signing typed data as described here: Ethers Signers.
So the problem is that when I trying to use permit function, it gives me 'Invalid signature' error. Permit function is called from standard erc721 contract and actually approves from account of erc20 tokens owner to erc721 contract address.
Relevant parts of code:
From ERC20Permit:
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "ERC20Permit: expired deadline");
bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));
bytes32 hash = _hashTypedDataV4(structHash);
address signer = ECDSA.recover(hash, v, r, s);
require(signer == owner, "ERC20Permit: invalid signature");
_approve(owner, spender, value);
}
From test.js file:
const types = {
Permit: [
{ name: 'owner', type: 'address' },
{ name: 'spender', type: 'address' },
{ name: 'value', type: 'uint256' },
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
}
const domain = {
name: "ERC20Permit-Token",
version: '1',
chainId: "31337",
verifyingContract: verifyAddr
}
const value = {
owner: _owner,
spender: _spender,
value: _value,
nonce: _nonce,
deadline: _deadline
}
const signer = _signer
const signature = await signer._signTypedData(domain, types, value)
All the arguments on chain and from js are equal (I compared it with hardhat/console.sol). BUT the addresses of recovered signer and owner differ (from where the error actually comes).
I suppose that data signing with ethers and hashing in ERCPermit somehow give different results, so the addresses are not equal. But I'm not sure.
What can be the problem here? Any help appreciated.
Best Answer
Is the chain Id correct?
Check with this one: 1337 or others IDK
I had done some research on permits and chainid is important too.