第一价格密封拍卖智能合约全流程实现指南

前言

第一价格密封拍卖,作为一种"密封出价、价高者得、支付最高价"的经典竞价机制,天然契合智能合约的透明执行特性。本指南将完整呈现其链上实现:从开发阶段构建Commit-Reveal保密机制与保留价判定逻辑,到测试阶段验证拍卖流程、流拍处理及所有者特权,最终完成合约部署与链上验证。通过系统性的工程实践,为公平可信的链上资产竞拍提供可直接复用的技术方案。

概念

第一价格密封拍卖(First-price sealed-bid auction)是密封拍卖的一种形式,竞买人以独立密封方式提交报价,最高出价者按其所报价格成交付款

特征

  • 密封性:竞买人无法获知其他参与者的数量及出价信息,所有报价严格保密;
  • 一次性出价:每位竞买人只有一次报价机会,提交后不可更改;
  • "价高者得"原则 :拍卖师开启密封报价后,出价最高者赢得拍卖品;
  • 支付规则:获胜者需支付自己的出价金额(即最高出价),而非次高价;
  • 同步竞价:所有竞买人在规定时间内同时提交报价,采用独立密封方式;
  • 适用场景:多用于工程项目招标、大宗货物、土地房产等不动产交易以及资源开采权出让;

拍卖流程

第一阶段:准备与登记

  • 拍卖方发布拍卖公告,展示拍卖物品并提供相关说明资料
  • 潜在竞买人进行投标登记,提供身份证明等必要文件
  • 拍卖方设定保留价(底价),低于该价格的出价无效

第二阶段:密封投标

  • 竞买人在规定时间内填写报价单,将出价金额密封在信封中
  • 密封报价需包含竞买号、身份信息及报价金额
  • 竞买人提交密封报价并缴纳保证金

第三阶段:开标与成交

  • 拍卖师在指定时间当众开启所有密封信封
  • 按照"价高者得"原则确定最高出价者为中标人
  • 若出现相同报价,通常以投标在先(或编号在前)者为中标人

第四阶段:支付与交割

  • 中标者在规定时间内支付拍卖款项(即自己的最高出价)
  • 拍卖方将拍卖品交付给中标者,并办理相关手续
  • 未中标者的保证金予以退还

智能合约开发、测试、部署

智能合约

1. NFT智能合约
typescript 复制代码
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.22;

