Created
June 29, 2017 23:25
-
-
Save brynbellomy/e41c73ca5a02f0c4826bb677c873234c to your computer and use it in GitHub Desktop.
medium-auction.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.8; | |
contract Auction { | |
// static | |
address public owner; | |
uint public bidIncrement; | |
uint public startBlock; | |
uint public endBlock; | |
string public ipfsHash; | |
// state | |
bool public canceled; | |
uint public highestBindingBid; | |
address public highestBidder; | |
mapping(address => uint256) public fundsByBidder; | |
bool ownerHasWithdrawn; | |
event LogBid(address bidder, uint bid, address highestBidder, uint highestBid, uint highestBindingBid); | |
event LogWithdrawal(address withdrawer, address withdrawalAccount, uint amount); | |
event LogCanceled(); | |
function Auction(address _owner, uint _bidIncrement, uint _startBlock, uint _endBlock, string _ipfsHash) { | |
if (_startBlock >= _endBlock) throw; | |
if (_startBlock < block.number) throw; | |
if (_owner == 0) throw; | |
owner = _owner; | |
bidIncrement = _bidIncrement; | |
startBlock = _startBlock; | |
endBlock = _endBlock; | |
ipfsHash = _ipfsHash; | |
} | |
function getHighestBid() | |
constant | |
returns (uint) | |
{ | |
return fundsByBidder[highestBidder]; | |
} | |
function placeBid() | |
payable | |
onlyAfterStart | |
onlyBeforeEnd | |
onlyNotCanceled | |
onlyNotOwner | |
returns (bool success) | |
{ | |
// reject payments of 0 ETH | |
if (msg.value == 0) throw; | |
// calculate the user's total bid based on the current amount they've sent to the contract | |
// plus whatever has been sent with this transaction | |
uint newBid = fundsByBidder[msg.sender] + msg.value; | |
// if the user isn't even willing to overbid the highest binding bid, there's nothing for us | |
// to do except revert the transaction. | |
if (newBid <= highestBindingBid) throw; | |
// grab the previous highest bid (before updating fundsByBidder, in case msg.sender is the | |
// highestBidder and is just increasing their maximum bid). | |
uint highestBid = fundsByBidder[highestBidder]; | |
fundsByBidder[msg.sender] = newBid; | |
if (newBid <= highestBid) { | |
// if the user has overbid the highestBindingBid but not the highestBid, we simply | |
// increase the highestBindingBid and leave highestBidder alone. | |
// note that this case is impossible if msg.sender == highestBidder because you can never | |
// bid less ETH than you've already bid. | |
highestBindingBid = min(newBid + bidIncrement, highestBid); | |
} else { | |
// if msg.sender is already the highest bidder, they must simply be wanting to raise | |
// their maximum bid, in which case we shouldn't increase the highestBindingBid. | |
// if the user is NOT highestBidder, and has overbid highestBid completely, we set them | |
// as the new highestBidder and recalculate highestBindingBid. | |
if (msg.sender != highestBidder) { | |
highestBidder = msg.sender; | |
highestBindingBid = min(newBid, highestBid + bidIncrement); | |
} | |
highestBid = newBid; | |
} | |
LogBid(msg.sender, newBid, highestBidder, highestBid, highestBindingBid); | |
return true; | |
} | |
function min(uint a, uint b) | |
private | |
constant | |
returns (uint) | |
{ | |
if (a < b) return a; | |
return b; | |
} | |
function cancelAuction() | |
onlyOwner | |
onlyBeforeEnd | |
onlyNotCanceled | |
returns (bool success) | |
{ | |
canceled = true; | |
LogCanceled(); | |
return true; | |
} | |
function withdraw() | |
onlyEndedOrCanceled | |
returns (bool success) | |
{ | |
address withdrawalAccount; | |
uint withdrawalAmount; | |
if (canceled) { | |
// if the auction was canceled, everyone should simply be allowed to withdraw their funds | |
withdrawalAccount = msg.sender; | |
withdrawalAmount = fundsByBidder[withdrawalAccount]; | |
} else { | |
// the auction finished without being canceled | |
if (msg.sender == owner) { | |
// the auction's owner should be allowed to withdraw the highestBindingBid | |
withdrawalAccount = highestBidder; | |
withdrawalAmount = highestBindingBid; | |
ownerHasWithdrawn = true; | |
} else if (msg.sender == highestBidder) { | |
// the highest bidder should only be allowed to withdraw the difference between their | |
// highest bid and the highestBindingBid | |
withdrawalAccount = highestBidder; | |
if (ownerHasWithdrawn) { | |
withdrawalAmount = fundsByBidder[highestBidder]; | |
} else { | |
withdrawalAmount = fundsByBidder[highestBidder] - highestBindingBid; | |
} | |
} else { | |
// anyone who participated but did not win the auction should be allowed to withdraw | |
// the full amount of their funds | |
withdrawalAccount = msg.sender; | |
withdrawalAmount = fundsByBidder[withdrawalAccount]; | |
} | |
} | |
if (withdrawalAmount == 0) throw; | |
fundsByBidder[withdrawalAccount] -= withdrawalAmount; | |
// send the funds | |
if (!msg.sender.send(withdrawalAmount)) throw; | |
LogWithdrawal(msg.sender, withdrawalAccount, withdrawalAmount); | |
return true; | |
} | |
modifier onlyOwner { | |
if (msg.sender != owner) throw; | |
_; | |
} | |
modifier onlyNotOwner { | |
if (msg.sender == owner) throw; | |
_; | |
} | |
modifier onlyAfterStart { | |
if (block.number < startBlock) throw; | |
_; | |
} | |
modifier onlyBeforeEnd { | |
if (block.number > endBlock) throw; | |
_; | |
} | |
modifier onlyNotCanceled { | |
if (canceled) throw; | |
_; | |
} | |
modifier onlyEndedOrCanceled { | |
if (block.number < endBlock && !canceled) throw; | |
_; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment