Merge pull request #2831 from ethereum/docs

Various doc updates
This commit is contained in:
Alex Beregszaszi 2017-08-28 12:47:44 +01:00 committed by GitHub
commit b3c251c154
7 changed files with 30 additions and 23 deletions

View File

@ -214,6 +214,7 @@ In total::
0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000
If we wanted to call `sam` with the arguments `"dave"`, `true` and `[1,2,3]`, we would pass 292 bytes total, broken down into:
- `0xa5643bf2`: the Method ID. This is derived from the signature `sam(bytes,bool,uint256[])`. Note that `uint` is replaced with its canonical representation `uint256`.
- `0x0000000000000000000000000000000000000000000000000000000000000060`: the location of the data part of the first parameter (dynamic type), measured in bytes from the start of the arguments block. In this case, `0x60`.
- `0x0000000000000000000000000000000000000000000000000000000000000001`: the second parameter: boolean true.

View File

@ -9,9 +9,10 @@ This assembly language can also be used as "inline assembly" inside Solidity
source code. We start with describing how to use inline assembly and how it
differs from standalone assembly and then specify assembly itself.
TODO: Write about how scoping rules of inline assembly are a bit different
and the complications that arise when for example using internal functions
of libraries. Furthermore, write about the symbols defined by the compiler.
.. note::
TODO: Write about how scoping rules of inline assembly are a bit different
and the complications that arise when for example using internal functions
of libraries. Furthermore, write about the symbols defined by the compiler.
.. _inline-assembly:
@ -76,7 +77,7 @@ you really know what you are doing.
.. code::
pragma solidity ^0.4.0;
pragma solidity ^0.4.12;
library VectorSum {
// This function is less efficient because the optimizer currently fails to
@ -1005,7 +1006,7 @@ that modifies the stack and with every label that is annotated with a stack
adjustment. Every time a new
local variable is introduced, it is registered together with the current
stack height. If a variable is accessed (either for copying its value or for
assignment), the appropriate DUP or SWAP instruction is selected depending
assignment), the appropriate ``DUP`` or ``SWAP`` instruction is selected depending
on the difference between the current stack height and the
stack height at the point the variable was introduced.

View File

