BlindAuction.sol 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. contract BlindAuction {
  2. struct Bid {
  3. bytes32 blindedBid;
  4. uint deposit;
  5. }
  6. address public beneficiary;
  7. uint public auctionStart;
  8. uint public biddingEnd;
  9. uint public revealEnd;
  10. bool public ended;
  11. mapping(address => Bid[]) public bids;
  12. address public highestBidder;
  13. uint public highestBid;
  14. // Allowed withdrawals of previous bids
  15. mapping(address => uint) pendingReturns;
  16. event AuctionEnded(address winner, uint highestBid);
  17. /// Modifiers are a convenient way to validate inputs to
  18. /// functions. `onlyBefore` is applied to `bid` below:
  19. /// The new function body is the modifier's body where
  20. /// `_` is replaced by the old function body.
  21. modifier onlyBefore(uint _time) { if (now >= _time) throw; _ }
  22. modifier onlyAfter(uint _time) { if (now <= _time) throw; _ }
  23. function BlindAuction(
  24. uint _biddingTime,
  25. uint _revealTime,
  26. address _beneficiary
  27. ) {
  28. beneficiary = _beneficiary;
  29. auctionStart = now;
  30. biddingEnd = now + _biddingTime;
  31. revealEnd = biddingEnd + _revealTime;
  32. }
  33. /// Place a blinded bid with `_blindedBid` = sha3(value,
  34. /// fake, secret).
  35. /// The sent ether is only refunded if the bid is correctly
  36. /// revealed in the revealing phase. The bid is valid if the
  37. /// ether sent together with the bid is at least "value" and
  38. /// "fake" is not true. Setting "fake" to true and sending
  39. /// not the exact amount are ways to hide the real bid but
  40. /// still make the required deposit. The same address can
  41. /// place multiple bids.
  42. function bid(bytes32 _blindedBid)
  43. onlyBefore(biddingEnd)
  44. {
  45. bids[msg.sender].push(Bid({
  46. blindedBid: _blindedBid,
  47. deposit: msg.value
  48. }));
  49. }
  50. /// Reveal your blinded bids. You will get a refund for all
  51. /// correctly blinded invalid bids and for all bids except for
  52. /// the totally highest.
  53. function reveal(
  54. uint[] _values,
  55. bool[] _fake,
  56. bytes32[] _secret
  57. )
  58. onlyAfter(biddingEnd)
  59. onlyBefore(revealEnd)
  60. {
  61. uint length = bids[msg.sender].length;
  62. if (
  63. _values.length != length ||
  64. _fake.length != length ||
  65. _secret.length != length
  66. ) {
  67. throw;
  68. }
  69. uint refund;
  70. for (uint i = 0; i < length; i++) {
  71. var bid = bids[msg.sender][i];
  72. var (value, fake, secret) =
  73. (_values[i], _fake[i], _secret[i]);
  74. if (bid.blindedBid != sha3(value, fake, secret)) {
  75. // Bid was not actually revealed.
  76. // Do not refund deposit.
  77. continue;
  78. }
  79. refund += bid.deposit;
  80. if (!fake && bid.deposit >= value) {
  81. if (placeBid(msg.sender, value))
  82. refund -= value;
  83. }
  84. // Make it impossible for the sender to re-claim
  85. // the same deposit.
  86. bid.blindedBid = 0;
  87. }
  88. if (!msg.sender.send(refund))
  89. throw;
  90. }
  91. // This is an "internal" function which means that it
  92. // can only be called from the contract itself (or from
  93. // derived contracts).
  94. function placeBid(address bidder, uint value) internal
  95. returns (bool success)
  96. {
  97. if (value <= highestBid) {
  98. return false;
  99. }
  100. if (highestBidder != 0) {
  101. // Refund the previously highest bidder.
  102. pendingReturns[highestBidder] += highestBid;
  103. }
  104. highestBid = value;
  105. highestBidder = bidder;
  106. return true;
  107. }
  108. /// Withdraw a bid that was overbid.
  109. function withdraw() {
  110. var amount = pendingReturns[msg.sender];
  111. // It is important to set this to zero because the recipient
  112. // can call this function again as part of the receiving call
  113. // before `send` returns (see the remark above about
  114. // conditions -> effects -> interaction).
  115. pendingReturns[msg.sender] = 0;
  116. if (!msg.sender.send(amount))
  117. throw; // If anything fails, this will revert the changes above
  118. }
  119. /// End the auction and send the highest bid
  120. /// to the beneficiary.
  121. function auctionEnd()
  122. onlyAfter(revealEnd)
  123. {
  124. if (ended)
  125. throw;
  126. AuctionEnded(highestBidder, highestBid);
  127. ended = true;
  128. // We send all the money we have, because some
  129. // of the refunds might have failed.
  130. if (!beneficiary.send(this.balance))
  131. throw;
  132. }
  133. function () {
  134. throw;
  135. }
  136. }