pull/14/head
Manuel Araoz 9 years ago
parent 8b29ab728d
commit 0241046e1f
  1. 150
      contracts/BlindAuction.sol
  2. 16
      contracts/Ownable.sol
  3. 122
      contracts/SimpleAuction.sol
  4. 0
      contracts/examples/StoppableBid.sol

@ -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;
}
}

@ -3,14 +3,14 @@
* Base contract with an owner
*/
contract Ownable {
address owner;
address owner;
function Ownable() {
owner = msg.sender;
}
function Ownable() {
owner = msg.sender;
}
modifier onlyOwner() {
if (msg.sender == owner)
_
}
modifier onlyOwner() {
if (msg.sender == owner)
_
}
}

@ -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…
Cancel
Save