import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import {ERC721Burnable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import {ERC721Enumerable} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import {ERC721URIStorage} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract BoykaNFT is ERC721, ERC721Enumerable, ERC721URIStorage, ERC721Burnable, Ownable {
    uint256 private _nextTokenId;

    constructor(address initialOwner)
        ERC721("BoykaNFT", "BFT")
        Ownable(initialOwner)
    {}

    function safeMint(address to, string memory uri) public onlyOwner {
        uint256 tokenId = _nextTokenId++;
        _safeMint(to, tokenId);
        _setTokenURI(tokenId, uri);
    }

    // The following functions are overrides required by Solidity.

    function _update(address to, uint256 tokenId, address auth)
        internal
        override(ERC721, ERC721Enumerable)
        returns (address)
    {
        return super._update(to, tokenId, auth);
    }

    function _increaseBalance(address account, uint128 value)
        internal
        override(ERC721, ERC721Enumerable)
    {
        super._increaseBalance(account, value);
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override(ERC721, ERC721URIStorage)
        returns (string memory)
    {
        return super.tokenURI(tokenId);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC721, ERC721Enumerable, ERC721URIStorage)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }
}
2. 第一价格密封拍卖智能合约
ini 复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";

/**
 * @title 第一价格密封拍卖合约
 * @dev 采用 Commit-Reveal 机制确保出价保密性
 * @dev 新增功能:所有者特权 - 可随时强制结束拍卖 & 强制验证 reveal
 */
contract FirstPriceSealedAuction is Ownable, ReentrancyGuard, Pausable, IERC721Receiver {
    struct Auction {
        address seller;
        address nftContract;
        uint256 tokenId;
        uint256 reservePrice;      // 保留价
        uint256 commitDeadline;    // 承诺截止时间
        uint256 revealDeadline;     // 揭示截止时间
        address highestBidder;
        uint256 highestBid;
        bool ended;
        bool claimed;
    }

    struct BidCommitment {
        bytes32 commitment;  // 出价哈希
        bool hasCommitted;
        bool hasRevealed;
        uint256 amount;
    }

    // 拍卖ID => 拍卖信息
    mapping(uint256 => Auction) public auctions;
    // 拍卖ID => 竞标者地址 => 承诺信息
    mapping(uint256 => mapping(address => BidCommitment)) public commitments;
    // 记录已结束的拍卖数量
    uint256 public auctionCounter;

    // 事件定义
    event AuctionCreated(
        uint256 indexed auctionId,
        address indexed seller,
        address indexed nftContract,
        uint256 tokenId,
        uint256 reservePrice,
        uint256 commitDeadline,
        uint256 revealDeadline
    );

    event BidCommitted(
        uint256 indexed auctionId,
        address indexed bidder,
        bytes32 commitment
    );

    event BidRevealed(
        uint256 indexed auctionId,
        address indexed bidder,
        uint256 amount
    );

    event AuctionEnded(
        uint256 indexed auctionId,
        address indexed winner,
        uint256 winningBid
    );

    event NFTClaimed(uint256 indexed auctionId, address indexed winner);
    event FundsWithdrawn(uint256 indexed auctionId, address indexed seller, uint256 amount);

    /**
     * @dev 构造函数
     */
    constructor() Ownable(msg.sender) {}

    /**
     * @dev 创建新的拍卖
     */
    function createAuction(
        address nftContract,
        uint256 tokenId,
        uint256 reservePrice,
        uint256 commitDuration,
        uint256 revealDuration
    ) external whenNotPaused nonReentrant returns (uint256) {
        require(nftContract != address(0), "Invalid NFT contract");
        require(commitDuration > 0 && revealDuration > 0, "Invalid duration");
        
        // 转移NFT到合约
        IERC721(nftContract).safeTransferFrom(msg.sender, address(this), tokenId);

        uint256 auctionId = auctionCounter++;
        uint256 currentTime = block.timestamp;
        
        auctions[auctionId] = Auction({
            seller: msg.sender,
            nftContract: nftContract,
            tokenId: tokenId,
            reservePrice: reservePrice,
            commitDeadline: currentTime + commitDuration,
            revealDeadline: currentTime + commitDuration + revealDuration,
            highestBidder: address(0),
            highestBid: 0,
            ended: false,
            claimed: false
        });

        emit AuctionCreated(
            auctionId,
            msg.sender,
            nftContract,
            tokenId,
            reservePrice,
            currentTime + commitDuration,
            currentTime + commitDuration + revealDuration
        );

        return auctionId;
    }

    /**
     * @dev 提交出价承诺(哈希)
     */
    function commitBid(uint256 auctionId, bytes32 commitment) 
        external 
        payable 
        whenNotPaused 
        nonReentrant 
    {
        Auction storage auction = auctions[auctionId];
        require(block.timestamp < auction.commitDeadline, "Commit period ended");
        require(msg.value > 0, "Must send deposit");
        require(!commitments[auctionId][msg.sender].hasCommitted, "Already committed");

        commitments[auctionId][msg.sender] = BidCommitment({
            commitment: commitment,
            hasCommitted: true,
            hasRevealed: false,
            amount: msg.value
        });

        emit BidCommitted(auctionId, msg.sender, commitment);
    }

    /**
     * @dev 内部函数:处理 reveal 逻辑
     */
    function _processReveal(
        uint256 auctionId,
        address bidder,
        uint256 amount,
        uint256 secret
    ) internal {
        BidCommitment storage bid = commitments[auctionId][bidder];
        require(bid.hasCommitted, "No commitment found");
        require(!bid.hasRevealed, "Already revealed");
        
        // 验证哈希匹配
        bytes32 calculatedCommitment = keccak256(abi.encode(amount, secret));
        require(calculatedCommitment == bid.commitment, "Invalid commitment");

        bid.hasRevealed = true;
        bid.amount = amount;

        // 检查保证金是否足够
        require(bid.amount >= amount, "Insufficient deposit");

        // 记录最高出价
        Auction storage auction = auctions[auctionId];
        if (amount > auction.highestBid) {
            auction.highestBid = amount;
            auction.highestBidder = bidder;
        }

        emit BidRevealed(auctionId, bidder, amount);
    }

    /**
     * @dev 揭示实际出价(需等待 reveal 阶段)
     */
    function revealBid(
        uint256 auctionId,
        uint256 amount,
        uint256 secret
    ) external virtual whenNotPaused nonReentrant {
        Auction storage auction = auctions[auctionId];
        require(
            block.timestamp >= auction.commitDeadline && 
            block.timestamp < auction.revealDeadline,
            "Not reveal period"
        );
        
        _processReveal(auctionId, msg.sender, amount, secret);
    }

    /**
     * @dev 所有者特权:立即验证 reveal(无需等待时间)
     * @notice 允许所有者在任何时间(即使 commit 阶段未结束)强制验证某个竞标者的 reveal
     * @param auctionId 拍卖ID
     * @param bidder 要验证的竞标者地址
     * @param amount 竞标者声称的出价金额
     * @param secret 竞标者的秘密值
     */
    function forceRevealBid(
        uint256 auctionId,
        address bidder,
        uint256 amount,
        uint256 secret
    ) external onlyOwner nonReentrant {
        require(!auctions[auctionId].ended, "Auction already ended");
        _processReveal(auctionId, bidder, amount, secret);
    }

    /**
     * @dev 内部函数:结束拍卖
     */
    function _endAuction(uint256 auctionId) internal {
        Auction storage auction = auctions[auctionId];
        require(!auction.ended, "Auction already ended");
        
        auction.ended = true;

        // 如果最高出价低于保留价,则流拍
        if (auction.highestBid < auction.reservePrice || auction.highestBidder == address(0)) {
            emit AuctionEnded(auctionId, address(0), 0);
        } else {
            emit AuctionEnded(auctionId, auction.highestBidder, auction.highestBid);
        }
    }

    /**
     * @dev 正常结束拍卖(需等待揭示期结束)
     */
    function endAuction(uint256 auctionId) 
        external 
        nonReentrant 
    {
        Auction storage auction = auctions[auctionId];
        require(block.timestamp >= auction.revealDeadline, "Reveal period not ended");
        
        _endAuction(auctionId);
    }

    /**
     * @dev 所有者特权:强制结束拍卖
     */
    function forceEndAuction(uint256 auctionId) 
        external 
        onlyOwner 
        nonReentrant 
    {
        _endAuction(auctionId);
    }

    /**
     * @dev 胜标者领取NFT
     */
    function claimNFT(uint256 auctionId) external nonReentrant {
        Auction storage auction = auctions[auctionId];
        require(auction.ended, "Auction not ended");
        require(auction.highestBid >= auction.reservePrice, "Auction failed");
        require(msg.sender == auction.highestBidder, "Not winner");
        require(!auction.claimed, "NFT already claimed");

        auction.claimed = true;
        
        IERC721(auction.nftContract).safeTransferFrom(
            address(this),
            auction.highestBidder,
            auction.tokenId
        );

        emit NFTClaimed(auctionId, auction.highestBidder);
    }

    /**
     * @dev 卖家提取资金
     */
    function withdrawFunds(uint256 auctionId) external nonReentrant {
        Auction storage auction = auctions[auctionId];
        require(auction.ended, "Auction not ended");
        require(auction.highestBid >= auction.reservePrice, "Auction failed");
        require(msg.sender == auction.seller, "Only seller");
        
        uint256 amount = auction.highestBid;
        auction.highestBid = 0;

        (bool success, ) = payable(auction.seller).call{value: amount}("");
        require(success, "Transfer failed");

        emit FundsWithdrawn(auctionId, auction.seller, amount);
    }

    /**
     * @dev 退还失败竞标者的保证金
     */
    function refundDeposit(uint256 auctionId) external nonReentrant {
        Auction storage auction = auctions[auctionId];
        require(auction.ended, "Auction not ended");
        
        BidCommitment storage bid = commitments[auctionId][msg.sender];
        require(bid.hasCommitted, "No commitment");
        
        bool shouldRefund = !bid.hasRevealed || 
                            (bid.hasRevealed && msg.sender != auction.highestBidder) ||
                            auction.highestBid < auction.reservePrice;
                            
        require(shouldRefund, "Cannot refund");
        
        uint256 refundAmount = bid.amount;
        bid.amount = 0;

        (bool success, ) = payable(msg.sender).call{value: refundAmount}("");
        require(success, "Refund failed");
    }

    /**
     * @dev 获取拍卖详情
     */
    function getAuction(uint256 auctionId) external view returns (Auction memory) {
        return auctions[auctionId];
    }

    /**
     * @dev 获取竞标者承诺信息
     */
    function getCommitment(uint256 auctionId, address bidder) external view returns (BidCommitment memory) {
        return commitments[auctionId][bidder];
    }

    /**
     * @dev 紧急暂停合约
     */
    function pause() external onlyOwner {
        _pause();
    }

    /**
     * @dev 恢复合约
     */
    function unpause() external onlyOwner {
        _unpause();
    }

    /**
     * @dev 接收NFT的回调函数
     */
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external pure override returns (bytes4) {
        return this.onERC721Received.selector;
    }
}
编译指令
python 复制代码
npx hardhat compile

智能合约部署

1. NFT合约部署脚本
javascript 复制代码
module.exports=async ({getNamedAccounts,deployments})=>{
    const {deploy,log} = deployments;
    const {firstAccount,secondAccount} = await getNamedAccounts();
    console.log("firstAccount",firstAccount)
    const BoykaNFT=await deploy("BoykaNFT",{
        from:firstAccount,
        args: [firstAccount],//参数
        log: true,
    })
    console.log('nft合约',BoykaNFT.address)
};
module.exports.tags = ["all", "nft"];
2. 第一价格密封拍卖脚本
javascript 复制代码
module.exports=async ({getNamedAccounts,deployments})=>{
    const {deploy,log} = deployments;
    const {firstAccount,secondAccount} = await getNamedAccounts();
    console.log("firstAccount",firstAccount)
    const FirstPriceSealedAuction=await deploy("FirstPriceSealedAuction",{
        from:firstAccount,
        args: [],//参数
        log: true,
    })
    console.log('第一价格密封拍卖合约',FirstPriceSealedAuction.address)
};
module.exports.tags = ["all", "FirstPriceSealedAuction"];
部署指令
scss 复制代码
npx hardhat deploy --tags xxx,xxx  //(例如:nft,FirstPriceSealedAuction)

智能合约测试

第一价格密封拍卖拍卖流程测试脚本
javascript 复制代码
const {ethers,getNamedAccounts,deployments} = require("hardhat");
const { assert,expect } = require("chai");
describe("FirstPriceSealedAuction",function(){
    let FirstPriceSealedAuction;//合约
    let nft;//合约
    let addr1;
    let addr2;
    let addr3;
    let firstAccount//第一个账户
    let secondAccount//第二个账户
    let mekadate='ipfs://QmQT8VpmWQVhUhoDCEK1mdHXaFaJ3KawkRxHm96GUhrXLB';
    beforeEach(async function(){
        await deployments.fixture(["nft","FirstPriceSealedAuction"]);
        [addr1,addr2,addr3]=await ethers.getSigners();
       
        firstAccount=(await getNamedAccounts()).firstAccount;
        secondAccount=(await getNamedAccounts()).secondAccount;
        const nftDeployment = await deployments.get("BoykaNFT");
        nft = await ethers.getContractAt("BoykaNFT",nftDeployment.address);//已经部署的合约交互
        const FirstPriceSealedAuctionDeployment = await deployments.get("FirstPriceSealedAuction");//已经部署的合约交互
        FirstPriceSealedAuction = await ethers.getContractAt("FirstPriceSealedAuction",FirstPriceSealedAuctionDeployment.address);//已经部署的合约交互
    })
    describe("第一价格密封拍卖",function(){
        it("完整流程:创建、出价、揭示、结束、领取", async () => {
            // ==================== 准备阶段 ====================
            console.log("\n=== 准备阶段 ===");
            
            // 铸造NFT给firstAccount
            await nft.safeMint(firstAccount, mekadate);
            console.log("✓ NFT已铸造,所有者:", await nft.ownerOf(0));
            
            // firstAccount授权拍卖合约操作NFT
            const nftWithSeller = nft.connect(await ethers.getSigner(firstAccount));
            await nftWithSeller.approve(FirstPriceSealedAuction.target, 0);
            console.log("✓ NFT已授权给拍卖合约");

            // 创建拍卖:保留价1 ETH,commit和reveal各360秒
            const reservePrice = ethers.parseEther("1");
            const createAuctionTx = await FirstPriceSealedAuction.createAuction(
                nft.target,
                0,
                reservePrice,
                360,  // commit持续360秒
                360   // reveal持续360秒
            );
            await createAuctionTx.wait();
            
            const auctionId = 0;
            const auction = await FirstPriceSealedAuction.getAuction(auctionId);
            console.log("✓ 拍卖已创建,ID:", auctionId);
            console.log("  保留价:", ethers.formatEther(reservePrice), "ETH");
            console.log("  commit截止:", new Date(Number(auction.commitDeadline) * 1000).toLocaleString());
            console.log("  reveal截止:", new Date(Number(auction.revealDeadline) * 1000).toLocaleString());

            // ==================== Commit阶段 ====================
            console.log("\n=== Commit阶段 ===");
            
            // 准备出价:addr2出2 ETH,addr3出3 ETH
            const bidAmount2 = ethers.parseEther("2");
            const bidAmount3 = ethers.parseEther("3");
            const secret2 = 12345;
            const secret3 = 54321;
            
            // 计算承诺哈希
            const commitment2 = ethers.keccak256(
                ethers.AbiCoder.defaultAbiCoder().encode(
                    ["uint256", "uint256"],
                    [bidAmount2, secret2]
                )
            );
            const commitment3 = ethers.keccak256(
                ethers.AbiCoder.defaultAbiCoder().encode(
                    ["uint256", "uint256"],
                    [bidAmount3, secret3]
                )
            );
            
            // addr2提交承诺(发送2.5 ETH作为保证金)
            const auctionWithAddr2 = FirstPriceSealedAuction.connect(addr2);
            await auctionWithAddr2.commitBid(auctionId, commitment2, { value: ethers.parseEther("2.5") });
            console.log("✓ addr2已提交承诺,出价:", ethers.formatEther(bidAmount2), "ETH");
            
            // addr3提交承诺(发送3.5 ETH作为保证金)
            const auctionWithAddr3 = FirstPriceSealedAuction.connect(addr3);
            await auctionWithAddr3.commitBid(auctionId, commitment3, { value: ethers.parseEther("3.5") });
            console.log("✓ addr3已提交承诺,出价:", ethers.formatEther(bidAmount3), "ETH");
            
            // 验证承诺已存储
            const commitmentData2 = await FirstPriceSealedAuction.getCommitment(auctionId, addr2.address);
            const commitmentData3 = await FirstPriceSealedAuction.getCommitment(auctionId, addr3.address);
            assert.equal(commitmentData2.hasCommitted, true);
            assert.equal(commitmentData3.hasCommitted, true);
            
            // 快进时间到commit阶段结束
            await ethers.provider.send("evm_increaseTime", [400]); // 超过360秒
            await ethers.provider.send("evm_mine");
            console.log("⏰ 时间已推进到commit阶段结束");

            // ==================== Reveal阶段 ====================
            console.log("\n=== Reveal阶段 ===");
            
            // 验证当前时间已在reveal阶段
            const currentTime = await ethers.provider.getBlock('latest').then(b => b.timestamp);
            const auctionAfterCommit = await FirstPriceSealedAuction.getAuction(auctionId);
            assert.isAtLeast(currentTime, Number(auctionAfterCommit.commitDeadline));
            
            // addr2揭示出价
            await auctionWithAddr2.revealBid(auctionId, bidAmount2, secret2);
            console.log("✓ addr2已揭示出价");
            
            // addr3揭示出价
            await auctionWithAddr3.revealBid(auctionId, bidAmount3, secret3);
            console.log("✓ addr3已揭示出价");
            
            // 快进时间到reveal阶段结束
            await ethers.provider.send("evm_increaseTime", [400]);
            await ethers.provider.send("evm_mine");
            console.log("⏰ 时间已推进到reveal阶段结束");

            // ==================== 结束拍卖 ====================
            console.log("\n=== 结束拍卖 ===");
            
            // 结束拍卖
            await FirstPriceSealedAuction.endAuction(auctionId);
            console.log("✓ 拍卖已手动结束");
            
            // 验证拍卖状态和结果
            const endedAuction = await FirstPriceSealedAuction.getAuction(auctionId);
            assert.equal(endedAuction.ended, true);
            assert.equal(endedAuction.highestBidder, addr3.address);
            assert.equal(endedAuction.highestBid, bidAmount3);
            console.log("✓ 拍卖结果验证: addr3以", ethers.formatEther(bidAmount3), "ETH获胜");

            // ==================== 领取NFT ====================
            console.log("\n=== 领取NFT ===");
            
            // 验证auction.claimed状态
            assert.equal(endedAuction.claimed, false);
            
            // addr3领取NFT
            await auctionWithAddr3.claimNFT(auctionId);
            console.log("✓ 获胜者addr3已领取NFT");
            
            // 验证NFT所有权已转移
            const nftOwner = await nft.ownerOf(0);
            assert.equal(nftOwner, addr3.address);
            console.log("✓ NFT所有权已转移给addr3");

            // ==================== 提取资金 ====================
            console.log("\n=== 提取资金 ===");
            
            // 获取卖家提取前的余额
            const sellerBefore = await ethers.provider.getBalance(firstAccount);
            
            // 卖家提取拍卖资金
            const auctionWithSeller = FirstPriceSealedAuction.connect(await ethers.getSigner(firstAccount));
            const withdrawTx = await auctionWithSeller.withdrawFunds(auctionId);
            await withdrawTx.wait();
            console.log("✓ 卖家已提取拍卖资金");
            
            // 验证卖家余额增加(考虑gas费用)
            const sellerAfter = await ethers.provider.getBalance(firstAccount);
            const balanceIncrease = sellerAfter - sellerBefore;
            console.log("  卖家余额增加:", ethers.formatEther(balanceIncrease), "ETH");
            expect(balanceIncrease).to.be.closeTo(bidAmount3, ethers.parseEther("0.01")); // 考虑gas费用

            // ==================== 退还保证金 ====================
            console.log("\n=== 退还保证金 ===");
            
            // addr2(失败者)取回保证金
            const addr2BalanceBefore = await ethers.provider.getBalance(addr2.address);
            await auctionWithAddr2.refundDeposit(auctionId);
            const addr2BalanceAfter = await ethers.provider.getBalance(addr2.address);
            
            const addr2Refund = addr2BalanceAfter - addr2BalanceBefore;
            console.log("✓ 失败者addr2已取回保证金:", ethers.formatEther(addr2Refund), "ETH");
            expect(addr2Refund).to.be.closeTo(ethers.parseEther("2.5"), ethers.parseEther("0.01"));
            
            // 验证获胜者addr3不能取回保证金
            try {
                await auctionWithAddr3.refundDeposit(auctionId);
                assert.fail("获胜者不应该能取回保证金");
            } catch (error) {
                console.log("✓ 获胜者无法取回保证金(预期行为)");
            }
            
            console.log("\n🎉 完整拍卖流程测试通过!");
        });
    })
})
测试指令
bash 复制代码
npx hardhat test ./test/xxx.js //(例如:FirstPriceSealedAuction.js)

总结

至此,第一价格密封拍卖智能合约全流程实现已完成。该机制以"密封出价、价高者得"为核心,通过Commit-Reveal模式与保留价判定保障链上竞价公平性。开发基于OpenZeppelin构建安全架构,测试运用Hardhat完成多场景验证,最终部署为NFT竞拍提供透明可信的技术方案。

相关推荐
焦点链创研究所8 小时前
Fusaka升级对以太坊都有哪些好处?
人工智能·科技·web3·去中心化·区块链
Keegan小钢10 小时前
BlockLever实战营日志 #7 | 前端UI设计
web3·ai编程
Biteagle20 小时前
ZK + 比特币:B² Network 如何重塑 Layer2 的信任边界
web3·区块链
OpenBuild.xyz1 天前
对话 Nexus:从 DEX Alpha 到 APAC 生态的社区共建之路|AMA 回顾文章
web3·去中心化·区块链
Biteagle2 天前
BTC邮票:比特币链上艺术的「永恒封印」
区块链·智能合约
古城小栈2 天前
Java 在 Web3 时代的新定位
java·开发语言·web3
Biteagle2 天前
SNARK的信任魔法:从「毒性仪式」到以太坊隐私圣杯
web3·区块链·智能合约
Biteagle2 天前
Solana 架构深度解析:如何成为 Web3 的性能怪兽?
web3
古城小栈2 天前
Spring Boot 集成区块链:智能合约调用接口开发全解析
spring boot·区块链·智能合约