这是一个使用MetaMask签名消息,然后在链上进行验证的实用教程。
这里有一个demo:https://leon-do.github.io/ecrecover/
Sign Message
async function signMessage() {
if (!window.ethereum) return alert("Please Install Metamask");
// connect and get metamask account
const accounts = await ethereum.request({ method: "eth_requestAccounts" });
// message to sign
const message = "hello";
console.log({ message });
// hash message
const hashedMessage = Web3.utils.sha3(message);
console.log({ hashedMessage });
// sign hashed message
const signature = await ethereum.request({
method: "personal_sign",
params: [hashedMessage, accounts[0]],
});
console.log({ signature });
// split signature
const r = signature.slice(0, 66);
const s = "0x" + signature.slice(66, 130);
const v = parseInt(signature.slice(130, 132), 16);
console.log({ r, s, v });
}
需注意:
下面是验证签名所需的信息。可在智能合约中使用它。
hashedMessage = 0x1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8
r = 0xb7cf302145348387b9e69fde82d8e634a0f8761e78da3bfa059efced97cbed0d
s = 0x2a66b69167cafe0ccfc726aec6ee393fea3cf0e4f3f9c394705e0f56d9bfe1c9
v = 28
创建Solidity合约。
// 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;
}
}
需注意:
输入散列消息和签名(r, s, v)来验证地址。
游戏开发者部署智能合约的例子:
// 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;
}
}
获胜后,玩家会从游戏服务器获得一张签名(优惠券)来领取奖品。
0 xb7cf302145348387b9e69fde82d8e634a0f8761e78da3bfa059efced97cbed0d2a66b69167cafe0ccfc726aec6ee393fea3cf0e4f3f9c394705e0f56d9bfe1c91c
玩家在Unity中解析签名:
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);
然后,玩家可以与智能合约进行交互,领取奖品。
Source:https://www.web3.university/article/how-to-verify-a-signed-message-in-solidity
ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。
Layer 2道友 - 欢迎对Layer 2感兴趣的区块链技术爱好者、研究分析人与Gavin(微信: chinadefi)联系,共同探讨Layer 2带来的落地机遇。敬请关注我们的微信公众号 “去中心化金融社区”。