Basically on verifying the signature with the generated hash of the signed message, I'm getting the correct signer on JS, but not on Solidity.
JS Code (According to Keir Finlow-Bates' suggestion):
async function signHello() {
// Encode parameters
const encodedParams = ethers.utils.defaultAbiCoder.encode(
['string'],
['hello']
);
const hash = ethers.utils.hexlify(ethers.utils.toUtf8Bytes(encodedParams));
const prefixedHash = ethers.utils.solidityKeccak256(
['string', 'bytes'],
['\x19Ethereum Signed Message:\n' + hash.length, hash]
);
console.log("Hash: ", prefixedHash)
// Sign the message
const signature = await wallet.signMessage(ethers.utils.arrayify(prefixedHash));
console.log("Signature:", signature);
return {'hash': prefixedHash, 'signature': signature}
}
function getSigner(hash, signature) {
const digest = ethers.utils.keccak256(ethers.utils.solidityPack(['string', 'bytes32'], ["\x19Ethereum Signed Message:\n32", hash]));
return ethers.utils.recoverAddress(digest, signature);
}
signHello().then((res) => {
console.log(getSigner(res.hash, res.signature)) // getting the correct signer address here
})
JS Code:
const ethers = require('ethers');
const provider = new ethers.providers.JsonRpcProvider("https://polygon-mumbai.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY");
const privateKey = "YOUR_ACCOUNT_PRIVATE_KEY";
const wallet = new ethers.Wallet(privateKey, provider);
async function signHello() {
// Encode parameters
const encodedParams = ethers.utils.defaultAbiCoder.encode(
['string'],
['hello']
);
let hash = ethers.utils.keccak256(encodedParams);
console.log("Hash: ", hash)
// Sign the message
const signature = await wallet.signMessage(hash);
console.log("Signature:", signature);
return {'hash': hash, 'signature': signature}
}
function getSigner(hash, signature) {
return ethers.utils.verifyMessage(hash, signature)
// Using the code below, getting the same incorrect signer address as getting from the getSigner() solidity function
// const digest = ethers.utils.keccak256(ethers.utils.solidityPack(['string', 'bytes32'], ["\x19Ethereum Signed Message:\n32", hash]));
// return ethers.utils.recoverAddress(digest, signature);
}
signHello().then((res) => {
console.log(getSigner(res.hash, res.signature)) // getting the correct signer address here
})
Solidity Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
contract Signer {
function getHash() public pure returns (bytes32) {
return keccak256(
abi.encode(
"hello"
)
);
}
function getSigner(bytes32 _hash, bytes memory _signature)
public
pure
returns (address)
{
bytes32 r;
bytes32 s;
uint8 v;
if (_signature.length != 65) {
return address(0);
}
assembly {
r := mload(add(_signature, 32))
s := mload(add(_signature, 64))
v := byte(0, mload(add(_signature, 96)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return address(0);
} else {
return
ecrecover(
keccak256(
abi.encodePacked(
"\x19Ethereum Signed Message:\n32",
_hash
)
),
v,
r,
s
);
}
}
function getSignerUsingOpenzeppelin(bytes32 _hash, bytes memory _signature)
public
pure
returns (address)
{
return ECDSA.recover(_hash, _signature);
}
}
PS, I'm getting the same hash for hello in both JS as well as Solidity codes, i.e., 0x984002fcc0ca639f96622add24c2edd2fe72c65e71ca3faa243e091e0bc7cdab.
Using the JS Code (According to Keir Finlow-Bates' suggestion), getting this hash:
0xd9f807e25c27377c0d87443b1736dfaa5c3a582d7023b696acf4dde098ee659e
Which is when used with the corresponding generated signature, returning the correct/expected signer.
But, now the question is how to generate the same hash in solidity?
As keccak256(abi.encode("hello")) is returning a different hash i.e., 0x984002fcc0ca639f96622add24c2edd2fe72c65e71ca3faa243e091e0bc7cdab.
– SYED ASAD KAZMI Mar 02 '24 at 08:57return ECDSA.recover(_hash, _signature);Usually people complain they're not recovering the right signature because they're not adding the signed message prefix. You either have to do it explicitly, or use both signing and recovery functions that do it for you. I suspect you're mixing them up here.
– Keir Finlow-Bates Mar 03 '24 at 15:130xbd4e3e4488312fbdbebf9d859581be67532efbb0152c94e698f9829aa83b4a3f, but still how to get the same hash using solidity, that's where I'm stuck now. – SYED ASAD KAZMI Mar 03 '24 at 19:02