ecrecover return the different address from signer's #1419
-
Hello, Solidity Contract:
JavaScript: const { expect } = require("chai");
describe("TestSign", function() {
it("Recovered address according to messageHash", async function() {
// Get the ContractFactory and Signers here.
const TestSign= await ethers.getContractFactory("TestSign");
const [signer] = await ethers.getSigners();
const hardhatTestSign = await TestSign.deploy();
const test = 0x512345673440;
const testBytes = ethers.utils.arrayify(test);
const messageHash = ethers.utils.hashMessage(testBytes);
//Sign the messageHash
const messageHashBytes = ethers.utils.arrayify(messageHash);
const signature = await signer.signMessage(messageHashBytes);
//Recover the address from signature
const recoveredAddress = ethers.utils.verifyMessage(messageHashBytes, signature);
//Expect the recovered address is equal to the address of signer
expect(recoveredAddress).to.equal(signer.address);
console.log("singerAddress :", signer.address);
console.log("recovered address from ethers :", recoveredAddress);
//Recover the address from contract TestSign
const split = ethers.utils.splitSignature(signature);
const actualSigner = await hardhatTestSign.recover(messageHash, split.v, split.r, split.s);
console.log("recovered address from ecrecover:", actualSigner);
expect(actualSigner).to.equal(signer.address);
});
}); The first expection passing but the second expection failing. The following is version of solidity, ethers and hardhat. Could you please tell why this happen? Thanks. |
Beta Was this translation helpful? Give feedback.
Replies: 8 comments
-
A few quick questions. What backend are you using? Is it ganache or some such thing? Or a real network like Ropsten? Ganache used to have a bug where it ignored the v (yParity). Can you try this with a few different values and see if they all fail? Or only about 50% of them fail? |
Beta Was this translation helpful? Give feedback.
-
(Oh; also can you console.log all values; in case for example something is returning a checksum vs non-checksum address, they may be equal in nibbles, but not in case) |
Beta Was this translation helpful? Give feedback.
-
@ricmoo
I have tried different values of test, but all of them failed. |
Beta Was this translation helpful? Give feedback.
-
Can you console.log the signatures too? Also, one other thing I just noticed, your data should have quotes around it (i.e. |
Beta Was this translation helpful? Give feedback.
-
@ricmoo |
Beta Was this translation helpful? Give feedback.
-
Oh! As I was trying up a script to test this, I see a mistake. You are passing messageHash into If you use: const data = "0x512345673440";
console.log(ethers.utils.verifyMessage(ethers.utils.arrayify(data), signature));
// 0xDA606925E15d926B943b0a300c229f5E27190E9a You probably want to fix your Signing up, which then might make it all work: // Replace this:
// const signature = await signer.signMessage(messageHashBytes);
// with:
const signature = await signer.signMessage(arrayify(test)); Let me know if that helps. :) |
Beta Was this translation helpful? Give feedback.
-
(moving to discussions) |
Beta Was this translation helpful? Give feedback.
-
@ricmoo
The final conclusion:
verifyMessage require testBytes and signature
But ecrecover require hashMessage(testBytes) and signature
Thanks. |
Beta Was this translation helpful? Give feedback.
Oh! As I was trying up a script to test this, I see a mistake. You are passing messageHash into
verifyMessage
, but verifyMessage accept the data being signed (which it then hashes itself). You are effectively hashing the data twice. You just happen to signing and verifying again the data hashed twice, but passing the data hashed once to Solidity.If you use:
You probably want to fix your Signing up, which then might make it all work: