mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Use store example
This commit is contained in:
parent
b688d33055
commit
666c46ac29
@ -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
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user