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

BLUR空投领取机制解析:交易嵌入Proof的原理与疑问

BLUR空投合约技术疑问解答

近期BLUR推出了需发布Twitter推文才能获得代币领取资格的空投活动,我分析了其合约代码,但仍有两个技术疑问。

领取函数代码

function claim(
        address account,
        uint256 amount,
        bytes32[] memory proof
    ) external {
        bytes32 leaf = keccak256(abi.encodePacked(account, amount));
        require(!claimed[leaf], "Airdrop already claimed");
        MerkleVerifier._verifyProof(leaf, merkleRoot, proof);
        claimed[leaf] = true;

        require(IERC20(token).transfer(account, amount), "Transfer failed");

        emit Claimed(account, amount);
    }

Merkle验证库代码

pragma solidity 0.8.17;

/**
 * @title MerkleVerifier
 * @dev Utility functions for Merkle tree computations
 */
library MerkleVerifier {
    error InvalidProof();

    /**
     * @dev Verify the merkle proof
     * @param leaf leaf
     * @param root root
     * @param proof proof
     */
    function _verifyProof(
        bytes32 leaf,
        bytes32 root,
        bytes32[] memory proof
    ) public pure {
        bytes32 computedRoot = _computeRoot(leaf, proof);
        if (computedRoot != root) {
            revert InvalidProof();
        }
    }

    /**
     * @dev Compute the merkle root
     * @param leaf leaf
     * @param proof proof
     */
    function _computeRoot(
        bytes32 leaf,
        bytes32[] memory proof
    ) public pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            computedHash = _hashPair(computedHash, proofElement);
        }
        return computedHash;
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(
        bytes32 a,
        bytes32 b
    ) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

疑问解答

1. 为何无法通过复制他人的proof绕过Twitter验证来作弊?

  • 每个proof对应唯一的账户地址+空投金额组合:合约会用你调用claim时传入的account和amount计算出leaf哈希值,这个值和原主人的leaf完全不同。用别人的proof验证自己的leaf,计算出的根节点会和合约里的merkleRoot不匹配,直接触发InvalidProof错误。
  • 已领取的记录会被锁定:合约里的claimed映射会记录每个leaf是否被领取过,就算你用原主人的地址和proof重复调用,只要对方已经领过,就会触发"Airdrop already claimed"的报错。

2. proof是如何生成的?在没有预言机的情况下,合约如何关联Twitter的用户行为?

  • proof生成逻辑:BLUR的后台会先收集所有完成Twitter任务(发推文)的用户地址和对应空投金额,把这些(account, amount)组合作为叶子节点构建Merkle树,计算出树的根节点merkleRoot并写入合约。每个用户的(account, amount)对应树里的一个叶子,后台会为这个叶子生成对应的Merkle证明(即proof数组),只有完成任务的用户才能从BLUR前端拿到自己的proof。
  • Twitter行为的关联方式:合约本身不直接验证Twitter行为,所有Twitter任务的验证都是在BLUR的中心化后台完成的。用户发推文后,后台会检查推文内容、发布者是否绑定了对应钱包地址等条件,验证通过后才会把专属proof返回给用户,让用户可以调用claim函数。合约只负责验证proof和merkleRoot的匹配性,以及地址、金额和proof的对应关系。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:37:48