Use store example

This commit is contained in:
Denton Liu 2016-08-10 11:11:13 -04:00
parent b688d33055
commit 666c46ac29

View File

@ -18,74 +18,57 @@ introduces a potential security risk. You may read
more about this on the :ref:`security_considerations` page. more about this on the :ref:`security_considerations` page.
This is an example of the withdrawal pattern in practice in This is an example of the withdrawal pattern in practice in
an Ether storage contract. an Ether "store" contract.
:: ::
contract WithdrawalPatternAuction { contract WithdrawalStore {
address public beneficiary;
uint public auctionStart;
uint public biddingTime;
address public highestBidder; struct Item {
uint public highestBid; uint price;
uint quantity;
}
mapping(address => uint) pendingReturns; modifier onlyOwner {
if (msg.sender == owner) {
_
}
else {
throw;
}
}
bool ended; address owner;
mapping (string => Item) inventory;
function WithdrawalPatternAuction( function WithdrawalStore() {
uint _biddingTime, owner = msg.sender;
address _beneficiary }
function updateInventory(
string _item,
uint _price,
uint _quantity
) onlyOwner {
inventory[_item] = Item(_price, _quantity);
}
// Notice that the owner withdraws their own Ether
function withdraw() onlyOwner {
owner.send(this.balance);
}
function buy(string _item) returns (bool) {
if (
inventory[_item].quantity > 0 &&
inventory[_item].price <= msg.value
) { ) {
beneficiary = _beneficiary; inventory[_item].quantity--;
auctionStart = now; return true;
biddingTime = _biddingTime;
} }
else {
function bid() { return false;
if (now > auctionStart + biddingTime) {
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 () {
throw;
} }
} }
@ -93,66 +76,55 @@ This is as opposed to the more intuitive sending pattern.
:: ::
contract SendPatternAuction { contract SendStore {
address public beneficiary;
uint public auctionStart;
uint public biddingTime;
address public highestBidder; struct Item {
uint public highestBid; uint price;
uint quantity;
}
bool ended; modifier onlyOwner {
if (msg.sender == owner) {
_
}
else {
throw;
}
}
function WithdrawalPatternAuction( address owner;
uint _biddingTime, mapping (string => Item) inventory;
address _beneficiary
function SendStore() {
owner = msg.sender;
}
function updateInventory(
string _item,
uint _price,
uint _quantity
) onlyOwner {
inventory[_item] = Item(_price, _quantity);
}
function buy(string _item) returns (bool) {
if (
inventory[_item].quantity > 0 &&
inventory[_item].price <= msg.value
) { ) {
beneficiary = _beneficiary; inventory[_item].quantity--;
auctionStart = now; owner.send(msg.value);// WARNING - this send is unchecked!!
biddingTime = _biddingTime; return true;
} }
else {
function bid() { return false;
if (now > auctionStart + biddingTime) {
throw;
} }
if (msg.value <= highestBid) {
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 () {
throw;
} }
} }
Notice that, in this example, an attacker could trap Notice that, in this example, an attacker could trap
the previous highest bidder's funds in the contract the owner's funds in the contract by causing the
by causing the execution of `send` to fail. execution of `send` to fail through a callstack attack.
The full auction example can be found at
:ref:`simple_auction`.
.. index:: access;restricting .. index:: access;restricting