公开拍卖是展示智能合约复杂逻辑的经典案例。本文通过实现一个完整的拍卖系统,详细介绍拍卖的创建、竞价、结束等核心功能,帮助开发者理解如何构建复杂的智能合约应用。

Auction System


一、什么是公开拍卖

一、1 基本概念

公开拍卖是使用智能合约实现的去中心化拍卖系统,参与者可以出价竞拍物品,系统自动处理竞价、退款和结算。区块链的透明性和自动执行特性使其成为实现公平拍卖的理想平台。

二、2 拍卖的特点

1
透明性:
  • 所有出价公开
  • 竞价历史可查
  • 结果不可篡改
  • 提高信任度
1
自动化:
  • 自动处理竞价
  • 自动退款
  • 自动结算
  • 减少人工干预
1
去中心化:
  • 无需中介机构
  • 降低交易成本
  • 提高效率
  • 全球可访问

二、如何设计拍卖系统

三、1 核心功能

1
拍卖创建:
  • 设置拍卖物品
  • 设置起拍价
  • 设置拍卖时长
  • 设置卖家地址
1
竞价功能:
  • 接收出价
  • 验证出价有效性
  • 自动退款前一个出价
  • 更新最高出价
1
结束拍卖:
  • 判断拍卖结束
  • 处理最终结算
  • 退款未中标者
  • 转移物品所有权

四、2 数据结构

1
拍卖结构:
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
简单拍卖:
pragma solidity ^0.8.0;
1
2
3
4
5
6
7
contract SimpleAuction {
address public seller;
uint256 public startingPrice;
uint256 public highestBid;
address public highestBidder;
uint256 public endTime;
bool public ended;
1
mapping(address => uint256) public pendingReturns;
1
2
3
event AuctionCreated(uint256 startingPrice, uint256 endTime);
event BidPlaced(address indexed bidder, uint256 amount);
event AuctionEnded(address indexed winner, uint256 amount);
1
2
3
4
5
constructor(uint256 _startingPrice, uint256 _duration) {
seller = msg.sender;
startingPrice = _startingPrice;
endTime = block.timestamp + _duration;
ended = false;
1
emit AuctionCreated(_startingPrice, endTime);
}
1
2
3
4
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");
1
2
if (highestBidder != address(0)) {
pendingReturns[highestBidder] += highestBid;
    }
    
1
2
highestBid = msg.value;
highestBidder = msg.sender;
1
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
return true;
}
1
2
3
function endAuction() public {
require(block.timestamp >= endTime, "Auction not ended");
require(!ended, "Auction already ended");
1
2
ended = true;
emit AuctionEnded(highestBidder, highestBid);
1
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
部署和创建:
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"), // 起拍价 1 ETH
7 * 24 * 60 * 60 // 7天
);
await tx.wait();

八、2 参与竞价

1
2
3
出价:
// 出价 2 ETH
await auction.bid(0, { value: ethers.utils.parseEther("2.0") });
1
2
// 出价 3 ETH(自动退款之前的2 ETH)
await auction.bid(0, { value: ethers.utils.parseEther("3.0") });

`提取退款:```javascript

1
await auction.withdraw(0);
1
2
3
4
5
6
7
8
9
10

### 九、3 结束拍卖

结束并结算:
// 等待拍卖结束
await auction.endAuction(0);

// 卖家收到最高出价
// 未中标者可以提取退款

五、应用场景

十、1 NFT拍卖

1
数字艺术品:
  • NFT拍卖
  • 限量版收藏
  • 创作者收益
  • 版税分配
1
实际案例:
  • OpenSea拍卖
  • Foundation拍卖
  • SuperRare拍卖

十一、2 实物拍卖

1
商品拍卖:
  • 二手商品
  • 收藏品
  • 奢侈品
  • 特殊物品
1
供应链:
  • 原材料拍卖
  • 库存处理
  • 批量采购
  • 反向拍卖

十二、3 服务拍卖

1
服务竞标:
  • 开发服务
  • 设计服务
  • 咨询服务
  • 专业服务

六、功能扩展

十三、1 反向拍卖

1
2
3
4
最低价获胜:
contract ReverseAuction {
uint256 public lowestBid;
address public lowestBidder;
1
2
3
4
require(msg.value < lowestBid || lowestBid == 0, "Bid too high");
// 退款之前的出价
if (lowestBidder != address(0)) {
pendingReturns[lowestBidder] += lowestBid;
    }
1
2
lowestBid = msg.value;
lowestBidder = msg.sender;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

### 十四、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");
// 处理出价
}

十五、3 荷兰式拍卖

1
2
3
4
5
降价拍卖:
contract DutchAuction {
uint256 public currentPrice;
uint256 public priceDecrement;
uint256 public timeInterval;
1
2
3
4
function getCurrentPrice() public view returns (uint256) {
uint256 elapsed = block.timestamp - startTime;
uint256 decrements = elapsed / timeInterval;
return startingPrice - (decrements * priceDecrement);
}
1
2
3
function buy() public payable {
require(msg.value >= currentPrice, "Insufficient payment");
// 完成购买
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

## 七、最佳实践

### 十六、1 安全考虑

重入保护:
bool private locked;

modifier nonReentrant() {
require(!locked, "Reentrant call");
locked = true;
_;
locked = false;
}

function withdraw(uint256 auctionId) public nonReentrant {
// 提取退款
}
`时间验证:`solidity

十七、2 Gas优化

1
2
3
4
批量操作:
function batchWithdraw(uint256[] memory auctionIds) public {
for (uint256 i = 0; i < auctionIds.length; i++) {
withdraw(auctionIds[i]);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

### 十八、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
核心功能:
  • 拍卖创建
  • 竞价机制
  • 结束结算
1
设计要点:
  • 防止重入攻击
  • 时间控制
  • 资金安全
  • 状态管理
1
应用场景:
  • 商品拍卖
  • 服务竞标
  • 各种拍卖场景

通过实现拍卖系统,可以深入理解智能合约的复杂逻辑,掌握状态管理、资金处理等核心技能,为开发更复杂的去中心化应用打下坚实基础。

本文标题: Solidity编程实战公开拍

发布时间: 2023年12月23日 00:00

最后更新: 2025年12月30日 08:54

原始链接: https://haoxiang.eu.org/7e389acb/

版权声明: 本文著作权归作者所有,均采用CC BY-NC-SA 4.0许可协议,转载请注明出处!

× 喜欢就赞赏一下呗!
打赏二维码