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