@ -508,6 +508,7 @@ Pure Functions
Functions can be declared ``pure`` in which case they promise not to read from or modify the state.
In addition to the list of state modifying statements explained above, the following are considered reading from the state:
#. Reading from state variables.
#. Accessing ``this.balance`` or ``<address>.balance``.
#. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``).
@ -1118,7 +1119,7 @@ are all compiled as calls (``DELEGATECALL``) to an external
contract/library. If you use libraries, take care that an
actual external function call is performed.
``msg.sender``, ``msg.value`` and ``this`` will retain their values
in this call, though (prior to Homestead, because of the use of `CALLCODE`, ``msg.sender`` and
in this call, though (prior to Homestead, because of the use of ``CALLCODE``, ``msg.sender`` and
``msg.value`` changed, though).
The following example shows how to use memory types and

View File

@ -389,6 +389,9 @@ There are two other ways to trigger exceptions: The ``revert`` function can be u
revert the current call. In the future it might be possible to also include details about the error
in a call to ``revert``. The ``throw`` keyword can also be used as an alternative to ``revert()``.
.. note::
From version 0.4.13 the ``throw`` keyword is deprecated and will be phased out in the future.
When exceptions happen in a sub-call, they "bubble up" (i.e. exceptions are rethrown) automatically. Exceptions to this rule are ``send``
and the low-level functions ``call``, ``delegatecall`` and ``callcode`` -- those return ``false`` in case
of an exception instead of "bubbling up".

View File

@ -84,10 +84,8 @@ Layout of Call Data
*******************
When a Solidity contract is deployed and when it is called from an
account, the input data is assumed to be in the format in `the ABI
specification
<https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI>`_. The
ABI specification requires arguments to be padded to multiples of 32
account, the input data is assumed to be in the format in :ref:`the ABI
specification <ABI>`. The ABI specification requires arguments to be padded to multiples of 32
bytes. The internal function calls use a different convention.
@ -145,13 +143,13 @@ Different types have different rules for cleaning up invalid values:
Internals - The Optimizer
*************************
The Solidity optimizer operates on assembly, so it can be and also is used by other languages. It splits the sequence of instructions into basic blocks at JUMPs and JUMPDESTs. Inside these blocks, the instructions are analysed and every modification to the stack, to memory or storage is recorded as an expression which consists of an instruction and a list of arguments which are essentially pointers to other expressions. The main idea is now to find expressions that are always equal (on every input) and combine them into an expression class. The optimizer first tries to find each new expression in a list of already known expressions. If this does not work, the expression is simplified according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is done recursively, we can also apply the latter rule if the second factor is a more complex expression where we know that it will always evaluate to one. Modifications to storage and memory locations have to erase knowledge about storage and memory locations which are not known to be different: If we first write to location x and then to location y and both are input variables, the second could overwrite the first, so we actually do not know what is stored at x after we wrote to y. On the other hand, if a simplification of the expression x - y evaluates to a non-zero constant, we know that we can keep our knowledge about what is stored at x.
The Solidity optimizer operates on assembly, so it can be and also is used by other languages. It splits the sequence of instructions into basic blocks at ``JUMPs`` and ``JUMPDESTs``. Inside these blocks, the instructions are analysed and every modification to the stack, to memory or storage is recorded as an expression which consists of an instruction and a list of arguments which are essentially pointers to other expressions. The main idea is now to find expressions that are always equal (on every input) and combine them into an expression class. The optimizer first tries to find each new expression in a list of already known expressions. If this does not work, the expression is simplified according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is done recursively, we can also apply the latter rule if the second factor is a more complex expression where we know that it will always evaluate to one. Modifications to storage and memory locations have to erase knowledge about storage and memory locations which are not known to be different: If we first write to location x and then to location y and both are input variables, the second could overwrite the first, so we actually do not know what is stored at x after we wrote to y. On the other hand, if a simplification of the expression x - y evaluates to a non-zero constant, we know that we can keep our knowledge about what is stored at x.
At the end of this process, we know which expressions have to be on the stack in the end and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all JUMP and JUMPI instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown JUMP. If a JUMPI is found whose condition evaluates to a constant, it is transformed to an unconditional jump.
At the end of this process, we know which expressions have to be on the stack in the end and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all ``JUMP`` and ``JUMPI`` instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown ``JUMP``. If a ``JUMPI`` is found whose condition evaluates to a constant, it is transformed to an unconditional jump.
As the last step, the code in each block is completely re-generated. A dependency graph is created from the expressions on the stack at the end of the block and every operation that is not part of this graph is essentially dropped. Now code is generated that applies the modifications to memory and storage in the order they were made in the original code (dropping modifications which were found not to be needed) and finally, generates all values that are required to be on the stack in the correct place.
These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a JUMPI and during the analysis, the condition evaluates to a constant, the JUMPI is replaced depending on the value of the constant, and thus code like
These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a ``JUMPI`` and during the analysis, the condition evaluates to a constant, the ``JUMPI`` is replaced depending on the value of the constant, and thus code like
::
@ -330,7 +328,7 @@ Encoding of the Metadata Hash in the Bytecode
Because we might support other ways to retrieve the metadata file in the future,
the mapping ``{"bzzr0": <Swarm hash>}`` is stored
[CBOR](https://tools.ietf.org/html/rfc7049)-encoded. Since the beginning of that
`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the beginning of that
encoding is not easy to find, its length is added in a two-byte big-endian
encoding. The current version of the Solidity compiler thus adds the following
to the end of the deployed bytecode::
@ -361,7 +359,7 @@ In order to verify the compilation, sources can be retrieved from Swarm
via the link in the metadata file.
The compiler of the correct version (which is checked to be part of the "official" compilers)
is invoked on that input with the specified settings. The resulting
bytecode is compared to the data of the creation transaction or CREATE opcode data.
bytecode is compared to the data of the creation transaction or ``CREATE`` opcode data.
This automatically verifies the metadata since its hash is part of the bytecode.
Excess data corresponds to the constructor input data, which should be decoded
according to the interface and presented to the user.
@ -372,7 +370,7 @@ Tips and Tricks
***************
* Use ``delete`` on arrays to delete all its elements.
* Use shorter types for struct elements and sort them such that short types are grouped together. This can lower the gas costs as multiple SSTORE operations might be combined into a single (SSTORE costs 5000 or 20000 gas, so this is what you want to optimise). Use the gas price estimator (with optimiser enabled) to check!
* Use shorter types for struct elements and sort them such that short types are grouped together. This can lower the gas costs as multiple ``SSTORE`` operations might be combined into a single (``SSTORE`` costs 5000 or 20000 gas, so this is what you want to optimise). Use the gas price estimator (with optimiser enabled) to check!
* Make your state variables public - the compiler will create :ref:`getters <visibility-and-getters>` for you automatically.
* 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)``.
@ -469,7 +467,7 @@ Global Variables
- ``require(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for malformed input or error in external component)
- ``revert()``: abort execution and revert state changes
- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments
- ``sha3(...) returns (bytes32)``: an alias to `keccak256`
- ``sha3(...) returns (bytes32)``: an alias to ``keccak256``
- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the (tightly packed) arguments
- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the (tightly packed) arguments
- ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error
@ -478,7 +476,7 @@ Global Variables
- ``this`` (current contract's type): the current contract, explicitly convertible to ``address``
- ``super``: the contract one level higher in the inheritance hierarchy
- ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address
- ``suicide(address recipieint)``: an alias to `selfdestruct``
- ``suicide(address recipieint)``: an alias to ``selfdestruct``
- ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei
- ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure
- ``<address>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure
@ -519,7 +517,7 @@ Reserved Keywords
These keywords are reserved in Solidity. They might become part of the syntax in the future:
``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``let``, ``match``, ``null``,
``of``, ``pure``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``, ``view``.
``of``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``.
Language Grammar
================

View File

@ -535,6 +535,9 @@ Safe Remote Purchase
enum State { Created, Locked, Inactive }
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.
function Purchase() payable {
seller = msg.sender;
value = msg.value / 2;

View File

@ -54,7 +54,7 @@ Operators:
* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation)
* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift)
Division always truncates (it is just compiled to the DIV opcode of the EVM), but it does not truncate if both
Division always truncates (it is just compiled to the ``DIV`` opcode of the EVM), but it does not truncate if both
operators are :ref:`literals<rational_literals>` (or literal expressions).
Division by zero and modulus with zero throws a runtime exception.
@ -467,10 +467,10 @@ context, there is always a default, but it can be overridden by appending
either ``storage`` or ``memory`` to the type. The default for function parameters (including return parameters) is ``memory``, the default for local variables is ``storage`` and the location is forced
to ``storage`` for state variables (obviously).
There is also a third data location, "calldata", which is a non-modifiable,
There is also a third data location, ``calldata``, which is a non-modifiable,
non-persistent area where function arguments are stored. Function parameters
(not return parameters) of external functions are forced to "calldata" and
behave mostly like memory.
(not return parameters) of external functions are forced to ``calldata`` and
behave mostly like ``memory``.
Data locations are important because they change how assignments behave:
assignments between storage and memory and also to a state variable (even from other state variables)