I have tried several ways of signing hashes with ethers.js which from front returns the signer correctly but in the contract deployed two years ago it is not able to pull the same signer.
This is the contract functións:
function notarizeWithSign(bytes32 hash, bytes memory sig) public {
require(hash != keccak256(abi.encodePacked("")), "hash vacio");
require(records[hash] == address(0), "Documento ya notariado");
require(notarizedAddress == msg.sender, "Usted no es el notario");
require(notarizedAddress == recoverSigner(prefixed(hash), sig), "Documento no firmado por el notario");
records[hash] = msg.sender;
timestamps[hash] = block.timestamp;
emit LogNotarized(hash, msg.sender, block.timestamp);
}
function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) {
(uint8 v, bytes32 r, bytes32 s) = splitSignature(sig);
return ecrecover(message, v, r, s);
}
/// signature methods.
function splitSignature(bytes memory sig)
internal
pure
returns (
uint8 v,
bytes32 r,
bytes32 s
)
{
require(sig.length == 65);
assembly {
// first 32 bytes, after the length prefix.
r := mload(add(sig, 32))
// second 32 bytes.
s := mload(add(sig, 64))
// final byte (first byte of the next 32 bytes).
v := byte(0, mload(add(sig, 96)))
}
return (v, r, s);
}
/// builds a prefixed hash to mimic the behavior of eth_sign.
function prefixed(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
This is one of the signature forms that works in front, the address address matches recoveredAddress, but the contract does not return the same result
// Obtener la cuenta del usuario
const signer = await provider.getSigner();
const address = await signer.getAddress();
const hash = ethers.hashMessage(inputData);
// Firma directamente el string (dato en bruto)
const signature = await signer.signMessage(hash);
// Verificar la firma (obtener la dirección del firmante) sobre el string original
const recoveredAddress = ethers.verifyMessage(hash, signature);
The solutions I have found are from ethers.js v5:
They ask to use the arraify
function which is now non-existent in v6.
A common case is to sign a hash. In this case, if the hash is a string, it must be converted to an array first, using the
arrayify
utility function.
What is the way to sign with ethers.js so that my contract can correctly get the signer?