mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Change example to auction
This commit is contained in:
parent
a6c9d85399
commit
b688d33055
@ -22,32 +22,70 @@ an Ether storage contract.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
contract WithdrawalPattern {
|
contract WithdrawalPatternAuction {
|
||||||
|
address public beneficiary;
|
||||||
|
uint public auctionStart;
|
||||||
|
uint public biddingTime;
|
||||||
|
|
||||||
mapping (address => uint) etherStore;
|
address public highestBidder;
|
||||||
mapping (address => uint) pendingReturns;
|
uint public highestBid;
|
||||||
|
|
||||||
function sendEther(uint amount) {
|
mapping(address => uint) pendingReturns;
|
||||||
if (amount > etherStore[msg.sender]) {
|
|
||||||
throw;
|
bool ended;
|
||||||
}
|
|
||||||
etherStore[msg.sender] -= amount;
|
function WithdrawalPatternAuction(
|
||||||
pendingReturns[msg.sender] += amount;
|
uint _biddingTime,
|
||||||
|
address _beneficiary
|
||||||
|
) {
|
||||||
|
beneficiary = _beneficiary;
|
||||||
|
auctionStart = now;
|
||||||
|
biddingTime = _biddingTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
function withdraw() {
|
function bid() {
|
||||||
uint amount = pendingReturns[msg.sender];
|
if (now > auctionStart + biddingTime) {
|
||||||
// It is important to zero the mapping entry
|
|
||||||
// before sending otherwise this could open
|
|
||||||
// the contract to a re-entrancy attack
|
|
||||||
pendingReturns[msg.sender] = 0;
|
|
||||||
if (!msg.sender.send(amount)) {
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
if (msg.value <= highestBid) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note that funds for unsucessful
|
||||||
|
// bids are returned using the
|
||||||
|
// pendingReturns mapping
|
||||||
|
if (highestBidder != 0) {
|
||||||
|
pendingReturns[highestBidder] += highestBid;
|
||||||
|
}
|
||||||
|
highestBidder = msg.sender;
|
||||||
|
highestBid = 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
|
||||||
|
}
|
||||||
|
|
||||||
|
function auctionEnd() {
|
||||||
|
if (now <= auctionStart + biddingTime)
|
||||||
|
throw;
|
||||||
|
if (ended)
|
||||||
|
throw;
|
||||||
|
|
||||||
|
ended = true;
|
||||||
|
|
||||||
|
if (!beneficiary.send(this.balance))
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function () {
|
function () {
|
||||||
etherStore[msg.sender] += msg.value;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,28 +93,66 @@ This is as opposed to the more intuitive sending pattern.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
contract SendPattern {
|
contract SendPatternAuction {
|
||||||
|
address public beneficiary;
|
||||||
|
uint public auctionStart;
|
||||||
|
uint public biddingTime;
|
||||||
|
|
||||||
mapping (address => uint) etherStore;
|
address public highestBidder;
|
||||||
|
uint public highestBid;
|
||||||
|
|
||||||
function sendEther(uint amount) {
|
bool ended;
|
||||||
if (amount > etherStore[msg.sender]) {
|
|
||||||
|
function WithdrawalPatternAuction(
|
||||||
|
uint _biddingTime,
|
||||||
|
address _beneficiary
|
||||||
|
) {
|
||||||
|
beneficiary = _beneficiary;
|
||||||
|
auctionStart = now;
|
||||||
|
biddingTime = _biddingTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
function bid() {
|
||||||
|
if (now > auctionStart + biddingTime) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
etherStore[msg.sender] -= amount;
|
if (msg.value <= highestBid) {
|
||||||
if (!msg.sender.send(amount)) {
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note that funds are
|
||||||
|
// immedietally sent back to
|
||||||
|
// unsucessful bidders
|
||||||
|
if (highestBidder != 0) {
|
||||||
|
msg.sender.send(amount);// DANGER - send is unchecked!
|
||||||
|
}
|
||||||
|
highestBidder = msg.sender;
|
||||||
|
highestBid = msg.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function auctionEnd() {
|
||||||
|
if (now <= auctionStart + biddingTime)
|
||||||
|
throw;
|
||||||
|
if (ended)
|
||||||
|
throw;
|
||||||
|
|
||||||
|
ended = true;
|
||||||
|
|
||||||
|
if (!beneficiary.send(this.balance))
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function () {
|
function () {
|
||||||
etherStore[msg.sender] += msg.value;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
An example of this pattern in a less contrived
|
Notice that, in this example, an attacker could trap
|
||||||
application can be found on the :ref:`simple_auction`
|
the previous highest bidder's funds in the contract
|
||||||
example.
|
by causing the execution of `send` to fail.
|
||||||
|
|
||||||
|
The full auction example can be found at
|
||||||
|
:ref:`simple_auction`.
|
||||||
|
|
||||||
.. index:: access;restricting
|
.. index:: access;restricting
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user