parent
8b29ab728d
commit
0241046e1f
@ -1,150 +0,0 @@ |
||||
contract BlindAuction { |
||||
struct Bid { |
||||
bytes32 blindedBid; |
||||
uint deposit; |
||||
} |
||||
|
||||
address public beneficiary; |
||||
uint public auctionStart; |
||||
uint public biddingEnd; |
||||
uint public revealEnd; |
||||
bool public ended; |
||||
|
||||
mapping(address => Bid[]) public bids; |
||||
|
||||
address public highestBidder; |
||||
uint public highestBid; |
||||
|
||||
// Allowed withdrawals of previous bids |
||||
mapping(address => uint) pendingReturns; |
||||
|
||||
event AuctionEnded(address winner, uint highestBid); |
||||
|
||||
/// Modifiers are a convenient way to validate inputs to |
||||
/// functions. `onlyBefore` is applied to `bid` below: |
||||
/// The new function body is the modifier's body where |
||||
/// `_` is replaced by the old function body. |
||||
modifier onlyBefore(uint _time) { if (now >= _time) throw; _ } |
||||
modifier onlyAfter(uint _time) { if (now <= _time) throw; _ } |
||||
|
||||
function BlindAuction( |
||||
uint _biddingTime, |
||||
uint _revealTime, |
||||
address _beneficiary |
||||
) { |
||||
beneficiary = _beneficiary; |
||||
auctionStart = now; |
||||
biddingEnd = now + _biddingTime; |
||||
revealEnd = biddingEnd + _revealTime; |
||||
} |
||||
|
||||
/// Place a blinded bid with `_blindedBid` = sha3(value, |
||||
/// fake, secret). |
||||
/// The sent ether is only refunded if the bid is correctly |
||||
/// revealed in the revealing phase. The bid is valid if the |
||||
/// ether sent together with the bid is at least "value" and |
||||
/// "fake" is not true. Setting "fake" to true and sending |
||||
/// not the exact amount are ways to hide the real bid but |
||||
/// still make the required deposit. The same address can |
||||
/// place multiple bids. |
||||
function bid(bytes32 _blindedBid) |
||||
onlyBefore(biddingEnd) |
||||
{ |
||||
bids[msg.sender].push(Bid({ |
||||
blindedBid: _blindedBid, |
||||
deposit: msg.value |
||||
})); |
||||
} |
||||
|
||||
/// Reveal your blinded bids. You will get a refund for all |
||||
/// correctly blinded invalid bids and for all bids except for |
||||
/// the totally highest. |
||||
function reveal( |
||||
uint[] _values, |
||||
bool[] _fake, |
||||
bytes32[] _secret |
||||
) |
||||
onlyAfter(biddingEnd) |
||||
onlyBefore(revealEnd) |
||||
{ |
||||
uint length = bids[msg.sender].length; |
||||
if ( |
||||
_values.length != length || |
||||
_fake.length != length || |
||||
_secret.length != length |
||||
) { |
||||
throw; |
||||
} |
||||
|
||||
uint refund; |
||||
for (uint i = 0; i < length; i++) { |
||||
var bid = bids[msg.sender][i]; |
||||
var (value, fake, secret) = |
||||
(_values[i], _fake[i], _secret[i]); |
||||
if (bid.blindedBid != sha3(value, fake, secret)) { |
||||
// Bid was not actually revealed. |
||||
// Do not refund deposit. |
||||
continue; |
||||
} |
||||
refund += bid.deposit; |
||||
if (!fake && bid.deposit >= value) { |
||||
if (placeBid(msg.sender, value)) |
||||
refund -= value; |
||||
} |
||||
// Make it impossible for the sender to re-claim |
||||
// the same deposit. |
||||
bid.blindedBid = 0; |
||||
} |
||||
if (!msg.sender.send(refund)) |
||||
throw; |
||||
} |
||||
|
||||
// This is an "internal" function which means that it |
||||
// can only be called from the contract itself (or from |
||||
// derived contracts). |
||||
function placeBid(address bidder, uint value) internal |
||||
returns (bool success) |
||||
{ |
||||
if (value <= highestBid) { |
||||
return false; |
||||
} |
||||
if (highestBidder != 0) { |
||||
// Refund the previously highest bidder. |
||||
pendingReturns[highestBidder] += highestBid; |
||||
} |
||||
highestBid = value; |
||||
highestBidder = bidder; |
||||
return true; |
||||
} |
||||
|
||||
/// Withdraw a bid that was overbid. |
||||
function withdraw() { |
||||
var amount = pendingReturns[msg.sender]; |
||||
// It is important to set this to zero because the recipient |
||||
// can call this function again as part of the receiving call |
||||
// before `send` returns (see the remark above about |
||||
// conditions -> effects -> interaction). |
||||
pendingReturns[msg.sender] = 0; |
||||
if (!msg.sender.send(amount)) |
||||
throw; // If anything fails, this will revert the changes above |
||||
} |
||||
|
||||
/// End the auction and send the highest bid |
||||
/// to the beneficiary. |
||||
function auctionEnd() |
||||
onlyAfter(revealEnd) |
||||
{ |
||||
if (ended) |
||||
throw; |
||||
AuctionEnded(highestBidder, highestBid); |
||||
ended = true; |
||||
// We send all the money we have, because some |
||||
// of the refunds might have failed. |
||||
if (!beneficiary.send(this.balance)) |
||||
throw; |
||||
} |
||||
|
||||
function () { |
||||
throw; |
||||
} |
||||
} |
@ -1,122 +0,0 @@ |
||||
contract SimpleAuction { |
||||
// Parameters of the auction. Times are either |
||||
// absolute unix timestamps (seconds since 1970-01-01) |
||||
// or time periods in seconds. |
||||
address public beneficiary; |
||||
uint public auctionStart; |
||||
uint public biddingTime; |
||||
|
||||
// Current state of the auction. |
||||
address public highestBidder; |
||||
uint public highestBid; |
||||
|
||||
// Allowed withdrawals of previous bids |
||||
mapping(address => uint) pendingReturns; |
||||
|
||||
// Set to true at the end, disallows any change |
||||
bool ended; |
||||
|
||||
// Events that will be fired on changes. |
||||
event HighestBidIncreased(address bidder, uint amount); |
||||
event AuctionEnded(address winner, uint amount); |
||||
|
||||
// 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 a simple auction with `_biddingTime` |
||||
/// seconds bidding time on behalf of the |
||||
/// beneficiary address `_beneficiary`. |
||||
function SimpleAuction( |
||||
uint _biddingTime, |
||||
address _beneficiary |
||||
) { |
||||
beneficiary = _beneficiary; |
||||
auctionStart = now; |
||||
biddingTime = _biddingTime; |
||||
} |
||||
|
||||
/// Bid on the auction with the value sent |
||||
/// together with this transaction. |
||||
/// The value will only be refunded if the |
||||
/// auction is not won. |
||||
function bid() { |
||||
// No arguments are necessary, all |
||||
// information is already part of |
||||
// the transaction. |
||||
if (now > auctionStart + biddingTime) { |
||||
// Revert the call if the bidding |
||||
// period is over. |
||||
throw; |
||||
} |
||||
if (msg.value <= highestBid) { |
||||
// If the bid is not higher, send the |
||||
// money back. |
||||
throw; |
||||
} |
||||
if (highestBidder != 0) { |
||||
// Sending back the money by simply using |
||||
// highestBidder.send(highestBid) is a security risk |
||||
// because it can be prevented by the caller by e.g. |
||||
// raising the call stack to 1023. It is always safer |
||||
// to let the recipient withdraw their money themselves. |
||||
pendingReturns[highestBidder] += highestBid; |
||||
} |
||||
highestBidder = msg.sender; |
||||
highestBid = msg.value; |
||||
HighestBidIncreased(msg.sender, msg.value); |
||||
} |
||||
|
||||
/// Withdraw a bid that was overbid. |
||||
function withdraw() { |
||||
var amount = pendingReturns[msg.sender]; |
||||
// It is important to set this to zero because the recipient |
||||
// can call this function again as part of the receiving call |
||||
// before `send` returns. |
||||
pendingReturns[msg.sender] = 0; |
||||
if (!msg.sender.send(amount)) |
||||
throw; // If anything fails, this will revert the changes above |
||||
} |
||||
|
||||
/// End the auction and send the highest bid |
||||
/// to the beneficiary. |
||||
function auctionEnd() { |
||||
// It is a good guideline to structure functions that interact |
||||
// with other contracts (i.e. they call functions or send Ether) |
||||
// into three phases: |
||||
// 1. checking conditions |
||||
// 2. performing actions (potentially changing conditions) |
||||
// 3. interacting with other contracts |
||||
// If these phases are mixed up, the other contract could call |
||||
// back into the current contract and modify the state or cause |
||||
// effects (ether payout) to be perfromed multiple times. |
||||
// If functions called internally include interaction with external |
||||
// contracts, they also have to be considered interaction with |
||||
// external contracts. |
||||
|
||||
// 1. Conditions |
||||
if (now <= auctionStart + biddingTime) |
||||
throw; // auction did not yet end |
||||
if (ended) |
||||
throw; // this function has already been called |
||||
|
||||
// 2. Effects |
||||
ended = true; |
||||
AuctionEnded(highestBidder, highestBid); |
||||
|
||||
// 3. Interaction |
||||
if (!beneficiary.send(highestBid)) |
||||
throw; |
||||
} |
||||
|
||||
function () { |
||||
// This function gets executed if a |
||||
// transaction with invalid data is sent to |
||||
// the contract or just ether without data. |
||||
// We revert the send so that no-one |
||||
// accidentally loses money when using the |
||||
// contract. |
||||
throw; |
||||
} |
||||
} |
Loading…
Reference in new issue