本次範例擷取自Solidity document其中一個example, simple auction是以eth為主要交易貨幣下所使用的拍賣合約,在實際拍賣現場,由第三方規定拍賣時間並發布合約,參與者可以執行出價function,並支付同等價位的eth,每次出價都要比目前最高出價的金額還高,當拍賣結束,由第三方結束contract,結束的同時會確認是不是超過結束時間,並將最高出價的金額從合約傳送給給寄賣者
pragma solidity^0.4.25;
contract SimpleAuction{
//宣告兩組address和uint,最高出價者及受益人
address public beneficiary; //受益人
uint public auctionEnded; //拍賣時間
address public highestBidder; //出價最高者
uint public highestBid; //最高出價
//紀錄每個參與的投標者,所投入的金錢
mapping (address => uint) pendingReturn;
//拍賣狀態
bool ended;
//兩個event會公開訊息到blockchain上
event HighestBidIncreased(address _highestBidder, uint256 _amount);
event WinnerAuction(address _winner, uint256 _amount);
//兩個modifier,判斷時拍賣間結束
modifier BidCondition(){
require(msg.value > 0,"bid can't less than 0");
require(msg.value > highestBid,"not higher than highestBid");
_;
}
modifier EndYet(){
require(now <= auctionEnded,"Auction had been ended");
_;
}
modifier End(){
require(now >= auctionEnded,"Auction not ended yet");
require(!ended,"Auction not been ended");
_;
}
//由第三方啟動合約,設定拍賣受益人及拍賣時間
constructor(address _beneficiary, uint _auctionTime) public{
beneficiary = _beneficiary;
auctionEnded = now + _auctionTime;
}
//三個function,分別是出價、提款、結束拍賣
function bid() public EndYet BidCondition payable{
highestBidder = msg.sender;
highestBid = msg.value;
pendingReturn[highestBidder] += highestBid;
emit HighestBidIncreased(highestBidder,highestBid);
}
function withdraw() public returns(bool){
uint value = pendingReturn[msg.sender];
msg.sender.transfer(value);
pendingReturn[msg.sender] = 0;
}
function auctionEnd() public End {
ended = true;
emit WinnerAuction(highestBidder,highestBid);
beneficiary.transfer(highestBid);
}
}
modifier BidCondition(){
require(msg.value > 0,"bid can't less than 0");
require(msg.value > highestBid,"not higher than highestBid");
_;
}
modifier EndYet(){
require(now <= auctionEnded,"Auction had been ended");
_;
}
modifier End(){
require(now >= auctionEnded,"Auction not ended yet");
require(!ended,"Auction not been ended");
_;
}
BidCondition
主要是確認叫價者所支付的ETH不得為0,並且要高於目前最高出價EndYet
確認目前的拍賣時間還未結束End
確認出價者所支付的ETH是否在拍賣時間內以及確認拍賣結束狀態是否為true event HighestBidIncreased(address _highestBidder, uint256 _amount);
event WinnerAuction(address _winner, uint256 _amount);
兩個event分別會在有人叫價紀錄叫價價格及拍賣結束宣告得標者和得標金額的時候觸發,將紀錄放到當前transaction log裡面
function bid() public EndYet BidCondition payable{
highestBidder = msg.sender;
highestBid = msg.value;
pendingReturn[highestBidder] += highestBid;
emit HighestBidIncreased(highestBidder,highestBid);
}
出價時,會優先執行modifier EndYet()
和 modifier BidCondition()
,確認有沒有符合條件,如果通過所規定得條件,就視為最高出價者,並將每次所支付的錢累計在pendingReturn,預備後續沒有得標可以提款的機會,最後觸發event HighestBidIncreased 將最高出價者和最高出價 紀錄到 transaction receipt 的 log
function withdraw() public returns(bool){
uint value = pendingReturn[msg.sender];
msg.sender.transfer(value);
pendingReturn[msg.sender] = 0;
}
沒有得標的出價者可以執行withdraw() function拿回所投入的金額,最後將pedingResturn上的紀錄回復為初始值
function auctionEnd() public End {
ended = true;
emit WinnerAuction(highestBidder,highestBid);
beneficiary.transfer(highestBid);
}
由於成交是在拍賣結束後才可以執行,當auctionEnd() funtion 執行時,會優先執行modifier End function,確認目前執行時間是否超過拍賣時間以及確認拍賣結束function狀態是否為false
,表示還沒有call過auctionEnd()
function。符合條件之後,將會先觸發event WinnerAuction
宣告得標者及得標金額,再將得標金額轉回給受益人