How to Verify a Signed Message in Solidity

Leon Do
June 15, 2022


This is a practical tutorial on signing a message using MetaMask and then verifying it on-chain.

Here’s a demo:


-- CODE language-js line-numbers --


  • This is using the method personal_sign to prevent accidental transaction spending. This will relate to \x19Ethereum Signed Message:\n32 prefix found in the smart contract (below).
  • This is signing the hashed message.


Below is the required information to verify a signature. Use this in your smart contract.

-- CODE language-js line-numbers -- hashedMessage = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8 r = 0xb7cf302145348387b9e69fde82d8e634a0f8761e78da3bfa059efced97cbed0d s = 0x2a66b69167cafe0ccfc726aec6ee393fea3cf0e4f3f9c394705e0f56d9bfe1c9 v = 28

Smart Contract

Create the solidity contract.

-- CODE language-js line-numbers -- // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract Verify { 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; } }


  • Notice the prefix,\x19Ethereum Signed Message:\n32 is required to verify a signed message.
  • The prefix is hashed along with the message.
  • ecrecover should return the address of the signer.

Verify in Solidity

Input the hashed message and signature (r, s, v) to verify the address.

Use Case: Unity Gaming

  • Game developer creates a game, server, and smart contract that issues prizes if the player wins.
  • Player wins and tells the game developer they won.
  • Game server provides the player with a signature (explained above) that allows the user to claim. Think of this as a coupon.
  • Player then interacts with the contract and submits the signature (coupon) to claim their prize.

Example smart contract deployed by game developer:

-- CODE language-js line-numbers -- // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // game developer depoloys contract contract Verify { // game developer's account address public owner = 0xdD4c825203f97984e7867F11eeCc813A036089D1; // player claims price function claimPrize(bytes32 _hashedMessage, uint8 _v, bytes32 _r, bytes32 _s) public view returns (bool) { bytes memory prefix = "\x19Ethereum Signed Message:\n32"; bytes32 prefixedHashMessage = keccak256(abi.encodePacked(prefix, _hashedMessage)); address signer = ecrecover(prefixedHashMessage, _v, _r, _s); // if the signature is signed by the owner if (signer == owner) { // give player (msg.sender) a prize return true; } return false; } }

After winning, the player gets a signature (coupon) from the game server to claim their prize


Player parses the signature in Unity

-- CODE language-js line-numbers -- string signature = "0xb7cf302145348387b9e69fde82d8e634a0f8761e78da3bfa059efced97cbed0d2a66b69167cafe0ccfc726aec6ee393fea3cf0e4f3f9c394705e0f56d9bfe1c91c"; string r = signature.Substring(0, 66); string s = "0x" + signature.Substring(66, 64); int v = int.Parse(signature.Substring(130, 2), System.Globalization.NumberStyles.HexNumber);

The player can then interact with the smart contract to claim their prize. More information here.

true means the player received their prize


Got further questions? Hop into our Discord — we’ve got a thriving community ❤️‍🔥

#off-topic-lounge for general inquiries.

#gaming-general for gaming development chat.

#gaming-showcase to show your stuff.

About ChainSafe

ChainSafe is a leader in blockchain development and infrastructure solutions for web3. We’re working toward a more decentralized future by building client implementations for Ethereum, Filecoin, Polkadot, and Mina. We’re also maintaining the web3.js library, working on a Gaming SDK that connects NFTs to Unity, building a distributed cloud storage application, and bootstrapping a multi-chain bridge. To learn more, click here.

Want to help build the foundations of web3? Join us!

Have a question, comment, or suggestion? Drop into our Discord and join the conversation! We’re also always looking for talented people. Check out our open positions and get in touch ➡️➡️ [email protected]

More articles