实现一个繁难的拍卖合约
角色剖析:4 类角色(拍卖师 actioneer,委托人 seller,竞买人 bidder,买受人 buyer)
功能分析:拍卖的根本准则是价高者得,在设定的拍卖时限内,出价最高者最终取得拍卖得标物(提醒:在数据结构上,不必太简单的设计,只需能记录以后最高价的竞买人及其金额、拍卖完结工夫即可。)
- 竞拍性能:竞买人能够屡次出价,价格必须高于以后记录的最高价,并将最高价和竞买人替换。
- 竞拍完结:竞拍完结时,发表胜利者。
状态变量定义和初始化
定义变量:委托人、拍卖师、买受人、竞拍完结标记、工夫限度、竞拍最高金额。(提醒:合约调用者为拍卖师,如果波及到转账的角色须要用 address
payable,构造函数能够初始化拍卖师 [即 msg.sender]、拍卖时限、竞拍完结标记,竞买人在程序中抉择不同 account,依据 account 和 msg.value 更新买受人和最高金额 )
竞拍性能
只有竞拍未完结都能够发动竞拍(提醒:从调用信息窗口抉择买家,输出竞拍价格,用 msg.sender 和 msg.value 取得买家和价格信息)
但须要满足以下条件:竞拍未完结;竞拍时的价格肯定要比之前的价格高;竞拍在时限内;
当竞拍被容许时,须要退钱给上一个买家,并替换原有的最高价格和买受人。
完结竞拍
判断是否超过时限,并且是第一次执行本操作,确认通过后,转账给委托人。
合约代码
pragma solidity ^0.8.4;
contract auction {
uint auctionEndTime;
address public auctioneer;
address public buyer;
address payable public seller;
uint public auctionAmount;
// Allowed withdrawals of previous bids
mapping(address => uint) pendingReturns;
// A sign to judge whether the auction is over
// Set to true at the end, disallows any change.
bool ended;
// Events that will be emitted on changes.
event auctionAmountIncreased(address bidder, uint amount);
event AuctionEnded(address winner, uint amount);
// Errors that describe failures.
/// The auction has already ended.
error AuctionAlreadyEnded();
/// There is already a higher or equal bid.
error BidNotHighEnough(uint auctionAmount);
/// The auction has not ended yet.
error AuctionNotYetEnded();
/// The function auctionEnd has already been called.
error AuctionEndAlreadyCalled();
constructor(
uint biddingTime,
address payable sellerAddress
) {
seller = sellerAddress;
auctionEndTime = block.timestamp + biddingTime;
auctioneer = msg.sender;
}
/// Bid function
function bid() external payable {
// Revert the call if the bidding period is over.
if (block.timestamp > auctionEndTime)
revert AuctionAlreadyEnded();
// Return money if the bid is not high enough
if (msg.value <= auctionAmount)
revert BidNotHighEnough(auctionAmount);
if (auctionAmount != 0) {pendingReturns[buyer] += auctionAmount;
}
buyer = msg.sender;
auctionAmount = msg.value;
emit auctionAmountIncreased(msg.sender, msg.value);
}
/// End the auction and send the highest bid to the seller.
function auctionEnd() external payable {
// Analyzing conditions
if (block.timestamp < auctionEndTime)
revert AuctionNotYetEnded();
if (ended)
revert AuctionEndAlreadyCalled();
ended = true;
emit AuctionEnded(buyer, auctionAmount);
// transfer
seller.transfer(auctionAmount);
}
}
首先,依照要求 deploy 拍卖合约,依照要求设置相干参数,其中 seller 的地址是 0x78731D3Ca6b7E34aC0F824c42a7cC18A495cabaB
,竞拍的工夫是 120
。
如下所示:
deploy 胜利之后,进行初始查问,右下可知,auctioneer 即为合约调用者的地址,seller 地址与刚刚输出的地址统一。初始 buyer 地址默认为 0,出价金额也为 0。
而后进行第一次竞拍,切换至地址结尾为 35cb2
的账户,出价为 1949 wei,进行竞拍:
查问后可知,竞拍胜利,并且呈现在以后 buyer 地位:
而后进行第二次竞拍,切换至地址结尾为 C02db
的账户,出价为 6666 wei,进行竞拍:
查问后可知,竞拍胜利,并且呈现在以后 buyer 地位:
而后进行第三次竞拍,切换至地址结尾为 5E7f2
的账户,出价为 9999 wei,进行竞拍:
查问后可知,竞拍胜利,并且呈现在以后 buyer 地位:
最初,待拍卖工夫完结后进行 auctionEnd,依据定义,价高者得,因而 winner 是出价 9999 wei 的账户,后果如下: