mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1024 from ethereum/docupdate
Update documentation to version 0.4.0.
This commit is contained in:
commit
8951affb62
@ -36,12 +36,12 @@ become the new richest.
|
|||||||
|
|
||||||
mapping (address => uint) pendingWithdrawals;
|
mapping (address => uint) pendingWithdrawals;
|
||||||
|
|
||||||
function WithdrawalContract() {
|
function WithdrawalContract() payable {
|
||||||
richest = msg.sender;
|
richest = msg.sender;
|
||||||
mostSent = msg.value;
|
mostSent = msg.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function becomeRichest() returns (bool) {
|
function becomeRichest() payable returns (bool) {
|
||||||
if (msg.value > mostSent) {
|
if (msg.value > mostSent) {
|
||||||
pendingWithdrawals[richest] += msg.value;
|
pendingWithdrawals[richest] += msg.value;
|
||||||
richest = msg.sender;
|
richest = msg.sender;
|
||||||
@ -66,7 +66,7 @@ become the new richest.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
This is as opposed to the more intuitive sending pattern.
|
This is as opposed to the more intuitive sending pattern:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ This is as opposed to the more intuitive sending pattern.
|
|||||||
address public richest;
|
address public richest;
|
||||||
uint public mostSent;
|
uint public mostSent;
|
||||||
|
|
||||||
function SendContract() {
|
function SendContract() payable {
|
||||||
richest = msg.sender;
|
richest = msg.sender;
|
||||||
mostSent = msg.value;
|
mostSent = msg.value;
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ restrictions highly readable.
|
|||||||
throw;
|
throw;
|
||||||
// Do not forget the "_;"! It will
|
// Do not forget the "_;"! It will
|
||||||
// be replaced by the actual function
|
// be replaced by the actual function
|
||||||
// body when the modifier is invoked.
|
// body when the modifier is used.
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -187,9 +187,8 @@ restrictions highly readable.
|
|||||||
// fee being associated with a function call.
|
// fee being associated with a function call.
|
||||||
// If the caller sent too much, he or she is
|
// If the caller sent too much, he or she is
|
||||||
// refunded, but only after the function body.
|
// refunded, but only after the function body.
|
||||||
// This is dangerous, because if the function
|
// This was dangerous before Solidity version 0.4.0,
|
||||||
// uses `return` explicitly, this will not be
|
// where it was possible to skip the part after `_;`.
|
||||||
// done! This behavior will be fixed in Version 0.4.0.
|
|
||||||
modifier costs(uint _amount) {
|
modifier costs(uint _amount) {
|
||||||
if (msg.value < _amount)
|
if (msg.value < _amount)
|
||||||
throw;
|
throw;
|
||||||
@ -204,10 +203,10 @@ restrictions highly readable.
|
|||||||
owner = _newOwner;
|
owner = _newOwner;
|
||||||
// just some example condition
|
// just some example condition
|
||||||
if (uint(owner) & 0 == 1)
|
if (uint(owner) & 0 == 1)
|
||||||
// in this case, overpaid fees will not
|
// This did not refund for Solidity
|
||||||
// be refunded
|
// before version 0.4.0.
|
||||||
return;
|
return;
|
||||||
// otherwise, refund overpaid fees
|
// refund overpaid fees
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,13 +264,14 @@ function finishes.
|
|||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
**Modifier May be Skipped**.
|
**Modifier May be Skipped**.
|
||||||
|
This only applies to Solidity before version 0.4.0:
|
||||||
Since modifiers are applied by simply replacing
|
Since modifiers are applied by simply replacing
|
||||||
code and not by using a function call,
|
code and not by using a function call,
|
||||||
the code in the transitionNext modifier
|
the code in the transitionNext modifier
|
||||||
can be skipped if the function itself uses
|
can be skipped if the function itself uses
|
||||||
return. If you want to do that, make sure
|
return. If you want to do that, make sure
|
||||||
to call nextStage manually from those functions.
|
to call nextStage manually from those functions.
|
||||||
With version 0.4.0 (unreleased), modifier code
|
Starting with version 0.4.0, modifier code
|
||||||
will run even if the function explicitly returns.
|
will run even if the function explicitly returns.
|
||||||
|
|
||||||
::
|
::
|
||||||
@ -317,6 +317,7 @@ function finishes.
|
|||||||
|
|
||||||
// Order of the modifiers matters here!
|
// Order of the modifiers matters here!
|
||||||
function bid()
|
function bid()
|
||||||
|
payable
|
||||||
timedTransitions
|
timedTransitions
|
||||||
atStage(Stages.AcceptingBlindedBids)
|
atStage(Stages.AcceptingBlindedBids)
|
||||||
{
|
{
|
||||||
@ -331,9 +332,6 @@ function finishes.
|
|||||||
|
|
||||||
// This modifier goes to the next stage
|
// This modifier goes to the next stage
|
||||||
// after the function is done.
|
// after the function is done.
|
||||||
// If you use `return` in the function,
|
|
||||||
// `nextStage` will not be called
|
|
||||||
// automatically.
|
|
||||||
modifier transitionNext()
|
modifier transitionNext()
|
||||||
{
|
{
|
||||||
_;
|
_;
|
||||||
@ -345,8 +343,6 @@ function finishes.
|
|||||||
atStage(Stages.AnotherStage)
|
atStage(Stages.AnotherStage)
|
||||||
transitionNext
|
transitionNext
|
||||||
{
|
{
|
||||||
// If you want to use `return` here,
|
|
||||||
// you have to call `nextStage()` manually.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function h()
|
function h()
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
Contracts
|
Contracts
|
||||||
##########
|
##########
|
||||||
|
|
||||||
Contracts in Solidity are what classes are in object oriented languages. They
|
Contracts in Solidity are similar to classes in object-oriented languages. They
|
||||||
contain persistent data in state variables and functions that can modify these
|
contain persistent data in state variables and functions that can modify these
|
||||||
variables. Calling a function on a different contract (instance) will perform
|
variables. Calling a function on a different contract (instance) will perform
|
||||||
an EVM function call and thus switch the context such that state variables are
|
an EVM function call and thus switch the context such that state variables are
|
||||||
@ -78,6 +78,11 @@ This means that cyclic creation dependencies are impossible.
|
|||||||
// This is the constructor which registers the
|
// This is the constructor which registers the
|
||||||
// creator and the assigned name.
|
// creator and the assigned name.
|
||||||
function OwnedToken(bytes32 _name) {
|
function OwnedToken(bytes32 _name) {
|
||||||
|
// State variables are accessed via their name
|
||||||
|
// and not via e.g. this.owner. This also applies
|
||||||
|
// to functions and especially in the constructors,
|
||||||
|
// you can only call them like that ("internall"),
|
||||||
|
// because the contract itself does not exist yet.
|
||||||
owner = msg.sender;
|
owner = msg.sender;
|
||||||
// We do an explicit type conversion from `address`
|
// We do an explicit type conversion from `address`
|
||||||
// to `TokenCreator` and assume that the type of
|
// to `TokenCreator` and assume that the type of
|
||||||
@ -241,7 +246,7 @@ Accessor Functions
|
|||||||
==================
|
==================
|
||||||
|
|
||||||
The compiler automatically creates accessor functions for
|
The compiler automatically creates accessor functions for
|
||||||
all public state variables. For the contract given below, the compiler will
|
all **public** state variables. For the contract given below, the compiler will
|
||||||
generate a function called ``data`` that does not take any
|
generate a function called ``data`` that does not take any
|
||||||
arguments and returns a ``uint``, the value of the state
|
arguments and returns a ``uint``, the value of the state
|
||||||
variable ``data``. The initialization of state variables can
|
variable ``data``. The initialization of state variables can
|
||||||
@ -328,7 +333,7 @@ inheritable properties of contracts and may be overridden by derived contracts.
|
|||||||
// This contract only defines a modifier but does not use
|
// This contract only defines a modifier but does not use
|
||||||
// it - it will be used in derived contracts.
|
// it - it will be used in derived contracts.
|
||||||
// The function body is inserted where the special symbol
|
// The function body is inserted where the special symbol
|
||||||
// "_" in the definition of a modifier appears.
|
// "_;" in the definition of a modifier appears.
|
||||||
// This means that if the owner calls this function, the
|
// This means that if the owner calls this function, the
|
||||||
// function is executed and otherwise, an exception is
|
// function is executed and otherwise, an exception is
|
||||||
// thrown.
|
// thrown.
|
||||||
@ -367,7 +372,10 @@ inheritable properties of contracts and may be overridden by derived contracts.
|
|||||||
|
|
||||||
function Register(uint initialPrice) { price = initialPrice; }
|
function Register(uint initialPrice) { price = initialPrice; }
|
||||||
|
|
||||||
function register() costs(price) {
|
// It is important to also provide the
|
||||||
|
// "payable" keyword here, otherwise the function will
|
||||||
|
// automatically reject all Ether sent to it.
|
||||||
|
function register() payable costs(price) {
|
||||||
registeredAddresses[msg.sender] = true;
|
registeredAddresses[msg.sender] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,7 +458,7 @@ functions matches the given function identifier (or if no data was supplied at
|
|||||||
all).
|
all).
|
||||||
|
|
||||||
Furthermore, this function is executed whenever the contract receives plain
|
Furthermore, this function is executed whenever the contract receives plain
|
||||||
Ether (without data). In such a context, there is very little gas available to
|
Ether (without data). In such a context, there is usually very little gas available to
|
||||||
the function call (to be precise, 2300 gas), so it is important to make fallback functions as cheap as
|
the function call (to be precise, 2300 gas), so it is important to make fallback functions as cheap as
|
||||||
possible.
|
possible.
|
||||||
|
|
||||||
@ -474,26 +482,31 @@ Please ensure you test your fallback function thoroughly to ensure the execution
|
|||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract Test {
|
contract Test {
|
||||||
|
// This function is called for all messages sent to
|
||||||
|
// this contract (there is no other function).
|
||||||
|
// Sending Ether to this contract will cause an exception,
|
||||||
|
// because the fallback function does not have the "payable"
|
||||||
|
// modifier.
|
||||||
function() { x = 1; }
|
function() { x = 1; }
|
||||||
uint x;
|
uint x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This contract rejects any Ether sent to it. It is good
|
// This contract keeps all Ether sent to it with no way
|
||||||
// practise to include such a function for every contract
|
// to get it back.
|
||||||
// in order not to lose Ether.
|
contract Sink {
|
||||||
contract Rejector {
|
function() payable { }
|
||||||
function() { throw; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
contract Caller {
|
contract Caller {
|
||||||
function callTest(address testAddress) {
|
function callTest(Test test) {
|
||||||
Test(testAddress).call(0xabcdef01); // hash does not exist
|
test.call(0xabcdef01); // hash does not exist
|
||||||
// results in Test(testAddress).x becoming == 1.
|
// results in test.x becoming == 1.
|
||||||
Rejector r = Rejector(0x123);
|
|
||||||
r.send(2 ether);
|
// The following call will fail, reject the
|
||||||
// results in r.balance == 0
|
// Ether and return false:
|
||||||
|
test.send(2 ether);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -539,6 +552,11 @@ not possible to filter for specific anonymous events by name.
|
|||||||
|
|
||||||
All non-indexed arguments will be stored in the data part of the log.
|
All non-indexed arguments will be stored in the data part of the log.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Indexed arguments will not be stored themselves, you can only
|
||||||
|
search for the values, but it is impossible to retrieve the
|
||||||
|
values themselves.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.0;
|
||||||
@ -622,7 +640,7 @@ Inheritance
|
|||||||
Solidity supports multiple inheritance by copying code including polymorphism.
|
Solidity supports multiple inheritance by copying code including polymorphism.
|
||||||
|
|
||||||
All function calls are virtual, which means that the most derived function
|
All function calls are virtual, which means that the most derived function
|
||||||
is called, except when the contract is explicitly given.
|
is called, except when the contract name is explicitly given.
|
||||||
|
|
||||||
Even if a contract inherits from multiple other contracts, only a single
|
Even if a contract inherits from multiple other contracts, only a single
|
||||||
contract is created on the blockchain, the code from the base contracts
|
contract is created on the blockchain, the code from the base contracts
|
||||||
@ -636,6 +654,8 @@ Details are given in the following example.
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract owned {
|
contract owned {
|
||||||
function owned() { owner = msg.sender; }
|
function owned() { owner = msg.sender; }
|
||||||
address owner;
|
address owner;
|
||||||
@ -709,6 +729,8 @@ Note that above, we call ``mortal.kill()`` to "forward" the
|
|||||||
destruction request. The way this is done is problematic, as
|
destruction request. The way this is done is problematic, as
|
||||||
seen in the following example::
|
seen in the following example::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract mortal is owned {
|
contract mortal is owned {
|
||||||
function kill() {
|
function kill() {
|
||||||
if (msg.sender == owner) selfdestruct(owner);
|
if (msg.sender == owner) selfdestruct(owner);
|
||||||
@ -734,6 +756,8 @@ derived override, but this function will bypass
|
|||||||
``Base1.kill``, basically because it does not even know about
|
``Base1.kill``, basically because it does not even know about
|
||||||
``Base1``. The way around this is to use ``super``::
|
``Base1``. The way around this is to use ``super``::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract mortal is owned {
|
contract mortal is owned {
|
||||||
function kill() {
|
function kill() {
|
||||||
if (msg.sender == owner) selfdestruct(owner);
|
if (msg.sender == owner) selfdestruct(owner);
|
||||||
@ -773,6 +797,8 @@ Arguments for Base Constructors
|
|||||||
Derived contracts need to provide all arguments needed for
|
Derived contracts need to provide all arguments needed for
|
||||||
the base constructors. This can be done at two places::
|
the base constructors. This can be done at two places::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract Base {
|
contract Base {
|
||||||
uint x;
|
uint x;
|
||||||
function Base(uint _x) { x = _x; }
|
function Base(uint _x) { x = _x; }
|
||||||
@ -833,12 +859,16 @@ Abstract Contracts
|
|||||||
|
|
||||||
Contract functions can lack an implementation as in the following example (note that the function declaration header is terminated by ``;``)::
|
Contract functions can lack an implementation as in the following example (note that the function declaration header is terminated by ``;``)::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract Feline {
|
contract Feline {
|
||||||
function utterance() returns (bytes32);
|
function utterance() returns (bytes32);
|
||||||
}
|
}
|
||||||
|
|
||||||
Such contracts cannot be compiled (even if they contain implemented functions alongside non-implemented functions), but they can be used as base contracts::
|
Such contracts cannot be compiled (even if they contain implemented functions alongside non-implemented functions), but they can be used as base contracts::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract Cat is Feline {
|
contract Cat is Feline {
|
||||||
function utterance() returns (bytes32) { return "miaow"; }
|
function utterance() returns (bytes32) { return "miaow"; }
|
||||||
}
|
}
|
||||||
@ -1060,6 +1090,8 @@ available without having to add further code.
|
|||||||
Let us rewrite the set example from the
|
Let us rewrite the set example from the
|
||||||
:ref:`libraries` in this way::
|
:ref:`libraries` in this way::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
// This is the same code as before, just without comments
|
// This is the same code as before, just without comments
|
||||||
library Set {
|
library Set {
|
||||||
struct Data { mapping(uint => bool) flags; }
|
struct Data { mapping(uint => bool) flags; }
|
||||||
@ -1106,6 +1138,8 @@ Let us rewrite the set example from the
|
|||||||
|
|
||||||
It is also possible to extend elementary types in that way::
|
It is also possible to extend elementary types in that way::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
library Search {
|
library Search {
|
||||||
function indexOf(uint[] storage self, uint value) returns (uint) {
|
function indexOf(uint[] storage self, uint value) returns (uint) {
|
||||||
for (uint i = 0; i < self.length; i++)
|
for (uint i = 0; i < self.length; i++)
|
||||||
|
@ -25,17 +25,21 @@ To report an issue, please use the
|
|||||||
reporting issues, please mention the following details:
|
reporting issues, please mention the following details:
|
||||||
|
|
||||||
* Which version of Solidity you are using
|
* Which version of Solidity you are using
|
||||||
|
* What was the source code (if applicable)
|
||||||
* Which platform are you running on
|
* Which platform are you running on
|
||||||
* How to reproduce the issue
|
* How to reproduce the issue
|
||||||
* What was the result of the issue
|
* What was the result of the issue
|
||||||
* What the expected behaviour is
|
* What the expected behaviour is
|
||||||
|
|
||||||
|
Reducing the source code that caused the issue to a bare minimum is always
|
||||||
|
very helpful and sometimes even clarifies a misunderstanding.
|
||||||
|
|
||||||
Workflow for Pull Requests
|
Workflow for Pull Requests
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
In order to contribute, please fork off of the ``develop`` branch and make your
|
In order to contribute, please fork off of the ``develop`` branch and make your
|
||||||
changes there. Your commit messages should detail *why* you made your change, as
|
changes there. Your commit messages should detail *why* you made your change
|
||||||
opposed to *what* you did.
|
in addition to *what* you did (unless it is a tiny change).
|
||||||
|
|
||||||
If you need to pull in any changes from ``develop`` after making your fork (for
|
If you need to pull in any changes from ``develop`` after making your fork (for
|
||||||
example, to resolve potential merge conflicts), please avoid using ``git merge``
|
example, to resolve potential merge conflicts), please avoid using ``git merge``
|
||||||
|
@ -44,8 +44,12 @@ contract can be called internally.
|
|||||||
External Function Calls
|
External Function Calls
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
The expression ``this.g(8);`` is also a valid function call, but this time, the function
|
The expressions ``this.g(8);`` and ``c.g(2);`` (where ``g`` is a contract
|
||||||
|
instance) are also valid function calls, but this time, the function
|
||||||
will be called "externally", via a message call and not directly via jumps.
|
will be called "externally", via a message call and not directly via jumps.
|
||||||
|
Please note that function calls on ``this`` cannot be used in the constructor, as the
|
||||||
|
actual contract has not been created yet.
|
||||||
|
|
||||||
Functions of other contracts have to be called externally. For an external call,
|
Functions of other contracts have to be called externally. For an external call,
|
||||||
all function arguments have to be copied to memory.
|
all function arguments have to be copied to memory.
|
||||||
|
|
||||||
@ -53,7 +57,7 @@ When calling functions
|
|||||||
of other contracts, the amount of Wei sent with the call and the gas can be specified::
|
of other contracts, the amount of Wei sent with the call and the gas can be specified::
|
||||||
|
|
||||||
contract InfoFeed {
|
contract InfoFeed {
|
||||||
function info() returns (uint ret) { return 42; }
|
function info() payable returns (uint ret) { return 42; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -63,9 +67,17 @@ of other contracts, the amount of Wei sent with the call and the gas can be spec
|
|||||||
function callFeed() { feed.info.value(10).gas(800)(); }
|
function callFeed() { feed.info.value(10).gas(800)(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The modifier ``payable`` has to be used for ``info``, because otherwise,
|
||||||
|
we would not be able to send Ether to it in the call ``feed.info.value(10).gas(800)()``.
|
||||||
|
|
||||||
Note that the expression ``InfoFeed(addr)`` performs an explicit type conversion stating
|
Note that the expression ``InfoFeed(addr)`` performs an explicit type conversion stating
|
||||||
that "we know that the type of the contract at the given address is ``InfoFeed``" and
|
that "we know that the type of the contract at the given address is ``InfoFeed``" and
|
||||||
this does not execute a constructor. We could also have used ``function setFeed(InfoFeed _feed) { feed = _feed; }`` directly. Be careful about the fact that ``feed.info.value(10).gas(800)``
|
this does not execute a constructor. Explicit type conversions have to be
|
||||||
|
handled with extreme caution. Never call a function on a contract where you
|
||||||
|
are not sure about its type.
|
||||||
|
|
||||||
|
We could also have used ``function setFeed(InfoFeed _feed) { feed = _feed; }`` directly.
|
||||||
|
Be careful about the fact that ``feed.info.value(10).gas(800)``
|
||||||
only (locally) sets the value and amount of gas sent with the function call and only the
|
only (locally) sets the value and amount of gas sent with the function call and only the
|
||||||
parentheses at the end perform the actual call.
|
parentheses at the end perform the actual call.
|
||||||
|
|
||||||
@ -144,7 +156,7 @@ creation-dependencies are now possible.
|
|||||||
|
|
||||||
contract D {
|
contract D {
|
||||||
uint x;
|
uint x;
|
||||||
function D(uint a) {
|
function D(uint a) payable {
|
||||||
x = a;
|
x = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,6 +253,8 @@ This happens because Solidity inherits its scoping rules from JavaScript.
|
|||||||
This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block.
|
This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block.
|
||||||
As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``::
|
As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract ScopingErrors {
|
contract ScopingErrors {
|
||||||
function scoping() {
|
function scoping() {
|
||||||
uint i = 0;
|
uint i = 0;
|
||||||
@ -298,8 +312,10 @@ Catching exceptions is not yet possible.
|
|||||||
|
|
||||||
In the following example, we show how ``throw`` can be used to easily revert an Ether transfer and also how to check the return value of ``send``::
|
In the following example, we show how ``throw`` can be used to easily revert an Ether transfer and also how to check the return value of ``send``::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract Sharer {
|
contract Sharer {
|
||||||
function sendHalf(address addr) returns (uint balance) {
|
function sendHalf(address addr) payable returns (uint balance) {
|
||||||
if (!addr.send(msg.value / 2))
|
if (!addr.send(msg.value / 2))
|
||||||
throw; // also reverts the transfer to Sharer
|
throw; // also reverts the transfer to Sharer
|
||||||
return this.balance;
|
return this.balance;
|
||||||
@ -337,8 +353,9 @@ arising when writing manual assembly by the following features:
|
|||||||
We now want to describe the inline assembly language in detail.
|
We now want to describe the inline assembly language in detail.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
Inline assembly is still a relatively new feature and might change if it does not prove useful,
|
Inline assembly is a way to access the Ethereum Virtual Machine
|
||||||
so please try to keep up to date.
|
at a low level. This discards several important safety
|
||||||
|
features of Solidity.
|
||||||
|
|
||||||
Example
|
Example
|
||||||
-------
|
-------
|
||||||
|
@ -317,17 +317,12 @@ providing any data or if someone messed up the types so that they tried to
|
|||||||
call a function that does not exist.
|
call a function that does not exist.
|
||||||
|
|
||||||
The default behaviour (if no fallback function is explicitly given) in
|
The default behaviour (if no fallback function is explicitly given) in
|
||||||
these situations is to just accept the call and do nothing.
|
these situations is to throw an exception.
|
||||||
This is desireable in many cases, but should only be used if there is
|
|
||||||
a way to pull out Ether from a contract.
|
|
||||||
|
|
||||||
If the contract is not meant to receive Ether with simple transfers, you
|
If the contract is meant to receive Ether with simple transfers, you
|
||||||
should implement the fallback function as
|
should implement the fallback function as
|
||||||
|
|
||||||
``function() { throw; }``
|
``function() payable { }``
|
||||||
|
|
||||||
this will cause all transactions to this contract that do not call an
|
|
||||||
existing function to be reverted, so that all Ether is sent back.
|
|
||||||
|
|
||||||
Another use of the fallback function is to e.g. register that your
|
Another use of the fallback function is to e.g. register that your
|
||||||
contract received ether by using an event.
|
contract received ether by using an event.
|
||||||
@ -488,6 +483,8 @@ What happens if you send ether along with a function call to a contract?
|
|||||||
========================================================================
|
========================================================================
|
||||||
|
|
||||||
It gets added to the total balance of the contract, just like when you send ether when creating a contract.
|
It gets added to the total balance of the contract, just like when you send ether when creating a contract.
|
||||||
|
You can only send ether along to a function that has the ``payable`` modifier,
|
||||||
|
otherwise an exception is thrown.
|
||||||
|
|
||||||
Is it possible to get a tx receipt for a transaction executed contract-to-contract?
|
Is it possible to get a tx receipt for a transaction executed contract-to-contract?
|
||||||
===================================================================================
|
===================================================================================
|
||||||
|
@ -71,6 +71,9 @@ Discontinued:
|
|||||||
Solidity Tools
|
Solidity Tools
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
* `Dapple <https://github.com/nexusdev/dapple>`_
|
||||||
|
Package and deployment manager for Solidity.
|
||||||
|
|
||||||
* `Solidity REPL <https://github.com/raineorshine/solidity-repl>`_
|
* `Solidity REPL <https://github.com/raineorshine/solidity-repl>`_
|
||||||
Try Solidity instantly with a command-line Solidity console.
|
Try Solidity instantly with a command-line Solidity console.
|
||||||
|
|
||||||
|
@ -30,6 +30,11 @@ Storage
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The first line simply tells that the source code is written for
|
||||||
|
Solidity version 0.4.0 or anything newer that does not break functionality
|
||||||
|
(up to, but not including, version 0.5.0). This is to ensure that the
|
||||||
|
contract does not suddenly behave differently with a new compiler version.
|
||||||
|
|
||||||
A contract in the sense of Solidity is a collection of code (its functions) and
|
A contract in the sense of Solidity is a collection of code (its functions) and
|
||||||
data (its *state*) that resides at a specific address on the Ethereum
|
data (its *state*) that resides at a specific address on the Ethereum
|
||||||
blockchain. The line ``uint storedData;`` declares a state variable called ``storedData`` of
|
blockchain. The line ``uint storedData;`` declares a state variable called ``storedData`` of
|
||||||
|
@ -212,7 +212,6 @@ Tips and Tricks
|
|||||||
* Make your state variables public - the compiler will create :ref:`getters <visibility-and-accessors>` for you for free.
|
* Make your state variables public - the compiler will create :ref:`getters <visibility-and-accessors>` for you for free.
|
||||||
* If you end up checking conditions on input or state a lot at the beginning of your functions, try using :ref:`modifiers`.
|
* If you end up checking conditions on input or state a lot at the beginning of your functions, try using :ref:`modifiers`.
|
||||||
* If your contract has a function called ``send`` but you want to use the built-in send-function, use ``address(contractVariable).send(amount)``.
|
* If your contract has a function called ``send`` but you want to use the built-in send-function, use ``address(contractVariable).send(amount)``.
|
||||||
* If you do **not** want your contracts to receive ether when called via ``send``, you can add a throwing fallback function ``function() { throw; }``.
|
|
||||||
* Initialise storage structs with a single assignment: ``x = MyStruct({a: 1, b: 2});``
|
* Initialise storage structs with a single assignment: ``x = MyStruct({a: 1, b: 2});``
|
||||||
|
|
||||||
**********
|
**********
|
||||||
@ -338,3 +337,4 @@ Modifiers
|
|||||||
- ``constant`` for functions: Disallows modification of state - this is not enforced yet.
|
- ``constant`` for functions: Disallows modification of state - this is not enforced yet.
|
||||||
- ``anonymous`` for events: Does not store event signature as topic.
|
- ``anonymous`` for events: Does not store event signature as topic.
|
||||||
- ``indexed`` for event parameters: Stores the parameter as topic.
|
- ``indexed`` for event parameters: Stores the parameter as topic.
|
||||||
|
- ``payable`` for functions: Allows them to receive Ether together with a call.
|
||||||
|
@ -51,7 +51,7 @@ complete contract):
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
|
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
|
||||||
contract Fund {
|
contract Fund {
|
||||||
@ -75,7 +75,7 @@ outlined further below:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract Fund {
|
contract Fund {
|
||||||
/// Mapping of ether shares of the contract.
|
/// Mapping of ether shares of the contract.
|
||||||
@ -107,6 +107,11 @@ and stall those. Please be explicit about such cases in the documentation of you
|
|||||||
Sending and Receiving Ether
|
Sending and Receiving Ether
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
- Neither contracts nor "external accounts" are currently able to prevent that someone sends them Ether.
|
||||||
|
Contracts can react on and reject a regular transfer, but there are ways
|
||||||
|
to move Ether without creating a message call. One way is to simply "mine to"
|
||||||
|
the contract address and the second way is using ``selfdestruct(x)``.
|
||||||
|
|
||||||
- If a contract receives Ether (without a function being called), the fallback function is executed.
|
- If a contract receives Ether (without a function being called), the fallback function is executed.
|
||||||
If it does not have a fallback function, the Ether will be rejected (by throwing an exception).
|
If it does not have a fallback function, the Ether will be rejected (by throwing an exception).
|
||||||
During the execution of the fallback function, the contract can only rely
|
During the execution of the fallback function, the contract can only rely
|
||||||
@ -155,6 +160,7 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like
|
|||||||
|
|
||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
|
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
|
||||||
contract TxUserWallet {
|
contract TxUserWallet {
|
||||||
address owner;
|
address owner;
|
||||||
|
|
||||||
@ -186,7 +192,7 @@ Now someone tricks you into sending ether to the address of this attack wallet:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
If your wallet had checked msg.sender for authorization, it would get the address of the attack wallet, instead of the owner address. But by checking tx.origin, it gets the original address that kicked off the transaction, which is still the owner address. The attack wallet instantly drains all your funds.
|
If your wallet had checked ``msg.sender`` for authorization, it would get the address of the attack wallet, instead of the owner address. But by checking ``tx.origin``, it gets the original address that kicked off the transaction, which is still the owner address. The attack wallet instantly drains all your funds.
|
||||||
|
|
||||||
|
|
||||||
Minor Details
|
Minor Details
|
||||||
|
@ -255,10 +255,12 @@ activate themselves.
|
|||||||
/// together with this transaction.
|
/// together with this transaction.
|
||||||
/// The value will only be refunded if the
|
/// The value will only be refunded if the
|
||||||
/// auction is not won.
|
/// auction is not won.
|
||||||
function bid() {
|
function bid() payable {
|
||||||
// No arguments are necessary, all
|
// No arguments are necessary, all
|
||||||
// information is already part of
|
// information is already part of
|
||||||
// the transaction.
|
// the transaction. The keyword payable
|
||||||
|
// is required for the function to
|
||||||
|
// be able to receive Ether.
|
||||||
if (now > auctionStart + biddingTime) {
|
if (now > auctionStart + biddingTime) {
|
||||||
// Revert the call if the bidding
|
// Revert the call if the bidding
|
||||||
// period is over.
|
// period is over.
|
||||||
@ -330,16 +332,6 @@ activate themselves.
|
|||||||
if (!beneficiary.send(highestBid))
|
if (!beneficiary.send(highestBid))
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function () {
|
|
||||||
// This function gets executed if a
|
|
||||||
// transaction with invalid data is sent to
|
|
||||||
// the contract or just ether without data.
|
|
||||||
// We revert the send so that no-one
|
|
||||||
// accidentally loses money when using the
|
|
||||||
// contract.
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Blind Auction
|
Blind Auction
|
||||||
@ -433,6 +425,7 @@ high or low invalid bids.
|
|||||||
/// still make the required deposit. The same address can
|
/// still make the required deposit. The same address can
|
||||||
/// place multiple bids.
|
/// place multiple bids.
|
||||||
function bid(bytes32 _blindedBid)
|
function bid(bytes32 _blindedBid)
|
||||||
|
payable
|
||||||
onlyBefore(biddingEnd)
|
onlyBefore(biddingEnd)
|
||||||
{
|
{
|
||||||
bids[msg.sender].push(Bid({
|
bids[msg.sender].push(Bid({
|
||||||
@ -535,10 +528,6 @@ high or low invalid bids.
|
|||||||
if (!beneficiary.send(this.balance))
|
if (!beneficiary.send(this.balance))
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function () {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.. index:: purchase, remote purchase, escrow
|
.. index:: purchase, remote purchase, escrow
|
||||||
@ -558,7 +547,7 @@ Safe Remote Purchase
|
|||||||
enum State { Created, Locked, Inactive }
|
enum State { Created, Locked, Inactive }
|
||||||
State public state;
|
State public state;
|
||||||
|
|
||||||
function Purchase() {
|
function Purchase() payable {
|
||||||
seller = msg.sender;
|
seller = msg.sender;
|
||||||
value = msg.value / 2;
|
value = msg.value / 2;
|
||||||
if (2 * value != msg.value) throw;
|
if (2 * value != msg.value) throw;
|
||||||
@ -566,22 +555,22 @@ Safe Remote Purchase
|
|||||||
|
|
||||||
modifier require(bool _condition) {
|
modifier require(bool _condition) {
|
||||||
if (!_condition) throw;
|
if (!_condition) throw;
|
||||||
_
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlyBuyer() {
|
modifier onlyBuyer() {
|
||||||
if (msg.sender != buyer) throw;
|
if (msg.sender != buyer) throw;
|
||||||
_
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier onlySeller() {
|
modifier onlySeller() {
|
||||||
if (msg.sender != seller) throw;
|
if (msg.sender != seller) throw;
|
||||||
_
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
modifier inState(State _state) {
|
modifier inState(State _state) {
|
||||||
if (state != _state) throw;
|
if (state != _state) throw;
|
||||||
_
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
event aborted();
|
event aborted();
|
||||||
@ -608,6 +597,7 @@ Safe Remote Purchase
|
|||||||
function confirmPurchase()
|
function confirmPurchase()
|
||||||
inState(State.Created)
|
inState(State.Created)
|
||||||
require(msg.value == 2 * value)
|
require(msg.value == 2 * value)
|
||||||
|
payable
|
||||||
{
|
{
|
||||||
purchaseConfirmed();
|
purchaseConfirmed();
|
||||||
buyer = msg.sender;
|
buyer = msg.sender;
|
||||||
@ -630,10 +620,6 @@ Safe Remote Purchase
|
|||||||
if (!buyer.send(value) || !seller.send(this.balance))
|
if (!buyer.send(value) || !seller.send(this.balance))
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
function() {
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
********************
|
********************
|
||||||
|
@ -43,7 +43,7 @@ Functions are the executable units of code within a contract.
|
|||||||
pragma solidity ^0.4.0;
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract SimpleAuction {
|
contract SimpleAuction {
|
||||||
function bid() { // Function
|
function bid() payable { // Function
|
||||||
// ...
|
// ...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -69,7 +69,7 @@ Function modifiers can be used to amend the semantics of functions in a declarat
|
|||||||
|
|
||||||
modifier onlySeller() { // Modifier
|
modifier onlySeller() { // Modifier
|
||||||
if (msg.sender != seller) throw;
|
if (msg.sender != seller) throw;
|
||||||
_
|
_;
|
||||||
}
|
}
|
||||||
|
|
||||||
function abort() onlySeller { // Modifier usage
|
function abort() onlySeller { // Modifier usage
|
||||||
@ -91,7 +91,7 @@ Events are convenience interfaces with the EVM logging facilities.
|
|||||||
contract SimpleAuction {
|
contract SimpleAuction {
|
||||||
event HighestBidIncreased(address bidder, uint amount); // Event
|
event HighestBidIncreased(address bidder, uint amount); // Event
|
||||||
|
|
||||||
function bid() {
|
function bid() payable {
|
||||||
// ...
|
// ...
|
||||||
HighestBidIncreased(msg.sender, msg.value); // Triggering event
|
HighestBidIncreased(msg.sender, msg.value); // Triggering event
|
||||||
}
|
}
|
||||||
|
@ -615,7 +615,7 @@ indistinguishable from the numerals one and zero.
|
|||||||
Contract and Library Names
|
Contract and Library Names
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
Contracts should be named using the CapWords style.
|
Contracts and libraries should be named using the CapWords style.
|
||||||
|
|
||||||
|
|
||||||
Events
|
Events
|
||||||
|
@ -559,7 +559,7 @@ shown in the following example:
|
|||||||
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
|
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function contribute(uint campaignID) {
|
function contribute(uint campaignID) payable {
|
||||||
Campaign c = campaigns[campaignID];
|
Campaign c = campaigns[campaignID];
|
||||||
// Creates a new temporary memory struct, initialised with the given values
|
// Creates a new temporary memory struct, initialised with the given values
|
||||||
// and copies it over to storage.
|
// and copies it over to storage.
|
||||||
@ -572,9 +572,10 @@ shown in the following example:
|
|||||||
Campaign c = campaigns[campaignID];
|
Campaign c = campaigns[campaignID];
|
||||||
if (c.amount < c.fundingGoal)
|
if (c.amount < c.fundingGoal)
|
||||||
return false;
|
return false;
|
||||||
if (!c.beneficiary.send(c.amount))
|
uint amount = c.amount;
|
||||||
throw;
|
|
||||||
c.amount = 0;
|
c.amount = 0;
|
||||||
|
if (!c.beneficiary.send(amount))
|
||||||
|
throw;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -636,6 +637,8 @@ It is important to note that ``delete a`` really behaves like an assignment to `
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
pragma solidity ^0.4.0;
|
||||||
|
|
||||||
contract DeleteExample {
|
contract DeleteExample {
|
||||||
uint data;
|
uint data;
|
||||||
uint[] dataArray;
|
uint[] dataArray;
|
||||||
|
Loading…
Reference in New Issue
Block a user