MekaVerse NFT智能合约ECDSA白名单mint实现原理与使用方法咨询
ECDSA白名单机制原理与代码解析
底层原理基础
ECDSA是椭圆曲线数字签名算法,属于非对称加密体系,核心特性是:
- 签名方持有私钥,可对任意消息生成唯一签名
- 任意第三方可通过消息、签名,反推出签名方的公钥(对应以太坊地址)
- 无法通过签名、消息反推私钥,也无法在没有私钥的情况下伪造有效签名
MekaVerse就是用这个特性实现无链上存储的白名单,比传统的把白名单地址存在合约数组里的方案省90%以上的gas成本。
核心代码逻辑拆解
首先看你提到的签名校验函数:
function signatureWallet(address wallet, uint256[] memory _tokensId, uint256 _timestamp, bytes memory _signature) public view returns (address){ return ECDSA.recover(keccak256(abi.encode(wallet, _tokensId, _timestamp)), _signature); }
这段的执行步骤是:
- 把三个参数「调用者钱包地址
wallet、要铸造的tokenId数组_tokensId、时间戳_timestamp」用abi.encode编码成统一格式的字节流 - 用
keccak256把字节流哈希成固定32字节的消息摘要 - 调用OpenZeppelin的
ECDSA.recover方法,传入消息摘要和用户提交的签名,就能计算出这个签名对应的签名方以太坊地址
然后看mint函数里的校验逻辑:
address signerOwner = signatureWallet(wallet,_tokensId,_timestamp,_signature); require(signerOwner == owner(), "Not authorized to mint");
这段逻辑就是判断刚才反推出来的签名方地址,是不是等于合约的官方owner地址:
- 如果相等,说明你提交的签名是官方用自己的私钥签发的,你属于白名单用户
- 如果不相等,说明签名是伪造的,或者参数被篡改了,直接拒绝mint
这里有三个隐藏的安全设计你要注意:
- 签名和调用者钱包地址绑定:别人拿到你的签名也用不了,因为他调用的时候
wallet参数是他自己的地址,算出来的哈希和你签名用的哈希不一样,验签就会失败 - 签名和要铸造的tokenId绑定:你不能拿允许你mint 1、2号token的签名去mint 3、4号
- 签名有有效期:后面的
require(block.timestamp >= _timestamp - 30, "Out of time")就是限制签名的有效时间,防止签名被永久滥用
实际使用流程
项目方侧
- 提前统计所有白名单用户的钱包地址,以及每个用户允许铸造的tokenId范围、签名有效时间
- 用合约owner对应的私钥,对每个用户的「钱包地址+允许的tokenId数组+有效时间戳」做ECDSA签名
- 把对应的
_tokensId、_timestamp、_signature三个参数发放给对应的白名单用户
用户侧
- 拿到官方发放的三个参数
- 调用合约的mint函数,传入三个参数,支付对应的mint费用,就可以通过校验完成铸造
内容的提问来源于stack exchange,提问作者Ben BK
相关产品推荐
相关产品推荐

