区块链拍卖平台开发:合约所有权

基本代码

1.EcommerceStore.sol

合约中有关于商品信息的记录,EcommerceStoreEcommerceStoreV2 合约管理商品的生命周期,包括从添加到拍卖结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct Product {
uint256 id;
string name;
string category;
string imageLink;
string descLink;
uint256 auctionStartTime;
uint256 auctionEndTime;
uint256 startPrice;
ProductStatus status;
ProductCondition condition;
address highestBidder; // 记录最高出价者
uint256 highestBid; // 最高出价金额
mapping(address => mapping(bytes32 => Bid)) bids;
uint256 totalBids;
}

在商品的结构体中,highestBidder 字段记录了拍卖过程中出价最高的用户。这是商品所有权转移的一个潜在指示器。

revealBid 函数中,合约会确定最高的有效出价者。

揭示出价以及确认最高出价者:

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
function revealBid(
uint256 _productId,
string memory _amount,
string memory _secret
) public {
Product storage product = stores[productIdInStore[_productId]][_productId];
require(block.timestamp > product.auctionEndTime); // 确保在拍卖结束后
bytes32 sealedBid = keccak256(abi.encode(_amount, _secret));
Bid memory bidInfo = product.bids[msg.sender][sealedBid];
require(bidInfo.bidder > 0x0000000000000000000000000000000000000000);
require(bidInfo.revealed == false);

uint256 refund;
uint256 amount = stringToUint(_amount);
if (bidInfo.value > amount) {
refund = bidInfo.value;
} else {
refund = amount;
}

if (amount > product.highestBid) {
if (product.highestBidder == address(0)) {
product.highestBid = amount;
product.highestBidder = msg.sender;
} else {
product.highestBidder.transfer(product.highestBid);
product.highestBid = amount;
product.highestBidder = msg.sender;
}
} else {
msg.sender.transfer(refund);
}

product.bids[msg.sender][sealedBid].revealed = true;
}

revealBid 函数中,最高出价者和出价金额会被更新到 product.highestBidderproduct.highestBid 字段。这表示谁是最终的商品所有者。

2.Escrow.sol

托管合约负责在交易成功后处理资金和商品的所有权转移。托管合约定义了买家、卖家和仲裁者的角色,确保资金在交易完成后正确分配。

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
contract Escrow {
uint256 public productId;
address public buyer;
address public seller;
address public arbiter;
uint256 public amount;
bool public fundsDisbursed;
mapping(address => bool) releaseAmount;
mapping(address => bool) refundAmount;
uint256 public releaseCount;
uint256 public refundCount;

event CreateEscrow(uint _productId, address _buyer, address _seller, address _arbiter);
event UnlockAmount(uint _productId, string _operation, address _operator);
event DisburseAmount(uint _productId, uint _amount, address _beneficiary);

constructor(uint _productId, address _buyer, address _seller, address _arbiter) payable {
productId = _productId;
buyer = _buyer;
seller = _seller;
arbiter = _arbiter;
amount = msg.value;
fundsDisbursed = false;
emit CreateEscrow(_productId, _buyer, _seller, _arbiter);
}
}

托管合约有两个主要函数:releaseAmountToSellerrefundAmountToBuyer,它们分别处理交易成功时的资金释放和在交易争议时的退款。

  • releaseAmountToSeller 函数确保在买方和卖方(或仲裁者)达成一致后,资金会从托管合约转移给卖方,这表明商品的所有权已经成功转移到买家。

  • refundAmountToBuyer 函数在交易失败或争议时,将资金退还给买方。

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
function releaseAmountToSeller(address caller) public {
// 确保资金尚未被释放
require(!fundsDisbursed);

// 确保调用者是买家、卖家或仲裁者之一
require(caller == buyer || caller == seller || caller == arbiter);

// 检查并记录调用者是否已经同意释放资金
if (!releaseAmount[caller]) {
releaseAmount[caller] = true; // 标记调用者已同意
releaseCount += 1; // 增加同意释放资金的计数
emit UnlockAmount(productId, "release", caller); // 触发事件,记录释放请求
}

// 如果至少有两个角色同意释放资金
if (releaseCount == 2) {
payable(seller).transfer(amount); // 将托管的资金转移给卖家
fundsDisbursed = true; // 标记资金已被释放
emit DisburseAmount(productId, amount, seller); // 触发事件,记录资金已支付
}
}

function refundAmountToBuyer(address caller) public {
// 确保资金尚未被释放
require(!fundsDisbursed);

// 确保调用者是买家、卖家或仲裁者之一
require(caller == buyer || caller == seller || caller == arbiter);

// 检查并记录调用者是否已经同意退款
if (!refundAmount[caller]) {
refundAmount[caller] = true; // 标记调用者已同意
refundCount += 1; // 增加同意退款的计数
emit UnlockAmount(productId, "refund", caller); // 触发事件,记录退款请求
}

// 如果至少有两个角色同意退款
if (refundCount == 2) {
payable(buyer).transfer(amount); // 将托管的资金退还给买家
fundsDisbursed = true; // 标记资金已被释放
emit DisburseAmount(productId, amount, buyer); // 触发事件,记录资金已退还
}
}

这两个函数都是在特定条件下处理托管资金的释放或退还的关键逻辑。它们使用 require 来进行权限和状态检查,确保只有合法的调用者在正确的时间点才能执行操作。emit 用于记录事件,便于在区块链上跟踪交易的变化。这种设计可以有效地防止资金被错误地转移或多次转移。