4

I would like to verify that a message is sent by a certain address, and to get the signer address I use the following function:

function VerifyMessage(bytes32 _hashedMessage, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {
    bytes memory prefix = "\x19Ethereum Signed Message:\n32";
    bytes32 prefixedHashMessage = keccak256(abi.encodePacked(prefix, _hashedMessage));
    address signer = ecrecover(prefixedHashMessage, _v, _r, _s);
    return signer;
}

But in order to prevent the replication of the signature I would like to use nonce. How can I integrate the nonce into my logic? I have also frontend and backend in my application if any management might be required from those sides.

1 Answer 1

4

You can have a look at how the permit function in the ERC20 is implemented: https://github.com/fractional-company/contracts/blob/master/src/OpenZeppelin/drafts/ERC20Permit.sol#L57-L60

Basically you need to have a mapping (address => uint256) public nonces; in your contract, that saves the last used nonce for every signer.

The signer must sign a message that contains the current nonce, so you have to add nonces[msg.sender] inside abi.encodePacked(prefix, _hashedMessage). I'm using msg.sender, but of course if you're checking against another user you need to pass its address.

Putting it all together:

function VerifyMessage(bytes32 _hashedMessage, uint8 _v, bytes32 _r, bytes32 _s) public pure returns (address) {
    bytes memory prefix = "\x19Ethereum Signed Message:\n32";

    bytes32 prefixedHashMessage = keccak256(abi.encodePacked(
        prefix,
        nonces[msg.sender],
        _hashedMessage
    ));
    address signer = ecrecover(prefixedHashMessage, _v, _r, _s);

    require(msg.sender == signer);
    nonces[msg.sender] += 1;

    return signer;
}
2
  • May I ask how am I going to use the nonce at the client side while hashing? I tried adding it to the beginning of the message but that doesn't seem to work. I am currently hashing the message using web3.utils.sha3, and signing it using web3.eth.personal.sign Sep 24, 2022 at 13:35
  • @AhmetYazıcı I would try hashing using web3.utils.soliditySha3(nonce, message)
    – 0xSanson
    Sep 24, 2022 at 14:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.