SimpleAuction.sol 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. contract SimpleAuction {
  2. // Parameters of the auction. Times are either
  3. // absolute unix timestamps (seconds since 1970-01-01)
  4. // or time periods in seconds.
  5. address public beneficiary;
  6. uint public auctionStart;
  7. uint public biddingTime;
  8. // Current state of the auction.
  9. address public highestBidder;
  10. uint public highestBid;
  11. // Allowed withdrawals of previous bids
  12. mapping(address => uint) pendingReturns;
  13. // Set to true at the end, disallows any change
  14. bool ended;
  15. // Events that will be fired on changes.
  16. event HighestBidIncreased(address bidder, uint amount);
  17. event AuctionEnded(address winner, uint amount);
  18. // The following is a so-called natspec comment,
  19. // recognizable by the three slashes.
  20. // It will be shown when the user is asked to
  21. // confirm a transaction.
  22. /// Create a simple auction with `_biddingTime`
  23. /// seconds bidding time on behalf of the
  24. /// beneficiary address `_beneficiary`.
  25. function SimpleAuction(
  26. uint _biddingTime,
  27. address _beneficiary
  28. ) {
  29. beneficiary = _beneficiary;
  30. auctionStart = now;
  31. biddingTime = _biddingTime;
  32. }
  33. /// Bid on the auction with the value sent
  34. /// together with this transaction.
  35. /// The value will only be refunded if the
  36. /// auction is not won.
  37. function bid() {
  38. // No arguments are necessary, all
  39. // information is already part of
  40. // the transaction.
  41. if (now > auctionStart + biddingTime) {
  42. // Revert the call if the bidding
  43. // period is over.
  44. throw;
  45. }
  46. if (msg.value <= highestBid) {
  47. // If the bid is not higher, send the
  48. // money back.
  49. throw;
  50. }
  51. if (highestBidder != 0) {
  52. // Sending back the money by simply using
  53. // highestBidder.send(highestBid) is a security risk
  54. // because it can be prevented by the caller by e.g.
  55. // raising the call stack to 1023. It is always safer
  56. // to let the recipient withdraw their money themselves.
  57. pendingReturns[highestBidder] += highestBid;
  58. }
  59. highestBidder = msg.sender;
  60. highestBid = msg.value;
  61. HighestBidIncreased(msg.sender, msg.value);
  62. }
  63. /// Withdraw a bid that was overbid.
  64. function withdraw() {
  65. var amount = pendingReturns[msg.sender];
  66. // It is important to set this to zero because the recipient
  67. // can call this function again as part of the receiving call
  68. // before `send` returns.
  69. pendingReturns[msg.sender] = 0;
  70. if (!msg.sender.send(amount))
  71. throw; // If anything fails, this will revert the changes above
  72. }
  73. /// End the auction and send the highest bid
  74. /// to the beneficiary.
  75. function auctionEnd() {
  76. // It is a good guideline to structure functions that interact
  77. // with other contracts (i.e. they call functions or send Ether)
  78. // into three phases:
  79. // 1. checking conditions
  80. // 2. performing actions (potentially changing conditions)
  81. // 3. interacting with other contracts
  82. // If these phases are mixed up, the other contract could call
  83. // back into the current contract and modify the state or cause
  84. // effects (ether payout) to be perfromed multiple times.
  85. // If functions called internally include interaction with external
  86. // contracts, they also have to be considered interaction with
  87. // external contracts.
  88. // 1. Conditions
  89. if (now <= auctionStart + biddingTime)
  90. throw; // auction did not yet end
  91. if (ended)
  92. throw; // this function has already been called
  93. // 2. Effects
  94. ended = true;
  95. AuctionEnded(highestBidder, highestBid);
  96. // 3. Interaction
  97. if (!beneficiary.send(highestBid))
  98. throw;
  99. }
  100. function () {
  101. // This function gets executed if a
  102. // transaction with invalid data is sent to
  103. // the contract or just ether without data.
  104. // We revert the send so that no-one
  105. // accidentally loses money when using the
  106. // contract.
  107. throw;
  108. }
  109. }