无法验证智能合约的默克尔证明

发布于 2025-01-29 04:33:36 字数 2319 浏览 3 评论 0 原文

我使用的是隐形朋友NFT合同的副本(),我目前正在创建一个铸造页面。除了验证白名单铸造的默克尔证明外,一切都很好。

首先,我创建了一个2个ETH地址的数组,将默克尔树汇总在一起,计算root hash并在合同中进行更新:

let leafNodes;
let merkleTree;
let merkleProof;
let merkleRoot;
const whitelist = ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"];
leafNodes = whitelist.map(addr => keccak256(addr.concat("5")));
merkleTree = new MerkleTree(leafNodes, keccak256, { sortPairs: true });
merkleRoot = merkleTree.getRoot();
await contract.setMerkleProof(merkleRoot);

现在,当我创建默克尔证明并尝试在我的前端验证它时,它有效:

merkleProof = merkleTree.getHexProof(keccak256(owner.address.concat("5")));
console.log(merkleTree.verify(merkleProof, keccak256(owner.address.concat("5")), merkleRoot)) => returns "true"

但是,当我尝试使用生成的证据进行造币厂,它失败了:

await contract.mintListed(1, merkleProof, 5, { value: ethers.utils.parseEther("0.25") });
=> "Error: VM Exception while processing transaction: reverted with reason string 'Invalid proof'"

合同方,负责默克尔证明验证:

function _verify(
    bytes32[] calldata merkleProof,
    address sender,
    uint256 maxAmount
) private view returns (bool) {
    bytes32 leaf = keccak256(
        abi.encodePacked(sender, maxAmount.toString())
    );
    return MerkleProof.verify(merkleProof, merkleRoot, leaf);
}

这是返回错误的,因此失败了薄荷。我不知道为什么这样做,因为我在前端做同样的事情,而且运行良好。

和碎屑函数本身:

function mintListed(
    uint256 amount,
    bytes32[] calldata merkleProof,
    uint256 maxAmount
) public payable nonReentrant {
    address sender = _msgSender();

    require(isActive, "Sale is closed");
    require(
        amount <= maxAmount - _alreadyMinted[sender],
        "Insufficient mints left"
    );
    require(_verify(merkleProof, sender, maxAmount), "Invalid proof");
    require(msg.value == price * amount, "Incorrect payable amount");

    _alreadyMinted[sender] += amount;
    _internalMint(sender, amount);
}

当我从默克尔树中删除“ maxamount”并仅使用keccak256哈希德地址时,它可以正常工作,但我确实需要它。

我尝试了不同的方法在JS侧加盟字符串,但没有任何作用。

I'm using a copy of Invisible Friends NFT contract (https://etherscan.io/address/0x59468516a8259058bad1ca5f8f4bff190d30e066#code) and I'm currently in a process of creating a minting page. Everything is going well except validating merkle proofs for whitelist minting.

First, I created an array of 2 ETH addresses, put together merkle tree, calculate root hash and update it on the contract:

let leafNodes;
let merkleTree;
let merkleProof;
let merkleRoot;
const whitelist = ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"];
leafNodes = whitelist.map(addr => keccak256(addr.concat("5")));
merkleTree = new MerkleTree(leafNodes, keccak256, { sortPairs: true });
merkleRoot = merkleTree.getRoot();
await contract.setMerkleProof(merkleRoot);

Now, when I create merkle proof and try to verify it on my front-end, it works:

merkleProof = merkleTree.getHexProof(keccak256(owner.address.concat("5")));
console.log(merkleTree.verify(merkleProof, keccak256(owner.address.concat("5")), merkleRoot)) => returns "true"

However, when I try to mint using the generated proof, it fails:

await contract.mintListed(1, merkleProof, 5, { value: ethers.utils.parseEther("0.25") });
=> "Error: VM Exception while processing transaction: reverted with reason string 'Invalid proof'"

Contract side which is responsible for merkle proof verification:

function _verify(
    bytes32[] calldata merkleProof,
    address sender,
    uint256 maxAmount
) private view returns (bool) {
    bytes32 leaf = keccak256(
        abi.encodePacked(sender, maxAmount.toString())
    );
    return MerkleProof.verify(merkleProof, merkleRoot, leaf);
}

This returns false, therefore failing the mint. I can't figure out why it's doing this, since I'm doing the same thing on my front-end and it's working well.

And mintListed function itself:

function mintListed(
    uint256 amount,
    bytes32[] calldata merkleProof,
    uint256 maxAmount
) public payable nonReentrant {
    address sender = _msgSender();

    require(isActive, "Sale is closed");
    require(
        amount <= maxAmount - _alreadyMinted[sender],
        "Insufficient mints left"
    );
    require(_verify(merkleProof, sender, maxAmount), "Invalid proof");
    require(msg.value == price * amount, "Incorrect payable amount");

    _alreadyMinted[sender] += amount;
    _internalMint(sender, amount);
}

When I remove the "maxAmount" from merkle tree and using only keccak256 hashed addresses, it works, but I do need it.

I tried different ways to concatenate strings on JS side, but nothing works.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

£噩梦荏苒 2025-02-05 04:33:36

我设法解决了这个问题。

因此,

keccak256(addr.concat("5"))); 

keccak256(ethers.utils.solidityPack(["address", "string"], [addr, "5"]))

现在使用它可以很好地工作!

I managed to fix the issue.

So instead of

keccak256(addr.concat("5"))); 

I used

keccak256(ethers.utils.solidityPack(["address", "string"], [addr, "5"]))

Now it works fine!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文