公开拍卖是展示智能合约复杂逻辑的经典案例。本文通过实现一个完整的拍卖系统,详细介绍拍卖的创建、竞价、结束等核心功能,帮助开发者理解如何构建复杂的智能合约应用。
一、什么是公开拍卖 1. 基本概念 公开拍卖是使用智能合约实现的去中心化拍卖系统,参与者可以出价竞拍物品,系统自动处理竞价、退款和结算。区块链的透明性和自动执行特性使其成为实现公平拍卖的理想平台。
2. 拍卖的特点 透明性 自动化 去中心化 二、如何设计拍卖系统 1. 核心功能 拍卖创建 竞价功能 接收出价 验证出价有效性 自动退款前一个出价 更新最高出价 结束拍卖 判断拍卖结束 处理最终结算 退款未中标者 转移物品所有权 2. 数据结构 拍卖结构 1 2 3 4 5 6 7 8 9 10 struct Auction { address seller uint256 startingPrice uint256 highestBid address highestBidder uint256 endTime bool ended mapping(address = > uint256) bids }
三、如何实现拍卖系统 1. 基础实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 简单拍卖: pragma solidity ^0.8 .0 ; contract SimpleAuction { address public seller; uint 256 public startingPrice; uint 256 public highestBid; address public highestBidder; uint 256 public endTime; bool public ended; mapping(address => uint 256) public pendingReturns; event AuctionCreated(uint 256 startingPrice, uint 256 endTime); event BidPlaced(address indexed bidder, uint 256 amount); event AuctionEnded(address indexed winner, uint 256 amount); constructor(uint 256 _startingPrice, uint 256 _duration) { seller = msg.sender; startingPrice = _startingPrice; endTime = block.timestamp + _duration; ended = false ; emit AuctionCreated(_startingPrice, endTime);
}
1 2 3 4 5 6 7 function bid( ) public payable { require( block.timestamp < endTime, "Auction ended" ) require( msg.value > highestBid, "Bid too low" ) require( msg.value >= startingPrice, "Bid below starting price" ) if ( highestBidder != address( 0 ) ) { pendingReturns[highestBidder] += highestBid
}
1 2 3 4 highestBid = msg.value;highestBidder = msg.sender; emit BidPlaced(msg.sender, msg.value);
}
1 2 3 4 5 function withdraw( ) public returns ( bool) { uint256 amount = pendingReturns[msg.sender] if ( amount > 0 ) { pendingReturns[msg.sender] = 0 payable( msg.sender) .transfer( amount)
}
}
1 2 3 4 5 6 7 8 function endAuction( ) public { require( block.timestamp >= endTime, "Auction not ended" ) require( !ended, "Auction already ended" ) ended = true emit AuctionEnded( highestBidder, highestBid) payable( seller) .transfer( highestBid)
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 #### 2 . 完整实现 功能完整拍卖: contract AuctionSystem { string itemDescription address[] bidders } Auction[] public auctions mapping( uint256 => mapping( address => uint256) ) public pendingReturns event AuctionCreated( uint256 indexed auctionId, address indexed seller, string itemDescription, uint256 startingPrice, uint256 endTime ) event BidPlaced( address indexed bidder, uint256 amount ) event AuctionEnded( address indexed winner, ) function createAuction( string memory itemDescription, uint256 duration ) public returns ( uint256) { uint256 auctionId = auctions.length auctions.push( ) Auction storage auction = auctions[auctionId] auction.seller = msg.sender auction.itemDescription = itemDescription auction.startingPrice = startingPrice auction.endTime = block.timestamp + duration auction.ended = false emit AuctionCreated( auctionId, msg.sender, itemDescription, startingPrice, auction.endTime) return auctionId } function bid( uint256 auctionId) public payable { require( block.timestamp < auction.endTime, "Auction ended" ) require( !auction.ended, "Auction already ended" ) require( msg.value > auction.highestBid, "Bid too low" ) require( msg.value >= auction.startingPrice, "Bid below starting price" ) if ( auction.highestBidder != address( 0 ) ) { pendingReturns[auctionId][auction.highestBidder] += auction.highestBid } if ( auction.bids[msg.sender] == 0 ) { auction.bidders.push( msg.sender) } auction.bids[msg.sender] += msg.value auction.highestBid = msg.value auction.highestBidder = msg.sender emit BidPlaced( auctionId, msg.sender, msg.value) } function withdraw( uint256 auctionId) public returns ( bool) { uint256 amount = pendingReturns[auctionId][msg.sender] pendingReturns[auctionId][msg.sender] = 0 } } function endAuction( uint256 auctionId) public { require( block.timestamp >= auction.endTime, "Auction not ended" ) auction.ended = true emit AuctionEnded( auctionId, auction.highestBidder, auction.highestBid) payable( auction.seller) .transfer( auction.highestBid) } function getAuction( uint256 auctionId) public view returns ( address seller, uint256 highestBid, address highestBidder, uint256 endTime, bool ended) { return ( auction.seller, auction.itemDescription, auction.startingPrice, auction.highestBid, auction.highestBidder, auction.endTime, auction.ended) } function getBidders( uint256 auctionId) public view returns ( address[] memory) { return auctions[auctionId].bidders } function getBid( uint256 auctionId, address bidder) public view returns ( uint256) { return auctions[auctionId].bids[bidder] }
四、如何使用拍卖系统 1. 创建拍卖 部署和创建 1 2 3 4 5 6 7 8 9 10 11 12 const AuctionSystem = await ethers.getContractFactory ("AuctionSystem" );const auction = await AuctionSystem .deploy ();await auction.deployed ();const tx = await auction.createAuction ( "Rare NFT Artwork" , ethers.utils.parseEther ("1.0" ), 7 * 24 * 60 * 60 );await tx.wait ();
2. 参与竞价 1 2 3 4 5 6 出价:await auction.bid (0 , { value: ethers.utils.parseEther ("2.0" ) });await auction.bid (0 , { value: ethers.utils.parseEther ("3.0" ) });
提取退款:
await auction.withdraw(0);
3. 结束拍卖 结束并结算: // 等待拍卖结束 await auction.endAuction(0);
// 卖家收到最高出价 // 未中标者可以提取退款
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 ## 五、应用场景 #### 1. NFT拍卖 #### 数字艺术品 - NFT拍卖 - 限量版收藏 - 创作者收益 - 版税分配 #### 实际案例 - OpenSea拍卖 - Foundation拍卖 - SuperRare拍卖 #### 2. 实物拍卖 #### 商品拍卖 - 二手商品 - 收藏品 - 奢侈品 - 特殊物品 #### 供应链 - 原材料拍卖 - 库存处理 - 批量采购 - 反向拍卖 #### 3. 服务拍卖 #### 服务竞标 - 开发服务 - 设计服务 - 咨询服务 - 专业服务 ## 六、功能扩展 #### 1. 反向拍卖
最低价获胜: contract ReverseAuction { uint256 public lowestBid; address public lowestBidder;
require(msg.value < lowestBid || lowestBid == 0, “Bid too high”); // 退款之前的出价 if (lowestBidder != address(0)) { pendingReturns[lowestBidder] += lowestBid;
lowestBid = msg.value; lowestBidder = msg.sender;
2. 密封投标 隐藏出价: contract SealedBidAuction { mapping(address => bytes32) public sealedBids; uint256 public revealDeadline;
function placeBid(bytes32 sealedBid) public {
sealedBids[msg.sender] = sealedBid; }
function revealBid(uint256 bid, bytes32 secret) public {
require(keccak256(abi.encodePacked(bid, secret)) == sealedBids[msg.sender], “Invalid reveal”); // 处理出价 }
降价拍卖: contract DutchAuction { uint256 public currentPrice; uint256 public priceDecrement; uint256 public timeInterval;
function getCurrentPrice() public view returns (uint256) {
uint256 elapsed = block.timestamp - startTime; uint256 decrements = elapsed / timeInterval; return startingPrice - (decrements * priceDecrement);
function buy() public payable {
require(msg.value >= currentPrice, “Insufficient payment”); // 完成购买
七、最佳实践 1. 安全考虑 重入保护: bool private locked;
modifier nonReentrant() { require(!locked, “Reentrant call”); locked = true; _; locked = false; }
function withdraw(uint256 auctionId) public nonReentrant { // 提取退款 }时间验证:solidity
批量操作: function batchWithdraw(uint256[] memory auctionIds) public { for (uint256 i = 0; i < auctionIds.length; i++) { withdraw(auctionIds[i]);
3. 用户体验 清晰接口: function getAuctionStatus(uint256 auctionId) view bool isActive, uint256 timeRemaining, uint256 currentBid, address currentBidder ) { isActive = block.timestamp < auction.endTime && !auction.ended; timeRemaining = auction.endTime > block.timestamp ? auction.endTime - block.timestamp : 0; currentBid = auction.highestBid; currentBidder = auction.highestBidder; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 ## 八、总结 公开拍卖是展示智能合约复杂逻辑的优秀案例。关键要点: #### 核心功能 - 拍卖创建 - 竞价机制 - 结束结算 #### 设计要点 - 防止重入攻击 - 时间控制 - 资金安全 - 状态管理 #### 应用场景 - 商品拍卖 - 服务竞标 - 各种拍卖场景 通过实现拍卖系统,可以深入理解智能合约的复杂逻辑,掌握状态管理、资金处理等核心技能,为开发更复杂的去中心化应用打下坚实基础。
本文标题: Solidity编程实战公开拍
发布时间: 2023年12月23日 00:00
最后更新: 2026年09月16日 05:40
原始链接: https://haoxiang.eu.org/7e389acb/
版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0 许可协议,转载请注明出处!