You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何向特定NFT持有者空投代币/NFT并实现领取权限控制

特定NFT持有者代币发放实现方案

你在BAYC主合约里找不到对应ERC20分发逻辑是正常的:BAYC发放的ApeCoin采用独立合约部署,分发逻辑没有写入BAYC的ERC721主合约,项目方先在固定区块高度对所有BAYC/MAYC持有者持仓做快照,用Merkle白名单的方式做资格校验,不需要实时跨合约读持仓状态。

两类通用实现路径

根据使用场景选对应方案即可:

  • 快照+Merkle白名单方案
    适合一次性、固定总量的空投场景(比如BAYC发ApeCoin)。实现逻辑:先选定快照区块高度,拉取该高度下所有目标NFT持有者的地址、对应可领取额度,整理成列表生成Merkle树,把Merkle根存在空投合约中。用户申领时,从项目方的链下服务获取对应地址的Merkle证明,调用合约申领方法时提交证明,合约验证证明有效、对应地址/NFT未领取过,就发放对应代币。
    这个方案gas成本极低,不需要在链上做复杂的跨合约持仓校验,还能避免快照后NFT转卖导致的重复申领问题,是行业内空投的主流方案。核心要做hasClaimed映射标记领取状态,避免重复发放。
  • 实时跨合约校验方案
    适合你提到的「持有合约1NFT可领合约2NFT」的联动场景,不需要提前做快照,用户申领时合约实时校验持仓状态即可。

双ERC721联动免费申领实现要点

你要的两个ERC721合约联动的逻辑非常简单,核心是做好资格校验和防重复领取,最小实现逻辑如下:

  1. 部署合约2时,在构造函数中传入合约1的地址,存为不可变变量,减少后续调用gas。
  2. 不要按地址标记领取状态,要按合约1的NFT ID标记领取状态,避免一个NFT被转卖后新老持有者重复领取,也能支持持有多个合约1NFT的用户领多个合约2NFT。
  3. 核心申领逻辑参考最小可用代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC721.sol";

contract LinkedNFT is ERC721 {
    IERC721 public immutable originalNft;
    // 标记原NFT的tokenId是否已申领过新NFT
    mapping(uint256 => bool) public hasClaimed;
    uint256 public currentTokenId;

    constructor(address _originalNft) ERC721("LinkedNFT", "LNFT") {
        originalNft = IERC721(_originalNft);
    }

    /**
     * @param originalTokenId 用户持有的原NFT的tokenId
     */
    function claim(uint256 originalTokenId) external {
        // 校验调用者是原NFT对应ID的当前持有人
        require(originalNft.ownerOf(originalTokenId) == msg.sender, "Not the owner of target NFT");
        // 校验该原NFT未申领过
        require(!hasClaimed[originalTokenId], "This NFT already claimed");

        hasClaimed[originalTokenId] = true;
        _safeMint(msg.sender, currentTokenId);
        currentTokenId++;
    }
}
  1. 可选调整项:
    • 如果要求单地址不管持有多少原NFT都只能领1个,把hasClaimed的key改成用户地址即可,逻辑更简单。
    • 如果需要限制申领窗口,可以增加截止时间变量,超过时间后claim方法不可调用。
    • 如果要避免用户临时转NFT刷资格,可以增加持仓时长校验,要求用户持有原NFT超过一定区块数才能申领,普通场景不需要加这个逻辑。

注意避坑

不要在申领方法里尝试遍历查询用户的所有原NFT持仓,ERC721没有标准的批量查询持仓接口,遍历操作gas成本极高,还容易被恶意攻击。要么提前做快照用Merkle方案,要么让用户主动传入自己持有的原NFT ID,合约只做单个ID的所有权校验即可。
如果是发放固定总量的ERC20空投,优先选快照+Merkle方案,实时校验方案会导致用户可以在申领期临时买NFT刷空投,科学家刷量的成本极低,也没法保证发放的公平性。

内容的提问来源于stack exchange,提问作者Dakata

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:33:20