Skip to content

Instantly share code, notes, and snippets.

@slavik0329
Created March 20, 2017 17:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slavik0329/c61aed6596bde40a3c382bb3a3dff0d1 to your computer and use it in GitHub Desktop.
Save slavik0329/c61aed6596bde40a3c382bb3a3dff0d1 to your computer and use it in GitHub Desktop.
pragma solidity ^0.4.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;
uint256 public auctionStart;
uint256 public biddingPeriod;
uint256 public recoverPeriod; // Amount of time in which contract creator can withdraw all funds
uint256 constant withdrawEventAmount = 1000000000000000; // 0.001 ETH
// Current state of the auction.
address public highestBidder;
uint256 public highestBid;
// Allowed withdrawals of previous bids
mapping(address => uint256) pendingReturns;
// Set to true at the end, disallows any change
bool ended;
// Events that will be fired on changes.
event HighestBidIncreased(address bidder, uint256 amount);
event AuctionEnded(address winner, uint256 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 `_biddingPeriod`
/// seconds bidding time on behalf of the
/// beneficiary address `_beneficiary`.
function SimpleAuction(
uint256 _biddingPeriod,
uint256 _recoverPeriod,
address _beneficiary
) {
biddingPeriod = _biddingPeriod;
recoverPeriod = _recoverPeriod;
beneficiary = _beneficiary;
auctionStart = now;
}
/// 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() isAuctionActive payable {
// No arguments are necessary, all
// information is already part of
// the transaction. The keyword payable
// is required for the function to
// be able to receive Ether.
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);
}
// Recover any ethers accidentally sent to contract after recoverPeriod has passed
function recoverAll() isRecoveryActive isBeneficiary returns (bool) {
if ( !beneficiary.send(this.balance) ) {
throw;
}
return true;
}
/// Withdraw a bid that was overbid.
function withdraw() returns (bool) {
var amount = pendingReturns[msg.sender];
if (amount > 0) {
// 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)) {
// No need to call throw here, just reset the amount owing
pendingReturns[msg.sender] = amount;
return false;
}
}
return true;
}
/// End the auction and send the highest bid
/// to the beneficiary.
function auctionEnd() isAuctionEnded {
// 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 (ended)
throw; // this function has already been called
// 2. Effects
ended = true;
AuctionEnded(highestBidder, highestBid);
// 3. Interaction
if (!beneficiary.send(highestBid))
throw;
}
modifier isBeneficiary {
if (msg.sender != beneficiary) {
throw;
}
_;
}
modifier isAuctionActive {
if (now < auctionStart || now > (auctionStart + biddingPeriod)) {
throw;
}
_;
}
modifier isAuctionEnded {
if (now < (auctionStart + biddingPeriod)) {
throw;
}
_;
}
modifier isRecoveryActive {
if (now < (auctionStart + recoverPeriod)) {
throw;
}
_;
}
function () payable {
if ( msg.value == withdrawEventAmount ) { // 0.001 ETH for withdrawal
withdraw();
} else {
bid();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment