Solidity Example Simple Open Auction
Contents
Solidity Example Simple Open Auction Main Tips
- This example of a smart contract will show how to create a basic auction smart contract using Solidity.
- The auction we script we will show here is a learning step for creating a blind auction in the next tutorial
Solidity Example Simple Open Auction
The very idea of this auction is that during a set period of time, anyone can send their bids.
If a bid that is greater than the previous one is sent, then the previous bid is returned to the bidder.
Once the time is up, the contract must be manually activated for the beneficiary to receive the greatest bid. (contracts cannot activate themselves)
Here’s the code itself with explanations commented:
Example
pragma solidity ^0.4.11; contract SimpleAuction { // Auction parameters. Times are either // in the format of unix timestamps (seconds that have passed since 1970-01-01) // or a time period in seconds. address public beneficiaryAddress; uint public auctionClose; // Current state of the auction. address public topBidder; uint public topBid; // Allowed withdrawals of previous bids mapping(address => uint) returnsPending; // Will be set true once the auction is complete, preventing any further change bool auctionComplete; // Events to fire when change happens. event topBidIncreased(address bidder, uint bidAmount); event auctionResult(address winner, uint bidAmount); // The following is a so-called natspec comment, // recognizable by the three slashes. // It will be shown when the user is asked to // confirm a transaction. /// Create an auction with_biddingTime
/// seconds for bidding on behalf of the /// beneficiary address_beneficiary
. function SimpleAuction( uint _biddingTime, address _beneficiary ) { beneficiaryAddress = _beneficiary; auctionClose = now + _biddingTime; } /// You may bid on the auction with the value sent /// along with this transaction. /// The value may only be refunded if the /// auction was not won. function bid() payable { // No argument is necessary, all // information is already added to // the transaction. The keyword payable // is required so the function // receives Ether. // Revert the call in case the bidding // period is over. require(now <= auctionClose); // If the bid is not greater, // the money is sent back. require(msg.value > topBid); if (topBidder != 0) { // Sending the money back by simply using // topBidder.send(topBid) is a risk to the security // since it could execute a contract that is not trusted. // It is always preferable to let the recipients // withdraw their money themselves. returnsPending[topBidder] += topBid; } topBidder = msg.sender; topBid = msg.value; topBidIncreased(msg.sender, msg.value); } /// Withdraw a bid that was overbid. function withdraw() returns (bool) { uint bidAmount = returnsPending[msg.sender]; if (bidAmount > 0) { // It is important to set this to zero because the recipient // can call this function again as part of the receiving call // beforesend
returns. returnsPending[msg.sender] = 0; if (!msg.sender.send(bidAmount)) { //Calling throw not necessary here, simply reset the bidAmount owing returnsPending[msg.sender] = bidAmount; return false; } } return true; } /// Auction ends and highest bid is sent /// to the beneficiary. function auctionClose() { // It is a good practice to structure functions which interact // with other contracts (i.e. call functions or send Ether) // into three phases: // 1. check conditions // 2. perform actions (potentially change conditions) // 3. interact with other contracts // If these phases get mixed up, the other contract might call // back into the current contract and change the state or cause // effects (ether payout) to be done multiple times. // If functions that are called internally include interactions with external // contracts, they have to be considered interaction with // external contracts too. // 1. Conditions require(now >= auctionClose); // auction did not yet end require(!auctionComplete); // this function has already been called // 2. Effects auctionComplete = true; auctionResult(topBidder, topBid); // 3. Interaction beneficiaryAddress.transfer(topBid); } }