diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/abi-spec.rst | 345 | ||||
-rw-r--r-- | docs/assembly.rst | 1022 | ||||
-rw-r--r-- | docs/bugs.json | 110 | ||||
-rw-r--r-- | docs/bugs.rst | 61 | ||||
-rw-r--r-- | docs/bugs_by_version.json | 373 | ||||
-rw-r--r-- | docs/common-patterns.rst | 57 | ||||
-rw-r--r-- | docs/conf.py | 12 | ||||
-rw-r--r-- | docs/contracts.rst | 162 | ||||
-rw-r--r-- | docs/contributing.rst | 21 | ||||
-rw-r--r-- | docs/control-structures.rst | 565 | ||||
-rw-r--r-- | docs/frequently-asked-questions.rst | 17 | ||||
-rw-r--r-- | docs/grammar.txt | 81 | ||||
-rw-r--r-- | docs/index.rst | 46 | ||||
-rw-r--r-- | docs/installing-solidity.rst | 84 | ||||
-rw-r--r-- | docs/introduction-to-smart-contracts.rst | 37 | ||||
-rw-r--r-- | docs/layout-of-source-files.rst | 21 | ||||
-rw-r--r-- | docs/logo.svg | 27 | ||||
-rw-r--r-- | docs/miscellaneous.rst | 150 | ||||
-rw-r--r-- | docs/security-considerations.rst | 37 | ||||
-rw-r--r-- | docs/solidity-by-example.rst | 145 | ||||
-rw-r--r-- | docs/solidity-in-depth.rst | 1 | ||||
-rw-r--r-- | docs/structure-of-a-contract.rst | 8 | ||||
-rw-r--r-- | docs/style-guide.rst | 81 | ||||
-rw-r--r-- | docs/types.rst | 110 | ||||
-rw-r--r-- | docs/units-and-global-variables.rst | 34 | ||||
-rw-r--r-- | docs/using-the-compiler.rst | 275 | ||||
-rw-r--r-- | docs/utils/SolidityLexer.py | 27 |
27 files changed, 3002 insertions, 907 deletions
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst new file mode 100644 index 00000000..e39c8861 --- /dev/null +++ b/docs/abi-spec.rst @@ -0,0 +1,345 @@ +.. index:: abi, application binary interface + +.. _ABI: + +****************************************** +Application Binary Interface Specification +****************************************** + +Basic design +============ + +The Application Binary Interface is the standard way to interact with contracts in the Ethereum ecosystem, both +from outside the blockchain and for contract-to-contract interaction. Data is encoded following its type, +according to this specification. + +We assume the Application Binary Interface (ABI) is strongly typed, known at compilation time and static. No introspection mechanism will be provided. We assert that all contracts will have the interface definitions of any contracts they call available at compile-time. + +This specification does not address contracts whose interface is dynamic or otherwise known only at run-time. Should these cases become important they can be adequately handled as facilities built within the Ethereum ecosystem. + +Function Selector +================= + +The first four bytes of the call data for a function call specifies the function to be called. It is the +first (left, high-order in big-endian) four bytes of the Keccak (SHA-3) hash of the signature of the function. The signature is defined as the canonical expression of the basic prototype, i.e. +the function name with the parenthesised list of parameter types. Parameter types are split by a single comma - no spaces are used. + +Argument Encoding +================= + +Starting from the fifth byte, the encoded arguments follow. This encoding is also used in other places, e.g. the return values and also event arguments are encoded in the same way, without the four bytes specifying the function. + +Types +===== + +The following elementary types exist: + +- `uint<M>`: unsigned integer type of `M` bits, `0 < M <= 256`, `M % 8 == 0`. e.g. `uint32`, `uint8`, `uint256`. + +- `int<M>`: two's complement signed integer type of `M` bits, `0 < M <= 256`, `M % 8 == 0`. + +- `address`: equivalent to `uint160`, except for the assumed interpretation and language typing. + +- `uint`, `int`: synonyms for `uint256`, `int256` respectively (not to be used for computing the function selector). + +- `bool`: equivalent to `uint8` restricted to the values 0 and 1 + +- `fixed<M>x<N>`: signed fixed-point decimal number of `M` bits, `0 < M <= 256`, `M % 8 ==0`, and `0 < N <= 80`, which denotes the value `v` as `v / (10 ** N)`. + +- `ufixed<M>x<N>`: unsigned variant of `fixed<M>x<N>`. + +- `fixed`, `ufixed`: synonyms for `fixed128x19`, `ufixed128x19` respectively (not to be used for computing the function selector). + +- `bytes<M>`: binary type of `M` bytes, `0 < M <= 32`. + +- `function`: equivalent to `bytes24`: an address, followed by a function selector + +The following (fixed-size) array type exists: + +- `<type>[M]`: a fixed-length array of the given fixed-length type. + +The following non-fixed-size types exist: + +- `bytes`: dynamic sized byte sequence. + +- `string`: dynamic sized unicode string assumed to be UTF-8 encoded. + +- `<type>[]`: a variable-length array of the given fixed-length type. + +Types can be combined to anonymous structs by enclosing a finite non-negative number +of them inside parentheses, separated by commas: + +- `(T1,T2,...,Tn)`: anonymous struct (ordered tuple) consisting of the types `T1`, ..., `Tn`, `n >= 0` + +It is possible to form structs of structs, arrays of structs and so on. + + +Formal Specification of the Encoding +==================================== + +We will now formally specify the encoding, such that it will have the following +properties, which are especially useful if some arguments are nested arrays: + +Properties: + + 1. The number of reads necessary to access a value is at most the depth of the value inside the argument array structure, i.e. four reads are needed to retrieve `a_i[k][l][r]`. In a previous version of the ABI, the number of reads scaled linearly with the total number of dynamic parameters in the worst case. + + 2. The data of a variable or array element is not interleaved with other data and it is relocatable, i.e. it only uses relative "addresses" + +We distinguish static and dynamic types. Static types are encoded in-place and dynamic types are encoded at a separately allocated location after the current block. + +**Definition:** The following types are called "dynamic": +* `bytes` +* `string` +* `T[]` for any `T` +* `T[k]` for any dynamic `T` and any `k > 0` + +All other types are called "static". + +**Definition:** `len(a)` is the number of bytes in a binary string `a`. +The type of `len(a)` is assumed to be `uint256`. + +We define `enc`, the actual encoding, as a mapping of values of the ABI types to binary strings such +that `len(enc(X))` depends on the value of `X` if and only if the type of `X` is dynamic. + +**Definition:** For any ABI value `X`, we recursively define `enc(X)`, depending +on the type of `X` being + +- `(T1,...,Tk)` for `k >= 0` and any types `T1`, ..., `Tk` + + `enc(X) = head(X(1)) ... head(X(k-1)) tail(X(0)) ... tail(X(k-1))` + + where `X(i)` is the `ith` component of the value, and + `head` and `tail` are defined for `Ti` being a static type as + + `head(X(i)) = enc(X(i))` and `tail(X(i)) = ""` (the empty string) + + and as + + `head(X(i)) = enc(len(head(X(0)) ... head(X(k-1)) tail(X(0)) ... tail(X(i-1))))` + `tail(X(i)) = enc(X(i))` + + otherwise, i.e. if `Ti` is a dynamic type. + + Note that in the dynamic case, `head(X(i))` is well-defined since the lengths of + the head parts only depend on the types and not the values. Its value is the offset + of the beginning of `tail(X(i))` relative to the start of `enc(X)`. + +- `T[k]` for any `T` and `k`: + + `enc(X) = enc((X[0], ..., X[k-1]))` + + i.e. it is encoded as if it were an anonymous struct with `k` elements + of the same type. + +- `T[]` where `X` has `k` elements (`k` is assumed to be of type `uint256`): + + `enc(X) = enc(k) enc([X[1], ..., X[k]])` + + i.e. it is encoded as if it were an array of static size `k`, prefixed with + the number of elements. + +- `bytes`, of length `k` (which is assumed to be of type `uint256`): + + `enc(X) = enc(k) pad_right(X)`, i.e. the number of bytes is encoded as a + `uint256` followed by the actual value of `X` as a byte sequence, followed by + the minimum number of zero-bytes such that `len(enc(X))` is a multiple of 32. + +- `string`: + + `enc(X) = enc(enc_utf8(X))`, i.e. `X` is utf-8 encoded and this value is interpreted as of `bytes` type and encoded further. Note that the length used in this subsequent encoding is the number of bytes of the utf-8 encoded string, not its number of characters. + +- `uint<M>`: `enc(X)` is the big-endian encoding of `X`, padded on the higher-order (left) side with zero-bytes such that the length is a multiple of 32 bytes. +- `address`: as in the `uint160` case +- `int<M>`: `enc(X)` is the big-endian two's complement encoding of `X`, padded on the higher-oder (left) side with `0xff` for negative `X` and with zero bytes for positive `X` such that the length is a multiple of 32 bytes. +- `bool`: as in the `uint8` case, where `1` is used for `true` and `0` for `false` +- `fixed<M>x<N>`: `enc(X)` is `enc(X * 10**N)` where `X * 10**N` is interpreted as a `int256`. +- `fixed`: as in the `fixed128x19` case +- `ufixed<M>x<N>`: `enc(X)` is `enc(X * 10**N)` where `X * 10**N` is interpreted as a `uint256`. +- `ufixed`: as in the `ufixed128x19` case +- `bytes<M>`: `enc(X)` is the sequence of bytes in `X` padded with zero-bytes to a length of 32. + +Note that for any `X`, `len(enc(X))` is a multiple of 32. + +Function Selector and Argument Encoding +======================================= + +All in all, a call to the function `f` with parameters `a_1, ..., a_n` is encoded as + + `function_selector(f) enc((a_1, ..., a_n))` + +and the return values `v_1, ..., v_k` of `f` are encoded as + + `enc((v_1, ..., v_k))` + +i.e. the values are combined into an anonymous struct and encoded. + +Examples +======== + +Given the contract: + +:: + + contract Foo { + function bar(bytes3[2] xy) {} + function baz(uint32 x, bool y) returns (bool r) { r = x > 32 || y; } + function sam(bytes name, bool z, uint[] data) {} + } + + +Thus for our `Foo` example if we wanted to call `baz` with the parameters `69` and `true`, we would pass 68 bytes total, which can be broken down into: + +- `0xcdcd77c0`: the Method ID. This is derived as the first 4 bytes of the Keccak hash of the ASCII form of the signature `baz(uint32,bool)`. +- `0x0000000000000000000000000000000000000000000000000000000000000045`: the first parameter, a uint32 value `69` padded to 32 bytes +- `0x0000000000000000000000000000000000000000000000000000000000000001`: the second parameter - boolean `true`, padded to 32 bytes + +In total:: + + 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001 + +It returns a single `bool`. If, for example, it were to return `false`, its output would be the single byte array `0x0000000000000000000000000000000000000000000000000000000000000000`, a single bool. + +If we wanted to call `bar` with the argument `["abc", "def"]`, we would pass 68 bytes total, broken down into: + +- `0xfce353f6`: the Method ID. This is derived from the signature `bar(bytes3[2])`. +- `0x6162630000000000000000000000000000000000000000000000000000000000`: the first part of the first parameter, a `bytes3` value `"abc"` (left-aligned). +- `0x6465660000000000000000000000000000000000000000000000000000000000`: the second part of the first parameter, a `bytes3` value `"def"` (left-aligned). + +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. +- `0x00000000000000000000000000000000000000000000000000000000000000a0`: the location of the data part of the third parameter (dynamic type), measured in bytes. In this case, `0xa0`. +- `0x0000000000000000000000000000000000000000000000000000000000000004`: the data part of the first argument, it starts with the length of the byte array in elements, in this case, 4. +- `0x6461766500000000000000000000000000000000000000000000000000000000`: the contents of the first argument: the UTF-8 (equal to ASCII in this case) encoding of `"dave"`, padded on the right to 32 bytes. +- `0x0000000000000000000000000000000000000000000000000000000000000003`: the data part of the third argument, it starts with the length of the array in elements, in this case, 3. +- `0x0000000000000000000000000000000000000000000000000000000000000001`: the first entry of the third parameter. +- `0x0000000000000000000000000000000000000000000000000000000000000002`: the second entry of the third parameter. +- `0x0000000000000000000000000000000000000000000000000000000000000003`: the third entry of the third parameter. + +In total:: + + 0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003 + +Use of Dynamic Types +==================== + +A call to a function with the signature `f(uint,uint32[],bytes10,bytes)` with values `(0x123, [0x456, 0x789], "1234567890", "Hello, world!")` is encoded in the following way: + +We take the first four bytes of `sha3("f(uint256,uint32[],bytes10,bytes)")`, i.e. `0x8be65246`. +Then we encode the head parts of all four arguments. For the static types `uint256` and `bytes10`, these are directly the values we want to pass, whereas for the dynamic types `uint32[]` and `bytes`, we use the offset in bytes to the start of their data area, measured from the start of the value encoding (i.e. not counting the first four bytes containing the hash of the function signature). These are: + + - `0x0000000000000000000000000000000000000000000000000000000000000123` (`0x123` padded to 32 bytes) + - `0x0000000000000000000000000000000000000000000000000000000000000080` (offset to start of data part of second parameter, 4*32 bytes, exactly the size of the head part) + - `0x3132333435363738393000000000000000000000000000000000000000000000` (`"1234567890"` padded to 32 bytes on the right) + - `0x00000000000000000000000000000000000000000000000000000000000000e0` (offset to start of data part of fourth parameter = offset to start of data part of first dynamic parameter + size of data part of first dynamic parameter = 4\*32 + 3\*32 (see below)) + +After this, the data part of the first dynamic argument, `[0x456, 0x789]` follows: + + - `0x0000000000000000000000000000000000000000000000000000000000000002` (number of elements of the array, 2) + - `0x0000000000000000000000000000000000000000000000000000000000000456` (first element) + - `0x0000000000000000000000000000000000000000000000000000000000000789` (second element) + +Finally, we encode the data part of the second dynamic argument, `"Hello, world!"`: + + - `0x000000000000000000000000000000000000000000000000000000000000000d` (number of elements (bytes in this case): 13) + - `0x48656c6c6f2c20776f726c642100000000000000000000000000000000000000` (`"Hello, world!"` padded to 32 bytes on the right) + +All together, the encoding is (newline after function selector and each 32-bytes for clarity): + +:: + + 0x8be65246 + 0000000000000000000000000000000000000000000000000000000000000123 + 0000000000000000000000000000000000000000000000000000000000000080 + 3132333435363738393000000000000000000000000000000000000000000000 + 00000000000000000000000000000000000000000000000000000000000000e0 + 0000000000000000000000000000000000000000000000000000000000000002 + 0000000000000000000000000000000000000000000000000000000000000456 + 0000000000000000000000000000000000000000000000000000000000000789 + 000000000000000000000000000000000000000000000000000000000000000d + 48656c6c6f2c20776f726c642100000000000000000000000000000000000000 + +Events +====== + +Events are an abstraction of the Ethereum logging/event-watching protocol. Log entries provide the contract's address, a series of up to four topics and some arbitrary length binary data. Events leverage the existing function ABI in order to interpret this (together with an interface spec) as a properly typed structure. + +Given an event name and series of event parameters, we split them into two sub-series: those which are indexed and those which are not. Those which are indexed, which may number up to 3, are used alongside the Keccak hash of the event signature to form the topics of the log entry. Those which as not indexed form the byte array of the event. + +In effect, a log entry using this ABI is described as: + +- `address`: the address of the contract (intrinsically provided by Ethereum); +- `topics[0]`: `keccak(EVENT_NAME+"("+EVENT_ARGS.map(canonical_type_of).join(",")+")")` (`canonical_type_of` is a function that simply returns the canonical type of a given argument, e.g. for `uint indexed foo`, it would return `uint256`). If the event is declared as `anonymous` the `topics[0]` is not generated; +- `topics[n]`: `EVENT_INDEXED_ARGS[n - 1]` (`EVENT_INDEXED_ARGS` is the series of `EVENT_ARGS` that are indexed); +- `data`: `abi_serialise(EVENT_NON_INDEXED_ARGS)` (`EVENT_NON_INDEXED_ARGS` is the series of `EVENT_ARGS` that are not indexed, `abi_serialise` is the ABI serialisation function used for returning a series of typed values from a function, as described above). + +JSON +==== + +The JSON format for a contract's interface is given by an array of function and/or event descriptions. A function description is a JSON object with the fields: + +- `type`: `"function"`, `"constructor"`, or `"fallback"` (the :ref:`unnamed "default" function <fallback-function>`); +- `name`: the name of the function; +- `inputs`: an array of objects, each of which contains: + * `name`: the name of the parameter; + * `type`: the canonical type of the parameter. +- `outputs`: an array of objects similar to `inputs`, can be omitted if function doesn't return anything; +- `constant`: `true` if function is :ref:`specified to not modify blockchain state <constant-functions>`); +- `payable`: `true` if function accepts ether, defaults to `false`. + +`type` can be omitted, defaulting to `"function"`. + +Constructor and fallback function never have `name` or `outputs`. Fallback function doesn't have `inputs` either. + +Sending non-zero ether to non-payable function will throw. Don't do it. + +An event description is a JSON object with fairly similar fields: + +- `type`: always `"event"` +- `name`: the name of the event; +- `inputs`: an array of objects, each of which contains: + * `name`: the name of the parameter; + * `type`: the canonical type of the parameter. + * `indexed`: `true` if the field is part of the log's topics, `false` if it one of the log's data segment. +- `anonymous`: `true` if the event was declared as `anonymous`. + +For example, + +:: + + contract Test { + function Test(){ b = 0x12345678901234567890123456789012; } + event Event(uint indexed a, bytes32 b) + event Event2(uint indexed a, bytes32 b) + function foo(uint a) { Event(a, b); } + bytes32 b; + } + +would result in the JSON: + +.. code:: json + + [{ + "type":"event", + "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], + "name":"Event" + }, { + "type":"event", + "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], + "name":"Event2" + }, { + "type":"event", + "inputs": [{"name":"a","type":"uint256","indexed":true},{"name":"b","type":"bytes32","indexed":false}], + "name":"Event2" + }, { + "type":"function", + "inputs": [{"name":"a","type":"uint256"}], + "name":"foo", + "outputs": [] + }] diff --git a/docs/assembly.rst b/docs/assembly.rst new file mode 100644 index 00000000..00601371 --- /dev/null +++ b/docs/assembly.rst @@ -0,0 +1,1022 @@ +################# +Solidity Assembly +################# + +.. index:: ! assembly, ! asm, ! evmasm + +Solidity defines an assembly language that can also be used without Solidity. +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. + +.. _inline-assembly: + +Inline Assembly +=============== + +For more fine-grained control especially in order to enhance the language by writing libraries, +it is possible to interleave Solidity statements with inline assembly in a language close +to the one of the virtual machine. Due to the fact that the EVM is a stack machine, it is +often hard to address the correct stack slot and provide arguments to opcodes at the correct +point on the stack. Solidity's inline assembly tries to facilitate that and other issues +arising when writing manual assembly by the following features: + +* functional-style opcodes: ``mul(1, add(2, 3))`` instead of ``push1 3 push1 2 add push1 1 mul`` +* assembly-local variables: ``let x := add(2, 3) let y := mload(0x40) x := add(x, y)`` +* access to external variables: ``function f(uint x) { assembly { x := sub(x, 1) } }`` +* labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))`` +* loops: ``for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }`` +* switch statements: ``switch x case 0 { y := mul(x, 2) } default { y := 0 }`` +* function calls: ``function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } }`` + +We now want to describe the inline assembly language in detail. + +.. warning:: + Inline assembly is a way to access the Ethereum Virtual Machine + at a low level. This discards several important safety + features of Solidity. + +Example +------- + +The following example provides library code to access the code of another contract and +load it into a ``bytes`` variable. This is not possible at all with "plain Solidity" and the +idea is that assembly libraries will be used to enhance the language in such ways. + +.. code:: + + pragma solidity ^0.4.0; + + library GetCode { + function at(address _addr) returns (bytes o_code) { + assembly { + // retrieve the size of the code, this needs assembly + let size := extcodesize(_addr) + // allocate output byte array - this could also be done without assembly + // by using o_code = new bytes(size) + o_code := mload(0x40) + // new "memory end" including padding + mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) + // store length in memory + mstore(o_code, size) + // actually retrieve the code, this needs assembly + extcodecopy(_addr, add(o_code, 0x20), 0, size) + } + } + } + +Inline assembly could also be beneficial in cases where the optimizer fails to produce +efficient code. Please be aware that assembly is much more difficult to write because +the compiler does not perform checks, so you should use it for complex things only if +you really know what you are doing. + +.. code:: + + pragma solidity ^0.4.0; + + library VectorSum { + // This function is less efficient because the optimizer currently fails to + // remove the bounds checks in array access. + function sumSolidity(uint[] _data) returns (uint o_sum) { + for (uint i = 0; i < _data.length; ++i) + o_sum += _data[i]; + } + + // We know that we only access the array in bounds, so we can avoid the check. + // 0x20 needs to be added to an array because the first slot contains the + // array length. + function sumAsm(uint[] _data) returns (uint o_sum) { + for (uint i = 0; i < _data.length; ++i) { + assembly { + o_sum := mload(add(add(_data, 0x20), mul(i, 0x20))) + } + } + } + } + + +Syntax +------ + +Assembly parses comments, literals and identifiers exactly as Solidity, so you can use the +usual ``//`` and ``/* */`` comments. Inline assembly is marked by ``assembly { ... }`` and inside +these curly braces, the following can be used (see the later sections for more details) + + - literals, i.e. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters) + - opcodes (in "instruction style"), e.g. ``mload sload dup1 sstore``, for a list see below + - opcodes in functional style, e.g. ``add(1, mlod(0))`` + - labels, e.g. ``name:`` + - variable declarations, e.g. ``let x := 7`` or ``let x := add(y, 3)`` + - identifiers (labels or assembly-local variables and externals if used as inline assembly), e.g. ``jump(name)``, ``3 x add`` + - assignments (in "instruction style"), e.g. ``3 =: x`` + - assignments in functional style, e.g. ``x := add(y, 3)`` + - blocks where local variables are scoped inside, e.g. ``{ let x := 3 { let y := add(x, 1) } }`` + +Opcodes +------- + +This document does not want to be a full description of the Ethereum virtual machine, but the +following list can be used as a reference of its opcodes. + +If an opcode takes arguments (always from the top of the stack), they are given in parentheses. +Note that the order of arguments can be seen to be reversed in non-functional style (explained below). +Opcodes marked with ``-`` do not push an item onto the stack, those marked with ``*`` are +special and all others push exactly one item onte the stack. + +In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to +(excluding) position ``b`` and ``storage[p]`` signifies the storage contents at position ``p``. + +The opcodes ``pushi`` and ``jumpdest`` cannot be used directly. + +In the grammar, opcodes are represented as pre-defined identifiers. + ++-------------------------+------+-----------------------------------------------------------------+ +| stop + `-` | stop execution, identical to return(0,0) | ++-------------------------+------+-----------------------------------------------------------------+ +| add(x, y) | | x + y | ++-------------------------+------+-----------------------------------------------------------------+ +| sub(x, y) | | x - y | ++-------------------------+------+-----------------------------------------------------------------+ +| mul(x, y) | | x * y | ++-------------------------+------+-----------------------------------------------------------------+ +| div(x, y) | | x / y | ++-------------------------+------+-----------------------------------------------------------------+ +| sdiv(x, y) | | x / y, for signed numbers in two's complement | ++-------------------------+------+-----------------------------------------------------------------+ +| mod(x, y) | | x % y | ++-------------------------+------+-----------------------------------------------------------------+ +| smod(x, y) | | x % y, for signed numbers in two's complement | ++-------------------------+------+-----------------------------------------------------------------+ +| exp(x, y) | | x to the power of y | ++-------------------------+------+-----------------------------------------------------------------+ +| not(x) | | ~x, every bit of x is negated | ++-------------------------+------+-----------------------------------------------------------------+ +| lt(x, y) | | 1 if x < y, 0 otherwise | ++-------------------------+------+-----------------------------------------------------------------+ +| gt(x, y) | | 1 if x > y, 0 otherwise | ++-------------------------+------+-----------------------------------------------------------------+ +| slt(x, y) | | 1 if x < y, 0 otherwise, for signed numbers in two's complement | ++-------------------------+------+-----------------------------------------------------------------+ +| sgt(x, y) | | 1 if x > y, 0 otherwise, for signed numbers in two's complement | ++-------------------------+------+-----------------------------------------------------------------+ +| eq(x, y) | | 1 if x == y, 0 otherwise | ++-------------------------+------+-----------------------------------------------------------------+ +| iszero(x) | | 1 if x == 0, 0 otherwise | ++-------------------------+------+-----------------------------------------------------------------+ +| and(x, y) | | bitwise and of x and y | ++-------------------------+------+-----------------------------------------------------------------+ +| or(x, y) | | bitwise or of x and y | ++-------------------------+------+-----------------------------------------------------------------+ +| xor(x, y) | | bitwise xor of x and y | ++-------------------------+------+-----------------------------------------------------------------+ +| byte(n, x) | | nth byte of x, where the most significant byte is the 0th byte | ++-------------------------+------+-----------------------------------------------------------------+ +| addmod(x, y, m) | | (x + y) % m with arbitrary precision arithmetics | ++-------------------------+------+-----------------------------------------------------------------+ +| mulmod(x, y, m) | | (x * y) % m with arbitrary precision arithmetics | ++-------------------------+------+-----------------------------------------------------------------+ +| signextend(i, x) | | sign extend from (i*8+7)th bit counting from least significant | ++-------------------------+------+-----------------------------------------------------------------+ +| keccak256(p, n) | | keccak(mem[p...(p+n))) | ++-------------------------+------+-----------------------------------------------------------------+ +| sha3(p, n) | | keccak(mem[p...(p+n))) | ++-------------------------+------+-----------------------------------------------------------------+ +| jump(label) | `-` | jump to label / code position | ++-------------------------+------+-----------------------------------------------------------------+ +| jumpi(label, cond) | `-` | jump to label if cond is nonzero | ++-------------------------+------+-----------------------------------------------------------------+ +| pc | | current position in code | ++-------------------------+------+-----------------------------------------------------------------+ +| pop(x) | `-` | remove the element pushed by x | ++-------------------------+------+-----------------------------------------------------------------+ +| dup1 ... dup16 | | copy ith stack slot to the top (counting from top) | ++-------------------------+------+-----------------------------------------------------------------+ +| swap1 ... swap16 | `*` | swap topmost and ith stack slot below it | ++-------------------------+------+-----------------------------------------------------------------+ +| mload(p) | | mem[p..(p+32)) | ++-------------------------+------+-----------------------------------------------------------------+ +| mstore(p, v) | `-` | mem[p..(p+32)) := v | ++-------------------------+------+-----------------------------------------------------------------+ +| mstore8(p, v) | `-` | mem[p] := v & 0xff - only modifies a single byte | ++-------------------------+------+-----------------------------------------------------------------+ +| sload(p) | | storage[p] | ++-------------------------+------+-----------------------------------------------------------------+ +| sstore(p, v) | `-` | storage[p] := v | ++-------------------------+------+-----------------------------------------------------------------+ +| msize | | size of memory, i.e. largest accessed memory index | ++-------------------------+------+-----------------------------------------------------------------+ +| gas | | gas still available to execution | ++-------------------------+------+-----------------------------------------------------------------+ +| address | | address of the current contract / execution context | ++-------------------------+------+-----------------------------------------------------------------+ +| balance(a) | | wei balance at address a | ++-------------------------+------+-----------------------------------------------------------------+ +| caller | | call sender (excluding delegatecall) | ++-------------------------+------+-----------------------------------------------------------------+ +| callvalue | | wei sent together with the current call | ++-------------------------+------+-----------------------------------------------------------------+ +| calldataload(p) | | call data starting from position p (32 bytes) | ++-------------------------+------+-----------------------------------------------------------------+ +| calldatasize | | size of call data in bytes | ++-------------------------+------+-----------------------------------------------------------------+ +| calldatacopy(t, f, s) | `-` | copy s bytes from calldata at position f to mem at position t | ++-------------------------+------+-----------------------------------------------------------------+ +| codesize | | size of the code of the current contract / execution context | ++-------------------------+------+-----------------------------------------------------------------+ +| codecopy(t, f, s) | `-` | copy s bytes from code at position f to mem at position t | ++-------------------------+------+-----------------------------------------------------------------+ +| extcodesize(a) | | size of the code at address a | ++-------------------------+------+-----------------------------------------------------------------+ +| extcodecopy(a, t, f, s) | `-` | like codecopy(t, f, s) but take code at address a | ++-------------------------+------+-----------------------------------------------------------------+ +| returndatasize | | size of the last returndata | ++-------------------------+------+-----------------------------------------------------------------+ +| returndatacopy(t, f, s) | `-` | copy s bytes from returndata at position f to mem at position t | ++-------------------------+------+-----------------------------------------------------------------+ +| create(v, p, s) | | create new contract with code mem[p..(p+s)) and send v wei | +| | | and return the new address | ++-------------------------+------+-----------------------------------------------------------------+ +| create2(v, n, p, s) | | create new contract with code mem[p..(p+s)) at address | +| | | keccak256(<address> . n . keccak256(mem[p..(p+s))) and send v | +| | | wei and return the new address | ++-------------------------+------+-----------------------------------------------------------------+ +| call(g, a, v, in, | | call contract at address a with input mem[in..(in+insize)) | +| insize, out, outsize) | | providing g gas and v wei and output area | +| | | mem[out..(out+outsize)) returning 0 on error (eg. out of gas) | +| | | and 1 on success | ++-------------------------+------+-----------------------------------------------------------------+ +| callcode(g, a, v, in, | | identical to `call` but only use the code from a and stay | +| insize, out, outsize) | | in the context of the current contract otherwise | ++-------------------------+------+-----------------------------------------------------------------+ +| delegatecall(g, a, in, | | identical to `callcode` but also keep ``caller`` | +| insize, out, outsize) | | and ``callvalue`` | ++-------------------------+------+-----------------------------------------------------------------+ +| staticcall(g, a, in, | | identical to `call(g, a, 0, in, insize, out, outsize)` but do | +| insize, out, outsize) | | not allow state modifications | ++-------------------------+------+-----------------------------------------------------------------+ +| return(p, s) | `-` | end execution, return data mem[p..(p+s)) | ++-------------------------+------+-----------------------------------------------------------------+ +| revert(p, s) | `-` | end execution, revert state changes, return data mem[p..(p+s)) | ++-------------------------+------+-----------------------------------------------------------------+ +| selfdestruct(a) | `-` | end execution, destroy current contract and send funds to a | ++-------------------------+------+-----------------------------------------------------------------+ +| invalid | `-` | end execution with invalid instruction | ++-------------------------+------+-----------------------------------------------------------------+ +| log0(p, s) | `-` | log without topics and data mem[p..(p+s)) | ++-------------------------+------+-----------------------------------------------------------------+ +| log1(p, s, t1) | `-` | log with topic t1 and data mem[p..(p+s)) | ++-------------------------+------+-----------------------------------------------------------------+ +| log2(p, s, t1, t2) | `-` | log with topics t1, t2 and data mem[p..(p+s)) | ++-------------------------+------+-----------------------------------------------------------------+ +| log3(p, s, t1, t2, t3) | `-` | log with topics t1, t2, t3 and data mem[p..(p+s)) | ++-------------------------+------+-----------------------------------------------------------------+ +| log4(p, s, t1, t2, t3, | `-` | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) | +| t4) | | | ++-------------------------+------+-----------------------------------------------------------------+ +| origin | | transaction sender | ++-------------------------+------+-----------------------------------------------------------------+ +| gasprice | | gas price of the transaction | ++-------------------------+------+-----------------------------------------------------------------+ +| blockhash(b) | | hash of block nr b - only for last 256 blocks excluding current | ++-------------------------+------+-----------------------------------------------------------------+ +| coinbase | | current mining beneficiary | ++-------------------------+------+-----------------------------------------------------------------+ +| timestamp | | timestamp of the current block in seconds since the epoch | ++-------------------------+------+-----------------------------------------------------------------+ +| number | | current block number | ++-------------------------+------+-----------------------------------------------------------------+ +| difficulty | | difficulty of the current block | ++-------------------------+------+-----------------------------------------------------------------+ +| gaslimit | | block gas limit of the current block | ++-------------------------+------+-----------------------------------------------------------------+ + +Literals +-------- + +You can use integer constants by typing them in decimal or hexadecimal notation and an +appropriate ``PUSHi`` instruction will automatically be generated. The following creates code +to add 2 and 3 resulting in 5 and then computes the bitwise and with the string "abc". +Strings are stored left-aligned and cannot be longer than 32 bytes. + +.. code:: + + assembly { 2 3 add "abc" and } + +Functional Style +----------------- + +You can type opcode after opcode in the same way they will end up in bytecode. For example +adding ``3`` to the contents in memory at position ``0x80`` would be + +.. code:: + + 3 0x80 mload add 0x80 mstore + +As it is often hard to see what the actual arguments for certain opcodes are, +Solidity inline assembly also provides a "functional style" notation where the same code +would be written as follows + +.. code:: + + mstore(0x80, add(mload(0x80), 3)) + +Functional style expressions cannot use instructional style internally, i.e. +``1 2 mstore(0x80, add)`` is not valid assembly, it has to be written as +``mstore(0x80, add(2, 1))``. For opcodes that do not take arguments, the +parentheses can be omitted. + +Note that the order of arguments is reversed in functional-style as opposed to the instruction-style +way. If you use functional-style, the first argument will end up on the stack top. + + +Access to External Variables and Functions +------------------------------------------ + +Solidity variables and other identifiers can be accessed by simply using their name. +For memory variables, this will push the address and not the value onto the +stack. Storage variables are different: Values in storage might not occupy a +full storage slot, so their "address" is composed of a slot and a byte-offset +inside that slot. To retrieve the slot pointed to by the variable ``x``, you +used ``x_slot`` and to retrieve the byte-offset you used ``x_offset``. + +In assignments (see below), we can even use local Solidity variables to assign to. + +Functions external to inline assembly can also be accessed: The assembly will +push their entry label (with virtual function resolution applied). The calling semantics +in solidity are: + + - the caller pushes return label, arg1, arg2, ..., argn + - the call returns with ret1, ret2, ..., retm + +This feature is still a bit cumbersome to use, because the stack offset essentially +changes during the call, and thus references to local variables will be wrong. + +.. code:: + + pragma solidity ^0.4.11; + + contract C { + uint b; + function f(uint x) returns (uint r) { + assembly { + r := mul(x, sload(b_slot)) // ignore the offset, we know it is zero + } + } + } + +Labels +------ + +Another problem in EVM assembly is that ``jump`` and ``jumpi`` use absolute addresses +which can change easily. Solidity inline assembly provides labels to make the use of +jumps easier. Note that labels are a low-level feature and it is possible to write +efficient assembly without labels, just using assembly functions, loops and switch instructions +(see below). The following code computes an element in the Fibonacci series. + +.. code:: + + { + let n := calldataload(4) + let a := 1 + let b := a + loop: + jumpi(loopend, eq(n, 0)) + a add swap1 + n := sub(n, 1) + jump(loop) + loopend: + mstore(0, a) + return(0, 0x20) + } + +Please note that automatically accessing stack variables can only work if the +assembler knows the current stack height. This fails to work if the jump source +and target have different stack heights. It is still fine to use such jumps, but +you should just not access any stack variables (even assembly variables) in that case. + +Furthermore, the stack height analyser goes through the code opcode by opcode +(and not according to control flow), so in the following case, the assembler +will have a wrong impression about the stack height at label ``two``: + +.. code:: + + { + let x := 8 + jump(two) + one: + // Here the stack height is 2 (because we pushed x and 7), + // but the assembler thinks it is 1 because it reads + // from top to bottom. + // Accessing the stack variable x here will lead to errors. + x := 9 + jump(three) + two: + 7 // push something onto the stack + jump(one) + three: + } + +This problem can be fixed by manually adjusting the stack height for the +assembler - you can provide a stack height delta that is added +to the stack height just prior to the label. +Note that you will not have to care about these things if you just use +loops and assembly-level functions. + +As an example how this can be done in extreme cases, please see the following. + +.. code:: + + { + let x := 8 + jump(two) + 0 // This code is unreachable but will adjust the stack height correctly + one: + x := 9 // Now x can be accessed properly. + jump(three) + pop // Similar negative correction. + two: + 7 // push something onto the stack + jump(one) + three: + pop // We have to pop the manually pushed value here again. + } + +Declaring Assembly-Local Variables +---------------------------------- + +You can use the ``let`` keyword to declare variables that are only visible in +inline assembly and actually only in the current ``{...}``-block. What happens +is that the ``let`` instruction will create a new stack slot that is reserved +for the variable and automatically removed again when the end of the block +is reached. You need to provide an initial value for the variable which can +be just ``0``, but it can also be a complex functional-style expression. + +.. code:: + + pragma solidity ^0.4.0; + + contract C { + function f(uint x) returns (uint b) { + assembly { + let v := add(x, 1) + mstore(0x80, v) + { + let y := add(sload(v), 1) + b := y + } // y is "deallocated" here + b := add(b, v) + } // v is "deallocated" here + } + } + + +Assignments +----------- + +Assignments are possible to assembly-local variables and to function-local +variables. Take care that when you assign to variables that point to +memory or storage, you will only change the pointer and not the data. + +There are two kinds of assignments: functional-style and instruction-style. +For functional-style assignments (``variable := value``), you need to provide a value in a +functional-style expression that results in exactly one stack value +and for instruction-style (``=: variable``), the value is just taken from the stack top. +For both ways, the colon points to the name of the variable. The assignment +is performed by replacing the variable's value on the stack by the new value. + +.. code:: + + assembly { + let v := 0 // functional-style assignment as part of variable declaration + let g := add(v, 2) + sload(10) + =: v // instruction style assignment, puts the result of sload(10) into v + } + +Switch +------ + +You can use a switch statement as a very basic version of "if/else". +It takes the value of an expression and compares it to several constants. +The branch corresponding to the matching constant is taken. Contrary to the +error-prone behaviour of some programming languages, control flow does +not continue from one case to the next. There can be a fallback or default +case called ``default``. + +.. code:: + + assembly { + let x := 0 + switch calldataload(4) + case 0 { + x := calldataload(0x24) + } + default { + x := calldataload(0x44) + } + sstore(0, div(x, 2)) + } + +The list of cases does not require curly braces, but the body of a +case does require them. + +Loops +----- + +Assembly supports a simple for-style loop. For-style loops have +a header containing an initializing part, a condition and a post-iteration +part. The condition has to be a functional-style expression, while +the other two are blocks. If the initializing part +declares any variables, the scope of these variables is extended into the +body (including the condition and the post-iteration part). + +The following example computes the sum of an area in memory. + +.. code:: + + assembly { + let x := 0 + for { let i := 0 } lt(i, 0x100) { i := add(i, 0x20) } { + x := add(x, mload(i)) + } + } + +Functions +--------- + +Assembly allows the definition of low-level functions. These take their +arguments (and a return PC) from the stack and also put the results onto the +stack. Calling a function looks the same way as executing a functional-style +opcode. + +Functions can be defined anywhere and are visible in the block they are +declared in. Inside a function, you cannot access local variables +defined outside of that function. There is no explicit ``return`` +statement. + +If you call a function that returns multiple values, you have to assign +them to a tuple using ``a, b := f(x)`` or ``let a, b := f(x)``. + +The following example implements the power function by square-and-multiply. + +.. code:: + + assembly { + function power(base, exponent) -> result { + switch exponent + case 0 { result := 1 } + case 1 { result := base } + default { + result := power(mul(base, base), div(exponent, 2)) + switch mod(exponent, 2) + case 1 { result := mul(base, result) } + } + } + } + +Things to Avoid +--------------- + +Inline assembly might have a quite high-level look, but it actually is extremely +low-level. Function calls, loops and switches are converted by simple +rewriting rules and after that, the only thing the assembler does for you is re-arranging +functional-style opcodes, managing jump labels, counting stack height for +variable access and removing stack slots for assembly-local variables when the end +of their block is reached. Especially for those two last cases, it is important +to know that the assembler only counts stack height from top to bottom, not +necessarily following control flow. Furthermore, operations like swap will only +swap the contents of the stack but not the location of variables. + +Conventions in Solidity +----------------------- + +In contrast to EVM assembly, Solidity knows types which are narrower than 256 bits, +e.g. ``uint24``. In order to make them more efficient, most arithmetic operations just +treat them as 256-bit numbers and the higher-order bits are only cleaned at the +point where it is necessary, i.e. just shortly before they are written to memory +or before comparisons are performed. This means that if you access such a variable +from within inline assembly, you might have to manually clean the higher order bits +first. + +Solidity manages memory in a very simple way: There is a "free memory pointer" +at position ``0x40`` in memory. If you want to allocate memory, just use the memory +from that point on and update the pointer accordingly. + +Elements in memory arrays in Solidity always occupy multiples of 32 bytes (yes, this is +even true for ``byte[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory +arrays are pointers to memory arrays. The length of a dynamic array is stored at the +first slot of the array and then only the array elements follow. + +.. warning:: + Statically-sized memory arrays do not have a length field, but it will be added soon + to allow better convertibility between statically- and dynamically-sized arrays, so + please do not rely on that. + + +Standalone Assembly +=================== + +The assembly language described as inline assembly above can also be used +standalone and in fact, the plan is to use it as an intermediate language +for the Solidity compiler. In this form, it tries to achieve several goals: + +1. Programs written in it should be readable, even if the code is generated by a compiler from Solidity. +2. The translation from assembly to bytecode should contain as few "surprises" as possible. +3. Control flow should be easy to detect to help in formal verification and optimization. + +In order to achieve the first and last goal, assembly provides high-level constructs +like ``for`` loops, ``switch`` statements and function calls. It should be possible +to write assembly programs that do not make use of explicit ``SWAP``, ``DUP``, +``JUMP`` and ``JUMPI`` statements, because the first two obfuscate the data flow +and the last two obfuscate control flow. Furthermore, functional statements of +the form ``mul(add(x, y), 7)`` are preferred over pure opcode statements like +``7 y x add mul`` because in the first form, it is much easier to see which +operand is used for which opcode. + +The second goal is achieved by introducing a desugaring phase that only removes +the higher level constructs in a very regular way and still allows inspecting +the generated low-level assembly code. The only non-local operation performed +by the assembler is name lookup of user-defined identifiers (functions, variables, ...), +which follow very simple and regular scoping rules and cleanup of local variables from the stack. + +Scoping: An identifier that is declared (label, variable, function, assembly) +is only visible in the block where it was declared (including nested blocks +inside the current block). It is not legal to access local variables across +function borders, even if they would be in scope. Shadowing is not allowed. +Local variables cannot be accessed before they were declared, but labels, +functions and assemblies can. Assemblies are special blocks that are used +for e.g. returning runtime code or creating contracts. No identifier from an +outer assembly is visible in a sub-assembly. + +If control flow passes over the end of a block, pop instructions are inserted +that match the number of local variables declared in that block. +Whenever a local variable is referenced, the code generator needs +to know its current relative position in the stack and thus it needs to +keep track of the current so-called stack height. Since all local variables +are removed at the end of a block, the stack height before and after the block +should be the same. If this is not the case, a warning is issued. + +Why do we use higher-level constructs like ``switch``, ``for`` and functions: + +Using ``switch``, ``for`` and functions, it should be possible to write +complex code without using ``jump`` or ``jumpi`` manually. This makes it much +easier to analyze the control flow, which allows for improved formal +verification and optimization. + +Furthermore, if manual jumps are allowed, computing the stack height is rather complicated. +The position of all local variables on the stack needs to be known, otherwise +neither references to local variables nor removing local variables automatically +from the stack at the end of a block will work properly. The desugaring +mechanism correctly inserts operations at unreachable blocks that adjust the +stack height properly in case of jumps that do not have a continuing control flow. + +Example: + +We will follow an example compilation from Solidity to desugared assembly. +We consider the runtime bytecode of the following Solidity program:: + + contract C { + function f(uint x) returns (uint y) { + y = 1; + for (uint i = 0; i < x; i++) + y = 2 * y; + } + } + +The following assembly will be generated:: + + { + mstore(0x40, 0x60) // store the "free memory pointer" + // function dispatcher + switch div(calldataload(0), exp(2, 226)) + case 0xb3de648b { + let (r) = f(calldataload(4)) + let ret := $allocate(0x20) + mstore(ret, r) + return(ret, 0x20) + } + default { revert(0, 0) } + // memory allocator + function $allocate(size) -> pos { + pos := mload(0x40) + mstore(0x40, add(pos, size)) + } + // the contract function + function f(x) -> y { + y := 1 + for { let i := 0 } lt(i, x) { i := add(i, 1) } { + y := mul(2, y) + } + } + } + +After the desugaring phase it looks as follows:: + + { + mstore(0x40, 0x60) + { + let $0 := div(calldataload(0), exp(2, 226)) + jumpi($case1, eq($0, 0xb3de648b)) + jump($caseDefault) + $case1: + { + // the function call - we put return label and arguments on the stack + $ret1 calldataload(4) jump(f) + // This is unreachable code. Opcodes are added that mirror the + // effect of the function on the stack height: Arguments are + // removed and return values are introduced. + pop pop + let r := 0 + $ret1: // the actual return point + $ret2 0x20 jump($allocate) + pop pop let ret := 0 + $ret2: + mstore(ret, r) + return(ret, 0x20) + // although it is useless, the jump is automatically inserted, + // since the desugaring process is a purely syntactic operation that + // does not analyze control-flow + jump($endswitch) + } + $caseDefault: + { + revert(0, 0) + jump($endswitch) + } + $endswitch: + } + jump($afterFunction) + allocate: + { + // we jump over the unreachable code that introduces the function arguments + jump($start) + let $retpos := 0 let size := 0 + $start: + // output variables live in the same scope as the arguments and is + // actually allocated. + let pos := 0 + { + pos := mload(0x40) + mstore(0x40, add(pos, size)) + } + // This code replaces the arguments by the return values and jumps back. + swap1 pop swap1 jump + // Again unreachable code that corrects stack height. + 0 0 + } + f: + { + jump($start) + let $retpos := 0 let x := 0 + $start: + let y := 0 + { + let i := 0 + $for_begin: + jumpi($for_end, iszero(lt(i, x))) + { + y := mul(2, y) + } + $for_continue: + { i := add(i, 1) } + jump($for_begin) + $for_end: + } // Here, a pop instruction will be inserted for i + swap1 pop swap1 jump + 0 0 + } + $afterFunction: + stop + } + + +Assembly happens in four stages: + +1. Parsing +2. Desugaring (removes switch, for and functions) +3. Opcode stream generation +4. Bytecode generation + +We will specify steps one to three in a pseudo-formal way. More formal +specifications will follow. + + +Parsing / Grammar +----------------- + +The tasks of the parser are the following: + +- Turn the byte stream into a token stream, discarding C++-style comments + (a special comment exists for source references, but we will not explain it here). +- Turn the token stream into an AST according to the grammar below +- Register identifiers with the block they are defined in (annotation to the + AST node) and note from which point on, variables can be accessed. + +The assembly lexer follows the one defined by Solidity itself. + +Whitespace is used to delimit tokens and it consists of the characters +Space, Tab and Linefeed. Comments are regular JavaScript/C++ comments and +are interpreted in the same way as Whitespace. + +Grammar:: + + AssemblyBlock = '{' AssemblyItem* '}' + AssemblyItem = + Identifier | + AssemblyBlock | + FunctionalAssemblyExpression | + AssemblyLocalDefinition | + FunctionalAssemblyAssignment | + AssemblyAssignment | + LabelDefinition | + AssemblySwitch | + AssemblyFunctionDefinition | + AssemblyFor | + 'break' | 'continue' | + SubAssembly | 'dataSize' '(' Identifier ')' | + LinkerSymbol | + 'errorLabel' | 'bytecodeSize' | + NumberLiteral | StringLiteral | HexLiteral + Identifier = [a-zA-Z_$] [a-zA-Z_0-9]* + FunctionalAssemblyExpression = Identifier '(' ( AssemblyItem ( ',' AssemblyItem )* )? ')' + AssemblyLocalDefinition = 'let' IdentifierOrList ':=' FunctionalAssemblyExpression + FunctionalAssemblyAssignment = IdentifierOrList ':=' FunctionalAssemblyExpression + IdentifierOrList = Identifier | '(' IdentifierList ')' + IdentifierList = Identifier ( ',' Identifier)* + AssemblyAssignment = '=:' Identifier + LabelDefinition = Identifier ':' + AssemblySwitch = 'switch' FunctionalAssemblyExpression AssemblyCase* + ( 'default' AssemblyBlock )? + AssemblyCase = 'case' FunctionalAssemblyExpression AssemblyBlock + AssemblyFunctionDefinition = 'function' Identifier '(' IdentifierList? ')' + ( '->' '(' IdentifierList ')' )? AssemblyBlock + AssemblyFor = 'for' ( AssemblyBlock | FunctionalAssemblyExpression) + FunctionalAssemblyExpression ( AssemblyBlock | FunctionalAssemblyExpression) AssemblyBlock + SubAssembly = 'assembly' Identifier AssemblyBlock + LinkerSymbol = 'linkerSymbol' '(' StringLiteral ')' + NumberLiteral = HexNumber | DecimalNumber + HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') + StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' + HexNumber = '0x' [0-9a-fA-F]+ + DecimalNumber = [0-9]+ + + +Desugaring +---------- + +An AST transformation removes for, switch and function constructs. The result +is still parseable by the same parser, but it will not use certain constructs. +If jumpdests are added that are only jumped to and not continued at, information +about the stack content is added, unless no local variables of outer scopes are +accessed or the stack height is the same as for the previous instruction. + +Pseudocode:: + + desugar item: AST -> AST = + match item { + AssemblyFunctionDefinition('function' name '(' arg1, ..., argn ')' '->' ( '(' ret1, ..., retm ')' body) -> + <name>: + { + jump($<name>_start) + let $retPC := 0 let argn := 0 ... let arg1 := 0 + $<name>_start: + let ret1 := 0 ... let retm := 0 + { desugar(body) } + swap and pop items so that only ret1, ... retm, $retPC are left on the stack + jump + 0 (1 + n times) to compensate removal of arg1, ..., argn and $retPC + } + AssemblyFor('for' { init } condition post body) -> + { + init // cannot be its own block because we want variable scope to extend into the body + // find I such that there are no labels $forI_* + $forI_begin: + jumpi($forI_end, iszero(condition)) + { body } + $forI_continue: + { post } + jump($forI_begin) + $forI_end: + } + 'break' -> + { + // find nearest enclosing scope with label $forI_end + pop all local variables that are defined at the current point + but not at $forI_end + jump($forI_end) + 0 (as many as variables were removed above) + } + 'continue' -> + { + // find nearest enclosing scope with label $forI_continue + pop all local variables that are defined at the current point + but not at $forI_continue + jump($forI_continue) + 0 (as many as variables were removed above) + } + AssemblySwitch(switch condition cases ( default: defaultBlock )? ) -> + { + // find I such that there is no $switchI* label or variable + let $switchI_value := condition + for each of cases match { + case val: -> jumpi($switchI_caseJ, eq($switchI_value, val)) + } + if default block present: -> + { defaultBlock jump($switchI_end) } + for each of cases match { + case val: { body } -> $switchI_caseJ: { body jump($switchI_end) } + } + $switchI_end: + } + FunctionalAssemblyExpression( identifier(arg1, arg2, ..., argn) ) -> + { + if identifier is function <name> with n args and m ret values -> + { + // find I such that $funcallI_* does not exist + $funcallI_return argn ... arg2 arg1 jump(<name>) + pop (n + 1 times) + if the current context is `let (id1, ..., idm) := f(...)` -> + let id1 := 0 ... let idm := 0 + $funcallI_return: + else -> + 0 (m times) + $funcallI_return: + turn the functional expression that leads to the function call + into a statement stream + } + else -> desugar(children of node) + } + default node -> + desugar(children of node) + } + +Opcode Stream Generation +------------------------ + +During opcode stream generation, we keep track of the current stack height +in a counter, +so that accessing stack variables by name is possible. The stack height is modified with every opcode +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 +on the difference between the current stack height and the +stack height at the point the variable was introduced. + +Pseudocode:: + + codegen item: AST -> opcode_stream = + match item { + AssemblyBlock({ items }) -> + join(codegen(item) for item in items) + if last generated opcode has continuing control flow: + POP for all local variables registered at the block (including variables + introduced by labels) + warn if the stack height at this point is not the same as at the start of the block + Identifier(id) -> + lookup id in the syntactic stack of blocks + match type of id + Local Variable -> + DUPi where i = 1 + stack_height - stack_height_of_identifier(id) + Label -> + // reference to be resolved during bytecode generation + PUSH<bytecode position of label> + SubAssembly -> + PUSH<bytecode position of subassembly data> + FunctionalAssemblyExpression(id ( arguments ) ) -> + join(codegen(arg) for arg in arguments.reversed()) + id (which has to be an opcode, might be a function name later) + AssemblyLocalDefinition(let (id1, ..., idn) := expr) -> + register identifiers id1, ..., idn as locals in current block at current stack height + codegen(expr) - assert that expr returns n items to the stack + FunctionalAssemblyAssignment((id1, ..., idn) := expr) -> + lookup id1, ..., idn in the syntactic stack of blocks, assert that they are variables + codegen(expr) + for j = n, ..., i: + SWAPi where i = 1 + stack_height - stack_height_of_identifier(idj) + POP + AssemblyAssignment(=: id) -> + look up id in the syntactic stack of blocks, assert that it is a variable + SWAPi where i = 1 + stack_height - stack_height_of_identifier(id) + POP + LabelDefinition(name:) -> + JUMPDEST + NumberLiteral(num) -> + PUSH<num interpreted as decimal and right-aligned> + HexLiteral(lit) -> + PUSH32<lit interpreted as hex and left-aligned> + StringLiteral(lit) -> + PUSH32<lit utf-8 encoded and left-aligned> + SubAssembly(assembly <name> block) -> + append codegen(block) at the end of the code + dataSize(<name>) -> + assert that <name> is a subassembly -> + PUSH32<size of code generated from subassembly <name>> + linkerSymbol(<lit>) -> + PUSH32<zeros> and append position to linker table + } diff --git a/docs/bugs.json b/docs/bugs.json new file mode 100644 index 00000000..a0c0e7c4 --- /dev/null +++ b/docs/bugs.json @@ -0,0 +1,110 @@ +[ + { + "name": "SkipEmptyStringLiteral", + "summary": "If \"\" is used in a function call, the following function arguments will not be correctly passed to the function.", + "description": "If the empty string literal \"\" is used as an argument in a function call, it is skipped by the encoder. This has the effect that the encoding of all arguments following this is shifted left by 32 bytes and thus the function call data is corrupted.", + "fixed": "0.4.12", + "severity": "low" + }, + { + "name": "ConstantOptimizerSubtraction", + "summary": "In some situations, the optimizer replaces certain numbers in the code with routines that compute different numbers.", + "description": "The optimizer tries to represent any number in the bytecode by routines that compute them with less gas. For some special numbers, an incorrect routine is generated. This could allow an attacker to e.g. trick victims about a specific amount of ether, or function calls to call different functions (or none at all).", + "link": "https://blog.ethereum.org/2017/05/03/solidity-optimizer-bug/", + "fixed": "0.4.11", + "severity": "low", + "conditions": { + "optimizer": true + } + }, + { + "name": "IdentityPrecompileReturnIgnored", + "summary": "Failure of the identity precompile was ignored.", + "description": "Calls to the identity contract, which is used for copying memory, ignored its return value. On the public chain, calls to the identity precompile can be made in a way that they never fail, but this might be different on private chains.", + "severity": "low", + "fixed": "0.4.7" + }, + { + "name": "OptimizerStateKnowledgeNotResetForJumpdest", + "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.", + "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was simplified to just use the empty state, but this implementation was not done properly. This bug can cause data corruption.", + "severity": "medium", + "introduced": "0.4.5", + "fixed": "0.4.6", + "conditions": { + "optimizer": true + } + }, + { + "name": "HighOrderByteCleanStorage", + "summary": "For short types, the high order bytes were not cleaned properly and could overwrite existing data.", + "description": "Types shorter than 32 bytes are packed together into the same 32 byte storage slot, but storage writes always write 32 bytes. For some types, the higher order bytes were not cleaned properly, which made it sometimes possible to overwrite a variable in storage when writing to another one.", + "link": "https://blog.ethereum.org/2016/11/01/security-alert-solidity-variables-can-overwritten-storage/", + "severity": "high", + "introduced": "0.1.6", + "fixed": "0.4.4" + }, + { + "name": "OptimizerStaleKnowledgeAboutSHA3", + "summary": "The optimizer did not properly reset its knowledge about SHA3 operations resulting in some hashes (also used for storage variable positions) not being calculated correctly.", + "description": "The optimizer performs symbolic execution in order to save re-evaluating expressions whose value is already known. This knowledge was not properly reset across control flow paths and thus the optimizer sometimes thought that the result of a SHA3 operation is already present on the stack. This could result in data corruption by accessing the wrong storage slot.", + "severity": "medium", + "fixed": "0.4.3", + "conditions": { + "optimizer": true + } + }, + { + "name": "LibrariesNotCallableFromPayableFunctions", + "summary": "Library functions threw an exception when called from a call that received Ether.", + "description": "Library functions are protected against sending them Ether through a call. Since the DELEGATECALL opcode forwards the information about how much Ether was sent with a call, the library function incorrectly assumed that Ether was sent to the library and threw an exception.", + "severity": "low", + "introduced": "0.4.0", + "fixed": "0.4.2" + }, + { + "name": "SendFailsForZeroEther", + "summary": "The send function did not provide enough gas to the recipient if no Ether was sent with it.", + "description": "The recipient of an Ether transfer automatically receives a certain amount of gas from the EVM to handle the transfer. In the case of a zero-transfer, this gas is not provided which causes the recipient to throw an exception.", + "severity": "low", + "fixed": "0.4.0" + }, + { + "name": "DynamicAllocationInfiniteLoop", + "summary": "Dynamic allocation of an empty memory array caused an infinite loop and thus an exception.", + "description": "Memory arrays can be created provided a length. If this length is zero, code was generated that did not terminate and thus consumed all gas.", + "severity": "low", + "fixed": "0.3.6" + }, + { + "name": "OptimizerClearStateOnCodePathJoin", + "summary": "The optimizer did not properly reset its internal state at jump destinations, which could lead to data corruption.", + "description": "The optimizer performs symbolic execution at certain stages. At jump destinations, multiple code paths join and thus it has to compute a common state from the incoming edges. Computing this common state was not done correctly. This bug can cause data corruption, but it is probably quite hard to use for targeted attacks.", + "severity": "low", + "fixed": "0.3.6", + "conditions": { + "optimizer": true + } + }, + { + "name": "CleanBytesHigherOrderBits", + "summary": "The higher order bits of short bytesNN types were not cleaned before comparison.", + "description": "Two variables of type bytesNN were considered different if their higher order bits, which are not part of the actual value, were different. An attacker might use this to reach seemingly unreachable code paths by providing incorrectly formatted input data.", + "severity": "medium/high", + "fixed": "0.3.3" + }, + { + "name": "ArrayAccessCleanHigherOrderBits", + "summary": "Access to array elements for arrays of types with less than 32 bytes did not correctly clean the higher order bits, causing corruption in other array elements.", + "description": "Multiple elements of an array of values that are shorter than 17 bytes are packed into the same storage slot. Writing to a single element of such an array did not properly clean the higher order bytes and thus could lead to data corruption.", + "severity": "medium/high", + "fixed": "0.3.1" + }, + { + "name": "AncientCompiler", + "summary": "This compiler version is ancient and might contain several undocumented or undiscovered bugs.", + "description": "The list of bugs is only kept for compiler versions starting from 0.3.0, so older versions might contain undocumented bugs.", + "severity": "high", + "fixed": "0.3.0" + } +]
\ No newline at end of file diff --git a/docs/bugs.rst b/docs/bugs.rst new file mode 100644 index 00000000..55771a35 --- /dev/null +++ b/docs/bugs.rst @@ -0,0 +1,61 @@ +.. index:: Bugs + +.. _known_bugs: + +################## +List of Known Bugs +################## + +Below, you can find a JSON-formatted list of some of the known security-relevant bugs in the +Solidity compiler. The file itself is hosted in the `Github repository +<https://github.com/ethereum/solidity/blob/develop/docs/bugs.json>`_. +The list stretches back as far as version 0.3.0, bugs known to be present only +in versions preceding that are not listed. + +There is another file called `bugs_by_version.json +<https://github.com/ethereum/solidity/blob/develop/docs/bugs_by_version.json>`_, +which can be used to check which bugs affect a specific version of the compiler. + +Contract source verification tools and also other tools interacting with +contracts should consult this list according to the following criteria: + + - It is mildly suspicious if a contract was compiled with a nightly + compiler version instead of a released version. This list does not keep + track of unreleased or nightly versions. + - It is also mildly suspicious if a contract was compiled with a version that was + not the most recent at the time the contract was created. For contracts + created from other contracts, you have to follow the creation chain + back to a transaction and use the date of that transaction as creation date. + - It is highly suspicious if a contract was compiled with a compiler that + contains a known bug and the contract was created at a time where a newer + compiler version containing a fix was already released. + +The JSON file of known bugs below is an array of objects, one for each bug, +with the following keys: + +name + Unique name given to the bug +summary + Short description of the bug +description + Detailed description of the bug +link + URL of a website with more detailed information, optional +introduced + The first published compiler version that contained the bug, optional +fixed + The first published compiler version that did not contain the bug anymore +publish + The date at which the bug became known publicly, optional +severity + Severity of the bug: low, medium, high. Takes into account + discoverability in contract tests, likelihood of occurrence and + potential damage by exploits. +conditions + Conditions that have to be met to trigger the bug. Currently, this + is an object that can contain a boolean value ``optimizer``, which + means that the optimizer has to be switched on to enable the bug. + If no conditions are given, assume that the bug is present. + +.. literalinclude:: bugs.json + :language: js diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json new file mode 100644 index 00000000..d6802eec --- /dev/null +++ b/docs/bugs_by_version.json @@ -0,0 +1,373 @@ +{ + "0.1.0": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-07-10" + }, + "0.1.1": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-08-04" + }, + "0.1.2": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-08-20" + }, + "0.1.3": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-09-25" + }, + "0.1.4": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-09-30" + }, + "0.1.5": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-10-07" + }, + "0.1.6": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-10-16" + }, + "0.1.7": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-11-17" + }, + "0.2.0": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2015-12-02" + }, + "0.2.1": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2016-01-30" + }, + "0.2.2": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits", + "AncientCompiler" + ], + "released": "2016-02-17" + }, + "0.3.0": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits", + "ArrayAccessCleanHigherOrderBits" + ], + "released": "2016-03-11" + }, + "0.3.1": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits" + ], + "released": "2016-03-31" + }, + "0.3.2": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin", + "CleanBytesHigherOrderBits" + ], + "released": "2016-04-18" + }, + "0.3.3": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin" + ], + "released": "2016-05-27" + }, + "0.3.4": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin" + ], + "released": "2016-05-31" + }, + "0.3.5": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther", + "DynamicAllocationInfiniteLoop", + "OptimizerClearStateOnCodePathJoin" + ], + "released": "2016-06-10" + }, + "0.3.6": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "SendFailsForZeroEther" + ], + "released": "2016-08-10" + }, + "0.4.0": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "LibrariesNotCallableFromPayableFunctions" + ], + "released": "2016-09-08" + }, + "0.4.1": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3", + "LibrariesNotCallableFromPayableFunctions" + ], + "released": "2016-09-09" + }, + "0.4.10": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction" + ], + "released": "2017-03-15" + }, + "0.4.11": { + "bugs": [ + "SkipEmptyStringLiteral" + ], + "released": "2017-05-03" + }, + "0.4.12": { + "bugs": [], + "released": "2017-07-03" + }, + "0.4.13": { + "bugs": [], + "released": "2017-07-06" + }, + "0.4.2": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage", + "OptimizerStaleKnowledgeAboutSHA3" + ], + "released": "2016-09-17" + }, + "0.4.3": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "HighOrderByteCleanStorage" + ], + "released": "2016-10-25" + }, + "0.4.4": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored" + ], + "released": "2016-10-31" + }, + "0.4.5": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored", + "OptimizerStateKnowledgeNotResetForJumpdest" + ], + "released": "2016-11-21" + }, + "0.4.6": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction", + "IdentityPrecompileReturnIgnored" + ], + "released": "2016-11-22" + }, + "0.4.7": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction" + ], + "released": "2016-12-15" + }, + "0.4.8": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction" + ], + "released": "2017-01-13" + }, + "0.4.9": { + "bugs": [ + "SkipEmptyStringLiteral", + "ConstantOptimizerSubtraction" + ], + "released": "2017-01-31" + } +}
\ No newline at end of file diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index fa5e68a6..acef13b7 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -23,12 +23,12 @@ contract in order to become the "richest", inspired by `King of the Ether <https://www.kingoftheether.com/>`_. In the following contract, if you are usurped as the richest, -you will recieve the funds of the person who has gone on to +you will receive the funds of the person who has gone on to become the new richest. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract WithdrawalContract { address public richest; @@ -52,17 +52,12 @@ become the new richest. } } - function withdraw() returns (bool) { + function withdraw() { uint amount = pendingWithdrawals[msg.sender]; // Remember to zero the pending refund before // sending to prevent re-entrancy attacks pendingWithdrawals[msg.sender] = 0; - if (msg.sender.send(amount)) { - return true; - } else { - pendingWithdrawals[msg.sender] = amount; - return false; - } + msg.sender.transfer(amount); } } @@ -70,7 +65,7 @@ This is as opposed to the more intuitive sending pattern: :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract SendContract { address public richest; @@ -81,14 +76,10 @@ This is as opposed to the more intuitive sending pattern: mostSent = msg.value; } - function becomeRichest() returns (bool) { + function becomeRichest() payable returns (bool) { if (msg.value > mostSent) { - // Check if call succeeds to prevent an attacker - // from trapping the previous person's funds in - // this contract through a callstack attack - if (!richest.send(msg.value)) { - throw; - } + // This line can cause problems (explained below). + richest.transfer(msg.value); richest = msg.sender; mostSent = msg.value; return true; @@ -100,12 +91,16 @@ This is as opposed to the more intuitive sending pattern: Notice that, in this example, an attacker could trap the contract into an unusable state by causing ``richest`` to be -the address of a contract that has a fallback function -which consumes more than the 2300 gas stipend. That way, -whenever ``send`` is called to deliver funds to the -"poisoned" contract, it will cause execution to always fail -because there will not be enough gas to finish the execution -of the fallback function. +the address of a contract that has a fallback function +which fails (e.g. by using ``revert()`` or by just +conssuming more than the 2300 gas stipend). That way, +whenever ``transfer`` is called to deliver funds to the +"poisoned" contract, it will fail and thus also ``becomeRichest`` +will fail, with the contract being stuck forever. + +In contrast, if you use the "withdraw" pattern from the first example, +the attacker can only cause his or her own withdraw to fail and not the +rest of the contract's workings. .. index:: access;restricting @@ -135,7 +130,7 @@ restrictions highly readable. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract AccessRestriction { // These will be assigned at the construction @@ -152,8 +147,7 @@ restrictions highly readable. // a certain address. modifier onlyBy(address _account) { - if (msg.sender != _account) - throw; + require(msg.sender == _account); // Do not forget the "_;"! It will // be replaced by the actual function // body when the modifier is used. @@ -169,7 +163,7 @@ restrictions highly readable. } modifier onlyAfter(uint _time) { - if (now < _time) throw; + require(now >= _time); _; } @@ -190,8 +184,7 @@ restrictions highly readable. // This was dangerous before Solidity version 0.4.0, // where it was possible to skip the part after `_;`. modifier costs(uint _amount) { - if (msg.value < _amount) - throw; + require(msg.value >= _amount); _; if (msg.value > _amount) msg.sender.send(msg.value - _amount); @@ -232,7 +225,7 @@ reached at a certain point in **time**. An example for this is a blind auction contract which starts in the stage "accepting blinded bids", then transitions to "revealing bids" which is ended by -"determine auction autcome". +"determine auction outcome". .. index:: function;modifier @@ -276,7 +269,7 @@ function finishes. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract StateMachine { enum Stages { @@ -293,7 +286,7 @@ function finishes. uint public creationTime = now; modifier atStage(Stages _stage) { - if (stage != _stage) throw; + require(stage == _stage); _; } diff --git a/docs/conf.py b/docs/conf.py index 2bc79fd9..ca8c0fec 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,6 +15,7 @@ import sys import os +import re # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -49,16 +50,21 @@ master_doc = 'index' # General information about the project. project = 'Solidity' -copyright = '2016, Ethereum' +copyright = '2016-2017, Ethereum' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '0.4.7' +with open('../CMakeLists.txt', 'r') as f: + version = re.search('PROJECT_VERSION "([^"]+)"', f.read()).group(1) # The full version, including alpha/beta/rc tags. -release = '0.4.7-develop' +if os.path.isfile('../prerelease.txt') != True or os.path.getsize('../prerelease.txt') == 0: + release = version +else: + # This is a prerelease version + release = version + '-develop' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/contracts.rst b/docs/contracts.rst index e82b7495..e9ea1b3b 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -20,14 +20,14 @@ Contracts can be created "from outside" or from Solidity contracts. When a contract is created, its constructor (a function with the same name as the contract) is executed once. -A constructor is optional. Only one constructor is allowed and this means +A constructor is optional. Only one constructor is allowed, and this means overloading is not supported. From ``web3.js``, i.e. the JavaScript API, this is done as follows:: // Need to specify some source including contract name for the data param below - var source = "contract CONTRACT_NAME { function CONTRACT_NAME(unit a, uint b) {} }"; + var source = "contract CONTRACT_NAME { function CONTRACT_NAME(uint a, uint b) {} }"; // The json abi array generated by the compiler var abiArray = [ @@ -145,11 +145,11 @@ This means that cyclic creation dependencies are impossible. .. index:: ! visibility, external, public, private, internal -.. _visibility-and-accessors: +.. _visibility-and-getters: -************************ -Visibility and Accessors -************************ +********************** +Visibility and Getters +********************** Since Solidity knows two kinds of function calls (internal ones that do not create an actual EVM call (also called @@ -173,7 +173,7 @@ and the default is ``internal``. ``public``: Public functions are part of the contract interface and can be either called internally or via - messages. For public state variables, an automatic accessor + messages. For public state variables, an automatic getter function (see below) is generated. ``internal``: @@ -243,12 +243,13 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value } } -.. index:: ! accessor;function, ! function;accessor +.. index:: ! getter;function, ! function;getter +.. _getter_functions: -Accessor Functions -================== +Getter Functions +================ -The compiler automatically creates accessor functions for +The compiler automatically creates getter functions for all **public** state variables. For the contract given below, the compiler will generate a function called ``data`` that does not take any arguments and returns a ``uint``, the value of the state @@ -271,9 +272,9 @@ be done at declaration. } } -The accessor functions have external visibility. If the +The getter functions have external visibility. If the symbol is accessed internally (i.e. without ``this.``), -it is evaluated as a state variable and if it is accessed externally +it is evaluated as a state variable. If it is accessed externally (i.e. with ``this.``), it is evaluated as a function. :: @@ -321,13 +322,13 @@ is no good way to provide the key for the mapping. Function Modifiers ****************** -Modifiers can be used to easily change the behaviour of functions, for example -to automatically check a condition prior to executing the function. They are +Modifiers can be used to easily change the behaviour of functions. For example, +they can automatically check a condition prior to executing the function. Modifiers are inheritable properties of contracts and may be overridden by derived contracts. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract owned { function owned() { owner = msg.sender; } @@ -341,8 +342,7 @@ inheritable properties of contracts and may be overridden by derived contracts. // function is executed and otherwise, an exception is // thrown. modifier onlyOwner { - if (msg.sender != owner) - throw; + require(msg.sender == owner); _; } } @@ -390,7 +390,7 @@ inheritable properties of contracts and may be overridden by derived contracts. contract Mutex { bool locked; modifier noReentrancy() { - if (locked) throw; + require(!locked); locked = true; _; locked = false; @@ -401,13 +401,13 @@ inheritable properties of contracts and may be overridden by derived contracts. /// The `return 7` statement assigns 7 to the return value but still /// executes the statement `locked = false` in the modifier. function f() noReentrancy returns (uint) { - if (!msg.sender.call()) throw; + require(msg.sender.call()); return 7; } } -Multiple modifiers can be applied to a function by specifying them in a -whitespace-separated list and will be evaluated in order. +Multiple modifiers are applied to a function by specifying them in a +whitespace-separated list and are evaluated in the order presented. .. warning:: In an earlier version of Solidity, ``return`` statements in functions @@ -428,8 +428,25 @@ change by overriding). Constant State Variables ************************ -State variables can be declared as constant (this is not yet implemented -for array and struct types and not possible for mapping types). +State variables can be declared as ``constant``. In this case, they have to be +assigned from an expression which is a constant at compile time. Any expression +that accesses storage, blockchain data (e.g. ``now``, ``this.balance`` or +``block.number``) or +execution data (``msg.gas``) or make calls to external contracts are disallowed. Expressions +that might have a side-effect on memory allocation are allowed, but those that +might have a side-effect on other memory objects are not. The built-in functions +``keccak256``, ``sha256``, ``ripemd160``, ``ecrecover``, ``addmod`` and ``mulmod`` +are allowed (even though they do call external contracts). + +The reason behind allowing side-effects on the memory allocator is that it +should be possible to construct complex objects like e.g. lookup-tables. +This feature is not yet fully usable. + +The compiler does not reserve a storage slot for these variables, and every occurrence is +replaced by the respective constant expression (which might be computed to a single value by the optimizer). + +Not all types for constants are implemented at this time. The only supported types are +value types and strings. :: @@ -438,18 +455,17 @@ for array and struct types and not possible for mapping types). contract C { uint constant x = 32**22 + 8; string constant text = "abc"; + bytes32 constant myHash = keccak256("abc"); } -This has the effect that the compiler does not reserve a storage slot -for these variables and every occurrence is replaced by their constant value. -The value expression can only contain integer arithmetics. +.. _constant-functions: ****************** Constant Functions ****************** -Functions can be declared constant. These functions promise not to modify the state. +Functions can be declared constant in which case they promise not to modify the state. :: @@ -462,7 +478,7 @@ Functions can be declared constant. These functions promise not to modify the st } .. note:: - Accessor methods are marked constant. + Getter methods are marked constant. .. warning:: The compiler does not enforce yet that a constant method is not modifying state. @@ -478,7 +494,7 @@ Fallback Function A contract can have exactly one unnamed function. This function cannot have arguments and cannot return anything. It is executed on a call to the contract if none of the other -functions matches the given function identifier (or if no data was supplied at +functions match the given function identifier (or if no data was supplied at all). Furthermore, this function is executed whenever the contract receives plain @@ -496,7 +512,8 @@ In particular, the following operations will consume more gas than the stipend p Please ensure you test your fallback function thoroughly to ensure the execution cost is less than 2300 gas before deploying a contract. .. warning:: - Contracts that receive Ether but do not define a fallback function + Contracts that receive Ether directly (without a function call, i.e. using ``send`` or ``transfer``) + but do not define a fallback function throw an exception, sending back the Ether (this was different before Solidity v0.4.0). So if you want your contract to receive Ether, you have to implement a fallback function. @@ -554,13 +571,12 @@ the contract and will be incorporated into the blockchain and stay there as long as a block is accessible (forever as of Frontier and Homestead, but this might change with Serenity). Log and event data is not accessible from within contracts (not even from -the contract that created a log). +the contract that created them). SPV proofs for logs are possible, so if an external entity supplies a contract with such a proof, it can check that the log actually -exists inside the blockchain (but be aware of the fact that -ultimately, also the block headers have to be supplied because -the contract can only see the last 256 block hashes). +exists inside the blockchain. But be aware that block headers have to be supplied because +the contract can only see the last 256 block hashes. Up to three parameters can receive the attribute ``indexed`` which will cause the respective arguments @@ -577,7 +593,7 @@ not possible to filter for specific anonymous events by name. 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 + Indexed arguments will not be stored themselves. You can only search for the values, but it is impossible to retrieve the values themselves. @@ -592,7 +608,7 @@ All non-indexed arguments will be stored in the data part of the log. uint _value ); - function deposit(bytes32 _id) { + function deposit(bytes32 _id) payable { // Any call to this function (even deeply nested) can // be detected from the JavaScript API by filtering // for `Deposit` to be called. @@ -666,9 +682,9 @@ Solidity supports multiple inheritance by copying code including polymorphism. All function calls are virtual, which means that the most derived function is called, except when the contract name is explicitly given. -Even if a contract inherits from multiple other contracts, only a single -contract is created on the blockchain, the code from the base contracts -is always copied into the final contract. +When a contract inherits from multiple contracts, only a single +contract is created on the blockchain, and the code from all the base contracts +is copied into the created contract. The general inheritance system is very similar to `Python's <https://docs.python.org/3/tutorial/classes.html#inheritance>`_, @@ -805,7 +821,7 @@ derived override, but this function will bypass } If ``Base1`` calls a function of ``super``, it does not simply -call this function on one of its base contracts, it rather +call this function on one of its base contracts. Rather, it calls this function on the next base contract in the final inheritance graph, so it will call ``Base2.kill()`` (note that the final inheritance sequence is -- starting with the most @@ -821,7 +837,7 @@ Arguments for Base Constructors =============================== 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 in two ways:: pragma solidity ^0.4.0; @@ -836,7 +852,7 @@ the base constructors. This can be done at two places:: } } -Either directly in the inheritance list (``is Base(7)``) or in +One way is directly in the inheritance list (``is Base(7)``). The other is in the way a modifier would be invoked as part of the header of the derived constructor (``Base(_y * _y)``). The first way to do it is more convenient if the constructor argument is a @@ -852,7 +868,7 @@ Multiple Inheritance and Linearization ====================================== Languages that allow multiple inheritance have to deal with -several problems, one of them being the `Diamond Problem <https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem>`_. +several problems. One is the `Diamond Problem <https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem>`_. Solidity follows the path of Python and uses "`C3 Linearization <https://en.wikipedia.org/wiki/C3_linearization>`_" to force a specific order in the DAG of base classes. This results in the desirable property of monotonicity but @@ -877,6 +893,13 @@ cannot be resolved. A simple rule to remember is to specify the base classes in the order from "most base-like" to "most derived". +Inheriting Different Kinds of Members of the Same Name +====================================================== + +When the inheritance results in a contract with a function and a modifier of the same name, it is considered as an error. +This error is produced also by an event and a modifier of the same name, and a function and an event of the same name. +As an exception, a state variable getter can override a public function. + .. index:: ! contract;abstract, ! abstract contract ****************** @@ -901,6 +924,35 @@ Such contracts cannot be compiled (even if they contain implemented functions al If a contract inherits from an abstract contract and does not implement all non-implemented functions by overriding, it will itself be abstract. +.. index:: ! contract;interface, ! interface contract + +********** +Interfaces +********** + +Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions: + +#. Cannot inherit other contracts or interfaces. +#. Cannot define constructor. +#. Cannot define variables. +#. Cannot define structs. +#. Cannot define enums. + +Some of these restrictions might be lifted in the future. + +Interfaces are basically limited to what the Contract ABI can represent, and the conversion between the ABI and +an Interface should be possible without any information loss. + +Interfaces are denoted by their own keyword: + +:: + + interface Token { + function transfer(address recipient, uint amount); + } + +Contracts can inherit interfaces as they would inherit other contracts. + .. index:: ! library, callcode, delegatecall .. _libraries: @@ -927,9 +979,9 @@ contracts (``L.f()`` if ``L`` is the name of the library). Furthermore, if the library were a base contract. Of course, calls to internal functions use the internal calling convention, which means that all internal types can be passed and memory types will be passed by reference and not copied. -In order to realise this in the EVM, code of internal library functions -(and all functions called from therein) will be pulled into the calling -contract and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. +To realize this in the EVM, code of internal library functions +and all functions called from therein will be pulled into the calling +contract, and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. .. index:: using for, set @@ -939,7 +991,7 @@ more advanced example to implement a set). :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; library Set { // We define a new struct datatype that will be used to @@ -985,16 +1037,15 @@ more advanced example to implement a set). // The library functions can be called without a // specific instance of the library, since the // "instance" will be the current contract. - if (!Set.insert(knownValues, value)) - throw; + require(Set.insert(knownValues, value)); } // In this contract, we can also directly access knownValues.flags, if we want. } Of course, you do not have to follow this way to use libraries - they can also be used without defining struct -data types, functions also work without any storage -reference parameters, can have multiple storage reference +data types. Functions also work without any storage +reference parameters, and they can have multiple storage reference parameters and in any position. The calls to ``Set.contains``, ``Set.insert`` and ``Set.remove`` @@ -1080,7 +1131,7 @@ Restrictions for libraries in comparison to contracts: - No state variables - Cannot inherit nor be inherited -- Cannot recieve Ether +- Cannot receive Ether (These might be lifted at a later point.) @@ -1116,7 +1167,7 @@ available without having to add further code. Let us rewrite the set example from the :ref:`libraries` in this way:: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; // This is the same code as before, just without comments library Set { @@ -1157,8 +1208,7 @@ Let us rewrite the set example from the // corresponding member functions. // The following function call is identical to // Set.insert(knownValues, value) - if (!knownValues.insert(value)) - throw; + require(knownValues.insert(value)); } } diff --git a/docs/contributing.rst b/docs/contributing.rst index 42204d5c..9d1b2ce3 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -12,7 +12,7 @@ In particular, we need help in the following areas: * Improving the documentation * Responding to questions from other users on `StackExchange - <http://ethereum.stackexchange.com/>`_ and the `Solidity Gitter + <https://ethereum.stackexchange.com>`_ and the `Solidity Gitter <https://gitter.im/ethereum/solidity>`_ * Fixing and responding to `Solidity's GitHub issues <https://github.com/ethereum/solidity/issues>`_, especially those tagged as @@ -74,3 +74,22 @@ To run a subset of tests, filters can be used: ``soltest -t TestSuite/TestName -- --ipcpath /tmp/testeth/geth.ipc``, where ``TestName`` can be a wildcard ``*``. Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests. + +Whiskers +======== + +*Whiskers* is a templating system similar to `Mustache <https://mustache.github.io>`_. It is used by the +compiler in various places to aid readability, and thus maintainability and verifiability, of the code. + +The syntax comes with a substantial difference to Mustache: the template markers ``{{`` and ``}}`` are +replaced by ``<`` and ``>`` in order to aid parsing and avoid conflicts with :ref:`inline-assembly` +(The symbols ``<`` and ``>`` are invalid in inline assembly, while ``{`` and ``}`` are used to delimit blocks). +Another limitation is that lists are only resolved one depth and they will not recurse. This may change in the future. + +A rough specification is the following: + +Any occurrence of ``<name>`` is replaced by the string-value of the supplied variable ``name`` without any +escaping and without iterated replacements. An area can be delimited by ``<#name>...</name>``. It is replaced +by as many concatenations of its contents as there were sets of variables supplied to the template system, +each time replacing any ``<inner>`` items by their respective value. Top-level variables can also be used +inside such areas. diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 974a093f..03787c20 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -104,7 +104,7 @@ contract can be called internally. External Function Calls ----------------------- -The expressions ``this.g(8);`` and ``c.g(2);`` (where ``g`` is a contract +The expressions ``this.g(8);`` and ``c.g(2);`` (where ``c`` 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. Please note that function calls on ``this`` cannot be used in the constructor, as the @@ -113,8 +113,8 @@ actual contract has not been created yet. Functions of other contracts have to be called externally. For an external call, all function arguments have to be copied to memory. -When calling functions -of other contracts, the amount of Wei sent with the call and the gas can be specified:: +When calling functions of other contracts, the amount of Wei sent with the call and +the gas can be specified with special options ``.value()`` and ``.gas()``, respectively:: contract InfoFeed { function info() payable returns (uint ret) { return 42; } @@ -127,8 +127,8 @@ 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)(); } } -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)()``. +The modifier ``payable`` has to be used for ``info``, because otherwise, the `.value()` +option would not be available. 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 @@ -207,8 +207,8 @@ Creating Contracts via ``new`` ============================== A contract can create a new contract using the ``new`` keyword. The full -code of the contract being created has to be known and, thus, recursive -creation-dependencies are now possible. +code of the contract being created has to be known in advance, so recursive +creation-dependencies are not possible. :: @@ -235,7 +235,7 @@ creation-dependencies are now possible. } } -As seen in the example, it is possible to forward Ether to the creation, +As seen in the example, it is possible to forward Ether to the creation using the ``.value()`` option, but it is not possible to limit the amount of gas. If the creation fails (due to out-of-stack, not enough balance or other problems), an exception is thrown. @@ -361,511 +361,72 @@ As a result, the following code is legal, despite being poorly written:: return bar;// returns 5 } -.. index:: ! exception, ! throw +.. index:: ! exception, ! throw, ! assert, ! require, ! revert -Exceptions -========== +Error handling: Assert, Require, Revert and Exceptions +====================================================== + +Solidity uses state-reverting exceptions to handle errors. Such an exception will undo all changes made to the +state in the current call (and all its sub-calls) and also flag an error to the caller. +The convenience functions ``assert`` and ``require`` can be used to check for conditions and throw an exception +if the condition is not met. The difference between the two is that ``assert`` should only be used for internal errors +and ``require`` should be used to check external conditions (invalid inputs or errors in external components). +The idea behind that is that analysis tools can check your contract and try to come up with situations and +series of function calls that will reach a failing assertion. If this is possible, this means there is a bug +in your contract you should fix. + +There are two other ways to trigger execptions: The ``revert`` function can be used to flag an error and +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()``. -There are some cases where exceptions are thrown automatically (see below). You can use the ``throw`` instruction to throw an exception manually. The effect of an exception is that the currently executing call is stopped and reverted (i.e. all changes to the state and balances are undone) and the exception is also "bubbled up" through Solidity function calls (exceptions are ``send`` and the low-level functions ``call``, ``delegatecall`` and ``callcode``, those return ``false`` in case of an exception). +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". 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, you can see how ``require`` can be used to easily check conditions on inputs +and how ``assert`` can be used for internal error checking:: pragma solidity ^0.4.0; contract Sharer { function sendHalf(address addr) payable returns (uint balance) { - if (!addr.send(msg.value / 2)) - throw; // also reverts the transfer to Sharer + require(msg.value % 2 == 0); // Only allow even numbers + uint balanceBeforeTransfer = this.balance; + addr.transfer(msg.value / 2); + // Since transfer throws an exception on failure and + // cannot call back here, there should be no way for us to + // still have half of the money. + assert(this.balance == balanceBeforeTransfer - msg.value / 2); return this.balance; } } -Currently, there are situations, where exceptions happen automatically in Solidity: - -1. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``). -2. If you access a fixed-length ``bytesN`` at a too large or negative index. -3. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``. -4. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly"). -5. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``). -6. If you convert a value too big or negative into an enum type. -7. If you perform an external function call targeting a contract that contains no code. -8. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function). -9. If your contract receives Ether via a public accessor function. - -Internally, Solidity performs an "invalid jump" when an exception is thrown and thus causes the EVM to revert all changes made to the state. The reason for this is that there is no safe way to continue execution, because an expected effect did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction (or at least call) without effect. - -.. index:: ! assembly, ! asm, ! evmasm - -Inline Assembly -=============== - -For more fine-grained control especially in order to enhance the language by writing libraries, -it is possible to interleave Solidity statements with inline assembly in a language close -to the one of the virtual machine. Due to the fact that the EVM is a stack machine, it is -often hard to address the correct stack slot and provide arguments to opcodes at the correct -point on the stack. Solidity's inline assembly tries to facilitate that and other issues -arising when writing manual assembly by the following features: - -* functional-style opcodes: ``mul(1, add(2, 3))`` instead of ``push1 3 push1 2 add push1 1 mul`` -* assembly-local variables: ``let x := add(2, 3) let y := mload(0x40) x := add(x, y)`` -* access to external variables: ``function f(uint x) { assembly { x := sub(x, 1) } }`` -* labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))`` - -We now want to describe the inline assembly language in detail. - -.. warning:: - Inline assembly is a way to access the Ethereum Virtual Machine - at a low level. This discards several important safety - features of Solidity. - -Example -------- - -The following example provides library code to access the code of another contract and -load it into a ``bytes`` variable. This is not possible at all with "plain Solidity" and the -idea is that assembly libraries will be used to enhance the language in such ways. - -.. code:: - - pragma solidity ^0.4.0; - - library GetCode { - function at(address _addr) returns (bytes o_code) { - assembly { - // retrieve the size of the code, this needs assembly - let size := extcodesize(_addr) - // allocate output byte array - this could also be done without assembly - // by using o_code = new bytes(size) - o_code := mload(0x40) - // new "memory end" including padding - mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) - // store length in memory - mstore(o_code, size) - // actually retrieve the code, this needs assembly - extcodecopy(_addr, add(o_code, 0x20), 0, size) - } - } - } - -Inline assembly could also be beneficial in cases where the optimizer fails to produce -efficient code. Please be aware that assembly is much more difficult to write because -the compiler does not perform checks, so you should use it for complex things only if -you really know what you are doing. - -.. code:: - - pragma solidity ^0.4.0; - - library VectorSum { - // This function is less efficient because the optimizer currently fails to - // remove the bounds checks in array access. - function sumSolidity(uint[] _data) returns (uint o_sum) { - for (uint i = 0; i < _data.length; ++i) - o_sum += _data[i]; - } - - // We know that we only access the array in bounds, so we can avoid the check. - // 0x20 needs to be added to an array because the first slot contains the - // array length. - function sumAsm(uint[] _data) returns (uint o_sum) { - for (uint i = 0; i < _data.length; ++i) { - assembly { - o_sum := mload(add(add(_data, 0x20), i)) - } - } - } - } - -Syntax ------- - -Inline assembly parses comments, literals and identifiers exactly as Solidity, so you can use the -usual ``//`` and ``/* */`` comments. Inline assembly is initiated by ``assembly { ... }`` and inside -these curly braces, the following can be used (see the later sections for more details) - - - literals, e.g. ``0x123``, ``42`` or ``"abc"`` (strings up to 32 characters) - - opcodes (in "instruction style"), e.g. ``mload sload dup1 sstore``, for a list see below - - opcodes in functional style, e.g. ``add(1, mload(0))`` - - labels, e.g. ``name:`` - - variable declarations, e.g. ``let x := 7`` or ``let x := add(y, 3)`` - - identifiers (externals, labels or assembly-local variables), e.g. ``jump(name)``, ``3 x add`` - - assignments (in "instruction style"), e.g. ``3 =: x`` - - assignments in functional style, e.g. ``x := add(y, 3)`` - - blocks where local variables are scoped inside, e.g. ``{ let x := 3 { let y := add(x, 1) } }`` - -Opcodes -------- - -This document does not want to be a full description of the Ethereum virtual machine, but the -following list can be used as a reference of its opcodes. - -If an opcode takes arguments (always from the top of the stack), they are given in parentheses. -Note that the order of arguments can be seen as being reversed compared to the instructional style (explained below). -Opcodes marked with ``-`` do not push an item onto the stack, those marked with ``*`` are -special and all others push exactly one item onte the stack. - -In the following, ``mem[a...b)`` signifies the bytes of memory starting at position ``a`` up to -(excluding) position ``b`` and ``storage[p]`` signifies the storage contents at position ``p``. - -The opcodes ``pushi`` and ``jumpdest`` cannot be used directly. - -+-------------------------+------+-----------------------------------------------------------------+ -| stop + `-` | stop execution, identical to return(0,0) | -+-------------------------+------+-----------------------------------------------------------------+ -| add(x, y) | | x + y | -+-------------------------+------+-----------------------------------------------------------------+ -| sub(x, y) | | x - y | -+-------------------------+------+-----------------------------------------------------------------+ -| mul(x, y) | | x * y | -+-------------------------+------+-----------------------------------------------------------------+ -| div(x, y) | | x / y | -+-------------------------+------+-----------------------------------------------------------------+ -| sdiv(x, y) | | x / y, for signed numbers in two's complement | -+-------------------------+------+-----------------------------------------------------------------+ -| mod(x, y) | | x % y | -+-------------------------+------+-----------------------------------------------------------------+ -| smod(x, y) | | x % y, for signed numbers in two's complement | -+-------------------------+------+-----------------------------------------------------------------+ -| exp(x, y) | | x to the power of y | -+-------------------------+------+-----------------------------------------------------------------+ -| not(x) | | ~x, every bit of x is negated | -+-------------------------+------+-----------------------------------------------------------------+ -| lt(x, y) | | 1 if x < y, 0 otherwise | -+-------------------------+------+-----------------------------------------------------------------+ -| gt(x, y) | | 1 if x > y, 0 otherwise | -+-------------------------+------+-----------------------------------------------------------------+ -| slt(x, y) | | 1 if x < y, 0 otherwise, for signed numbers in two's complement | -+-------------------------+------+-----------------------------------------------------------------+ -| sgt(x, y) | | 1 if x > y, 0 otherwise, for signed numbers in two's complement | -+-------------------------+------+-----------------------------------------------------------------+ -| eq(x, y) | | 1 if x == y, 0 otherwise | -+-------------------------+------+-----------------------------------------------------------------+ -| iszero(x) | | 1 if x == 0, 0 otherwise | -+-------------------------+------+-----------------------------------------------------------------+ -| and(x, y) | | bitwise and of x and y | -+-------------------------+------+-----------------------------------------------------------------+ -| or(x, y) | | bitwise or of x and y | -+-------------------------+------+-----------------------------------------------------------------+ -| xor(x, y) | | bitwise xor of x and y | -+-------------------------+------+-----------------------------------------------------------------+ -| byte(n, x) | | nth byte of x, where the most significant byte is the 0th byte | -+-------------------------+------+-----------------------------------------------------------------+ -| addmod(x, y, m) | | (x + y) % m with arbitrary precision arithmetics | -+-------------------------+------+-----------------------------------------------------------------+ -| mulmod(x, y, m) | | (x * y) % m with arbitrary precision arithmetics | -+-------------------------+------+-----------------------------------------------------------------+ -| signextend(i, x) | | sign extend from (i*8+7)th bit counting from least significant | -+-------------------------+------+-----------------------------------------------------------------+ -| sha3(p, n) | | keccak(mem[p...(p+n))) | -+-------------------------+------+-----------------------------------------------------------------+ -| jump(label) | `-` | jump to label / code position | -+-------------------------+------+-----------------------------------------------------------------+ -| jumpi(label, cond) | `-` | jump to label if cond is nonzero | -+-------------------------+------+-----------------------------------------------------------------+ -| pc | | current position in code | -+-------------------------+------+-----------------------------------------------------------------+ -| pop(x) | `-` | remove the element pushed by x | -+-------------------------+------+-----------------------------------------------------------------+ -| dup1 ... dup16 | | copy ith stack slot to the top (counting from top) | -+-------------------------+------+-----------------------------------------------------------------+ -| swap1 ... swap16 | `*` | swap topmost and ith stack slot below it | -+-------------------------+------+-----------------------------------------------------------------+ -| mload(p) | | mem[p..(p+32)) | -+-------------------------+------+-----------------------------------------------------------------+ -| mstore(p, v) | `-` | mem[p..(p+32)) := v | -+-------------------------+------+-----------------------------------------------------------------+ -| mstore8(p, v) | `-` | mem[p] := v & 0xff - only modifies a single byte | -+-------------------------+------+-----------------------------------------------------------------+ -| sload(p) | | storage[p] | -+-------------------------+------+-----------------------------------------------------------------+ -| sstore(p, v) | `-` | storage[p] := v | -+-------------------------+------+-----------------------------------------------------------------+ -| msize | | size of memory, i.e. largest accessed memory index | -+-------------------------+------+-----------------------------------------------------------------+ -| gas | | gas still available to execution | -+-------------------------+------+-----------------------------------------------------------------+ -| address | | address of the current contract / execution context | -+-------------------------+------+-----------------------------------------------------------------+ -| balance(a) | | wei balance at address a | -+-------------------------+------+-----------------------------------------------------------------+ -| caller | | call sender (excluding delegatecall) | -+-------------------------+------+-----------------------------------------------------------------+ -| callvalue | | wei sent together with the current call | -+-------------------------+------+-----------------------------------------------------------------+ -| calldataload(p) | | calldata starting from position p (32 bytes) | -+-------------------------+------+-----------------------------------------------------------------+ -| calldatasize | | size of calldata in bytes | -+-------------------------+------+-----------------------------------------------------------------+ -| calldatacopy(t, f, s) | `-` | copy s bytes from calldata at position f to mem at position t | -+-------------------------+------+-----------------------------------------------------------------+ -| codesize | | size of the code of the current contract / execution context | -+-------------------------+------+-----------------------------------------------------------------+ -| codecopy(t, f, s) | `-` | copy s bytes from code at position f to mem at position t | -+-------------------------+------+-----------------------------------------------------------------+ -| extcodesize(a) | | size of the code at address a | -+-------------------------+------+-----------------------------------------------------------------+ -| extcodecopy(a, t, f, s) | `-` | like codecopy(t, f, s) but take code at address a | -+-------------------------+------+-----------------------------------------------------------------+ -| create(v, p, s) | | create new contract with code mem[p..(p+s)) and send v wei | -| | | and return the new address | -+-------------------------+------+-----------------------------------------------------------------+ -| call(g, a, v, in, | | call contract at address a with input mem[in..(in+insize)) | -| insize, out, outsize) | | providing g gas and v wei and output area | -| | | mem[out..(out+outsize)) returning 0 on error (eg. out of gas) | -| | | and 1 on success | -+-------------------------+------+-----------------------------------------------------------------+ -| callcode(g, a, v, in, | | identical to `call` but only use the code from a and stay | -| insize, out, outsize) | | in the context of the current contract otherwise | -+-------------------------+------+-----------------------------------------------------------------+ -| delegatecall(g, a, in, | | identical to `callcode` but also keep ``caller`` | -| insize, out, outsize) | | and ``callvalue`` | -+-------------------------+------+-----------------------------------------------------------------+ -| return(p, s) | `-` | end execution, return data mem[p..(p+s)) | -+-------------------------+------+-----------------------------------------------------------------+ -| selfdestruct(a) | `-` | end execution, destroy current contract and send funds to a | -+-------------------------+------+-----------------------------------------------------------------+ -| log0(p, s) | `-` | log without topics and data mem[p..(p+s)) | -+-------------------------+------+-----------------------------------------------------------------+ -| log1(p, s, t1) | `-` | log with topic t1 and data mem[p..(p+s)) | -+-------------------------+------+-----------------------------------------------------------------+ -| log2(p, s, t1, t2) | `-` | log with topics t1, t2 and data mem[p..(p+s)) | -+-------------------------+------+-----------------------------------------------------------------+ -| log3(p, s, t1, t2, t3) | `-` | log with topics t1, t2, t3 and data mem[p..(p+s)) | -+-------------------------+------+-----------------------------------------------------------------+ -| log4(p, s, t1, t2, t3, | `-` | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) | -| t4) | | | -+-------------------------+------+-----------------------------------------------------------------+ -| origin | | transaction sender | -+-------------------------+------+-----------------------------------------------------------------+ -| gasprice | | gas price of the transaction | -+-------------------------+------+-----------------------------------------------------------------+ -| blockhash(b) | | hash of block nr b - only for last 256 blocks excluding current | -+-------------------------+------+-----------------------------------------------------------------+ -| coinbase | | current mining beneficiary | -+-------------------------+------+-----------------------------------------------------------------+ -| timestamp | | timestamp of the current block in seconds since the epoch | -+-------------------------+------+-----------------------------------------------------------------+ -| number | | current block number | -+-------------------------+------+-----------------------------------------------------------------+ -| difficulty | | difficulty of the current block | -+-------------------------+------+-----------------------------------------------------------------+ -| gaslimit | | block gas limit of the current block | -+-------------------------+------+-----------------------------------------------------------------+ - -Literals --------- - -You can use integer constants by typing them in decimal or hexadecimal notation and an -appropriate ``PUSHi`` instruction will automatically be generated. The following creates code -to add 2 and 3 resulting in 5 and then computes the bitwise and with the string "abc". -Strings are stored left-aligned and cannot be longer than 32 bytes. - -.. code:: - - assembly { 2 3 add "abc" and } - -Functional Style ------------------ - -You can type opcode after opcode in the same way they will end up in bytecode. For example -adding ``3`` to the contents in memory at position ``0x80`` would be - -.. code:: - - 3 0x80 mload add 0x80 mstore - -As it is often hard to see what the actual arguments for certain opcodes are, -Solidity inline assembly also provides a "functional style" notation where the same code -would be written as follows - -.. code:: - - mstore(0x80, add(mload(0x80), 3)) - -Functional style and instructional style can be mixed, but any opcode inside a -functional style expression has to return exactly one stack slot (most of the opcodes do). - -Note that the order of arguments is reversed in functional-style as opposed to the instruction-style -way. If you use functional-style, the first argument will end up on the stack top. - - -Access to External Variables and Functions ------------------------------------------- - -Solidity variables and other identifiers can be accessed by simply using their name. -For storage and memory variables, this will push the address and not the value onto the -stack. Also note that non-struct and non-array storage variable addresses occupy two slots -on the stack: One for the address and one for the byte offset inside the storage slot. -In assignments (see below), we can even use local Solidity variables to assign to. - -Functions external to inline assembly can also be accessed: The assembly will -push their entry label (with virtual function resolution applied). The calling semantics -in solidity are: - - - the caller pushes return label, arg1, arg2, ..., argn - - the call returns with ret1, ret2, ..., retn - -This feature is still a bit cumbersome to use, because the stack offset essentially -changes during the call, and thus references to local variables will be wrong. -It is planned that the stack height changes can be specified in inline assembly. - -.. code:: - - pragma solidity ^0.4.0; - - contract C { - uint b; - function f(uint x) returns (uint r) { - assembly { - b pop // remove the offset, we know it is zero - sload - x - mul - =: r // assign to return variable r - } - } - } - -Labels ------- - -Another problem in EVM assembly is that ``jump`` and ``jumpi`` use absolute addresses -which can change easily. Solidity inline assembly provides labels to make the use of -jumps easier. The following code computes an element in the Fibonacci series. - -.. code:: - - { - let n := calldataload(4) - let a := 1 - let b := a - loop: - jumpi(loopend, eq(n, 0)) - a add swap1 - n := sub(n, 1) - jump(loop) - loopend: - mstore(0, a) - return(0, 0x20) - } - -Please note that automatically accessing stack variables can only work if the -assembler knows the current stack height. This fails to work if the jump source -and target have different stack heights. It is still fine to use such jumps, -you should just not access any stack variables (even assembly variables) in that case. - -Furthermore, the stack height analyser goes through the code opcode by opcode -(and not according to control flow), so in the following case, the assembler -will have a wrong impression about the stack height at label ``two``: - -.. code:: - - { - jump(two) - one: - // Here the stack height is 1 (because we pushed 7), - // but the assembler thinks it is 0 because it reads - // from top to bottom. - // Accessing stack variables here will lead to errors. - jump(three) - two: - 7 // push something onto the stack - jump(one) - three: - } - -.. note:: - - ``invalidJumpLabel`` is a pre-defined label. Jumping to this location will always - result in an invalid jump, effectively aborting execution of the code. - -Declaring Assembly-Local Variables ----------------------------------- - -You can use the ``let`` keyword to declare variables that are only visible in -inline assembly and actually only in the current ``{...}``-block. What happens -is that the ``let`` instruction will create a new stack slot that is reserved -for the variable and automatically removed again when the end of the block -is reached. You need to provide an initial value for the variable which can -be just ``0``, but it can also be a complex functional-style expression. - -.. code:: - - pragma solidity ^0.4.0; - - contract C { - function f(uint x) returns (uint b) { - assembly { - let v := add(x, 1) - mstore(0x80, v) - { - let y := add(sload(v), 1) - b := y - } // y is "deallocated" here - b := add(b, v) - } // v is "deallocated" here - } - } - - -Assignments ------------ - -Assignments are possible to assembly-local variables and to function-local -variables. Take care that when you assign to variables that point to -memory or storage, you will only change the pointer and not the data. - -There are two kinds of assignments: Functional-style and instruction-style. -For functional-style assignments (``variable := value``), you need to provide a value in a -functional-style expression that results in exactly one stack value -and for instruction-style (``=: variable``), the value is just taken from the stack top. -For both ways, the colon points to the name of the variable. - -.. code:: - - assembly { - let v := 0 // functional-style assignment as part of variable declaration - let g := add(v, 2) - sload(10) - =: v // instruction style assignment, puts the result of sload(10) into v - } - - -Things to Avoid ---------------- - -Inline assembly might have a quite high-level look, but it actually is extremely -low-level. The only thing the assembler does for you is re-arranging -functional-style opcodes, managing jump labels, counting stack height for -variable access and removing stack slots for assembly-local variables when the end -of their block is reached. Especially for those two last cases, it is important -to know that the assembler only counts stack height from top to bottom, not -necessarily following control flow. Furthermore, operations like swap will only -swap the contents of the stack but not the location of variables. - -Conventions in Solidity ------------------------ - -In contrast to EVM assembly, Solidity knows types which are narrower than 256 bits, -e.g. ``uint24``. In order to make them more efficient, most arithmetic operations just -treat them as 256-bit numbers and the higher-order bits are only cleaned at the -point where it is necessary, i.e. just shortly before they are written to memory -or before comparisons are performed. This means that if you access such a variable -from within inline assembly, you might have to manually clean the higher order bits -first. - -Solidity manages memory in a very simple way: There is a "free memory pointer" -at position ``0x40`` in memory. If you want to allocate memory, just use the memory -from that point on and update the pointer accordingly. - -Elements in memory arrays in Solidity always occupy multiples of 32 bytes (yes, this is -even true for ``byte[]``, but not for ``bytes`` and ``string``). Multi-dimensional memory -arrays are pointers to memory arrays. The length of a dynamic array is stored at the -first slot of the array and then only the array elements follow. - -.. warning:: - Statically-sized memory arrays do not have a length field, but it will be added soon - to allow better convertibility between statically- and dynamically-sized arrays, so - please do not rely on that. +An ``assert``-style exception is generated in the following situations: + +#. If you access an array at a too large or negative index (i.e. ``x[i]`` where ``i >= x.length`` or ``i < 0``). +#. If you access a fixed-length ``bytesN`` at a too large or negative index. +#. If you divide or modulo by zero (e.g. ``5 / 0`` or ``23 % 0``). +#. If you shift by a negative amount. +#. If you convert a value too big or negative into an enum type. +#. If you call a zero-initialized variable of internal function type. +#. If you call ``assert`` with an argument that evaluates to false. + +A ``require``-style exception is generated in the following situations: + +#. Calling ``throw``. +#. Calling ``require`` with an argument that evaluates to ``false``. +#. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation ``call``, ``send``, ``delegatecall`` or ``callcode`` is used. The low level operations never throw exceptions but indicate failures by returning ``false``. +#. If you create a contract using the ``new`` keyword but the contract creation does not finish properly (see above for the definition of "not finish properly"). +#. If you perform an external function call targeting a contract that contains no code. +#. If your contract receives Ether via a public function without ``payable`` modifier (including the constructor and the fallback function). +#. If your contract receives Ether via a public getter function. +#. If a ``.transfer()`` fails. + +Internally, Solidity performs a revert operation (instruction ``0xfd``) for a ``require``-style exception and executes an invalid operation +(instruction ``0xfe``) to throw an ``assert``-style exception. In both cases, this causes +the EVM to revert all changes made to the state. The reason for reverting is that there is no safe way to continue execution, because an expected effect +did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction +(or at least call) without effect. Note that ``assert``-style exceptions consume all gas available to the call, while +``revert``-style exceptions will not consume any gas starting from the Metropolis release.
\ No newline at end of file diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 43fba332..03ee8388 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -68,7 +68,7 @@ creator. Save it. Then ``selfdestruct(creator);`` to kill and return funds. Note that if you ``import "mortal"`` at the top of your contracts and declare ``contract SomeContract is mortal { ...`` and compile with a compiler that already -has it (which includes `browser-solidity <https://ethereum.github.io/browser-solidity/>`_), then +has it (which includes `Remix <https://remix.ethereum.org/>`_), then ``kill()`` is taken care of for you. Once a contract is "mortal", then you can ``contractname.kill.sendTransaction({from:eth.coinbase})``, just the same as my examples. @@ -641,7 +641,7 @@ Not yet, as this requires two levels of dynamic arrays (``string`` is a dynamic If you issue a call for an array, it is possible to retrieve the whole array? Or must you write a helper function for that? =========================================================================================================================== -The automatic accessor function for a public state variable of array type only returns +The automatic getter function for a public state variable of array type only returns individual elements. If you want to return the complete array, you have to manually write a function to do that. @@ -660,23 +660,12 @@ https://github.com/ethereum/wiki/wiki/Subtleties After a successful CREATE operation's sub-execution, if the operation returns x, 5 * len(x) gas is subtracted from the remaining gas before the contract is created. If the remaining gas is less than 5 * len(x), then no gas is subtracted, the code of the created contract becomes the empty string, but this is not treated as an exceptional condition - no reverts happen. -How do I use ``.send()``? -========================= - -If you want to send 20 Ether from a contract to the address ``x``, you use ``x.send(20 ether);``. -Here, ``x`` can be a plain address or a contract. If the contract already explicitly defines -a function ``send`` (and thus overwrites the special function), you can use ``address(x).send(20 ether);``. - -Note that the call to ``send`` may fail in certain conditions, such as if you have insufficient funds, so you should always check the return value. -``send`` returns ``true`` if the send was successful and ``false`` otherwise. - What does the following strange check do in the Custom Token contract? ====================================================================== :: - if (balanceOf[_to] + _value < balanceOf[_to]) - throw; + require((balanceOf[_to] + _value) >= balanceOf[_to]); Integers in Solidity (and most other machine-related programming languages) are restricted to a certain range. For ``uint256``, this is ``0`` up to ``2**256 - 1``. If the result of some operation on those numbers diff --git a/docs/grammar.txt b/docs/grammar.txt index 0aa6690b..6c041460 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -7,23 +7,26 @@ ImportDirective = 'import' StringLiteral ('as' Identifier)? ';' | 'import' ('*' | Identifier) ('as' Identifier)? 'from' StringLiteral ';' | 'import' '{' Identifier ('as' Identifier)? ( ',' Identifier ('as' Identifier)? )* '}' 'from' StringLiteral ';' -ContractDefinition = ( 'contract' | 'library' ) Identifier +ContractDefinition = ( 'contract' | 'library' | 'interface' ) Identifier ( 'is' InheritanceSpecifier (',' InheritanceSpecifier )* )? '{' ContractPart* '}' ContractPart = StateVariableDeclaration | UsingForDeclaration | StructDefinition | ModifierDefinition | FunctionDefinition | EventDefinition | EnumDefinition -InheritanceSpecifier = Identifier ( '(' Expression ( ',' Expression )* ')' )? +InheritanceSpecifier = UserDefinedTypeName ( '(' Expression ( ',' Expression )* ')' )? StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' )? Identifier ('=' Expression)? ';' UsingForDeclaration = 'using' Identifier 'for' ('*' | TypeName) ';' StructDefinition = 'struct' Identifier '{' ( VariableDeclaration ';' (VariableDeclaration ';')* )? '}' + ModifierDefinition = 'modifier' Identifier ParameterList? Block +ModifierInvocation = Identifier ( '(' ExpressionList? ')' )? + FunctionDefinition = 'function' Identifier? ParameterList - ( FunctionCall | Identifier | 'constant' |' payable' | 'external' | 'public' | 'internal' | 'private' )* - ( 'returns' ParameterList )? Block + ( ModifierInvocation | 'constant' | 'payable' | 'external' | 'public' | 'internal' | 'private' )* + ( 'returns' ParameterList )? ( ';' | Block ) EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';' EnumValue = Identifier @@ -35,16 +38,24 @@ TypeNameList = '(' ( TypeName (',' TypeName )* )? ')' // semantic restriction: mappings and structs (recursively) containing mappings // are not allowed in argument lists -VariableDeclaration = TypeName Identifier -TypeName = ElementaryTypeName | Identifier StorageLocation? | Mapping | ArrayTypeName | FunctionTypeName +VariableDeclaration = TypeName StorageLocation? Identifier + +TypeName = ElementaryTypeName + | UserDefinedTypeName + | Mapping + | ArrayTypeName + | FunctionTypeName + +UserDefinedTypeName = Identifier ( '.' Identifier )* + Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')' -ArrayTypeName = TypeName StorageLocation? '[' Expression? ']' +ArrayTypeName = TypeName '[' Expression? ']' FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant' | 'payable' )* ( 'returns' TypeNameList )? StorageLocation = 'memory' | 'storage' Block = '{' Statement* '}' -Statement = IfStatement | WhileStatement | ForStatement | Block | +Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement | ( DoWhileStatement | PlaceholderStatement | Continue | Break | Return | Throw | SimpleStatement ) ';' @@ -54,21 +65,28 @@ WhileStatement = 'while' '(' Expression ')' Statement PlaceholderStatement = '_' SimpleStatement = VariableDefinition | ExpressionStatement ForStatement = 'for' '(' (SimpleStatement)? ';' (Expression)? ';' (ExpressionStatement)? ')' Statement +InlineAssemblyStatement = 'assembly' StringLiteral? InlineAssemblyBlock DoWhileStatement = 'do' Statement 'while' '(' Expression ')' Continue = 'continue' Break = 'break' Return = 'return' Expression? Throw = 'throw' -VariableDefinition = VariableDeclaration ( '=' Expression )? +VariableDefinition = ('var' IdentifierList | VariableDeclaration) ( '=' Expression )? +IdentifierList = '(' ( Identifier? ',' )* Identifier? ')' // Precedence by order (see github.com/ethereum/solidity/pull/732) -Expression = - ( Expression ('++' | '--') | FunctionCall | IndexAccess | MemberAccess | '(' Expression ')' ) +Expression + = Expression ('++' | '--') + | NewExpression + | IndexAccess + | MemberAccess + | FunctionCall + | '(' Expression ')' | ('!' | '~' | 'delete' | '++' | '--' | '+' | '-') Expression | Expression '**' Expression | Expression ('*' | '/' | '%') Expression | Expression ('+' | '-') Expression - | Expression ('<<' | '>>') + | Expression ('<<' | '>>') Expression | Expression '&' Expression | Expression '^' Expression | Expression '|' Expression @@ -78,23 +96,42 @@ Expression = | Expression '||' Expression | Expression '?' Expression ':' Expression | Expression ('=' | '|=' | '^=' | '&=' | '<<=' | '>>=' | '+=' | '-=' | '*=' | '/=' | '%=') Expression - | Expression? (',' Expression) | PrimaryExpression -PrimaryExpression = Identifier | BooleanLiteral | NumberLiteral | HexLiteral | StringLiteral +PrimaryExpression = BooleanLiteral + | NumberLiteral + | HexLiteral + | StringLiteral + | TupleExpression + | Identifier + | ElementaryTypeNameExpression + +ExpressionList = Expression ( ',' Expression )* +NameValueList = Identifier ':' Expression ( ',' Identifier ':' Expression )* -FunctionCall = ( PrimaryExpression | NewExpression | TypeName ) ( ( '.' Identifier ) | ( '[' Expression ']' ) )* '(' Expression? ( ',' Expression )* ')' -NewExpression = 'new' Identifier +FunctionCall = Expression '(' FunctionCallArguments ')' +FunctionCallArguments = '{' NameValueList? '}' + | ExpressionList? + +NewExpression = 'new' TypeName MemberAccess = Expression '.' Identifier IndexAccess = Expression '[' Expression? ']' BooleanLiteral = 'true' | 'false' -NumberLiteral = '0x'? [0-9]+ (' ' NumberUnit)? +NumberLiteral = ( HexNumber | DecimalNumber ) (' ' NumberUnit)? NumberUnit = 'wei' | 'szabo' | 'finney' | 'ether' | 'seconds' | 'minutes' | 'hours' | 'days' | 'weeks' | 'years' HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'') StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' -Identifier = [a-zA-Z_] [a-zA-Z_0-9]* +Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]* + +HexNumber = '0x' [0-9a-fA-F]+ +DecimalNumber = [0-9]+ + +TupleExpression = '(' ( Expression ( ',' Expression )* )? ')' + | '[' ( Expression ( ',' Expression )* )? ']' + +ElementaryTypeNameExpression = ElementaryTypeName ElementaryTypeName = 'address' | 'bool' | 'string' | 'var' | Int | Uint | Byte | Fixed | Ufixed @@ -108,3 +145,11 @@ Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | Fixed = 'fixed' | 'fixed0x8' | 'fixed0x16' | 'fixed0x24' | 'fixed0x32' | 'fixed0x40' | 'fixed0x48' | 'fixed0x56' | 'fixed0x64' | 'fixed0x72' | 'fixed0x80' | 'fixed0x88' | 'fixed0x96' | 'fixed0x104' | 'fixed0x112' | 'fixed0x120' | 'fixed0x128' | 'fixed0x136' | 'fixed0x144' | 'fixed0x152' | 'fixed0x160' | 'fixed0x168' | 'fixed0x176' | 'fixed0x184' | 'fixed0x192' | 'fixed0x200' | 'fixed0x208' | 'fixed0x216' | 'fixed0x224' | 'fixed0x232' | 'fixed0x240' | 'fixed0x248' | 'fixed0x256' | 'fixed8x8' | 'fixed8x16' | 'fixed8x24' | 'fixed8x32' | 'fixed8x40' | 'fixed8x48' | 'fixed8x56' | 'fixed8x64' | 'fixed8x72' | 'fixed8x80' | 'fixed8x88' | 'fixed8x96' | 'fixed8x104' | 'fixed8x112' | 'fixed8x120' | 'fixed8x128' | 'fixed8x136' | 'fixed8x144' | 'fixed8x152' | 'fixed8x160' | 'fixed8x168' | 'fixed8x176' | 'fixed8x184' | 'fixed8x192' | 'fixed8x200' | 'fixed8x208' | 'fixed8x216' | 'fixed8x224' | 'fixed8x232' | 'fixed8x240' | 'fixed8x248' | 'fixed16x8' | 'fixed16x16' | 'fixed16x24' | 'fixed16x32' | 'fixed16x40' | 'fixed16x48' | 'fixed16x56' | 'fixed16x64' | 'fixed16x72' | 'fixed16x80' | 'fixed16x88' | 'fixed16x96' | 'fixed16x104' | 'fixed16x112' | 'fixed16x120' | 'fixed16x128' | 'fixed16x136' | 'fixed16x144' | 'fixed16x152' | 'fixed16x160' | 'fixed16x168' | 'fixed16x176' | 'fixed16x184' | 'fixed16x192' | 'fixed16x200' | 'fixed16x208' | 'fixed16x216' | 'fixed16x224' | 'fixed16x232' | 'fixed16x240' | 'fixed24x8' | 'fixed24x16' | 'fixed24x24' | 'fixed24x32' | 'fixed24x40' | 'fixed24x48' | 'fixed24x56' | 'fixed24x64' | 'fixed24x72' | 'fixed24x80' | 'fixed24x88' | 'fixed24x96' | 'fixed24x104' | 'fixed24x112' | 'fixed24x120' | 'fixed24x128' | 'fixed24x136' | 'fixed24x144' | 'fixed24x152' | 'fixed24x160' | 'fixed24x168' | 'fixed24x176' | 'fixed24x184' | 'fixed24x192' | 'fixed24x200' | 'fixed24x208' | 'fixed24x216' | 'fixed24x224' | 'fixed24x232' | 'fixed32x8' | 'fixed32x16' | 'fixed32x24' | 'fixed32x32' | 'fixed32x40' | 'fixed32x48' | 'fixed32x56' | 'fixed32x64' | 'fixed32x72' | 'fixed32x80' | 'fixed32x88' | 'fixed32x96' | 'fixed32x104' | 'fixed32x112' | 'fixed32x120' | 'fixed32x128' | 'fixed32x136' | 'fixed32x144' | 'fixed32x152' | 'fixed32x160' | 'fixed32x168' | 'fixed32x176' | 'fixed32x184' | 'fixed32x192' | 'fixed32x200' | 'fixed32x208' | 'fixed32x216' | 'fixed32x224' | 'fixed40x8' | 'fixed40x16' | 'fixed40x24' | 'fixed40x32' | 'fixed40x40' | 'fixed40x48' | 'fixed40x56' | 'fixed40x64' | 'fixed40x72' | 'fixed40x80' | 'fixed40x88' | 'fixed40x96' | 'fixed40x104' | 'fixed40x112' | 'fixed40x120' | 'fixed40x128' | 'fixed40x136' | 'fixed40x144' | 'fixed40x152' | 'fixed40x160' | 'fixed40x168' | 'fixed40x176' | 'fixed40x184' | 'fixed40x192' | 'fixed40x200' | 'fixed40x208' | 'fixed40x216' | 'fixed48x8' | 'fixed48x16' | 'fixed48x24' | 'fixed48x32' | 'fixed48x40' | 'fixed48x48' | 'fixed48x56' | 'fixed48x64' | 'fixed48x72' | 'fixed48x80' | 'fixed48x88' | 'fixed48x96' | 'fixed48x104' | 'fixed48x112' | 'fixed48x120' | 'fixed48x128' | 'fixed48x136' | 'fixed48x144' | 'fixed48x152' | 'fixed48x160' | 'fixed48x168' | 'fixed48x176' | 'fixed48x184' | 'fixed48x192' | 'fixed48x200' | 'fixed48x208' | 'fixed56x8' | 'fixed56x16' | 'fixed56x24' | 'fixed56x32' | 'fixed56x40' | 'fixed56x48' | 'fixed56x56' | 'fixed56x64' | 'fixed56x72' | 'fixed56x80' | 'fixed56x88' | 'fixed56x96' | 'fixed56x104' | 'fixed56x112' | 'fixed56x120' | 'fixed56x128' | 'fixed56x136' | 'fixed56x144' | 'fixed56x152' | 'fixed56x160' | 'fixed56x168' | 'fixed56x176' | 'fixed56x184' | 'fixed56x192' | 'fixed56x200' | 'fixed64x8' | 'fixed64x16' | 'fixed64x24' | 'fixed64x32' | 'fixed64x40' | 'fixed64x48' | 'fixed64x56' | 'fixed64x64' | 'fixed64x72' | 'fixed64x80' | 'fixed64x88' | 'fixed64x96' | 'fixed64x104' | 'fixed64x112' | 'fixed64x120' | 'fixed64x128' | 'fixed64x136' | 'fixed64x144' | 'fixed64x152' | 'fixed64x160' | 'fixed64x168' | 'fixed64x176' | 'fixed64x184' | 'fixed64x192' | 'fixed72x8' | 'fixed72x16' | 'fixed72x24' | 'fixed72x32' | 'fixed72x40' | 'fixed72x48' | 'fixed72x56' | 'fixed72x64' | 'fixed72x72' | 'fixed72x80' | 'fixed72x88' | 'fixed72x96' | 'fixed72x104' | 'fixed72x112' | 'fixed72x120' | 'fixed72x128' | 'fixed72x136' | 'fixed72x144' | 'fixed72x152' | 'fixed72x160' | 'fixed72x168' | 'fixed72x176' | 'fixed72x184' | 'fixed80x8' | 'fixed80x16' | 'fixed80x24' | 'fixed80x32' | 'fixed80x40' | 'fixed80x48' | 'fixed80x56' | 'fixed80x64' | 'fixed80x72' | 'fixed80x80' | 'fixed80x88' | 'fixed80x96' | 'fixed80x104' | 'fixed80x112' | 'fixed80x120' | 'fixed80x128' | 'fixed80x136' | 'fixed80x144' | 'fixed80x152' | 'fixed80x160' | 'fixed80x168' | 'fixed80x176' | 'fixed88x8' | 'fixed88x16' | 'fixed88x24' | 'fixed88x32' | 'fixed88x40' | 'fixed88x48' | 'fixed88x56' | 'fixed88x64' | 'fixed88x72' | 'fixed88x80' | 'fixed88x88' | 'fixed88x96' | 'fixed88x104' | 'fixed88x112' | 'fixed88x120' | 'fixed88x128' | 'fixed88x136' | 'fixed88x144' | 'fixed88x152' | 'fixed88x160' | 'fixed88x168' | 'fixed96x8' | 'fixed96x16' | 'fixed96x24' | 'fixed96x32' | 'fixed96x40' | 'fixed96x48' | 'fixed96x56' | 'fixed96x64' | 'fixed96x72' | 'fixed96x80' | 'fixed96x88' | 'fixed96x96' | 'fixed96x104' | 'fixed96x112' | 'fixed96x120' | 'fixed96x128' | 'fixed96x136' | 'fixed96x144' | 'fixed96x152' | 'fixed96x160' | 'fixed104x8' | 'fixed104x16' | 'fixed104x24' | 'fixed104x32' | 'fixed104x40' | 'fixed104x48' | 'fixed104x56' | 'fixed104x64' | 'fixed104x72' | 'fixed104x80' | 'fixed104x88' | 'fixed104x96' | 'fixed104x104' | 'fixed104x112' | 'fixed104x120' | 'fixed104x128' | 'fixed104x136' | 'fixed104x144' | 'fixed104x152' | 'fixed112x8' | 'fixed112x16' | 'fixed112x24' | 'fixed112x32' | 'fixed112x40' | 'fixed112x48' | 'fixed112x56' | 'fixed112x64' | 'fixed112x72' | 'fixed112x80' | 'fixed112x88' | 'fixed112x96' | 'fixed112x104' | 'fixed112x112' | 'fixed112x120' | 'fixed112x128' | 'fixed112x136' | 'fixed112x144' | 'fixed120x8' | 'fixed120x16' | 'fixed120x24' | 'fixed120x32' | 'fixed120x40' | 'fixed120x48' | 'fixed120x56' | 'fixed120x64' | 'fixed120x72' | 'fixed120x80' | 'fixed120x88' | 'fixed120x96' | 'fixed120x104' | 'fixed120x112' | 'fixed120x120' | 'fixed120x128' | 'fixed120x136' | 'fixed128x8' | 'fixed128x16' | 'fixed128x24' | 'fixed128x32' | 'fixed128x40' | 'fixed128x48' | 'fixed128x56' | 'fixed128x64' | 'fixed128x72' | 'fixed128x80' | 'fixed128x88' | 'fixed128x96' | 'fixed128x104' | 'fixed128x112' | 'fixed128x120' | 'fixed128x128' | 'fixed136x8' | 'fixed136x16' | 'fixed136x24' | 'fixed136x32' | 'fixed136x40' | 'fixed136x48' | 'fixed136x56' | 'fixed136x64' | 'fixed136x72' | 'fixed136x80' | 'fixed136x88' | 'fixed136x96' | 'fixed136x104' | 'fixed136x112' | 'fixed136x120' | 'fixed144x8' | 'fixed144x16' | 'fixed144x24' | 'fixed144x32' | 'fixed144x40' | 'fixed144x48' | 'fixed144x56' | 'fixed144x64' | 'fixed144x72' | 'fixed144x80' | 'fixed144x88' | 'fixed144x96' | 'fixed144x104' | 'fixed144x112' | 'fixed152x8' | 'fixed152x16' | 'fixed152x24' | 'fixed152x32' | 'fixed152x40' | 'fixed152x48' | 'fixed152x56' | 'fixed152x64' | 'fixed152x72' | 'fixed152x80' | 'fixed152x88' | 'fixed152x96' | 'fixed152x104' | 'fixed160x8' | 'fixed160x16' | 'fixed160x24' | 'fixed160x32' | 'fixed160x40' | 'fixed160x48' | 'fixed160x56' | 'fixed160x64' | 'fixed160x72' | 'fixed160x80' | 'fixed160x88' | 'fixed160x96' | 'fixed168x8' | 'fixed168x16' | 'fixed168x24' | 'fixed168x32' | 'fixed168x40' | 'fixed168x48' | 'fixed168x56' | 'fixed168x64' | 'fixed168x72' | 'fixed168x80' | 'fixed168x88' | 'fixed176x8' | 'fixed176x16' | 'fixed176x24' | 'fixed176x32' | 'fixed176x40' | 'fixed176x48' | 'fixed176x56' | 'fixed176x64' | 'fixed176x72' | 'fixed176x80' | 'fixed184x8' | 'fixed184x16' | 'fixed184x24' | 'fixed184x32' | 'fixed184x40' | 'fixed184x48' | 'fixed184x56' | 'fixed184x64' | 'fixed184x72' | 'fixed192x8' | 'fixed192x16' | 'fixed192x24' | 'fixed192x32' | 'fixed192x40' | 'fixed192x48' | 'fixed192x56' | 'fixed192x64' | 'fixed200x8' | 'fixed200x16' | 'fixed200x24' | 'fixed200x32' | 'fixed200x40' | 'fixed200x48' | 'fixed200x56' | 'fixed208x8' | 'fixed208x16' | 'fixed208x24' | 'fixed208x32' | 'fixed208x40' | 'fixed208x48' | 'fixed216x8' | 'fixed216x16' | 'fixed216x24' | 'fixed216x32' | 'fixed216x40' | 'fixed224x8' | 'fixed224x16' | 'fixed224x24' | 'fixed224x32' | 'fixed232x8' | 'fixed232x16' | 'fixed232x24' | 'fixed240x8' | 'fixed240x16' | 'fixed248x8' Ufixed = 'ufixed' | 'ufixed0x8' | 'ufixed0x16' | 'ufixed0x24' | 'ufixed0x32' | 'ufixed0x40' | 'ufixed0x48' | 'ufixed0x56' | 'ufixed0x64' | 'ufixed0x72' | 'ufixed0x80' | 'ufixed0x88' | 'ufixed0x96' | 'ufixed0x104' | 'ufixed0x112' | 'ufixed0x120' | 'ufixed0x128' | 'ufixed0x136' | 'ufixed0x144' | 'ufixed0x152' | 'ufixed0x160' | 'ufixed0x168' | 'ufixed0x176' | 'ufixed0x184' | 'ufixed0x192' | 'ufixed0x200' | 'ufixed0x208' | 'ufixed0x216' | 'ufixed0x224' | 'ufixed0x232' | 'ufixed0x240' | 'ufixed0x248' | 'ufixed0x256' | 'ufixed8x8' | 'ufixed8x16' | 'ufixed8x24' | 'ufixed8x32' | 'ufixed8x40' | 'ufixed8x48' | 'ufixed8x56' | 'ufixed8x64' | 'ufixed8x72' | 'ufixed8x80' | 'ufixed8x88' | 'ufixed8x96' | 'ufixed8x104' | 'ufixed8x112' | 'ufixed8x120' | 'ufixed8x128' | 'ufixed8x136' | 'ufixed8x144' | 'ufixed8x152' | 'ufixed8x160' | 'ufixed8x168' | 'ufixed8x176' | 'ufixed8x184' | 'ufixed8x192' | 'ufixed8x200' | 'ufixed8x208' | 'ufixed8x216' | 'ufixed8x224' | 'ufixed8x232' | 'ufixed8x240' | 'ufixed8x248' | 'ufixed16x8' | 'ufixed16x16' | 'ufixed16x24' | 'ufixed16x32' | 'ufixed16x40' | 'ufixed16x48' | 'ufixed16x56' | 'ufixed16x64' | 'ufixed16x72' | 'ufixed16x80' | 'ufixed16x88' | 'ufixed16x96' | 'ufixed16x104' | 'ufixed16x112' | 'ufixed16x120' | 'ufixed16x128' | 'ufixed16x136' | 'ufixed16x144' | 'ufixed16x152' | 'ufixed16x160' | 'ufixed16x168' | 'ufixed16x176' | 'ufixed16x184' | 'ufixed16x192' | 'ufixed16x200' | 'ufixed16x208' | 'ufixed16x216' | 'ufixed16x224' | 'ufixed16x232' | 'ufixed16x240' | 'ufixed24x8' | 'ufixed24x16' | 'ufixed24x24' | 'ufixed24x32' | 'ufixed24x40' | 'ufixed24x48' | 'ufixed24x56' | 'ufixed24x64' | 'ufixed24x72' | 'ufixed24x80' | 'ufixed24x88' | 'ufixed24x96' | 'ufixed24x104' | 'ufixed24x112' | 'ufixed24x120' | 'ufixed24x128' | 'ufixed24x136' | 'ufixed24x144' | 'ufixed24x152' | 'ufixed24x160' | 'ufixed24x168' | 'ufixed24x176' | 'ufixed24x184' | 'ufixed24x192' | 'ufixed24x200' | 'ufixed24x208' | 'ufixed24x216' | 'ufixed24x224' | 'ufixed24x232' | 'ufixed32x8' | 'ufixed32x16' | 'ufixed32x24' | 'ufixed32x32' | 'ufixed32x40' | 'ufixed32x48' | 'ufixed32x56' | 'ufixed32x64' | 'ufixed32x72' | 'ufixed32x80' | 'ufixed32x88' | 'ufixed32x96' | 'ufixed32x104' | 'ufixed32x112' | 'ufixed32x120' | 'ufixed32x128' | 'ufixed32x136' | 'ufixed32x144' | 'ufixed32x152' | 'ufixed32x160' | 'ufixed32x168' | 'ufixed32x176' | 'ufixed32x184' | 'ufixed32x192' | 'ufixed32x200' | 'ufixed32x208' | 'ufixed32x216' | 'ufixed32x224' | 'ufixed40x8' | 'ufixed40x16' | 'ufixed40x24' | 'ufixed40x32' | 'ufixed40x40' | 'ufixed40x48' | 'ufixed40x56' | 'ufixed40x64' | 'ufixed40x72' | 'ufixed40x80' | 'ufixed40x88' | 'ufixed40x96' | 'ufixed40x104' | 'ufixed40x112' | 'ufixed40x120' | 'ufixed40x128' | 'ufixed40x136' | 'ufixed40x144' | 'ufixed40x152' | 'ufixed40x160' | 'ufixed40x168' | 'ufixed40x176' | 'ufixed40x184' | 'ufixed40x192' | 'ufixed40x200' | 'ufixed40x208' | 'ufixed40x216' | 'ufixed48x8' | 'ufixed48x16' | 'ufixed48x24' | 'ufixed48x32' | 'ufixed48x40' | 'ufixed48x48' | 'ufixed48x56' | 'ufixed48x64' | 'ufixed48x72' | 'ufixed48x80' | 'ufixed48x88' | 'ufixed48x96' | 'ufixed48x104' | 'ufixed48x112' | 'ufixed48x120' | 'ufixed48x128' | 'ufixed48x136' | 'ufixed48x144' | 'ufixed48x152' | 'ufixed48x160' | 'ufixed48x168' | 'ufixed48x176' | 'ufixed48x184' | 'ufixed48x192' | 'ufixed48x200' | 'ufixed48x208' | 'ufixed56x8' | 'ufixed56x16' | 'ufixed56x24' | 'ufixed56x32' | 'ufixed56x40' | 'ufixed56x48' | 'ufixed56x56' | 'ufixed56x64' | 'ufixed56x72' | 'ufixed56x80' | 'ufixed56x88' | 'ufixed56x96' | 'ufixed56x104' | 'ufixed56x112' | 'ufixed56x120' | 'ufixed56x128' | 'ufixed56x136' | 'ufixed56x144' | 'ufixed56x152' | 'ufixed56x160' | 'ufixed56x168' | 'ufixed56x176' | 'ufixed56x184' | 'ufixed56x192' | 'ufixed56x200' | 'ufixed64x8' | 'ufixed64x16' | 'ufixed64x24' | 'ufixed64x32' | 'ufixed64x40' | 'ufixed64x48' | 'ufixed64x56' | 'ufixed64x64' | 'ufixed64x72' | 'ufixed64x80' | 'ufixed64x88' | 'ufixed64x96' | 'ufixed64x104' | 'ufixed64x112' | 'ufixed64x120' | 'ufixed64x128' | 'ufixed64x136' | 'ufixed64x144' | 'ufixed64x152' | 'ufixed64x160' | 'ufixed64x168' | 'ufixed64x176' | 'ufixed64x184' | 'ufixed64x192' | 'ufixed72x8' | 'ufixed72x16' | 'ufixed72x24' | 'ufixed72x32' | 'ufixed72x40' | 'ufixed72x48' | 'ufixed72x56' | 'ufixed72x64' | 'ufixed72x72' | 'ufixed72x80' | 'ufixed72x88' | 'ufixed72x96' | 'ufixed72x104' | 'ufixed72x112' | 'ufixed72x120' | 'ufixed72x128' | 'ufixed72x136' | 'ufixed72x144' | 'ufixed72x152' | 'ufixed72x160' | 'ufixed72x168' | 'ufixed72x176' | 'ufixed72x184' | 'ufixed80x8' | 'ufixed80x16' | 'ufixed80x24' | 'ufixed80x32' | 'ufixed80x40' | 'ufixed80x48' | 'ufixed80x56' | 'ufixed80x64' | 'ufixed80x72' | 'ufixed80x80' | 'ufixed80x88' | 'ufixed80x96' | 'ufixed80x104' | 'ufixed80x112' | 'ufixed80x120' | 'ufixed80x128' | 'ufixed80x136' | 'ufixed80x144' | 'ufixed80x152' | 'ufixed80x160' | 'ufixed80x168' | 'ufixed80x176' | 'ufixed88x8' | 'ufixed88x16' | 'ufixed88x24' | 'ufixed88x32' | 'ufixed88x40' | 'ufixed88x48' | 'ufixed88x56' | 'ufixed88x64' | 'ufixed88x72' | 'ufixed88x80' | 'ufixed88x88' | 'ufixed88x96' | 'ufixed88x104' | 'ufixed88x112' | 'ufixed88x120' | 'ufixed88x128' | 'ufixed88x136' | 'ufixed88x144' | 'ufixed88x152' | 'ufixed88x160' | 'ufixed88x168' | 'ufixed96x8' | 'ufixed96x16' | 'ufixed96x24' | 'ufixed96x32' | 'ufixed96x40' | 'ufixed96x48' | 'ufixed96x56' | 'ufixed96x64' | 'ufixed96x72' | 'ufixed96x80' | 'ufixed96x88' | 'ufixed96x96' | 'ufixed96x104' | 'ufixed96x112' | 'ufixed96x120' | 'ufixed96x128' | 'ufixed96x136' | 'ufixed96x144' | 'ufixed96x152' | 'ufixed96x160' | 'ufixed104x8' | 'ufixed104x16' | 'ufixed104x24' | 'ufixed104x32' | 'ufixed104x40' | 'ufixed104x48' | 'ufixed104x56' | 'ufixed104x64' | 'ufixed104x72' | 'ufixed104x80' | 'ufixed104x88' | 'ufixed104x96' | 'ufixed104x104' | 'ufixed104x112' | 'ufixed104x120' | 'ufixed104x128' | 'ufixed104x136' | 'ufixed104x144' | 'ufixed104x152' | 'ufixed112x8' | 'ufixed112x16' | 'ufixed112x24' | 'ufixed112x32' | 'ufixed112x40' | 'ufixed112x48' | 'ufixed112x56' | 'ufixed112x64' | 'ufixed112x72' | 'ufixed112x80' | 'ufixed112x88' | 'ufixed112x96' | 'ufixed112x104' | 'ufixed112x112' | 'ufixed112x120' | 'ufixed112x128' | 'ufixed112x136' | 'ufixed112x144' | 'ufixed120x8' | 'ufixed120x16' | 'ufixed120x24' | 'ufixed120x32' | 'ufixed120x40' | 'ufixed120x48' | 'ufixed120x56' | 'ufixed120x64' | 'ufixed120x72' | 'ufixed120x80' | 'ufixed120x88' | 'ufixed120x96' | 'ufixed120x104' | 'ufixed120x112' | 'ufixed120x120' | 'ufixed120x128' | 'ufixed120x136' | 'ufixed128x8' | 'ufixed128x16' | 'ufixed128x24' | 'ufixed128x32' | 'ufixed128x40' | 'ufixed128x48' | 'ufixed128x56' | 'ufixed128x64' | 'ufixed128x72' | 'ufixed128x80' | 'ufixed128x88' | 'ufixed128x96' | 'ufixed128x104' | 'ufixed128x112' | 'ufixed128x120' | 'ufixed128x128' | 'ufixed136x8' | 'ufixed136x16' | 'ufixed136x24' | 'ufixed136x32' | 'ufixed136x40' | 'ufixed136x48' | 'ufixed136x56' | 'ufixed136x64' | 'ufixed136x72' | 'ufixed136x80' | 'ufixed136x88' | 'ufixed136x96' | 'ufixed136x104' | 'ufixed136x112' | 'ufixed136x120' | 'ufixed144x8' | 'ufixed144x16' | 'ufixed144x24' | 'ufixed144x32' | 'ufixed144x40' | 'ufixed144x48' | 'ufixed144x56' | 'ufixed144x64' | 'ufixed144x72' | 'ufixed144x80' | 'ufixed144x88' | 'ufixed144x96' | 'ufixed144x104' | 'ufixed144x112' | 'ufixed152x8' | 'ufixed152x16' | 'ufixed152x24' | 'ufixed152x32' | 'ufixed152x40' | 'ufixed152x48' | 'ufixed152x56' | 'ufixed152x64' | 'ufixed152x72' | 'ufixed152x80' | 'ufixed152x88' | 'ufixed152x96' | 'ufixed152x104' | 'ufixed160x8' | 'ufixed160x16' | 'ufixed160x24' | 'ufixed160x32' | 'ufixed160x40' | 'ufixed160x48' | 'ufixed160x56' | 'ufixed160x64' | 'ufixed160x72' | 'ufixed160x80' | 'ufixed160x88' | 'ufixed160x96' | 'ufixed168x8' | 'ufixed168x16' | 'ufixed168x24' | 'ufixed168x32' | 'ufixed168x40' | 'ufixed168x48' | 'ufixed168x56' | 'ufixed168x64' | 'ufixed168x72' | 'ufixed168x80' | 'ufixed168x88' | 'ufixed176x8' | 'ufixed176x16' | 'ufixed176x24' | 'ufixed176x32' | 'ufixed176x40' | 'ufixed176x48' | 'ufixed176x56' | 'ufixed176x64' | 'ufixed176x72' | 'ufixed176x80' | 'ufixed184x8' | 'ufixed184x16' | 'ufixed184x24' | 'ufixed184x32' | 'ufixed184x40' | 'ufixed184x48' | 'ufixed184x56' | 'ufixed184x64' | 'ufixed184x72' | 'ufixed192x8' | 'ufixed192x16' | 'ufixed192x24' | 'ufixed192x32' | 'ufixed192x40' | 'ufixed192x48' | 'ufixed192x56' | 'ufixed192x64' | 'ufixed200x8' | 'ufixed200x16' | 'ufixed200x24' | 'ufixed200x32' | 'ufixed200x40' | 'ufixed200x48' | 'ufixed200x56' | 'ufixed208x8' | 'ufixed208x16' | 'ufixed208x24' | 'ufixed208x32' | 'ufixed208x40' | 'ufixed208x48' | 'ufixed216x8' | 'ufixed216x16' | 'ufixed216x24' | 'ufixed216x32' | 'ufixed216x40' | 'ufixed224x8' | 'ufixed224x16' | 'ufixed224x24' | 'ufixed224x32' | 'ufixed232x8' | 'ufixed232x16' | 'ufixed232x24' | 'ufixed240x8' | 'ufixed240x16' | 'ufixed248x8' + +InlineAssemblyBlock = '{' AssemblyItem* '}' + +AssemblyItem = Identifier | FunctionalAssemblyExpression | InlineAssemblyBlock | AssemblyLocalBinding | AssemblyAssignment | AssemblyLabel | NumberLiteral | StringLiteral | HexLiteral +AssemblyLocalBinding = 'let' Identifier ':=' FunctionalAssemblyExpression +AssemblyAssignment = ( Identifier ':=' FunctionalAssemblyExpression ) | ( '=:' Identifier ) +AssemblyLabel = Identifier ':' +FunctionalAssemblyExpression = Identifier '(' AssemblyItem? ( ',' AssemblyItem )* ')' diff --git a/docs/index.rst b/docs/index.rst index 9bee1515..3cdda62d 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,8 +1,13 @@ Solidity ======== +.. image:: logo.svg + :width: 120px + :alt: Solidity logo + :align: center + Solidity is a contract-oriented, high-level language whose syntax is similar to that of JavaScript -and it is designed to target the Ethereum Virtual Machine. +and it is designed to target the Ethereum Virtual Machine (EVM). Solidity is statically typed, supports inheritance, libraries and complex user-defined types among other features. @@ -11,8 +16,8 @@ As you will see, it is possible to create contracts for voting, crowdfunding, blind auctions, multi-signature wallets and more. .. note:: - The best way to try out Solidity right now is using the - `Browser-Based Compiler <https://ethereum.github.io/browser-solidity/>`_ + The best way to try out Solidity right now is using + `Remix <https://remix.ethereum.org/>`_ (it can take a while to load, please be patient). Useful links @@ -33,24 +38,30 @@ Useful links Available Solidity Integrations ------------------------------- -* `Browser-Based Compiler <https://ethereum.github.io/browser-solidity/>`_ +* `Remix <https://remix.ethereum.org/>`_ Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. * `Ethereum Studio <https://live.ether.camp/>`_ Specialized web IDE that also provides shell access to a complete Ethereum environment. +* `IntelliJ IDEA plugin <https://plugins.jetbrains.com/plugin/9475-intellij-solidity>`_ + Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs) + * `Visual Studio Extension <https://visualstudiogallery.msdn.microsoft.com/96221853-33c4-4531-bdd5-d2ea5acc4799/>`_ Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler. * `Package for SublimeText — Solidity language syntax <https://packagecontrol.io/packages/Ethereum/>`_ Solidity syntax highlighting for SublimeText editor. -* `Atom Ethereum interface <https://github.com/gmtDevs/atom-ethereum-interface>`_ - Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (requires backend node). +* `Etheratom <https://github.com/0mkara/etheratom>`_ + Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible). * `Atom Solidity Linter <https://atom.io/packages/linter-solidity>`_ Plugin for the Atom editor that provides Solidity linting. - + +* `Atom Solium Linter <https://atom.io/packages/linter-solium>`_ + Configurable Solidty linter for Atom using Solium as a base. + * `Solium <https://github.com/duaraghav8/Solium/>`_ A commandline linter for Solidity which strictly follows the rules prescribed by the `Solidity Style Guide <http://solidity.readthedocs.io/en/latest/style-guide.html>`_. @@ -75,8 +86,8 @@ Discontinued: Solidity Tools -------------- -* `Dapple <https://github.com/nexusdev/dapple>`_ - Package and deployment manager for Solidity. +* `Dapp <https://dapp.readthedocs.io>`_ + Build tool, package manager, and deployment assistant for Solidity. * `Solidity REPL <https://github.com/raineorshine/solidity-repl>`_ Try Solidity instantly with a command-line Solidity console. @@ -87,6 +98,18 @@ Solidity Tools * `evmdis <https://github.com/Arachnid/evmdis>`_ EVM Disassembler that performs static analysis on the bytecode to provide a higher level of abstraction than raw EVM operations. +* `Doxity <https://github.com/DigixGlobal/doxity>`_ + Documentation Generator for Solidity. + +Third-Party Solidity Parsers and Grammars +----------------------------------------- + +* `solidity-parser <https://github.com/ConsenSys/solidity-parser>`_ + Solidity parser for JavaScript + +* `Solidity Grammar for ANTLR 4 <https://github.com/federicobond/solidity-antlr4>`_ + Solidity grammar for the ANTLR 4 parser generator + Language Documentation ---------------------- @@ -97,7 +120,7 @@ and the :ref:`Ethereum Virtual Machine <the-ethereum-virtual-machine>`. The next section will explain several *features* of Solidity by giving useful :ref:`example contracts <voting>` Remember that you can always try out the contracts -`in your browser <https://ethereum.github.io/browser-solidity>`_! +`in your browser <https://remix.ethereum.org>`_! The last and most extensive section will cover all aspects of Solidity in depth. @@ -121,7 +144,10 @@ Contents solidity-by-example.rst solidity-in-depth.rst security-considerations.rst + using-the-compiler.rst + abi-spec.rst style-guide.rst common-patterns.rst + bugs.rst contributing.rst frequently-asked-questions.rst diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index ef38705c..9b5ba9f2 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -15,34 +15,35 @@ are not guaranteed to be working and despite best efforts they might contain und and/or broken changes. We recommend using the latest release. Package installers below will use the latest release. -Browser-Solidity -================ +Remix +===== If you just want to try Solidity for small contracts, you -can try `browser-solidity <https://ethereum.github.io/browser-solidity>`_ +can try `Remix <https://remix.ethereum.org/>`_ which does not need any installation. If you want to use it without connection to the Internet, you can go to https://github.com/ethereum/browser-solidity/tree/gh-pages and download the .ZIP file as explained on that page. - npm / Node.js ============= This is probably the most portable and most convenient way to install Solidity locally. A platform-independent JavaScript library is provided by compiling the C++ source -into JavaScript using Emscripten for browser-solidity and there is also an npm -package available. +into JavaScript using Emscripten. It can be used in projects directly (such as Remix). +Please refer to the `solc-js <https://github.com/ethereum/solc-js>`_ repository for instructions. -To install it, simply use +It also contains a commandline tool called `solcjs`, which can be installed via npm: .. code:: bash - npm install solc + npm install -g solc + +.. note:: -Details about the usage of the Node.js package can be found in the -`solc-js repository <https://github.com/ethereum/solc-js>`_. + The comandline options of `solcjs` are not compatible with `solc` and tools (such as `geth`) + expecting the behaviour of `solc` will not work with `solcjs`. Docker ====== @@ -82,6 +83,12 @@ If you want to use the cutting edge developer version: sudo apt-get update sudo apt-get install solc +Arch Linux also has packages, albeit limited to the latest development version: + +.. code:: bash + + pacman -S solidity-git + Homebrew is missing pre-built bottles at the time of writing, following a Jenkins to TravisCI migration, but Homebrew should still work just fine as a means to build-from-source. @@ -95,6 +102,28 @@ We will re-add the pre-built bottles soon. brew install solidity brew linkapps solidity +If you need a specific version of Solidity you can install a +Homebrew formula directly from Github. + +View +`solidity.rb commits on Github <https://github.com/ethereum/homebrew-ethereum/commits/master/solidity.rb>`_. + +Follow the history links until you have a raw file link of a +specific commit of ``solidity.rb``. + +Install it using ``brew``: + +.. code:: bash + + brew unlink solidity + # Install 0.4.8 + brew install https://raw.githubusercontent.com/ethereum/homebrew-ethereum/77cce03da9f289e5a3ffe579840d3c5dc0a62717/solidity.rb + +Gentoo Linux also provides a solidity package that can be installed using ``emerge``: + +.. code:: bash + + demerge ev-lang/solidity .. _building-from-source: @@ -119,6 +148,11 @@ you should fork Solidity and add your personal fork as a second remote: cd solidity git remote add personal git@github.com:[username]/solidity.git +Solidity has git submodules. Ensure they are properly loaded: + +.. code:: bash + + git submodule update --init --recursive Prerequisites - macOS --------------------- @@ -192,7 +226,14 @@ Building Solidity is quite similar on Linux, macOS and other Unices: cd build cmake .. && make -And even on Windows: +or even easier: + +.. code:: bash + + #note: this will install binaries solc and soltest at usr/local/bin + ./scripts/build.sh + +And even for Windows: .. code:: bash @@ -211,6 +252,25 @@ Alternatively, you can build for Windows on the command-line, like so: cmake --build . --config RelWithDebInfo +The version string in detail +============================ + +The Solidity version string contains four parts: + +- the version number +- pre-release tag, usually set to ``develop.YYYY.MM.DD`` or ``nightly.YYYY.MM.DD`` +- commit in the format of ``commit.GITHASH`` +- platform has arbitrary number of items, containing details about the platform and compiler + +If there are local modifications, the commit will be postfixed with ``.mod``. + +These parts are combined as required by Semver, where the Solidity pre-release tag equals to the Semver pre-release +and the Solidity commit and platform combined make up the Semver build metadata. + +A release example: ``0.4.8+commit.60cc1668.Emscripten.clang``. + +A pre-release example: ``0.4.9-nightly.2017.1.17+commit.6ecb4aa3.Emscripten.clang`` + Important information about versioning ====================================== @@ -227,4 +287,4 @@ Example: 3. a breaking change is introduced - version is bumped to 0.5.0 4. the 0.5.0 release is made -This behaviour works well with the version pragma. +This behaviour works well with the :ref:`version pragma <version_pragma>`. diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index aee1e03b..dc7c6cc9 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -33,9 +33,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. +contract does not suddenly behave differently with a new compiler version. The keyword ``pragma`` is called that way because, in general, +pragmas are instructions for the compiler about how to treat the +source code (e.g. `pragma once <https://en.wikipedia.org/wiki/Pragma_once>`_). . -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 blockchain. The line ``uint storedData;`` declares a state variable called ``storedData`` of type ``uint`` (unsigned integer of 256 bits). You can think of it as a single slot @@ -47,9 +49,9 @@ or retrieve the value of the variable. To access a state variable, you do not need the prefix ``this.`` as is common in other languages. -This contract does not yet do much apart from (due to the infrastructure -built by Ethereum) allowing anyone to store a single number that is accessible by -anyone in the world without (feasible) a way to prevent you from publishing +This contract does not do much yet (due to the infrastructure +built by Ethereum) apart from allowing anyone to store a single number that is accessible by +anyone in the world without a (feasible) way to prevent you from publishing this number. Of course, anyone could just call ``set`` again with a different value and overwrite your number, but the number will still be stored in the history of the blockchain. Later, we will see how you can impose access restrictions @@ -109,8 +111,7 @@ that does not allow any arithmetic operations. It is suitable for storing addresses of contracts or keypairs belonging to external persons. The keyword ``public`` automatically generates a function that allows you to access the current value of the state variable. -Without this keyword, other contracts have no way to access the variable -and only the code of this contract can write to it. +Without this keyword, other contracts have no way to access the variable. The function will look something like this:: function minter() returns (address) { return minter; } @@ -125,14 +126,14 @@ get the idea - the compiler figures that out for you. The next line, ``mapping (address => uint) public balances;`` also creates a public state variable, but it is a more complex datatype. The type maps addresses to unsigned integers. -Mappings can be seen as hashtables which are +Mappings can be seen as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_ which are virtually initialized such that every possible key exists and is mapped to a value whose byte-representation is all zeros. This analogy does not go too far, though, as it is neither possible to obtain a list of all keys of a mapping, nor a list of all values. So either keep in mind (or better, keep a list or use a more advanced data type) what you added to the mapping or use it in a context where this is not needed, -like this one. The accessor function created by the ``public`` keyword +like this one. The getter function created by the ``public`` keyword is a bit more complex in this case. It roughly looks like the following:: @@ -147,7 +148,7 @@ single account. The line ``event Sent(address from, address to, uint amount);`` declares a so-called "event" which is fired in the last line of the function -``send``. User interfaces (as well as server appliances of course) can +``send``. User interfaces (as well as server applications of course) can listen for those events being fired on the blockchain without much cost. As soon as it is fired, the listener will also receive the arguments ``from``, ``to`` and ``amount``, which makes it easy to track @@ -162,7 +163,7 @@ transactions. In order to listen for this event, you would use :: "Sender: " + Coin.balances.call(result.args.from) + "Receiver: " + Coin.balances.call(result.args.to)); } - } + }) Note how the automatically generated function ``balances`` is called from the user interface. @@ -194,7 +195,7 @@ Blockchain Basics ***************** Blockchains as a concept are not too hard to understand for programmers. The reason is that -most of the complications (mining, hashing, elliptic-curve cryptography, peer-to-peer networks, ...) +most of the complications (mining, `hashing <https://en.wikipedia.org/wiki/Cryptographic_hash_function>`_, `elliptic-curve cryptography <https://en.wikipedia.org/wiki/Elliptic_curve_cryptography>`_, `peer-to-peer networks <https://en.wikipedia.org/wiki/Peer-to-peer>`_, etc.) are just there to provide a certain set of features and promises. Once you accept these features as given, you do not have to worry about the underlying technology - or do you have to know how Amazon's AWS works internally in order to use it? @@ -283,8 +284,8 @@ determined at the time the contract is created (it is derived from the creator address and the number of transactions sent from that address, the so-called "nonce"). -Apart from the fact whether an account stores code or not, -the EVM treats the two types equally, though. +Regardless of whether or not the account stores code, the two types are +treated equally by the EVM. Every account has a persistent key-value store mapping 256-bit words to 256-bit words called **storage**. @@ -403,7 +404,7 @@ such situations, so that exceptions "bubble up" the call stack. As already said, the called contract (which can be the same as the caller) will receive a freshly cleared instance of memory and has access to the call payload - which will be provided in a separate area called the **calldata**. -After it finished execution, it can return data which will be stored at +After it has finished execution, it can return data which will be stored at a location in the caller's memory preallocated by the caller. Calls are **limited** to a depth of 1024, which means that for more complex @@ -424,8 +425,8 @@ address at runtime. Storage, current address and balance still refer to the calling contract, only the code is taken from the called address. This makes it possible to implement the "library" feature in Solidity: -Reusable library code that can be applied to a contract's storage in -order to e.g. implement a complex data structure. +Reusable library code that can be applied to a contract's storage, e.g. in +order to implement a complex data structure. .. index:: log @@ -437,7 +438,7 @@ that maps all the way up to the block level. This feature called **logs** is used by Solidity in order to implement **events**. Contracts cannot access log data after it has been created, but they can be efficiently accessed from outside the blockchain. -Since some part of the log data is stored in bloom filters, it is +Since some part of the log data is stored in `bloom filters <https://en.wikipedia.org/wiki/Bloom_filter>`_, it is possible to search for this data in an efficient and cryptographically secure way, so network peers that do not download the whole blockchain ("light clients") can still find these logs. diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 17ac8c6f..e4b403f6 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -7,6 +7,8 @@ and pragma directives. .. index:: ! pragma, version +.. _version_pragma: + Version Pragma ============== @@ -24,14 +26,14 @@ The version pragma is used as follows:: pragma solidity ^0.4.0; Such a source file will not compile with a compiler earlier than version 0.4.0 -and it will also not work on a compiler starting form version 0.5.0 (this +and it will also not work on a compiler starting from version 0.5.0 (this second condition is added by using ``^``). The idea behind this is that there will be no breaking changes until version ``0.5.0``, so we can always be sure that our code will compile the way we intended it to. We do not fix the exact version of the compiler, so that bugfix releases are still possible. It is possible to specify much more complex rules for the compiler version, -the expression follows those used by npm. +the expression follows those used by `npm <https://docs.npmjs.com/misc/semver>`_. .. index:: source file, ! import @@ -79,8 +81,9 @@ Paths ----- In the above, ``filename`` is always treated as a path with ``/`` as directory separator, -``.`` as the current and ``..`` as the parent directory. Path names that do not start -with ``.`` are treated as absolute paths. +``.`` as the current and ``..`` as the parent directory. When ``.`` or ``..`` is followed by a character except ``/``, +it is not considered as the current or the parent directory. +All path names are treated as absolute paths unless they start with the current ``.`` or the parent directory ``..``. To import a file ``x`` from the same directory as the current file, use ``import "./x" as x;``. If you use ``import "x" as x;`` instead, a different file could be referenced @@ -96,8 +99,8 @@ Use in Actual Compilers When the compiler is invoked, it is not only possible to specify how to discover the first element of a path, but it is possible to specify path prefix remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to -``/usr/local/dapp-bin/library`` and the compiler will read the files from there. If -remapping keys are prefixes of each other, the longest is tried first. This +``/usr/local/dapp-bin/library`` and the compiler will read the files from there. +If multiple remappings can be applied, the one with the longest key is tried first. This allows for a "fallback-remapping" with e.g. ``""`` maps to ``"/usr/local/include/solidity"``. Furthermore, these remappings can depend on the context, which allows you to configure packages to @@ -150,9 +153,9 @@ remapping ``=/``. If there are multiple remappings that lead to a valid file, the remapping with the longest common prefix is chosen. -**browser-solidity**: +**Remix**: -The `browser-based compiler <https://ethereum.github.io/browser-solidity>`_ +`Remix <https://remix.ethereum.org/>`_ provides an automatic remapping for github and will also automatically retrieve the file over the network: You can import the iterable mapping by e.g. @@ -182,7 +185,7 @@ Additionally, there is another type of comment called a natspec comment, for which the documentation is not yet written. They are written with a triple slash (``///``) or a double asterisk block(``/** ... */``) and they should be used directly above function declarations or statements. -You can use Doxygen-style tags inside these comments to document +You can use `Doxygen <https://en.wikipedia.org/wiki/Doxygen>`_-style tags inside these comments to document functions, annotate conditions for formal verification, and provide a **confirmation text** which is shown to users when they attempt to invoke a function. diff --git a/docs/logo.svg b/docs/logo.svg new file mode 100644 index 00000000..86b9f499 --- /dev/null +++ b/docs/logo.svg @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" id="Layer_1" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns" + xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="1300px" height="1300px" + viewBox="0 0 1300 1300" enable-background="new 0 0 1300 1300" xml:space="preserve"> +<title>Vector 1</title> +<desc>Created with Sketch.</desc> +<g id="Page-1" sketch:type="MSPage"> + <g id="solidity" transform="translate(402.000000, 118.000000)" sketch:type="MSLayerGroup"> + <g id="Group" sketch:type="MSShapeGroup"> + <path id="Shape" opacity="0.45" enable-background="new " d="M371.772,135.308L241.068,367.61H-20.158l130.614-232.302 + H371.772"/> + <path id="Shape_1_" opacity="0.6" enable-background="new " d="M241.068,367.61h261.318L371.772,135.308H110.456 + L241.068,367.61z"/> + <path id="Shape_2_" opacity="0.8" enable-background="new " d="M110.456,599.822L241.068,367.61L110.456,135.308 + L-20.158,367.61L110.456,599.822z"/> + <path id="Shape_3_" opacity="0.45" enable-background="new " d="M111.721,948.275l130.704-232.303h261.318L373.038,948.275 + H111.721"/> + <path id="Shape_4_" opacity="0.6" enable-background="new " d="M242.424,715.973H-18.893l130.613,232.303h261.317 + L242.424,715.973z"/> + <path id="Shape_5_" opacity="0.8" enable-background="new " d="M373.038,483.761L242.424,715.973l130.614,232.303 + l130.704-232.303L373.038,483.761z"/> + </g> + </g> +</g> +</svg> diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst index 1754752d..182de33a 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -56,6 +56,8 @@ So for the following contract snippet:: The position of ``data[4][9].b`` is at ``keccak256(uint256(9) . keccak256(uint256(4) . uint256(1))) + 1``. +.. index: memory layout + **************** Layout in Memory **************** @@ -72,7 +74,8 @@ Solidity always places new objects at the free memory pointer and memory is neve .. warning:: There are some operations in Solidity that need a temporary memory area larger than 64 bytes and therefore will not fit into the scratch space. They will be placed where the free memory points to, but given their short lifecycle, the pointer is not updated. The memory may or may not be zeroed out. Because of this, one shouldn't expect the free memory to be zeroed out. -.. index: memory layout + +.. index: calldata layout ******************* Layout of Call Data @@ -85,29 +88,54 @@ specification ABI specification requires arguments to be padded to multiples of 32 bytes. The internal function calls use a different convention. -***************** -Esoteric Features -***************** - -There are some types in Solidity's type system that have no counterpart in the syntax. One of these types are the types of functions. But still, using ``var`` it is possible to have local variables of these types:: - contract FunctionSelector { - function select(bool useB, uint x) returns (uint z) { - var f = a; - if (useB) f = b; - return f(x); - } - - function a(uint x) returns (uint z) { - return x * x; - } - - function b(uint x) returns (uint z) { - return 2 * x; - } - } - -Calling ``select(false, x)`` will compute ``x * x`` and ``select(true, x)`` will compute ``2 * x``. +.. index: variable cleanup + +********************************* +Internals - Cleaning Up Variables +********************************* + +When a value is shorter than 256-bit, in some cases the remaining bits +must be cleaned. +The Solidity compiler is designed to clean such remaining bits before any operations +that might be adversely affected by the potential garbage in the remaining bits. +For example, before writing a value to the memory, the remaining bits need +to be cleared because the memory contents can be used for computing +hashes or sent as the data of a message call. Similarly, before +storing a value in the storage, the remaining bits need to be cleaned +because otherwise the garbled value can be observed. + +On the other hand, we do not clean the bits if the immediately +following operation is not affected. For instance, since any non-zero +value is considered ``true`` by ``JUMPI`` instruction, we do not clean +the boolean values before they are used as the condition for +``JUMPI``. + +In addition to the design principle above, the Solidity compiler +cleans input data when it is loaded onto the stack. + +Different types have different rules for cleaning up invalid values: + ++---------------+---------------+-------------------+ +|Type |Valid Values |Invalid Values Mean| ++===============+===============+===================+ +|enum of n |0 until n - 1 |exception | +|members | | | ++---------------+---------------+-------------------+ +|bool |0 or 1 |1 | ++---------------+---------------+-------------------+ +|signed integers|sign-extended |currently silently | +| |word |wraps; in the | +| | |future exceptions | +| | |will be thrown | +| | | | +| | | | ++---------------+---------------+-------------------+ +|unsigned |higher bits |currently silently | +|integers |zeroed |wraps; in the | +| | |future exceptions | +| | |will be thrown | ++---------------+---------------+-------------------+ .. index:: optimizer, common subexpression elimination, constant propagation @@ -193,45 +221,6 @@ This means the following source mappings represent the same information: ``1:2:1;:9;2::2;;`` - -.. index:: ! commandline compiler, compiler;commandline, ! solc, ! linker - -.. _commandline-compiler: - -****************************** -Using the Commandline Compiler -****************************** - -One of the build targets of the Solidity repository is ``solc``, the solidity commandline compiler. -Using ``solc --help`` provides you with an explanation of all options. The compiler can produce various outputs, ranging from simple binaries and assembly over an abstract syntax tree (parse tree) to estimations of gas usage. -If you only want to compile a single file, you run it as ``solc --bin sourceFile.sol`` and it will print the binary. Before you deploy your contract, activate the optimizer while compiling using ``solc --optimize --bin sourceFile.sol``. If you want to get some of the more advanced output variants of ``solc``, it is probably better to tell it to output everything to separate files using ``solc -o outputDirectory --bin --ast --asm sourceFile.sol``. - -The commandline compiler will automatically read imported files from the filesystem, but -it is also possible to provide path redirects using ``context:prefix=path`` in the following way: - -:: - - solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol - -This essentially instructs the compiler to search for anything starting with -``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin`` and if it does not -find the file there, it will look at ``/usr/local/lib/fallback`` (the empty prefix -always matches). ``solc`` will not read files from the filesystem that lie outside of -the remapping targets and outside of the directories where explicitly specified source -files reside, so things like ``import "/etc/passwd";`` only work if you add ``=/`` as a remapping. - -You can restrict remappings to only certain source files by prefixing a context. - -The section on :ref:`import` provides more details on remappings. - -If there are multiple matches due to remappings, the one with the longest common prefix is selected. - -If your contracts use :ref:`libraries <libraries>`, you will notice that the bytecode contains substrings of the form ``__LibraryName______``. You can use ``solc`` as a linker meaning that it will insert the library addresses for you at those points: - -Either add ``--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"`` to your command to provide an address for each library or store the string in a file (one library per line) and run ``solc`` using ``--libraries fileName``. - -If ``solc`` is called with the option ``--link``, all input files are interpreted to be unlinked binaries (hex-encoded) in the ``__LibraryName____``-format given above and are linked in-place (if the input is read from stdin, it is written to stdout). All options except ``--libraries`` are ignored (including ``-o``) in this case. - ***************** Contract Metadata ***************** @@ -281,10 +270,10 @@ Comments are of course also not permitted and used here only for explanatory pur "myFile.sol": { // Required: keccak256 hash of the source file "keccak256": "0x123...", - // Required (unless "content" is used, see below): URL to the - // source file, protocol is more or less arbitrary, but a Swarm - // URL is recommended - "url": "bzzr://56ab..." + // Required (unless "content" is used, see below): Sorted URL(s) + // to the source file, protocol is more or less arbitrary, but a + // Swarm URL is recommended + "urls": [ "bzzr://56ab..." ] }, "mortal": { // Required: keccak256 hash of the source file @@ -325,6 +314,14 @@ Comments are of course also not permitted and used here only for explanatory pur } } +.. note:: + Note the ABI definition above has no fixed order. It can change with compiler versions. + +.. note:: + Since the bytecode of the resulting contract contains the metadata hash, any change to + the metadata will result in a change of the bytecode. Furthermore, since the metadata + includes a hash of all the sources used, a single whitespace change in any of the source + codes will result in a different metadata, and subsequently a different bytecode. Encoding of the Metadata Hash in the Bytecode ============================================= @@ -374,7 +371,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! -* 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-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)``. * Initialise storage structs with a single assignment: ``x = MyStruct({a: 1, b: 2});`` @@ -397,12 +394,14 @@ The following is the order of precedence for operators, listed in order of evalu +============+=====================================+============================================+ | *1* | Postfix increment and decrement | ``++``, ``--`` | + +-------------------------------------+--------------------------------------------+ -| | Function-like call | ``<func>(<args...>)`` | +| | New expression | ``new <typename>`` | + +-------------------------------------+--------------------------------------------+ | | Array subscripting | ``<array>[<index>]`` | + +-------------------------------------+--------------------------------------------+ | | Member access | ``<object>.<member>`` | + +-------------------------------------+--------------------------------------------+ +| | Function-like call | ``<func>(<args...>)`` | ++ +-------------------------------------+--------------------------------------------+ | | Parentheses | ``(<statement>)`` | +------------+-------------------------------------+--------------------------------------------+ | *2* | Prefix increment and decrement | ``++``, ``--`` | @@ -446,7 +445,7 @@ The following is the order of precedence for operators, listed in order of evalu | *16* | Comma operator | ``,`` | +------------+-------------------------------------+--------------------------------------------+ -.. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send +.. index:: assert, block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send Global Variables ================ @@ -464,6 +463,9 @@ Global Variables - ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``) - ``tx.gasprice`` (``uint``): gas price of the transaction - ``tx.origin`` (``address``): sender of the transaction (full call chain) +- ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error) +- ``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()` - ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the (tightly packed) arguments @@ -474,8 +476,9 @@ 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 -- ``<address>.balance`` (``uint256``): balance of the address in Wei -- ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to address, returns ``false`` on failure +- ``<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 .. index:: visibility, public, private, external, internal @@ -488,7 +491,7 @@ Function Visibility Specifiers return true; } -- ``public``: visible externally and internally (creates accessor function for storage/state variables) +- ``public``: visible externally and internally (creates getter function for storage/state variables) - ``private``: only visible in the current contract - ``external``: only visible externally (only for functions) - i.e. can only be message-called (via ``this.func``) - ``internal``: only visible internally @@ -510,10 +513,11 @@ Reserved Keywords These keywords are reserved in Solidity. They might become part of the syntax in the future: -``abstract``, ``after``, ``case``, ``catch``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``, +``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``, ``null``, ``of``, ``pure``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``, ``view``. Language Grammar ================ .. literalinclude:: grammar.txt + :language: none diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 77e1bf08..33c613d8 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -22,7 +22,11 @@ you should be more careful. This section will list some pitfalls and general security recommendations but can, of course, never be complete. Also, keep in mind that even if your smart contract code is bug-free, the compiler or the platform itself might -have a bug. +have a bug. A list of some publicly known security-relevant bugs of the compiler +can be found in the +:ref:`list of known bugs<known_bugs>`, which is also machine-readable. Note +that there is a bug bounty program that covers the code generator of the +Solidity compiler. As always, with open source documentation, please help us extend this section (especially, some examples would not hurt)! @@ -75,7 +79,7 @@ outlined further below: :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract Fund { /// Mapping of ether shares of the contract. @@ -84,8 +88,7 @@ outlined further below: function withdraw() { var share = shares[msg.sender]; shares[msg.sender] = 0; - if (!msg.sender.send(share)) - throw; + msg.sender.transfer(share); } } @@ -117,25 +120,27 @@ Sending and Receiving Ether During the execution of the fallback function, the contract can only rely on the "gas stipend" (2300 gas) being available to it at that time. This stipend is not enough to access storage in any way. To be sure that your contract can receive Ether in that way, check the gas requirements of the fallback function - (for example in the "details" section in browser-solidity). + (for example in the "details" section in Remix). - There is a way to forward more gas to the receiving contract using - ``addr.call.value(x)()``. This is essentially the same as ``addr.send(x)``, + ``addr.call.value(x)()``. This is essentially the same as ``addr.transfer(x)``, only that it forwards all remaining gas and opens up the ability for the - recipient to perform more expensive actions. This might include calling back + recipient to perform more expensive actions (and it only returns a failure code + and does not automatically propagate the error). This might include calling back into the sending contract or other state changes you might not have thought of. So it allows for great flexibility for honest users but also for malicious actors. -- If you want to send Ether using ``address.send``, there are certain details to be aware of: +- If you want to send Ether using ``address.transfer``, there are certain details to be aware of: 1. If the recipient is a contract, it causes its fallback function to be executed which can, in turn, call back the sending contract. 2. Sending Ether can fail due to the call depth going above 1024. Since the caller is in total control of the call - depth, they can force the transfer to fail; make sure to always check the return value of ``send``. Better yet, + depth, they can force the transfer to fail; take this possibility into account or use ``send`` and make sure to always check its return value. Better yet, write your contract using a pattern where the recipient can withdraw Ether instead. 3. Sending Ether can also fail because the execution of the recipient contract - requires more than the allotted amount of gas (explicitly by using ``throw`` or + requires more than the allotted amount of gas (explicitly by using ``require``, + ``assert``, ``revert``, ``throw`` or because the operation is just too expensive) - it "runs out of gas" (OOG). - If the return value of ``send`` is checked, this might provide a + If you use ``transfer`` or ``send`` with a return value check, this might provide a means for the recipient to block progress in the sending contract. Again, the best practice here is to use a :ref:`"withdraw" pattern instead of a "send" pattern <withdrawal_pattern>`. @@ -158,7 +163,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.11; // THIS CONTRACT CONTAINS A BUG - DO NOT USE contract TxUserWallet { @@ -168,9 +173,9 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like owner = msg.sender; } - function transfer(address dest, uint amount) { - if (tx.origin != owner) { throw; } - if (!dest.call.value(amount)()) throw; + function transferTo(address dest, uint amount) { + require(tx.origin == owner); + dest.transfer(amount); } } @@ -188,7 +193,7 @@ Now someone tricks you into sending ether to the address of this attack wallet: } function() { - TxUserWallet(msg.sender).transfer(owner, msg.sender.balance); + TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance); } } diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 915cfa76..450b0286 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -36,7 +36,7 @@ of votes. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; /// @title Voting with delegation. contract Ballot { @@ -51,8 +51,7 @@ of votes. } // This is a type for a single proposal. - struct Proposal - { + struct Proposal { bytes32 name; // short name (up to 32 bytes) uint voteCount; // number of accumulated votes } @@ -88,14 +87,14 @@ of votes. // Give `voter` the right to vote on this ballot. // May only be called by `chairperson`. function giveRightToVote(address voter) { - if (msg.sender != chairperson || voters[voter].voted) { - // `throw` terminates and reverts all changes to - // the state and to Ether balances. It is often - // a good idea to use this if functions are - // called incorrectly. But watch out, this - // will also consume all provided gas. - throw; - } + // If the argument of `require` evaluates to `false`, + // it terminates and reverts all changes to + // the state and to Ether balances. It is often + // a good idea to use this if functions are + // called incorrectly. But watch out, this + // will currently also consume all provided gas + // (this is planned to change in the future). + require((msg.sender == chairperson) && !voters[voter].voted && (voters[voter].weight == 0)); voters[voter].weight = 1; } @@ -103,8 +102,10 @@ of votes. function delegate(address to) { // assigns reference Voter sender = voters[msg.sender]; - if (sender.voted) - throw; + require(!sender.voted); + + // Self-delegation is not allowed. + require(to != msg.sender); // Forward the delegation as long as // `to` also delegated. @@ -114,16 +115,11 @@ of votes. // In this case, the delegation will not be executed, // but in other situations, such loops might // cause a contract to get "stuck" completely. - while ( - voters[to].delegate != address(0) && - voters[to].delegate != msg.sender - ) { + while (voters[to].delegate != address(0)) { to = voters[to].delegate; - } - // We found a loop in the delegation, not allowed. - if (to == msg.sender) { - throw; + // We found a loop in the delegation, not allowed. + require(to != msg.sender); } // Since `sender` is a reference, this @@ -146,8 +142,7 @@ of votes. /// to proposal `proposals[proposal].name`. function vote(uint proposal) { Voter sender = voters[msg.sender]; - if (sender.voted) - throw; + require(!sender.voted); sender.voted = true; sender.vote = proposal; @@ -170,7 +165,7 @@ of votes. } } } - + // Calls winningProposal() function to get the index // of the winner contained in the proposals array and then // returns the name of the winner @@ -219,7 +214,7 @@ activate themselves. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract SimpleAuction { // Parameters of the auction. Times are either @@ -270,22 +265,21 @@ activate themselves. // the transaction. The keyword payable // is required for the function to // be able to receive Ether. - if (now > auctionStart + biddingTime) { - // Revert the call if the bidding - // period is over. - throw; - } - if (msg.value <= highestBid) { - // If the bid is not higher, send the - // money back. - throw; - } + + // Revert the call if the bidding + // period is over. + require(now <= (auctionStart + biddingTime)); + + // If the bid is not higher, send the + // money back. + require(msg.value > highestBid); + if (highestBidder != 0) { // Sending back the money by simply using // highestBidder.send(highestBid) is a security risk // because it can be prevented by the caller by e.g. // raising the call stack to 1023. It is always safer - // to let the recipient withdraw their money themselves. + // to let the recipients withdraw their money themselves. pendingReturns[highestBidder] += highestBid; } highestBidder = msg.sender; @@ -302,7 +296,7 @@ activate themselves. // before `send` returns. pendingReturns[msg.sender] = 0; - if (!msg.sender.send(amount)) { + if (!msg.sender.send(amount)) { // No need to call throw here, just reset the amount owing pendingReturns[msg.sender] = amount; return false; @@ -322,24 +316,21 @@ activate themselves. // 3. interacting with other contracts // If these phases are mixed up, the other contract could call // back into the current contract and modify the state or cause - // effects (ether payout) to be perfromed multiple times. + // effects (ether payout) to be performed multiple times. // If functions called internally include interaction with external // contracts, they also have to be considered interaction with // external contracts. // 1. Conditions - if (now <= auctionStart + biddingTime) - throw; // auction did not yet end - if (ended) - throw; // this function has already been called + require(now >= (auctionStart + biddingTime)); // auction did not yet end + require(!ended); // this function has already been called // 2. Effects ended = true; AuctionEnded(highestBidder, highestBid); // 3. Interaction - if (!beneficiary.send(highestBid)) - throw; + beneficiary.transfer(highestBid); } } @@ -382,7 +373,7 @@ high or low invalid bids. :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract BlindAuction { struct Bid { @@ -410,8 +401,8 @@ high or low invalid bids. /// functions. `onlyBefore` is applied to `bid` below: /// The new function body is the modifier's body where /// `_` is replaced by the old function body. - modifier onlyBefore(uint _time) { if (now >= _time) throw; _; } - modifier onlyAfter(uint _time) { if (now <= _time) throw; _; } + modifier onlyBefore(uint _time) { require(now < _time); _; } + modifier onlyAfter(uint _time) { require(now > _time); _; } function BlindAuction( uint _biddingTime, @@ -455,13 +446,9 @@ high or low invalid bids. onlyBefore(revealEnd) { uint length = bids[msg.sender].length; - if ( - _values.length != length || - _fake.length != length || - _secret.length != length - ) { - throw; - } + require(_values.length == length); + require(_fake.length == length); + require(_secret.length == length); uint refund; for (uint i = 0; i < length; i++) { @@ -482,8 +469,7 @@ high or low invalid bids. // the same deposit. bid.blindedBid = 0; } - if (!msg.sender.send(refund)) - throw; + msg.sender.transfer(refund); } // This is an "internal" function which means that it @@ -528,14 +514,12 @@ high or low invalid bids. function auctionEnd() onlyAfter(revealEnd) { - if (ended) - throw; + require(!ended); AuctionEnded(highestBidder, highestBid); ended = true; // We send all the money we have, because some // of the refunds might have failed. - if (!beneficiary.send(this.balance)) - throw; + beneficiary.transfer(this.balance); } } @@ -547,7 +531,7 @@ Safe Remote Purchase :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract Purchase { uint public value; @@ -559,32 +543,32 @@ Safe Remote Purchase function Purchase() payable { seller = msg.sender; value = msg.value / 2; - if (2 * value != msg.value) throw; + require((2 * value) == msg.value); } - modifier require(bool _condition) { - if (!_condition) throw; + modifier condition(bool _condition) { + require(_condition); _; } modifier onlyBuyer() { - if (msg.sender != buyer) throw; + require(msg.sender == buyer); _; } modifier onlySeller() { - if (msg.sender != seller) throw; + require(msg.sender == seller); _; } modifier inState(State _state) { - if (state != _state) throw; + require(state == _state); _; } - event aborted(); - event purchaseConfirmed(); - event itemReceived(); + event Aborted(); + event PurchaseConfirmed(); + event ItemReceived(); /// Abort the purchase and reclaim the ether. /// Can only be called by the seller before @@ -593,10 +577,9 @@ Safe Remote Purchase onlySeller inState(State.Created) { - aborted(); + Aborted(); state = State.Inactive; - if (!seller.send(this.balance)) - throw; + seller.transfer(this.balance); } /// Confirm the purchase as buyer. @@ -605,10 +588,10 @@ Safe Remote Purchase /// is called. function confirmPurchase() inState(State.Created) - require(msg.value == 2 * value) + condition(msg.value == (2 * value)) payable { - purchaseConfirmed(); + PurchaseConfirmed(); buyer = msg.sender; state = State.Locked; } @@ -619,15 +602,17 @@ Safe Remote Purchase onlyBuyer inState(State.Locked) { - itemReceived(); + ItemReceived(); // It is important to change the state first because // otherwise, the contracts called using `send` below // can call in again here. state = State.Inactive; - // This actually allows both the buyer and the seller to - // block the refund. - if (!buyer.send(value) || !seller.send(this.balance)) - throw; + + // NOTE: This actually allows both the buyer and the seller to + // block the refund - the withdraw pattern should be used. + + buyer.transfer(value); + seller.transfer(this.balance); } } diff --git a/docs/solidity-in-depth.rst b/docs/solidity-in-depth.rst index 40704698..b6217b47 100644 --- a/docs/solidity-in-depth.rst +++ b/docs/solidity-in-depth.rst @@ -16,4 +16,5 @@ If something is missing here, please contact us on units-and-global-variables.rst control-structures.rst contracts.rst + assembly.rst miscellaneous.rst diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index c7af0c8c..224eb368 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -28,7 +28,7 @@ State variables are values which are permanently stored in contract storage. } See the :ref:`types` section for valid state variable types and -:ref:`visibility-and-accessors` for possible choices for +:ref:`visibility-and-getters` for possible choices for visibility. .. _structure-functions: @@ -49,7 +49,7 @@ Functions are the executable units of code within a contract. } :ref:`function-calls` can happen internally or externally -and have different levels of visibility (:ref:`visibility-and-accessors`) +and have different levels of visibility (:ref:`visibility-and-getters`) towards other contracts. .. _structure-function-modifiers: @@ -62,13 +62,13 @@ Function modifiers can be used to amend the semantics of functions in a declarat :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract Purchase { address public seller; modifier onlySeller() { // Modifier - if (msg.sender != seller) throw; + require(msg.sender == seller); _; } diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 272a1b31..0742d2e9 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -150,6 +150,74 @@ No:: ... } +Order of Functions +================== + +Ordering helps readers identify which functions they can call and to find the constructor and fallback definitions easier. + +Functions should be grouped according to their visibility and ordered: + +- constructor +- fallback function (if exists) +- external +- public +- internal +- private + +Within a grouping, place the ``constant`` functions last. + +Yes:: + + contract A { + function A() { + ... + } + + function() { + ... + } + + // External functions + // ... + + // External functions that are constant + // ... + + // Public functions + // ... + + // Internal functions + // ... + + // Private functions + // ... + } + +No:: + + contract A { + + // External functions + // ... + + // Private functions + // ... + + // Public functions + // ... + + function A() { + ... + } + + function() { + ... + } + + // Internal functions + // ... + } + Whitespace in Expressions ========================= @@ -194,6 +262,19 @@ No:: y = 2; long_variable = 3; +Don't include a whitespace in the fallback function: + +Yes:: + + function() { + ... + } + +No:: + + function () { + ... + } Control Structures ================== diff --git a/docs/types.rst b/docs/types.rst index b17a2771..67549499 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -52,21 +52,32 @@ Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) * Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) -* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation) +* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift) -Division always truncates (it just maps 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 an exception. +Division by zero and modulus with zero throws a runtime exception. -.. index:: address, balance, send, call, callcode, delegatecall +The result of a shift operation is the type of the left operand. The +expression ``x << y`` is equivalent to ``x * 2**y``, and ``x >> y`` is +equivalent to ``x / 2**y``. This means that shifting negative numbers +sign extends. Shifting by a negative amount throws a runtime exception. + +.. warning:: + The results produced by shift right of negative values of signed integer types is different from those produced + by other programming languages. In Solidity, shift right maps to division so the shifted negative values + are going to be rounded towards zero (truncated). In other programming languages the shift right of negative values + works like division with rounding down (towards negative infinity). + +.. index:: address, balance, send, call, callcode, delegatecall, transfer .. _address: Address ------- -``address``: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as base for all contracts. +``address``: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as a base for all contracts. Operators: @@ -75,27 +86,31 @@ Operators: Members of Addresses ^^^^^^^^^^^^^^^^^^^^ -* ``balance`` and ``send`` +* ``balance`` and ``transfer`` For a quick reference, see :ref:`address_related`. It is possible to query the balance of an address using the property ``balance`` -and to send Ether (in units of wei) to an address using the ``send`` function: +and to send Ether (in units of wei) to an address using the ``transfer`` function: :: address x = 0x123; address myAddress = this; - if (x.balance < 10 && myAddress.balance >= 10) x.send(10); + if (x.balance < 10 && myAddress.balance >= 10) x.transfer(10); .. note:: - If ``x`` is a contract address, its code (more specifically: its fallback function, if present) will be executed together with the ``send`` call (this is a limitation of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted. In this case, ``send`` returns ``false``. + If ``x`` is a contract address, its code (more specifically: its fallback function, if present) will be executed together with the ``transfer`` call (this is a limitation of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception. + +* ``send`` + +Send is the low-level counterpart of ``transfer``. If the execution fails, the current contract will not stop with an exception, but ``send`` will return ``false``. .. warning:: There are some dangers in using ``send``: The transfer fails if the call stack depth is at 1024 (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order - to make safe Ether transfers, always check the return value of ``send`` or even better: - Use a pattern where the recipient withdraws the money. + to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: + use a pattern where the recipient withdraws the money. * ``call``, ``callcode`` and ``delegatecall`` @@ -110,10 +125,12 @@ the function ``call`` is provided which takes an arbitrary number of arguments o ``call`` returns a boolean indicating whether the invoked function terminated (``true``) or caused an EVM exception (``false``). It is not possible to access the actual data returned (for this we would need to know the encoding and size in advance). -In a similar way, the function ``delegatecall`` can be used: The difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. +In a similar way, the function ``delegatecall`` can be used: the difference is that only the code of the given address is used, all other aspects (storage, balance, ...) are taken from the current contract. The purpose of ``delegatecall`` is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used. Prior to homestead, only a limited variant called ``callcode`` was available that did not provide access to the original ``msg.sender`` and ``msg.value`` values. All three functions ``call``, ``delegatecall`` and ``callcode`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. +The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``. + .. note:: All contracts inherit the members of address, so it is possible to query the balance of the current contract using ``this.balance``. @@ -136,9 +153,13 @@ Fixed-size byte arrays Operators: * Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``) -* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation) +* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation), ``<<`` (left shift), ``>>`` (right shift) * Index access: If ``x`` is of type ``bytesI``, then ``x[k]`` for ``0 <= k < I`` returns the ``k`` th byte (read-only). +The shifting operator works with any integer type as right operand (but will +return the type of the left operand), which denotes the number of bits to shift by. +Shifting by a negative amount will cause a runtime exception. + Members: * ``.length`` yields the fixed length of the byte array (read-only). @@ -162,6 +183,19 @@ Fixed Point Numbers **COMING SOON...** +.. index:: address, literal;address + +.. _address_literals: + +Address Literals +---------------- + +Hexadecimal literals that pass the address checksum test, for example +``0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF`` are of ``address`` type. +Hexadecimal literals that are between 39 and 41 digits +long and do not pass the checksum test produce +a warning and are treated as regular rational number literals. + .. index:: literal, literal;rational .. _rational_literals: @@ -171,12 +205,14 @@ Rational and Integer Literals Integer literals are formed from a sequence of numbers in the range 0-9. They are interpreted as decimals. For example, ``69`` means sixty nine. -Octal literals do not exist in Solidity and leading zeros are ignored. -For example, ``0100`` means one hundred. +Octal literals do not exist in Solidity and leading zeros are invalid. -Decimal literals are formed by a ``.`` with at least one number on +Decimal fraction literals are formed by a ``.`` with at least one number on one side. Examples include ``1.``, ``.1`` and ``1.3``. +Scientific notation is also supported, where the base can have fractions, while the exponent cannot. +Examples include ``2e10``, ``-2e10``, ``2e-10``, ``2.5e1``. + Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. by using them together with a non-literal expression). This means that computations do not overflow and divisions do not truncate @@ -196,7 +232,7 @@ a non-rational number). Integer literals and rational number literals belong to number literal types. Moreover, all number literal expressions (i.e. the expressions that contain only number literals and operators) belong to number literal - types. So the number literal expressions `1 + 2` and `2 + 1` both + types. So the number literal expressions ``1 + 2`` and ``2 + 1`` both belong to the same number literal type for the rational number three. .. warning:: @@ -219,7 +255,7 @@ a non-rational number). String Literals --------------- -String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; `"foo"`` represents three bytes not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``. +String literals are written with either double or single-quotes (``"foo"`` or ``'bar'``). They do not imply trailing zeroes as in C; ``"foo"`` represents three bytes not four. As with integer literals, their type can vary, but they are implicitly convertible to ``bytes1``, ..., ``bytes32``, if they fit, to ``bytes`` and to ``string``. String literals support escape characters, such as ``\n``, ``\xNN`` and ``\uNNNN``. ``\xNN`` takes a hex value and inserts the appropriate byte, while ``\uNNNN`` takes a Unicode codepoint and inserts an UTF-8 sequence. @@ -337,10 +373,10 @@ Example that shows how to use internal function types:: } function reduce( uint[] memory self, - function (uint x, uint y) returns (uint) f + function (uint, uint) returns (uint) f ) internal - returns (uint r) + returns (uint) { r = self[0]; for (uint i = 1; i < self.length; i++) { @@ -370,7 +406,7 @@ Example that shows how to use internal function types:: Another example that uses external function types:: - pragma solidity ^0.4.5; + pragma solidity ^0.4.11; contract Oracle { struct Request { @@ -395,7 +431,7 @@ Another example that uses external function types:: oracle.query("USD", this.oracleResponse); } function oracleResponse(bytes response) { - if (msg.sender != address(oracle)) throw; + require(msg.sender == address(oracle)); // Use the data } } @@ -422,19 +458,19 @@ 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-modifyable +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 -it behaves mostly like memory. +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) +assignments between storage and memory and also to a state variable (even from other state variables) always create an independent copy. Assignments to local storage variables only assign a reference though, and this reference always points to the state variable even if the latter is changed in the meantime. On the other hand, assignments from a memory stored reference type to another -memory-stored reference type does not create a copy. +memory-stored reference type do not create a copy. :: @@ -507,8 +543,8 @@ So ``bytes`` should always be preferred over ``byte[]`` because it is cheaper. that you are accessing the low-level bytes of the UTF-8 representation, and not the individual characters! -It is possible to mark arrays ``public`` and have Solidity create an accessor. -The numeric index will become a required parameter for the accessor. +It is possible to mark arrays ``public`` and have Solidity create a getter. +The numeric index will become a required parameter for the getter. .. index:: ! array;allocating, new @@ -605,7 +641,8 @@ Members contract ArrayContract { uint[2**20] m_aLotOfIntegers; - // Note that the following is not a pair of arrays but an array of pairs. + // Note that the following is not a pair of dynamic arrays but a + // dynamic array of pairs (i.e. of fixed size arrays of length two). bool[2][] m_pairsOfFlags; // newPairs is stored in memory - the default for function arguments @@ -672,7 +709,7 @@ shown in the following example: :: - pragma solidity ^0.4.0; + pragma solidity ^0.4.11; contract CrowdFunding { // Defines a new type with two fields. @@ -713,8 +750,7 @@ shown in the following example: return false; uint amount = c.amount; c.amount = 0; - if (!c.beneficiary.send(amount)) - throw; + c.beneficiary.transfer(amount); return true; } } @@ -742,11 +778,11 @@ assigning it to a local variable, as in Mappings ======== -Mapping types are declared as ``mapping _KeyType => _ValueType``. +Mapping types are declared as ``mapping(_KeyType => _ValueType)``. Here ``_KeyType`` can be almost any type except for a mapping, a dynamically sized array, a contract, an enum and a struct. ``_ValueType`` can actually be any type, including mappings. -Mappings can be seen as hashtables which are virtually initialized such that +Mappings can be seen as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_ which are virtually initialized such that every possible key exists and is mapped to a value whose byte-representation is all zeros: a type's :ref:`default value <default-value>`. The similarity ends here, though: The key data is not actually stored in a mapping, only its ``keccak256`` hash used to look up the value. @@ -756,11 +792,11 @@ Because of this, mappings do not have a length or a concept of a key or value be Mappings are only allowed for state variables (or as storage reference types in internal functions). -It is possible to mark mappings ``public`` and have Solidity create an accessor. -The ``_KeyType`` will become a required parameter for the accessor and it will +It is possible to mark mappings ``public`` and have Solidity create a getter. +The ``_KeyType`` will become a required parameter for the getter and it will return ``_ValueType``. -The ``_ValueType`` can be a mapping too. The accessor will have one parameter +The ``_ValueType`` can be a mapping too. The getter will have one parameter for each ``_KeyType``, recursively. :: diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index dd3d4be8..7d21f065 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -22,8 +22,8 @@ unit and units are considered naively in the following way: * ``1 minutes == 60 seconds`` * ``1 hours == 60 minutes`` * ``1 days == 24 hours`` - * ``1 weeks = 7 days`` - * ``1 years = 365 days`` + * ``1 weeks == 7 days`` + * ``1 years == 365 days`` Take care if you perform calendar calculations using these units, because not every year equals 365 days and not even every day has 24 hours @@ -55,7 +55,7 @@ Block and Transaction Properties - ``block.difficulty`` (``uint``): current block difficulty - ``block.gaslimit`` (``uint``): current block gaslimit - ``block.number`` (``uint``): current block number -- ``block.timestamp`` (``uint``): current block timestamp +- ``block.timestamp`` (``uint``): current block timestamp as seconds since unix epoch - ``msg.data`` (``bytes``): complete calldata - ``msg.gas`` (``uint``): remaining gas - ``msg.sender`` (``address``): sender of the message (current call) @@ -79,7 +79,19 @@ Block and Transaction Properties You can only access the hashes of the most recent 256 blocks, all other values will be zero. -.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send +.. index:: assert, revert, require + +Error Handling +-------------- + +``assert(bool condition)``: + throws if the condition is not met - to be used for internal errors. +``require(bool condition)``: + throws if the condition is not met - to be used for errors in inputs or external components. +``revert()``: + abort execution and revert state changes + +.. index:: keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, Mathematical and Cryptographic Functions ---------------------------------------- @@ -91,13 +103,14 @@ Mathematical and Cryptographic Functions ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments ``sha3(...) returns (bytes32)``: - alias to `keccak256()` + alias to ``keccak256()`` ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the (tightly packed) arguments ``ripemd160(...) returns (bytes20)``: compute RIPEMD-160 hash of the (tightly packed) arguments ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover the address associated with the public key from elliptic curve signature or return zero on error + (`example usage <https://ethereum.stackexchange.com/q/1777/222>`_) In the above, "tightly packed" means that the arguments are concatenated without padding. This means that the following are all identical:: @@ -117,6 +130,7 @@ This means that, for example, ``keccak256(0) == keccak256(uint8(0))`` and It might be that you run into Out-of-Gas for ``sha256``, ``ripemd160`` or ``ecrecover`` on a *private blockchain*. The reason for this is that those are implemented as so-called precompiled contracts and these contracts only really exist after they received the first message (although their contract code is hardcoded). Messages to non-existing contracts are more expensive and thus the execution runs into an Out-of-Gas error. A workaround for this problem is to first send e.g. 1 Wei to each of the contracts before you use them in your actual contracts. This is not an issue on the official or test net. +.. index:: balance, send, transfer, call, callcode, delegatecall .. _address_related: Address Related @@ -124,15 +138,23 @@ Address Related ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei +``<address>.transfer(uint256 amount)``: + send given amount of Wei to :ref:`address`, throws on failure ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure +``<address>.call(...) returns (bool)``: + issue low-level ``CALL``, returns ``false`` on failure +``<address>.callcode(...) returns (bool)``: + issue low-level ``CALLCODE``, returns ``false`` on failure +``<address>.delegatecall(...) returns (bool)``: + issue low-level ``DELEGATECALL``, returns ``false`` on failure For more information, see the section on :ref:`address`. .. warning:: There are some dangers in using ``send``: The transfer fails if the call stack depth is at 1024 (this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in order - to make safe Ether transfers, always check the return value of ``send`` or even better: + to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: Use a pattern where the recipient withdraws the money. .. index:: this, selfdestruct diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst new file mode 100644 index 00000000..7f82df70 --- /dev/null +++ b/docs/using-the-compiler.rst @@ -0,0 +1,275 @@ +****************** +Using the compiler +****************** + +.. index:: ! commandline compiler, compiler;commandline, ! solc, ! linker + +.. _commandline-compiler: + +Using the Commandline Compiler +****************************** + +One of the build targets of the Solidity repository is ``solc``, the solidity commandline compiler. +Using ``solc --help`` provides you with an explanation of all options. The compiler can produce various outputs, ranging from simple binaries and assembly over an abstract syntax tree (parse tree) to estimations of gas usage. +If you only want to compile a single file, you run it as ``solc --bin sourceFile.sol`` and it will print the binary. Before you deploy your contract, activate the optimizer while compiling using ``solc --optimize --bin sourceFile.sol``. If you want to get some of the more advanced output variants of ``solc``, it is probably better to tell it to output everything to separate files using ``solc -o outputDirectory --bin --ast --asm sourceFile.sol``. + +The commandline compiler will automatically read imported files from the filesystem, but +it is also possible to provide path redirects using ``prefix=path`` in the following way: + +:: + + solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol + +This essentially instructs the compiler to search for anything starting with +``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin`` and if it does not +find the file there, it will look at ``/usr/local/lib/fallback`` (the empty prefix +always matches). ``solc`` will not read files from the filesystem that lie outside of +the remapping targets and outside of the directories where explicitly specified source +files reside, so things like ``import "/etc/passwd";`` only work if you add ``=/`` as a remapping. + +If there are multiple matches due to remappings, the one with the longest common prefix is selected. + +For security reasons the compiler has restrictions what directories it can access. Paths (and their subdirectories) of source files specified on the commandline and paths defined by remappings are allowed for import statements, but everything else is rejected. Additional paths (and their subdirectories) can be allowed via the ``--allow-paths /sample/path,/another/sample/path`` switch. + +If your contracts use :ref:`libraries <libraries>`, you will notice that the bytecode contains substrings of the form ``__LibraryName______``. You can use ``solc`` as a linker meaning that it will insert the library addresses for you at those points: + +Either add ``--libraries "Math:0x12345678901234567890 Heap:0xabcdef0123456"`` to your command to provide an address for each library or store the string in a file (one library per line) and run ``solc`` using ``--libraries fileName``. + +If ``solc`` is called with the option ``--link``, all input files are interpreted to be unlinked binaries (hex-encoded) in the ``__LibraryName____``-format given above and are linked in-place (if the input is read from stdin, it is written to stdout). All options except ``--libraries`` are ignored (including ``-o``) in this case. + +If ``solc`` is called with the option ``--standard-json``, it will expect a JSON input (as explained below) on the standard input, and return a JSON output on the standard output. + +.. _compiler-api: + +Compiler Input and Output JSON Description +****************************************** + +These JSON formats are used by the compiler API as well as are available through ``solc``. These are subject to change, +some fields are optional (as noted), but it is aimed at to only make backwards compatible changes. + +The compiler API expects a JSON formatted input and outputs the compilation result in a JSON formatted output. + +Comments are of course not permitted and used here only for explanatory purposes. + +Input Description +----------------- + +.. code-block:: none + + { + // Required: Source code language, such as "Solidity", "serpent", "lll", "assembly", etc. + language: "Solidity", + // Required + sources: + { + // The keys here are the "global" names of the source files, + // imports can use other files via remappings (see below). + "myFile.sol": + { + // Optional: keccak256 hash of the source file + // It is used to verify the retrieved content if imported via URLs. + "keccak256": "0x123...", + // Required (unless "content" is used, see below): URL(s) to the source file. + // URL(s) should be imported in this order and the result checked against the + // keccak256 hash (if available). If the hash doesn't match or none of the + // URL(s) result in success, an error should be raised. + "urls": + [ + "bzzr://56ab...", + "ipfs://Qma...", + "file:///tmp/path/to/file.sol" + ] + }, + "mortal": + { + // Optional: keccak256 hash of the source file + "keccak256": "0x234...", + // Required (unless "urls" is used): literal contents of the source file + "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }" + } + }, + // Optional + settings: + { + // Optional: Sorted list of remappings + remappings: [ ":g/dir" ], + // Optional: Optimizer settings (enabled defaults to false) + optimizer: { + enabled: true, + runs: 500 + }, + // Metadata settings (optional) + metadata: { + // Use only literal content and not URLs (false by default) + useLiteralContent: true + }, + // Addresses of the libraries. If not all libraries are given here, it can result in unlinked objects whose output data is different. + libraries: { + // The top level key is the the name of the source file where the library is used. + // If remappings are used, this source file should match the global path after remappings were applied. + // If this key is an empty string, that refers to a global level. + "myFile.sol": { + "MyLib": "0x123123..." + } + } + // The following can be used to select desired outputs. + // If this field is omitted, then the compiler loads and does type checking, but will not generate any outputs apart from errors. + // The first level key is the file name and the second is the contract name, where empty contract name refers to the file itself, + // while the star refers to all of the contracts. + // + // The available output types are as follows: + // abi - ABI + // ast - AST of all source files + // legacyAST - legacy AST of all source files + // devdoc - Developer documentation (natspec) + // userdoc - User documentation (natspec) + // metadata - Metadata + // ir - New assembly format before desugaring + // evm.assembly - New assembly format after desugaring + // evm.legacyAssembly - Old-style assembly format in JSON + // evm.bytecode.object - Bytecode object + // evm.bytecode.opcodes - Opcodes list + // evm.bytecode.sourceMap - Source mapping (useful for debugging) + // evm.bytecode.linkReferences - Link references (if unlinked object) + // evm.deployedBytecode* - Deployed bytecode (has the same options as evm.bytecode) + // evm.methodIdentifiers - The list of function hashes + // evm.gasEstimates - Function gas estimates + // ewasm.wast - eWASM S-expressions format (not supported atm) + // ewasm.wasm - eWASM binary format (not supported atm) + // + // Note that using a using `evm`, `evm.bytecode`, `ewasm`, etc. will select every + // target part of that output. + // + outputSelection: { + // Enable the metadata and bytecode outputs of every single contract. + "*": { + "*": [ "metadata", "evm.bytecode" ] + }, + // Enable the abi and opcodes output of MyContract defined in file def. + "def": { + "MyContract": [ "abi", "evm.opcodes" ] + }, + // Enable the source map output of every single contract. + "*": { + "*": [ "evm.sourceMap" ] + }, + // Enable the legacy AST output of every single file. + "*": { + "": [ "legacyAST" ] + } + } + } + } + + +Output Description +------------------ + +.. code-block:: none + + { + // Optional: not present if no errors/warnings were encountered + errors: [ + { + // Optional: Location within the source file. + sourceLocation: { + file: "sourceFile.sol", + start: 0, + end: 100 + ], + // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc + type: "TypeError", + // Mandatory: Component where the error originated, such as "general", "ewasm", etc. + component: "general", + // Mandatory ("error" or "warning") + severity: "error", + // Mandatory + message: "Invalid keyword" + // Optional: the message formatted with source location + formattedMessage: "sourceFile.sol:100: Invalid keyword" + } + ], + // This contains the file-level outputs. In can be limited/filtered by the outputSelection settings. + sources: { + "sourceFile.sol": { + // Identifier (used in source maps) + id: 1, + // The AST object + ast: {}, + // The legacy AST object + legacyAST: {} + } + }, + // This contains the contract-level outputs. It can be limited/filtered by the outputSelection settings. + contracts: { + "sourceFile.sol": { + // If the language used has no contract names, this field should equal to an empty string. + "ContractName": { + // The Ethereum Contract ABI. If empty, it is represented as an empty array. + // See https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI + abi: [], + // See the Metadata Output documentation (serialised JSON string) + metadata: "{...}", + // User documentation (natspec) + userdoc: {}, + // Developer documentation (natspec) + devdoc: {}, + // Intermediate representation (string) + ir: "", + // EVM-related outputs + evm: { + // Assembly (string) + assembly: "", + // Old-style assembly (object) + legacyAssembly: {}, + // Bytecode and related details. + bytecode: { + // The bytecode as a hex string. + object: "00fe", + // Opcodes list (string) + opcodes: "", + // The source mapping as a string. See the source mapping definition. + sourceMap: "", + // If given, this is an unlinked object. + linkReferences: { + "libraryFile.sol": { + // Byte offsets into the bytecode. Linking replaces the 20 bytes located there. + "Library1": [ + { start: 0, length: 20 }, + { start: 200, length: 20 } + ] + } + } + }, + // The same layout as above. + deployedBytecode: { }, + // The list of function hashes + methodIdentifiers: { + "delegate(address)": "5c19a95c" + }, + // Function gas estimates + gasEstimates: { + creation: { + codeDepositCost: "420000", + executionCost: "infinite", + totalCost: "infinite" + }, + external: { + "delegate(address)": "25000" + }, + internal: { + "heavyLifting()": "infinite" + } + } + }, + // eWASM related outputs + ewasm: { + // S-expressions format + wast: "", + // Binary format (hex string) + wasm: "" + } + } + } + } + } diff --git a/docs/utils/SolidityLexer.py b/docs/utils/SolidityLexer.py index 779147f4..ef55c6a2 100644 --- a/docs/utils/SolidityLexer.py +++ b/docs/utils/SolidityLexer.py @@ -26,7 +26,7 @@ class SolidityLexer(RegexLexer): (r'/\*.*?\*/', Comment.Multiline) ], 'natspec': [ - (r'@author|@dev|@notice|@return|@param|@why3|@title', Keyword), + (r'@author|@dev|@notice|@return|@param|@title', Keyword), (r'.[^@*\n]*?', Comment.Special) ], 'docstringsingle': [ @@ -54,11 +54,10 @@ class SolidityLexer(RegexLexer): r'(<<|>>>?|==?|!=?|[-<>+*%&\|\^/])=?', Operator, 'slashstartsregex'), (r'[{(\[;,]', Punctuation, 'slashstartsregex'), (r'[})\].]', Punctuation), - (r'(for|in|while|do|break|return|continue|switch|case|default|if|else|' - r'throw|try|catch|finally|new|delete|typeof|instanceof|void|' - r'this|import|mapping|returns|private|public|external|internal|' - r'constant|memory|storage)\b', Keyword, 'slashstartsregex'), - (r'(var|let|with|function|event|modifier|struct|enum|contract|library)\b', Keyword.Declaration, 'slashstartsregex'), + (r'(anonymous|as|assembly|break|constant|continue|do|delete|else|external|for|hex|if|' + r'indexed|internal|import|is|mapping|memory|new|payable|public|pragma|' + r'private|return|returns|storage|super|this|throw|using|while)\b', Keyword, 'slashstartsregex'), + (r'(var|function|event|modifier|struct|enum|contract|library)\b', Keyword.Declaration, 'slashstartsregex'), (r'(bytes|string|address|uint|int|bool|byte|' + '|'.join( ['uint%d' % (i + 8) for i in range(0, 256, 8)] + @@ -67,16 +66,12 @@ class SolidityLexer(RegexLexer): ['ufixed%dx%d' % ((i), (j + 8)) for i in range(0, 256, 8) for j in range(0, 256 - i, 8)] + ['fixed%dx%d' % ((i), (j + 8)) for i in range(0, 256, 8) for j in range(0, 256 - i, 8)] ) + r')\b', Keyword.Type, 'slashstartsregex'), - (r'(abstract|boolean|byte|char|class|const|debugger|double|enum|export|' - r'extends|final|float|goto|implements|int|interface|long|native|' - r'package|private|protected|public|short|static|super|synchronized|throws|' - r'transient|volatile)\b', Keyword.Reserved), - (r'(true|false|null|NaN|Infinity|undefined)\b', Keyword.Constant), - (r'(Array|Boolean|Date|Error|Function|Math|netscape|' - r'Number|Object|Packages|RegExp|String|sun|decodeURI|' - r'decodeURIComponent|encodeURI|encodeURIComponent|' - r'Error|eval|isFinite|isNaN|parseFloat|parseInt|document|this|' - r'window)\b', Name.Builtin), + (r'(wei|szabo|finney|ether|seconds|minutes|hours|days|weeks|years)\b', Keyword.Type, 'slashstartsregex'), + (r'(abstract|after|case|catch|default|final|in|inline|interface|let|match|' + r'null|of|pure|relocatable|static|switch|try|type|typeof|view)\b', Keyword.Reserved), + (r'(true|false)\b', Keyword.Constant), + (r'(block|msg|tx|now|suicide|selfdestruct|addmod|mulmod|sha3|keccak256|log[0-4]|' + r'sha256|ecrecover|ripemd160|assert|revert)', Name.Builtin), (r'[$a-zA-Z_][a-zA-Z0-9_]*', Name.Other), (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float), (r'0x[0-9a-fA-F]+', Number.Hex), |