Solidity--使用Merkletrees为链上合约添加白名单【降低gas消耗】

前言

目前的NFT市场越来越火爆,入场的人越来越多,在很多NFT在公开销售的之前就会有设置白名单,让这些白名单的人提前可以购买,又或者制定的白名单的人才能进行购买,从而达到他们饥饿营销的手段,那么关于Solidity如何实现白名单,并且可以最大程度降低我的gas费用,我这边在下面文章总结了两种方式给大家分享。


文章目录


一、实现方式分类

合约白名单主要的实现方式一般分两种:

第一种:

数组存储所有白名单的地址,当使用的时候for循环判断msg.sender是否是存在白名单中.

缺点:如果名单过多,会消耗极高的gas

第二种:

MerkleTrees验证

优点:大大的降低了gas费用

目前市面上最优的方案就是使用第二种Merkletrees验证方式

接下来我们看看如何实现Merkletrees验证方式原理和如何实现

二、原理分析

Merkletrees 有三个类型节点,叶节点, 父节点,根节点

验证原理:

将白名单丢到算法里,取出根节点【树根】 ,树根只是哈希值,但里面包含了 全部的地址的基因,将【树根】作为变量存储在智能合约上,当验证用户是否属于白名单中,我们把当前用户地址扔进算法,然后取出来哈希值,简称为【树叶】,再将树叶作为参数,传入 智能合约中判断,如果和树根基因匹配就证明是白名单中er址通过验证.

 三、具体实现

实现分两个版块前端和合约

  1.   前端代码:
const {MerkleTree} = require('merkletreejs');
const keccak256 = require('keccak256');
const {ethers} = require("hardhat");

async function main (){
  let whitelistAddresses = [
    '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4',
    '0xc12ae5Ba30Da6eB11978939379D383beb5Df9b33',
    '0x0a290c8cE7C35c40F4F94070a9Ed592fC85c62B9',
    '0x43Be076d3Cd709a38D2f83Cd032297a194196517',
    '0xC7FaB03eecA24CcaB940932559C5565a4cE9cFFb',
    '0xE4336D25e9Ca0703b574a6fd1b342A4d0327bcfa',
    '0xeDcB8a28161f966C5863b8291E80dDFD1eB78491',
    '0x77cbd0fa30F83a249da282e9fE90A86d7936FdE7',
    '0xc39F9406284CcAeB426D0039a3F6ADe14573BaFe',
    '0x16Beb6b55F145E4269279B82c040B7435f1088Ee',
    '0x900b2909127Dff529f8b4DB3d83b957E6aE964c2',
    '0xeA2A799793cE3D2eC6BcD066563f385F25401e95',
    '0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2',
    '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
]; 

    //1.叶子节点数据制作
    let  leafNodes =[]; 
    for(let test in whitelistAddresses ){
        let leafNode = ethers.utils.keccak256(whitelistAddresses[test]);
        leafNodes.push(leafNode)
    
    }
 
    //2.生成树根
    let tree = new MerkleTree(leafNodes, keccak256, { sortPairs: true });
    console.log('root: ', tree.getHexRoot());
     
    //3.生成叶子的proof(需要检验的地址)
    console.log(tree.getHexProof(leafNodes[0]));
}

main ()


2.合约代码:

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";

contract Test {
  bytes32 root ;
  address private owner;

  modifier onlyOwner (){
    require(owner == msg.sender,"you are not owner");
       _;
  }
  
  constructor() {
        owner =msg.sender;
  }
  //在前端把树根生成,传入合约.
  function setRoot(bytes32 _root) public onlyOwner{
          root = _root;
           
  }
  //把树叶的proof生成传入做校验
  function verify(bytes32[] memory proof) public view returns(bool result){
          bytes32 leaf = keccak256(abi.encodePacked(msg.sender));
        return MerkleProof.verify(proof,root,leaf);
  }
}

以上代码的使用流程:

第一步:

1.在js里面先确定好白名单的地址,再把地址都转换成哈希【叶节点】

2.然后【叶节点】生成树根

3.最后再生成验证数据.

第二步:

1.使用以上第一步生成的树根,传入合约设置root.

2. 最后校验地址是否是白名单的地址,就调用合约verify方法,如果返回true则说明,校验通过.

以上就是今天要讲的内容,希望可以帮助大家.


如果对以上的文章有任何问题欢迎指正或者讲清楚的地方需要了解可联系我

wc:luo425116243

猜你喜欢

转载自blog.csdn.net/qq_33842966/article/details/125230624