"Invalid signature" error in ERC20Permit (EIP2612)

Hey, Iā€™m using permit for approval via signatures for ERC20 Tokens, I need to execute the permit function from the back-end, I created a transaction but got ā€œInvalid signatureā€. Permit is called from ERC20 contract ABI.
Hereā€™s my code:

async function makePermit() {
	const contract = new web3.eth.Contract(erc20ABI, contractAddress);
	const privateKey = "";
	const privateAccount = web3.eth.accounts.privateKeyToAccount(privateKey);
	
	const permit = await contract.methods.permit(account, receiverAddress, 1000, 1988064000, 27, r, s);
	

	const tx = {
		from: privateAccount.address,
		to: account,
		data: permit.encodeABI(),
		gas: await permit.estimateGas({ from: privateAccount.address }),
		gasPrice: await web3.eth.getGasPrice()
	};

	const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);
	const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
	console.log(receipt);	
}

To split my signature I use this:

  const pureSig = sig.replace("0x", "")
  r = new Buffer.from(pureSig.substring(0, 64), 'hex')
  s = new Buffer.from(pureSig.substring(64, 128), 'hex')
  v = new Buffer.from((parseInt(pureSig.substring(128, 130), 16)).toString());

Error screenshot:

Any thoughts? Thanks.

maybe you can compare that data content with an example that already works to see what is different

Yeah been searching for some examples but didnā€™t found any!

maybe you can find a transaction on chain specific to that EIP

Update: the problem doesnā€™t come from the split signature values, values are correct.

Still searching since a couple of days, starting to lose hope. If anyone has an idea, please share it.

any idea now? ???

1 Like

Yes I fixed it. It works fine.

1 Like

Can you please share how you managed to fix this, am experiencing same issue while using ethers.js and domain, types, message from @1inch/permit-signed-approvals-utils
also tried with pure js without that sdk and same result, cant get it to work somehow, splitting signature using const {v,r,s} = ethers.utils.splitSignature so cant be signature splitting issue

data_to_sign = JSON.stringify({
    "types": {
        "EIP712Domain": [
            {
                "name": "name",
                "type": "string"
            },
            {
                "name": "version",
                "type": "string"
            },
            {
                "name": "chainId",
                "type": "uint256"
            },
            {
                "name": "verifyingContract",
                "type": "address"
            }
        ],
        "Permit": [
            {
                "name": "owner",
                "type": "address"
            },
            {
                "name": "spender",
                "type": "address"
            },
            {
                "name": "value",
                "type": "uint256"
            },
            {
                "name": "nonce",
                "type": "uint256"
            },
            {
                "name": "deadline",
                "type": "uint256"
            }
        ]
    },
    "primaryType": "Permit",
    "domain": {
        "name": "USD Coin",
        "verifyingContract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "chainId": 1,
        "version": "1"
    },
    "message": {
        "owner": owner,
        "spender": spender,
        "value": 10000,
        "nonce": 0,
        "deadline": 1992689033
    }
})
var params = [owner, dataToSign]
      const signature = await window.ethereum.request({"eth_signTypedData_v4", params, address}, 
        function (err, result) {
          if (err) return console.dir(err)
          if (result.error) {
            handleError({message: result.error})
          }
        })

      const { v,r,s } = ethers.utils.splitSignature(signature)

but after trying to execute on chain permit with all the gained values, it says invalid signature

There is a syntax issue here with the request object (and a few more after this):

const signature = await window.ethereum.request({"eth_signTypedData_v4", params, address}, 

Can you post your full code that youā€™re using?

Hey, try setting ā€œversionā€ to 2 instead of 1 in your domain section, since usdc is on version 2 this should fix the problem. (This worked for me)
PS: I think you should first follow what @alex said, since what he said can cause problems too.

yea, lol that was actually the whole issue, ty

1 Like