mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Docs Solidity by example
This commit is contained in:
parent
c084f6462d
commit
7a2893842d
@ -4,12 +4,10 @@
|
||||
Blind Auction
|
||||
*************
|
||||
|
||||
In this section, we will show how easy it is to create a
|
||||
completely blind auction contract on Ethereum.
|
||||
We will start with an open auction where everyone
|
||||
can see the bids that are made and then extend this
|
||||
contract into a blind auction where it is not
|
||||
possible to see the actual bid until the bidding
|
||||
In this section, we will show how easy it is to create a completely blind
|
||||
auction contract on Ethereum. We will start with an open auction where
|
||||
everyone can see the bids that are made and then extend this contract into a
|
||||
blind auction where it is not possible to see the actual bid until the bidding
|
||||
period ends.
|
||||
|
||||
.. _simple_auction:
|
||||
@ -17,16 +15,12 @@ period ends.
|
||||
Simple Open Auction
|
||||
===================
|
||||
|
||||
The general idea of the following simple auction contract
|
||||
is that everyone can send their bids during
|
||||
a bidding period. The bids already include sending
|
||||
money / ether in order to bind the bidders to their
|
||||
bid. If the highest bid is raised, the previously
|
||||
highest bidder gets her money back.
|
||||
After the end of the bidding period, the
|
||||
contract has to be called manually for the
|
||||
beneficiary to receive their money - contracts cannot
|
||||
activate themselves.
|
||||
The general idea of the following simple auction contract is that everyone can
|
||||
send their bids during a bidding period. The bids already include sending money
|
||||
/ Ether in order to bind the bidders to their bid. If the highest bid is
|
||||
raised, the previously highest bidder gets their money back. After the end of
|
||||
the bidding period, the contract has to be called manually for the beneficiary
|
||||
to receive their money - contracts cannot activate themselves.
|
||||
|
||||
::
|
||||
|
||||
@ -161,38 +155,31 @@ activate themselves.
|
||||
Blind Auction
|
||||
=============
|
||||
|
||||
The previous open auction is extended to a blind auction
|
||||
in the following. The advantage of a blind auction is
|
||||
that there is no time pressure towards the end of
|
||||
the bidding period. Creating a blind auction on a
|
||||
transparent computing platform might sound like a
|
||||
contradiction, but cryptography comes to the rescue.
|
||||
The previous open auction is extended to a blind auction in the following. The
|
||||
advantage of a blind auction is that there is no time pressure towards the end
|
||||
of the bidding period. Creating a blind auction on a transparent computing
|
||||
platform might sound like a contradiction, but cryptography comes to the
|
||||
rescue.
|
||||
|
||||
During the **bidding period**, a bidder does not
|
||||
actually send her bid, but only a hashed version of it.
|
||||
Since it is currently considered practically impossible
|
||||
to find two (sufficiently long) values whose hash
|
||||
values are equal, the bidder commits to the bid by that.
|
||||
After the end of the bidding period, the bidders have
|
||||
to reveal their bids: They send their values
|
||||
unencrypted and the contract checks that the hash value
|
||||
is the same as the one provided during the bidding period.
|
||||
During the **bidding period**, a bidder does not actually send their bid, but
|
||||
only a hashed version of it. Since it is currently considered practically
|
||||
impossible to find two (sufficiently long) values whose hash values are equal,
|
||||
the bidder commits to the bid by that. After the end of the bidding period,
|
||||
the bidders have to reveal their bids: They send their values unencrypted and
|
||||
the contract checks that the hash value is the same as the one provided during
|
||||
the bidding period.
|
||||
|
||||
Another challenge is how to make the auction
|
||||
**binding and blind** at the same time: The only way to
|
||||
prevent the bidder from just not sending the money
|
||||
after they won the auction is to make her send it
|
||||
together with the bid. Since value transfers cannot
|
||||
be blinded in Ethereum, anyone can see the value.
|
||||
Another challenge is how to make the auction **binding and blind** at the same
|
||||
time: The only way to prevent the bidder from just not sending the money after
|
||||
they won the auction is to make them send it together with the bid. Since value
|
||||
transfers cannot be blinded in Ethereum, anyone can see the value.
|
||||
|
||||
The following contract solves this problem by
|
||||
accepting any value that is larger than the highest
|
||||
bid. Since this can of course only be checked during
|
||||
the reveal phase, some bids might be **invalid**, and
|
||||
this is on purpose (it even provides an explicit
|
||||
flag to place invalid bids with high value transfers):
|
||||
Bidders can confuse competition by placing several
|
||||
high or low invalid bids.
|
||||
The following contract solves this problem by accepting any value that is
|
||||
larger than the highest bid. Since this can of course only be checked during
|
||||
the reveal phase, some bids might be **invalid**, and this is on purpose (it
|
||||
even provides an explicit flag to place invalid bids with high value
|
||||
transfers): Bidders can confuse competition by placing several high or low
|
||||
invalid bids.
|
||||
|
||||
|
||||
::
|
||||
@ -296,24 +283,6 @@ high or low invalid bids.
|
||||
msg.sender.transfer(refund);
|
||||
}
|
||||
|
||||
// This is an "internal" function which means that it
|
||||
// can only be called from the contract itself (or from
|
||||
// derived contracts).
|
||||
function placeBid(address bidder, uint value) internal
|
||||
returns (bool success)
|
||||
{
|
||||
if (value <= highestBid) {
|
||||
return false;
|
||||
}
|
||||
if (highestBidder != address(0)) {
|
||||
// Refund the previously highest bidder.
|
||||
pendingReturns[highestBidder] += highestBid;
|
||||
}
|
||||
highestBid = value;
|
||||
highestBidder = bidder;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Withdraw a bid that was overbid.
|
||||
function withdraw() public {
|
||||
uint amount = pendingReturns[msg.sender];
|
||||
@ -339,4 +308,22 @@ high or low invalid bids.
|
||||
ended = true;
|
||||
beneficiary.transfer(highestBid);
|
||||
}
|
||||
|
||||
// This is an "internal" function which means that it
|
||||
// can only be called from the contract itself (or from
|
||||
// derived contracts).
|
||||
function placeBid(address bidder, uint value) internal
|
||||
returns (bool success)
|
||||
{
|
||||
if (value <= highestBid) {
|
||||
return false;
|
||||
}
|
||||
if (highestBidder != address(0)) {
|
||||
// Refund the previously highest bidder.
|
||||
pendingReturns[highestBidder] += highestBid;
|
||||
}
|
||||
highestBid = value;
|
||||
highestBidder = bidder;
|
||||
return true;
|
||||
}
|
||||
}
|
@ -354,17 +354,6 @@ The full contract
|
||||
expiration = now + duration;
|
||||
}
|
||||
|
||||
function isValidSignature(uint256 amount, bytes memory signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount)));
|
||||
|
||||
// check that the signature is from the payment sender
|
||||
return recoverSigner(message, signature) == sender;
|
||||
}
|
||||
|
||||
/// the recipient can close the channel at any time by presenting a
|
||||
/// signed amount from the sender. the recipient will be sent that amount,
|
||||
/// and the remainder will go back to the sender
|
||||
@ -391,6 +380,17 @@ The full contract
|
||||
selfdestruct(sender);
|
||||
}
|
||||
|
||||
function isValidSignature(uint256 amount, bytes memory signature)
|
||||
internal
|
||||
view
|
||||
returns (bool)
|
||||
{
|
||||
bytes32 message = prefixed(keccak256(abi.encodePacked(this, amount)));
|
||||
|
||||
// check that the signature is from the payment sender
|
||||
return recoverSigner(message, signature) == sender;
|
||||
}
|
||||
|
||||
/// All functions below this are just taken from the chapter
|
||||
/// 'creating and verifying signatures' chapter.
|
||||
|
||||
|
@ -38,9 +38,6 @@ and the sum of all balances is an invariant across the lifetime of the contract.
|
||||
event Transfer(address from, address to, uint amount);
|
||||
event Approval(address owner, address spender, uint amount);
|
||||
|
||||
function balanceOf(address tokenOwner) public view returns (uint balance) {
|
||||
return balances[tokenOwner];
|
||||
}
|
||||
function transfer(address to, uint amount) public returns (bool success) {
|
||||
balances.move(msg.sender, to, amount);
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
@ -62,4 +59,8 @@ and the sum of all balances is an invariant across the lifetime of the contract.
|
||||
emit Approval(msg.sender, spender, tokens);
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address tokenOwner) public view returns (uint balance) {
|
||||
return balances[tokenOwner];
|
||||
}
|
||||
}
|
||||
|
@ -31,19 +31,11 @@ you can use state machine-like constructs inside a contract.
|
||||
uint public value;
|
||||
address payable public seller;
|
||||
address payable public buyer;
|
||||
|
||||
enum State { Created, Locked, Release, Inactive }
|
||||
// The state variable has a default value of the first member, `State.created`
|
||||
State public state;
|
||||
|
||||
// Ensure that `msg.value` is an even number.
|
||||
// Division will truncate if it is an odd number.
|
||||
// Check via multiplication that it wasn't an odd number.
|
||||
constructor() public payable {
|
||||
seller = msg.sender;
|
||||
value = msg.value / 2;
|
||||
require((2 * value) == msg.value, "Value has to be even.");
|
||||
}
|
||||
|
||||
modifier condition(bool _condition) {
|
||||
require(_condition);
|
||||
_;
|
||||
@ -78,6 +70,15 @@ you can use state machine-like constructs inside a contract.
|
||||
event ItemReceived();
|
||||
event SellerRefunded();
|
||||
|
||||
// Ensure that `msg.value` is an even number.
|
||||
// Division will truncate if it is an odd number.
|
||||
// Check via multiplication that it wasn't an odd number.
|
||||
constructor() public payable {
|
||||
seller = msg.sender;
|
||||
value = msg.value / 2;
|
||||
require((2 * value) == msg.value, "Value has to be even.");
|
||||
}
|
||||
|
||||
/// Abort the purchase and reclaim the ether.
|
||||
/// Can only be called by the seller before
|
||||
/// the contract is locked.
|
||||
|
Loading…
Reference in New Issue
Block a user