Skip to content

Instantly share code, notes, and snippets.

@chriseth
Created February 20, 2018 11:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriseth/5e06fb08433a03d1e4c05224f4287264 to your computer and use it in GitHub Desktop.
Save chriseth/5e06fb08433a03d1e4c05224f4287264 to your computer and use it in GitHub Desktop.
Differences in Solidity documentation between 26ea9ce07cf85849cd881465a4322f14bff87eb8 and a6b52fdc34650c74597c1bcdc5075b6375c62650
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index e39c8861..8095a3b7 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -6,17 +6,19 @@
Application Binary Interface Specification
******************************************
-Basic design
+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.
+from outside the blockchain and for contract-to-contract interaction. Data is encoded according to its type,
+as described in this specification. The encoding is not self describing and thus requires a schema in order to decode.
-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.
+We assume the interface functions of a contract are strongly typed, known at compilation time and static. No introspection mechanism will be provided. We assume 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.
+.. _abi_function_selector:
+
Function Selector
=================
@@ -34,45 +36,47 @@ 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`.
+- ``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`.
+- ``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.
+- ``address``: equivalent to ``uint160``, except for the assumed interpretation and language typing. For computing the function selector, ``address`` is used.
-- `uint`, `int`: synonyms for `uint256`, `int256` respectively (not to be used for computing the function selector).
+- ``uint``, ``int``: synonyms for ``uint256``, ``int256`` respectively. For computing the function selector, ``uint256`` and ``int256`` have to be used.
-- `bool`: equivalent to `uint8` restricted to the values 0 and 1
+- ``bool``: equivalent to ``uint8`` restricted to the values 0 and 1. For computing the function selector, ``bool`` is used.
-- `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)`.
+- ``fixed<M>x<N>``: signed fixed-point decimal number of ``M`` bits, ``8 <= 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>`.
+- ``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).
+- ``fixed``, ``ufixed``: synonyms for ``fixed128x19``, ``ufixed128x19`` respectively. For computing the function selector, ``fixed128x19`` and ``ufixed128x19`` have to be used.
-- `bytes<M>`: binary type of `M` bytes, `0 < M <= 32`.
+- ``bytes<M>``: binary type of ``M`` bytes, ``0 < M <= 32``.
-- `function`: equivalent to `bytes24`: an address, followed by a function selector
+- ``function``: an address (20 bytes) folled by a function selector (4 bytes). Encoded identical to ``bytes24``.
The following (fixed-size) array type exists:
-- `<type>[M]`: a fixed-length array of the given fixed-length type.
+- ``<type>[M]``: a fixed-length array of ``M`` elements, ``M > 0``, of the given type.
-The following non-fixed-size types exist:
+The following non-fixed-size types exist:
-- `bytes`: dynamic sized byte sequence.
+- ``bytes``: dynamic sized byte sequence.
-- `string`: dynamic sized unicode string assumed to be UTF-8 encoded.
+- ``string``: dynamic sized unicode string assumed to be UTF-8 encoded.
-- `<type>[]`: a variable-length array of the given fixed-length type.
+- ``<type>[]``: a variable-length array of elements of the given type.
-Types can be combined to anonymous structs by enclosing a finite non-negative number
+Types can be combined to a tuple 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`
+- ``(T1,T2,...,Tn)``: tuple consisting of the types ``T1``, ..., ``Tn``, ``n >= 0``
-It is possible to form structs of structs, arrays of structs and so on.
+It is possible to form tuples of tuples, arrays of tuples and so on.
+.. note::
+ Solidity supports all the types presented above with the same names with the exception of tuples. The ABI tuple type is utilised for encoding Solidity ``structs``.
Formal Specification of the Encoding
====================================
@@ -82,97 +86,99 @@ 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.
+ 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`
+
+* ``bytes``
+* ``string``
+* ``T[]`` for any ``T``
+* ``T[k]`` for any dynamic ``T`` and any ``k > 0``
+* ``(T1,...,Tk)`` if any ``Ti`` is dynamic for ``1 <= i <= k``
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`.
+**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.
+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
+**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`
+- ``(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))`
+ ``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
+ 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)
+ ``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))`
+ ``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.
+ 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
+ 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`:
+ 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
+ ``enc(X) = enc((X[0], ..., X[k-1]))``
+
+ i.e. it is encoded as if it were a tuple 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]])`
+- ``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
+ 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`):
+- ``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.
+ ``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`:
+- ``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.
+ ``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.
+- ``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.
+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
+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))`
+ ``function_selector(f) enc((a_1, ..., a_n))``
-and the return values `v_1, ..., v_k` of `f` are encoded as
+and the return values ``v_1, ..., v_k`` of ``f`` are encoded as
- `enc((v_1, ..., v_k))`
+ ``enc((v_1, ..., v_k))``
-i.e. the values are combined into an anonymous struct and encoded.
+i.e. the values are combined into a tuple and encoded.
Examples
========
@@ -181,46 +187,49 @@ Given the contract:
::
+ pragma solidity ^0.4.16;
+
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) {}
+ function bar(bytes3[2]) public pure {}
+ function baz(uint32 x, bool y) public pure returns (bool r) { r = x > 32 || y; }
+ function sam(bytes, bool, uint[]) public pure {}
}
-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:
+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
+- ``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.
+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:
+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).
+- ``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.
+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::
@@ -229,26 +238,26 @@ In total::
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:
+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:
+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))
+ - ``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:
+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)
+ - ``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!"`:
+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)
+ - ``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):
@@ -270,56 +279,68 @@ 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.
+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 are 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).
+- ``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).
+
+For all fixed-length Solidity types, the ``EVENT_INDEXED_ARGS`` array contains the 32-byte encoded value directly. However, for *types of dynamic length*, which include ``string``, ``bytes``, and arrays, ``EVENT_INDEXED_ARGS`` will contain the *Keccak hash* of the encoded value, rather than the encoded value directly. This allows applications to efficiently query for values of dynamic-length types (by setting the hash of the encoded value as the topic), but leaves applications unable to decode indexed values they have not queried for. For dynamic-length types, application developers face a trade-off between fast search for predetermined values (if the argument is indexed) and legibility of arbitrary values (which requires that the arguments not be indexed). Developers may overcome this tradeoff and achieve both efficient search and arbitrary legibility by defining events with two arguments — one indexed, one not — intended to hold the same value.
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:
+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 (more below).
+ * ``components``: used for tuple types (more below).
-- `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`.
+- ``outputs``: an array of objects similar to ``inputs``, can be omitted if function doesn't return anything;
+- ``payable``: ``true`` if function accepts ether, defaults to ``false``;
+- ``stateMutability``: a string with one of the following values: ``pure`` (:ref:`specified to not read blockchain state <pure-functions>`), ``view`` (:ref:`specified to not modify the blockchain state <view-functions>`), ``nonpayable`` and ``payable`` (same as ``payable`` above).
+- ``constant``: ``true`` if function is either ``pure`` or ``view``
-`type` can be omitted, defaulting to `"function"`.
+``type`` can be omitted, defaulting to ``"function"``.
-Constructor and fallback function never have `name` or `outputs`. Fallback function doesn't have `inputs` either.
+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`.
+- ``type``: always ``"event"``
+- ``name``: the name of the event;
+- ``inputs``: an array of objects, each of which contains:
-For example,
+ * ``name``: the name of the parameter;
+ * ``type``: the canonical type of the parameter (more below).
+ * ``components``: used for tuple types (more below).
+ * ``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;
- }
+ pragma solidity ^0.4.0;
+
+ contract Test {
+ function Test() public { b = 0x12345678901234567890123456789012; }
+ event Event(uint indexed a, bytes32 b);
+ event Event2(uint indexed a, bytes32 b);
+ function foo(uint a) public { Event(a, b); }
+ bytes32 b;
+ }
would result in the JSON:
@@ -334,12 +355,120 @@ would result in the JSON:
"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": []
}]
+
+Handling tuple types
+--------------------
+
+Despite that names are intentionally not part of the ABI encoding they do make a lot of sense to be included
+in the JSON to enable displaying it to the end user. The structure is nested in the following way:
+
+An object with members ``name``, ``type`` and potentially ``components`` describes a typed variable.
+The canonical type is determined until a tuple type is reached and the string description up
+to that point is stored in ``type`` prefix with the word ``tuple``, i.e. it will be ``tuple`` followed by
+a sequence of ``[]`` and ``[k]`` with
+integers ``k``. The components of the tuple are then stored in the member ``components``,
+which is of array type and has the same structure as the top-level object except that
+``indexed`` is not allowed there.
+
+As an example, the code
+
+::
+
+ pragma solidity ^0.4.19;
+ pragma experimental ABIEncoderV2;
+
+ contract Test {
+ struct S { uint a; uint[] b; T[] c; }
+ struct T { uint x; uint y; }
+ function f(S s, T t, uint a) public { }
+ function g() public returns (S s, T t, uint a) {}
+ }
+
+would result in the JSON:
+
+.. code:: json
+
+ [
+ {
+ "name": "f",
+ "type": "function",
+ "inputs": [
+ {
+ "name": "s",
+ "type": "tuple",
+ "components": [
+ {
+ "name": "a",
+ "type": "uint256"
+ },
+ {
+ "name": "b",
+ "type": "uint256[]"
+ },
+ {
+ "name": "c",
+ "type": "tuple[]",
+ "components": [
+ {
+ "name": "x",
+ "type": "uint256"
+ },
+ {
+ "name": "y",
+ "type": "uint256"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name": "t",
+ "type": "tuple",
+ "components": [
+ {
+ "name": "x",
+ "type": "uint256"
+ },
+ {
+ "name": "y",
+ "type": "uint256"
+ }
+ ]
+ },
+ {
+ "name": "a",
+ "type": "uint256"
+ }
+ ],
+ "outputs": []
+ }
+ ]
+
+.. _abi_packed_mode:
+
+Non-standard Packed Mode
+========================
+
+Solidity supports a non-standard packed mode where:
+
+- no :ref:`function selector <abi_function_selector>` is encoded,
+- types shorter than 32 bytes are neither zero padded nor sign extended and
+- dynamic types are encoded in-place and without the length.
+
+As an example encoding ``int1, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in ::
+
+ 0xff42242448656c6c6f2c20776f726c6421
+ ^^ int1(-1)
+ ^^ bytes1(0x42)
+ ^^^^ uint16(0x2424)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field
+
+More specifically, each statically-sized type takes as many bytes as its range has
+and dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded without
+their length field. This means that the encoding is ambiguous as soon as there are two
+dynamically-sized elements.
diff --git a/docs/assembly.rst b/docs/assembly.rst
index 7ef41483..02522469 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -9,9 +9,7 @@ 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
===============
@@ -25,9 +23,10 @@ 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) } }``
+* access to external variables: ``function f(uint x) public { 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) }``
+* if statements: ``if slt(x, 0) { x := sub(0, x) }``
* 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))) } }``
@@ -38,6 +37,11 @@ We now want to describe the inline assembly language in detail.
at a low level. This discards several important safety
features of Solidity.
+.. note::
+ TODO: Write about how scoping rules of inline assembly are a bit different
+ and the complications that arise when for example using internal functions
+ of libraries. Furthermore, write about the symbols defined by the compiler.
+
Example
-------
@@ -50,7 +54,7 @@ idea is that assembly libraries will be used to enhance the language in such way
pragma solidity ^0.4.0;
library GetCode {
- function at(address _addr) returns (bytes o_code) {
+ function at(address _addr) public view returns (bytes o_code) {
assembly {
// retrieve the size of the code, this needs assembly
let size := extcodesize(_addr)
@@ -74,12 +78,12 @@ you really know what you are doing.
.. code::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
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) {
+ function sumSolidity(uint[] _data) public view returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i)
o_sum += _data[i];
}
@@ -87,13 +91,38 @@ you really know what you are doing.
// 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) {
+ function sumAsm(uint[] _data) public view returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i) {
assembly {
- o_sum := mload(add(add(_data, 0x20), mul(i, 0x20)))
+ o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20))))
}
}
}
+
+ // Same as above, but accomplish the entire code within inline assembly.
+ function sumPureAsm(uint[] _data) public view returns (uint o_sum) {
+ assembly {
+ // Load the length (first 32 bytes)
+ let len := mload(_data)
+
+ // Skip over the length field.
+ //
+ // Keep temporary variable so it can be incremented in place.
+ //
+ // NOTE: incrementing _data would result in an unusable
+ // _data variable after this assembly block
+ let data := add(_data, 0x20)
+
+ // Iterate until the bound is not met.
+ for
+ { let end := add(data, len) }
+ lt(data, end)
+ { data := add(data, 0x20) }
+ {
+ o_sum := add(o_sum, mload(data))
+ }
+ }
+ }
}
@@ -108,7 +137,7 @@ these curly braces, the following can be used (see the later sections for more d
- 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)``
+ - variable declarations, e.g. ``let x := 7``, ``let x := add(y, 3)`` or ``let x`` (initial value of empty (0) is assigned)
- 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)``
@@ -123,7 +152,7 @@ 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.
+special and all others push exactly one item onto 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``.
@@ -359,7 +388,7 @@ changes during the call, and thus references to local variables will be wrong.
contract C {
uint b;
- function f(uint x) returns (uint r) {
+ function f(uint x) public returns (uint r) {
assembly {
r := mul(x, sload(b_slot)) // ignore the offset, we know it is zero
}
@@ -372,7 +401,7 @@ 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
+efficient assembly without labels, just using assembly functions, loops, if and switch instructions
(see below). The following code computes an element in the Fibonacci series.
.. code::
@@ -418,31 +447,6 @@ will have a wrong impression about the stack height at label ``two``:
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
----------------------------------
@@ -455,10 +459,10 @@ be just ``0``, but it can also be a complex functional-style expression.
.. code::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract C {
- function f(uint x) returns (uint b) {
+ function f(uint x) public view returns (uint b) {
assembly {
let v := add(x, 1)
mstore(0x80, v)
@@ -488,13 +492,28 @@ 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
}
+If
+--
+
+The if statement can be used for conditionally executing code.
+There is no "else" part, consider using "switch" (see below) if
+you need multiple alternatives.
+
+.. code::
+
+ {
+ if eq(value, 0) { revert(0, 0) }
+ }
+
+The curly braces for the body are required.
+
Switch
------
@@ -507,7 +526,7 @@ case called ``default``.
.. code::
- assembly {
+ {
let x := 0
switch calldataload(4)
case 0 {
@@ -536,13 +555,27 @@ 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))
}
}
+For loops can also be written so that they behave like while loops:
+Simply leave the initialization and post-iteration parts empty.
+
+.. code::
+
+ {
+ let x := 0
+ let i := 0
+ for { } lt(i, 0x100) { } { // while(i < 0x100)
+ x := add(x, mload(i))
+ i := add(i, 0x20)
+ }
+ }
+
Functions
---------
@@ -563,7 +596,7 @@ The following example implements the power function by square-and-multiply.
.. code::
- assembly {
+ {
function power(base, exponent) -> result {
switch exponent
case 0 { result := 1 }
@@ -580,7 +613,7 @@ 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
+low-level. Function calls, loops, ifs 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
@@ -627,7 +660,7 @@ for the Solidity compiler. In this form, it tries to achieve several goals:
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
+like ``for`` loops, ``if`` and ``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
@@ -677,8 +710,10 @@ Example:
We will follow an example compilation from Solidity to desugared assembly.
We consider the runtime bytecode of the following Solidity program::
+ pragma solidity ^0.4.16;
+
contract C {
- function f(uint x) returns (uint y) {
+ function f(uint x) public pure returns (uint y) {
y = 1;
for (uint i = 0; i < x; i++)
y = 2 * y;
@@ -826,36 +861,37 @@ Grammar::
AssemblyItem =
Identifier |
AssemblyBlock |
- FunctionalAssemblyExpression |
+ AssemblyExpression |
AssemblyLocalDefinition |
- FunctionalAssemblyAssignment |
AssemblyAssignment |
+ AssemblyStackAssignment |
LabelDefinition |
+ AssemblyIf |
AssemblySwitch |
AssemblyFunctionDefinition |
AssemblyFor |
- 'break' | 'continue' |
- SubAssembly | 'dataSize' '(' Identifier ')' |
- LinkerSymbol |
- 'errorLabel' | 'bytecodeSize' |
- NumberLiteral | StringLiteral | HexLiteral
+ 'break' |
+ 'continue' |
+ SubAssembly
+ AssemblyExpression = AssemblyCall | Identifier | AssemblyLiteral
+ AssemblyLiteral = NumberLiteral | StringLiteral | HexLiteral
Identifier = [a-zA-Z_$] [a-zA-Z_0-9]*
- FunctionalAssemblyExpression = Identifier '(' ( AssemblyItem ( ',' AssemblyItem )* )? ')'
- AssemblyLocalDefinition = 'let' IdentifierOrList ':=' FunctionalAssemblyExpression
- FunctionalAssemblyAssignment = IdentifierOrList ':=' FunctionalAssemblyExpression
+ AssemblyCall = Identifier '(' ( AssemblyExpression ( ',' AssemblyExpression )* )? ')'
+ AssemblyLocalDefinition = 'let' IdentifierOrList ( ':=' AssemblyExpression )?
+ AssemblyAssignment = IdentifierOrList ':=' AssemblyExpression
IdentifierOrList = Identifier | '(' IdentifierList ')'
IdentifierList = Identifier ( ',' Identifier)*
- AssemblyAssignment = '=:' Identifier
+ AssemblyStackAssignment = '=:' Identifier
LabelDefinition = Identifier ':'
- AssemblySwitch = 'switch' FunctionalAssemblyExpression AssemblyCase*
+ AssemblyIf = 'if' AssemblyExpression AssemblyBlock
+ AssemblySwitch = 'switch' AssemblyExpression AssemblyCase*
( 'default' AssemblyBlock )?
- AssemblyCase = 'case' FunctionalAssemblyExpression AssemblyBlock
+ AssemblyCase = 'case' AssemblyExpression AssemblyBlock
AssemblyFunctionDefinition = 'function' Identifier '(' IdentifierList? ')'
( '->' '(' IdentifierList ')' )? AssemblyBlock
- AssemblyFor = 'for' ( AssemblyBlock | FunctionalAssemblyExpression)
- FunctionalAssemblyExpression ( AssemblyBlock | FunctionalAssemblyExpression) AssemblyBlock
+ AssemblyFor = 'for' ( AssemblyBlock | AssemblyExpression )
+ AssemblyExpression ( AssemblyBlock | AssemblyExpression ) 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\\] | '\\' .)* '"'
@@ -962,8 +998,8 @@ 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 bitween the current stack height and the
+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::
diff --git a/docs/bugs.json b/docs/bugs.json
index 1a67d626..c642793a 100644
--- a/docs/bugs.json
+++ b/docs/bugs.json
@@ -1,5 +1,34 @@
[
{
+ "name": "ZeroFunctionSelector",
+ "summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.",
+ "description": "If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.",
+ "fixed": "0.4.18",
+ "severity": "very low"
+ },
+ {
+ "name": "DelegateCallReturnValue",
+ "summary": "The low-level .delegatecall() does not return the execution outcome, but converts the value returned by the functioned called to a boolean instead.",
+ "description": "The return value of the low-level .delegatecall() function is taken from a position in memory, where the call data or the return data resides. This value is interpreted as a boolean and put onto the stack. This means if the called function returns at least 32 zero bytes, .delegatecall() returns false even if the call was successuful.",
+ "introduced": "0.3.0",
+ "fixed": "0.4.15",
+ "severity": "low"
+ },
+ {
+ "name": "ECRecoverMalformedInput",
+ "summary": "The ecrecover() builtin can return garbage for malformed input.",
+ "description": "The ecrecover precompile does not properly signal failure for malformed input (especially in the 'v' argument) and thus the Solidity function can return data that was previously present in the return area in memory.",
+ "fixed": "0.4.14",
+ "severity": "medium"
+ },
+ {
+ "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).",
@@ -100,4 +129,4 @@
"severity": "high",
"fixed": "0.3.0"
}
-]
\ No newline at end of file
+]
diff --git a/docs/bugs.rst b/docs/bugs.rst
index 55771a35..7629830d 100644
--- a/docs/bugs.rst
+++ b/docs/bugs.rst
@@ -48,7 +48,7 @@ fixed
publish
The date at which the bug became known publicly, optional
severity
- Severity of the bug: low, medium, high. Takes into account
+ Severity of the bug: very low, low, medium, high. Takes into account
discoverability in contract tests, likelihood of occurrence and
potential damage by exploits.
conditions
diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json
index 0f7346b4..5a4c9e29 100644
--- a/docs/bugs_by_version.json
+++ b/docs/bugs_by_version.json
@@ -1,6 +1,9 @@
{
"0.1.0": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStaleKnowledgeAboutSHA3",
@@ -15,6 +18,9 @@
},
"0.1.1": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStaleKnowledgeAboutSHA3",
@@ -29,6 +35,9 @@
},
"0.1.2": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStaleKnowledgeAboutSHA3",
@@ -43,6 +52,9 @@
},
"0.1.3": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStaleKnowledgeAboutSHA3",
@@ -57,6 +69,9 @@
},
"0.1.4": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStaleKnowledgeAboutSHA3",
@@ -71,6 +86,9 @@
},
"0.1.5": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStaleKnowledgeAboutSHA3",
@@ -85,6 +103,9 @@
},
"0.1.6": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -100,6 +121,9 @@
},
"0.1.7": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -115,6 +139,9 @@
},
"0.2.0": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -130,6 +157,9 @@
},
"0.2.1": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -145,6 +175,9 @@
},
"0.2.2": {
"bugs": [
+ "ZeroFunctionSelector",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -160,6 +193,10 @@
},
"0.3.0": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -174,6 +211,10 @@
},
"0.3.1": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -187,6 +228,10 @@
},
"0.3.2": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -200,6 +245,10 @@
},
"0.3.3": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -212,6 +261,10 @@
},
"0.3.4": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -224,6 +277,10 @@
},
"0.3.5": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -236,6 +293,10 @@
},
"0.3.6": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -246,6 +307,10 @@
},
"0.4.0": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -256,6 +321,10 @@
},
"0.4.1": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -266,16 +335,78 @@
},
"0.4.10": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction"
],
"released": "2017-03-15"
},
"0.4.11": {
- "bugs": [],
+ "bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral"
+ ],
"released": "2017-05-03"
},
+ "0.4.12": {
+ "bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput"
+ ],
+ "released": "2017-07-03"
+ },
+ "0.4.13": {
+ "bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput"
+ ],
+ "released": "2017-07-06"
+ },
+ "0.4.14": {
+ "bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue"
+ ],
+ "released": "2017-07-31"
+ },
+ "0.4.15": {
+ "bugs": [
+ "ZeroFunctionSelector"
+ ],
+ "released": "2017-08-08"
+ },
+ "0.4.16": {
+ "bugs": [
+ "ZeroFunctionSelector"
+ ],
+ "released": "2017-08-24"
+ },
+ "0.4.17": {
+ "bugs": [
+ "ZeroFunctionSelector"
+ ],
+ "released": "2017-09-21"
+ },
+ "0.4.18": {
+ "bugs": [],
+ "released": "2017-10-18"
+ },
+ "0.4.19": {
+ "bugs": [],
+ "released": "2017-11-30"
+ },
"0.4.2": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage",
@@ -283,8 +414,16 @@
],
"released": "2016-09-17"
},
+ "0.4.20": {
+ "bugs": [],
+ "released": "2018-02-14"
+ },
"0.4.3": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"HighOrderByteCleanStorage"
@@ -293,6 +432,10 @@
},
"0.4.4": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored"
],
@@ -300,6 +443,10 @@
},
"0.4.5": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored",
"OptimizerStateKnowledgeNotResetForJumpdest"
@@ -308,6 +455,10 @@
},
"0.4.6": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction",
"IdentityPrecompileReturnIgnored"
],
@@ -315,18 +466,30 @@
},
"0.4.7": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction"
],
"released": "2016-12-15"
},
"0.4.8": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction"
],
"released": "2017-01-13"
},
"0.4.9": {
"bugs": [
+ "ZeroFunctionSelector",
+ "DelegateCallReturnValue",
+ "ECRecoverMalformedInput",
+ "SkipEmptyStringLiteral",
"ConstantOptimizerSubtraction"
],
"released": "2017-01-31"
diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst
index acef13b7..7e09f534 100644
--- a/docs/common-patterns.rst
+++ b/docs/common-patterns.rst
@@ -36,12 +36,12 @@ become the new richest.
mapping (address => uint) pendingWithdrawals;
- function WithdrawalContract() payable {
+ function WithdrawalContract() public payable {
richest = msg.sender;
mostSent = msg.value;
}
- function becomeRichest() payable returns (bool) {
+ function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
pendingWithdrawals[richest] += msg.value;
richest = msg.sender;
@@ -52,7 +52,7 @@ become the new richest.
}
}
- function withdraw() {
+ function withdraw() public {
uint amount = pendingWithdrawals[msg.sender];
// Remember to zero the pending refund before
// sending to prevent re-entrancy attacks
@@ -71,12 +71,12 @@ This is as opposed to the more intuitive sending pattern:
address public richest;
uint public mostSent;
- function SendContract() payable {
+ function SendContract() public payable {
richest = msg.sender;
mostSent = msg.value;
}
- function becomeRichest() payable returns (bool) {
+ function becomeRichest() public payable returns (bool) {
if (msg.value > mostSent) {
// This line can cause problems (explained below).
richest.transfer(msg.value);
@@ -93,7 +93,7 @@ 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 fails (e.g. by using ``revert()`` or by just
-conssuming more than the 2300 gas stipend). That way,
+consuming 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.
@@ -121,7 +121,7 @@ unless you declare make your state variables ``public``.
Furthermore, you can restrict who can make modifications
to your contract's state or call your contract's
-functions and this is what this page is about.
+functions and this is what this section is about.
.. index:: function;modifier
@@ -157,6 +157,7 @@ restrictions highly readable.
/// Make `_newOwner` the new owner of this
/// contract.
function changeOwner(address _newOwner)
+ public
onlyBy(owner)
{
owner = _newOwner;
@@ -171,6 +172,7 @@ restrictions highly readable.
/// May only be called 6 weeks after
/// the contract has been created.
function disown()
+ public
onlyBy(owner)
onlyAfter(creationTime + 6 weeks)
{
@@ -191,6 +193,7 @@ restrictions highly readable.
}
function forceOwnerChange(address _newOwner)
+ public
costs(200 ether)
{
owner = _newOwner;
@@ -310,6 +313,7 @@ function finishes.
// Order of the modifiers matters here!
function bid()
+ public
payable
timedTransitions
atStage(Stages.AcceptingBlindedBids)
@@ -318,6 +322,7 @@ function finishes.
}
function reveal()
+ public
timedTransitions
atStage(Stages.RevealBids)
{
@@ -332,6 +337,7 @@ function finishes.
}
function g()
+ public
timedTransitions
atStage(Stages.AnotherStage)
transitionNext
@@ -339,6 +345,7 @@ function finishes.
}
function h()
+ public
timedTransitions
atStage(Stages.AreWeDoneYet)
transitionNext
@@ -346,6 +353,7 @@ function finishes.
}
function i()
+ public
timedTransitions
atStage(Stages.Finished)
{
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 356fa90d..afc32b16 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -10,57 +10,29 @@ variables. Calling a function on a different contract (instance) will perform
an EVM function call and thus switch the context such that state variables are
inaccessible.
-.. index:: ! contract;creation
+.. index:: ! contract;creation, constructor
******************
Creating Contracts
******************
-Contracts can be created "from outside" or from Solidity contracts.
+Contracts can be created "from outside" via Ethereum transactions or from within Solidity contracts.
+
+IDEs, such as `Remix <https://remix.ethereum.org/>`_, make the creation process seamless using UI elements.
+
+Creating contracts programatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/ethereum/web3.js>`_.
+As of today it has a method called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_
+to facilitate contract creation.
+
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
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(uint a, uint b) {} }";
-
- // The json abi array generated by the compiler
- var abiArray = [
- {
- "inputs":[
- {"name":"x","type":"uint256"},
- {"name":"y","type":"uint256"}
- ],
- "type":"constructor"
- },
- {
- "constant":true,
- "inputs":[],
- "name":"x",
- "outputs":[{"name":"","type":"bytes32"}],
- "type":"function"
- }
- ];
-
- var MyContract_ = web3.eth.contract(source);
- MyContract = web3.eth.contract(MyContract_.CONTRACT_NAME.info.abiDefinition);
- // deploy new contract
- var contractInstance = MyContract.new(
- 10,
- 11,
- {from: myAccount, gas: 1000000}
- );
-
.. index:: constructor;arguments
-Internally, constructor arguments are passed after the code of
-the contract itself, but you do not have to care about this
-if you use ``web3.js``.
+Internally, constructor arguments are passed :ref:`ABI encoded <ABI>` after the code of
+the contract itself, but you do not have to care about this if you use ``web3.js``.
If a contract wants to create another contract, the source code
(and the binary) of the created contract has to be known to the creator.
@@ -68,7 +40,7 @@ This means that cyclic creation dependencies are impossible.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract OwnedToken {
// TokenCreator is a contract type that is defined below.
@@ -80,11 +52,11 @@ This means that cyclic creation dependencies are impossible.
// This is the constructor which registers the
// creator and the assigned name.
- function OwnedToken(bytes32 _name) {
+ function OwnedToken(bytes32 _name) public {
// State variables are accessed via their name
// and not via e.g. this.owner. This also applies
// to functions and especially in the constructors,
- // you can only call them like that ("internall"),
+ // you can only call them like that ("internally"),
// because the contract itself does not exist yet.
owner = msg.sender;
// We do an explicit type conversion from `address`
@@ -95,7 +67,7 @@ This means that cyclic creation dependencies are impossible.
name = _name;
}
- function changeName(bytes32 newName) {
+ function changeName(bytes32 newName) public {
// Only the creator can alter the name --
// the comparison is possible since contracts
// are implicitly convertible to addresses.
@@ -103,7 +75,7 @@ This means that cyclic creation dependencies are impossible.
name = newName;
}
- function transfer(address newOwner) {
+ function transfer(address newOwner) public {
// Only the current owner can transfer the token.
if (msg.sender != owner) return;
// We also want to ask the creator if the transfer
@@ -118,25 +90,27 @@ This means that cyclic creation dependencies are impossible.
contract TokenCreator {
function createToken(bytes32 name)
+ public
returns (OwnedToken tokenAddress)
{
// Create a new Token contract and return its address.
// From the JavaScript side, the return type is simply
- // "address", as this is the closest type available in
+ // `address`, as this is the closest type available in
// the ABI.
return new OwnedToken(name);
}
- function changeName(OwnedToken tokenAddress, bytes32 name) {
- // Again, the external type of "tokenAddress" is
- // simply "address".
+ function changeName(OwnedToken tokenAddress, bytes32 name) public {
+ // Again, the external type of `tokenAddress` is
+ // simply `address`.
tokenAddress.changeName(name);
}
- function isTokenTransferOK(
- address currentOwner,
- address newOwner
- ) returns (bool ok) {
+ function isTokenTransferOK(address currentOwner, address newOwner)
+ public
+ view
+ returns (bool ok)
+ {
// Check some arbitrary condition.
address tokenAddress = msg.sender;
return (keccak256(newOwner) & 0xff) == (bytes20(tokenAddress) & 0xff);
@@ -199,10 +173,10 @@ return parameter list for functions.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract C {
- function f(uint a) private returns (uint b) { return a + 1; }
+ function f(uint a) private pure returns (uint b) { return a + 1; }
function setData(uint a) internal { data = a; }
uint public data;
}
@@ -213,37 +187,38 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
::
+ // This will not compile
+
pragma solidity ^0.4.0;
contract C {
uint private data;
function f(uint a) private returns(uint b) { return a + 1; }
- function setData(uint a) { data = a; }
+ function setData(uint a) public { data = a; }
function getData() public returns(uint) { return data; }
function compute(uint a, uint b) internal returns (uint) { return a+b; }
}
-
contract D {
- function readData() {
+ function readData() public {
C c = new C();
- uint local = c.f(7); // error: member "f" is not visible
+ uint local = c.f(7); // error: member `f` is not visible
c.setData(3);
local = c.getData();
- local = c.compute(3, 5); // error: member "compute" is not visible
+ local = c.compute(3, 5); // error: member `compute` is not visible
}
}
-
contract E is C {
- function g() {
+ function g() public {
C c = new C();
- uint val = compute(3, 5); // acces to internal member (from derivated to parent contract)
+ uint val = compute(3, 5); // access to internal member (from derived to parent contract)
}
}
.. index:: ! getter;function, ! function;getter
+.. _getter-functions:
Getter Functions
================
@@ -263,10 +238,9 @@ be done at declaration.
uint public data = 42;
}
-
contract Caller {
C c = new C();
- function f() {
+ function f() public {
uint local = c.data();
}
}
@@ -282,7 +256,7 @@ it is evaluated as a state variable. If it is accessed externally
contract C {
uint public data;
- function x() {
+ function x() public {
data = 3; // internal access
uint val = this.data(); // external access
}
@@ -305,7 +279,7 @@ The next example is a bit more complex:
It will generate a function of the following form::
- function data(uint arg1, bool arg2, uint arg3) returns (uint a, bytes3 b) {
+ function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) {
a = data[arg1][arg2][arg3].a;
b = data[arg1][arg2][arg3].b;
}
@@ -330,13 +304,13 @@ inheritable properties of contracts and may be overridden by derived contracts.
pragma solidity ^0.4.11;
contract owned {
- function owned() { owner = msg.sender; }
+ function owned() public { owner = msg.sender; }
address owner;
// This contract only defines a modifier but does not use
- // it - it will be used in derived contracts.
+ // it: it will be used in derived contracts.
// The function body is inserted where the special symbol
- // "_;" in the definition of a modifier appears.
+ // `_;` in the definition of a modifier appears.
// This means that if the owner calls this function, the
// function is executed and otherwise, an exception is
// thrown.
@@ -346,18 +320,16 @@ inheritable properties of contracts and may be overridden by derived contracts.
}
}
-
contract mortal is owned {
- // This contract inherits the "onlyOwner"-modifier from
- // "owned" and applies it to the "close"-function, which
- // causes that calls to "close" only have an effect if
+ // This contract inherits the `onlyOwner` modifier from
+ // `owned` and applies it to the `close` function, which
+ // causes that calls to `close` only have an effect if
// they are made by the stored owner.
- function close() onlyOwner {
+ function close() public onlyOwner {
selfdestruct(owner);
}
}
-
contract priced {
// Modifiers can receive arguments:
modifier costs(uint price) {
@@ -367,21 +339,20 @@ inheritable properties of contracts and may be overridden by derived contracts.
}
}
-
contract Register is priced, owned {
mapping (address => bool) registeredAddresses;
uint price;
- function Register(uint initialPrice) { price = initialPrice; }
+ function Register(uint initialPrice) public { price = initialPrice; }
// It is important to also provide the
- // "payable" keyword here, otherwise the function will
+ // `payable` keyword here, otherwise the function will
// automatically reject all Ether sent to it.
- function register() payable costs(price) {
+ function register() public payable costs(price) {
registeredAddresses[msg.sender] = true;
}
- function changePrice(uint _price) onlyOwner {
+ function changePrice(uint _price) public onlyOwner {
price = _price;
}
}
@@ -396,10 +367,10 @@ inheritable properties of contracts and may be overridden by derived contracts.
}
/// This function is protected by a mutex, which means that
- /// reentrant calls from within msg.sender.call cannot call f again.
+ /// reentrant calls from within `msg.sender.call` cannot call `f` again.
/// 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) {
+ function f() public noReentrancy returns (uint) {
require(msg.sender.call());
return 7;
}
@@ -457,38 +428,89 @@ value types and strings.
bytes32 constant myHash = keccak256("abc");
}
+.. index:: ! functions
-.. _constant-functions:
+.. _functions:
-******************
-Constant Functions
-******************
+*********
+Functions
+*********
+
+.. index:: ! view function, function;view
-Functions can be declared constant in which case they promise not to modify the state.
+.. _view-functions:
+
+View Functions
+==============
+
+Functions can be declared ``view`` in which case they promise not to modify the state.
+
+The following statements are considered modifying the state:
+
+#. Writing to state variables.
+#. :ref:`Emitting events <events>`.
+#. :ref:`Creating other contracts <creating-contracts>`.
+#. Using ``selfdestruct``.
+#. Sending Ether via calls.
+#. Calling any function not marked ``view`` or ``pure``.
+#. Using low-level calls.
+#. Using inline assembly that contains certain opcodes.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract C {
- function f(uint a, uint b) constant returns (uint) {
- return a * (b + 42);
+ function f(uint a, uint b) public view returns (uint) {
+ return a * (b + 42) + now;
}
}
.. note::
- Getter methods are marked constant.
+ ``constant`` is an alias to ``view``.
+
+.. note::
+ Getter methods are marked ``view``.
.. warning::
- The compiler does not enforce yet that a constant method is not modifying state.
+ The compiler does not enforce yet that a ``view`` method is not modifying state.
+
+.. index:: ! pure function, function;pure
+
+.. _pure-functions:
+
+Pure Functions
+==============
+
+Functions can be declared ``pure`` in which case they promise not to read from or modify the state.
+
+In addition to the list of state modifying statements explained above, the following are considered reading from the state:
+
+#. Reading from state variables.
+#. Accessing ``this.balance`` or ``<address>.balance``.
+#. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``).
+#. Calling any function not marked ``pure``.
+#. Using inline assembly that contains certain opcodes.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract C {
+ function f(uint a, uint b) public pure returns (uint) {
+ return a * (b + 42);
+ }
+ }
+
+.. warning::
+ The compiler does not enforce yet that a ``pure`` method is not reading from the state.
.. index:: ! fallback function, function;fallback
.. _fallback-function:
-*****************
Fallback Function
-*****************
+=================
A contract can have exactly one unnamed function. This function cannot have
arguments and cannot return anything.
@@ -497,9 +519,11 @@ functions match the given function identifier (or if no data was supplied at
all).
Furthermore, this function is executed whenever the contract receives plain
-Ether (without data). In such a context, there is usually very little gas available to
-the function call (to be precise, 2300 gas), so it is important to make fallback functions as cheap as
-possible.
+Ether (without data). Additionally, in order to receive Ether, the fallback function
+must be marked ``payable``. If no such function exists, the contract cannot receive
+Ether through regular transactions.
+
+In such a context, there is usually very little gas available to the function call (to be precise, 2300 gas), so it is important to make fallback functions as cheap as possible. Note that the gas required by a transaction (as opposed to an internal call) that invokes the fallback function is much higher, because each transaction charges an additional amount of 21000 gas or more for things like signature checking.
In particular, the following operations will consume more gas than the stipend provided to a fallback function:
@@ -510,6 +534,10 @@ 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.
+.. note::
+ Even though the fallback function cannot have arguments, one can still use ``msg.data`` to retrieve
+ any payload supplied with the call.
+
.. warning::
Contracts that receive Ether directly (without a function call, i.e. using ``send`` or ``transfer``)
but do not define a fallback function
@@ -517,6 +545,14 @@ Please ensure you test your fallback function thoroughly to ensure the execution
before Solidity v0.4.0). So if you want your contract to receive Ether,
you have to implement a fallback function.
+.. warning::
+ A contract without a payable fallback function can receive Ether as a recipient of a `coinbase transaction` (aka `miner block reward`)
+ or as a destination of a ``selfdestruct``.
+
+ A contract cannot react to such Ether transfers and thus also cannot reject them. This is a design choice of the EVM and Solidity cannot work around it.
+
+ It also means that ``this.balance`` can be higher than the sum of some manual accounting implemented in a contract (i.e. having a counter updated in the fallback function).
+
::
pragma solidity ^0.4.0;
@@ -525,9 +561,9 @@ Please ensure you test your fallback function thoroughly to ensure the execution
// This function is called for all messages sent to
// this contract (there is no other function).
// Sending Ether to this contract will cause an exception,
- // because the fallback function does not have the "payable"
+ // because the fallback function does not have the `payable`
// modifier.
- function() { x = 1; }
+ function() public { x = 1; }
uint x;
}
@@ -535,21 +571,101 @@ Please ensure you test your fallback function thoroughly to ensure the execution
// This contract keeps all Ether sent to it with no way
// to get it back.
contract Sink {
- function() payable { }
+ function() public payable { }
}
-
contract Caller {
- function callTest(Test test) {
+ function callTest(Test test) public {
test.call(0xabcdef01); // hash does not exist
// results in test.x becoming == 1.
- // The following call will fail, reject the
- // Ether and return false:
- test.send(2 ether);
+ // The following will not compile, but even
+ // if someone sends ether to that contract,
+ // the transaction will fail and reject the
+ // Ether.
+ //test.send(2 ether);
+ }
+ }
+
+.. index:: ! overload
+
+.. _overload-function:
+
+Function Overloading
+====================
+
+A Contract can have multiple functions of the same name but with different arguments.
+This also applies to inherited functions. The following example shows overloading of the
+``f`` function in the scope of contract ``A``.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(uint _in) public pure returns (uint out) {
+ out = 1;
+ }
+
+ function f(uint _in, bytes32 _key) public pure returns (uint out) {
+ out = 2;
}
}
+Overloaded functions are also present in the external interface. It is an error if two
+externally visible functions differ by their Solidity types but not by their external types.
+
+::
+
+ // This will not compile
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(B _in) public pure returns (B out) {
+ out = _in;
+ }
+
+ function f(address _in) public pure returns (address out) {
+ out = _in;
+ }
+ }
+
+ contract B {
+ }
+
+
+Both ``f`` function overloads above end up accepting the address type for the ABI although
+they are considered different inside Solidity.
+
+Overload resolution and Argument matching
+-----------------------------------------
+
+Overloaded functions are selected by matching the function declarations in the current scope
+to the arguments supplied in the function call. Functions are selected as overload candidates
+if all arguments can be implicitly converted to the expected types. If there is not exactly one
+candidate, resolution fails.
+
+.. note::
+ Return parameters are not taken into account for overload resolution.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(uint8 _in) public pure returns (uint8 out) {
+ out = _in;
+ }
+
+ function f(uint256 _in) public pure returns (uint256 out) {
+ out = _in;
+ }
+ }
+
+Calling ``f(50)`` would create a type error since ``250`` can be implicitly converted both to ``uint8``
+and ``uint256`` types. On another hand ``f(256)`` would resolve to ``f(uint256)`` overload as ``256`` cannot be implicitly
+converted to ``uint8``.
+
.. index:: ! event
.. _events:
@@ -607,7 +723,7 @@ All non-indexed arguments will be stored in the data part of the log.
uint _value
);
- function deposit(bytes32 _id) payable {
+ function deposit(bytes32 _id) public payable {
// Any call to this function (even deeply nested) can
// be detected from the JavaScript API by filtering
// for `Deposit` to be called.
@@ -621,14 +737,14 @@ The use in the JavaScript API would be as follows:
var abi = /* abi as generated by the compiler */;
var ClientReceipt = web3.eth.contract(abi);
- var clientReceipt = ClientReceipt.at(0x123 /* address */);
+ var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */);
var event = clientReceipt.Deposit();
// watch for changes
event.watch(function(error, result){
// result will contain various information
- // including the argumets given to the Deposit
+ // including the argumets given to the `Deposit`
// call.
if (!error)
console.log(result);
@@ -653,12 +769,19 @@ as topics. The event call above can be performed in the same way as
::
- log3(
- msg.value,
- 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20,
- msg.sender,
- _id
- );
+ pragma solidity ^0.4.10;
+
+ contract C {
+ function f() public payable {
+ bytes32 _id = 0x420042;
+ log3(
+ bytes32(msg.value),
+ bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
+ bytes32(msg.sender),
+ _id
+ );
+ }
+ }
where the long hexadecimal number is equal to
``keccak256("Deposit(address,hash256,uint256)")``, the signature of the event.
@@ -693,15 +816,14 @@ Details are given in the following example.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract owned {
function owned() { owner = msg.sender; }
address owner;
}
-
- // Use "is" to derive from another contract. Derived
+ // Use `is` to derive from another contract. Derived
// contracts can access all non-private members including
// internal functions and state variables. These cannot be
// accessed externally via `this`, though.
@@ -711,28 +833,25 @@ Details are given in the following example.
}
}
-
// These abstract contracts are only provided to make the
// interface known to the compiler. Note the function
// without body. If a contract does not implement all
// functions it can only be used as an interface.
contract Config {
- function lookup(uint id) returns (address adr);
+ function lookup(uint id) public returns (address adr);
}
-
contract NameReg {
- function register(bytes32 name);
- function unregister();
+ function register(bytes32 name) public;
+ function unregister() public;
}
-
- // Multiple inheritance is possible. Note that "owned" is
- // also a base class of "mortal", yet there is only a single
- // instance of "owned" (as for virtual inheritance in C++).
+ // Multiple inheritance is possible. Note that `owned` is
+ // also a base class of `mortal`, yet there is only a single
+ // instance of `owned` (as for virtual inheritance in C++).
contract named is owned, mortal {
function named(bytes32 name) {
- Config config = Config(0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970);
+ Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).register(name);
}
@@ -741,9 +860,9 @@ Details are given in the following example.
// types of output parameters, that causes an error.
// Both local and message-based function calls take these overrides
// into account.
- function kill() {
+ function kill() public {
if (msg.sender == owner) {
- Config config = Config(0xd5f9d8d94886e70b06e474c3fb14fd43e2f23970);
+ Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970);
NameReg(config.lookup(1)).unregister();
// It is still possible to call a specific
// overridden function.
@@ -752,16 +871,15 @@ Details are given in the following example.
}
}
-
// If a constructor takes an argument, it needs to be
// provided in the header (or modifier-invocation-style at
// the constructor of the derived contract (see below)).
contract PriceFeed is owned, mortal, named("GoldFeed") {
- function updateInfo(uint newInfo) {
+ function updateInfo(uint newInfo) public {
if (msg.sender == owner) info = newInfo;
}
- function get() constant returns(uint r) { return info; }
+ function get() public view returns(uint r) { return info; }
uint info;
}
@@ -772,23 +890,25 @@ seen in the following example::
pragma solidity ^0.4.0;
+ contract owned {
+ function owned() public { owner = msg.sender; }
+ address owner;
+ }
+
contract mortal is owned {
- function kill() {
+ function kill() public {
if (msg.sender == owner) selfdestruct(owner);
}
}
-
contract Base1 is mortal {
- function kill() { /* do cleanup 1 */ mortal.kill(); }
+ function kill() public { /* do cleanup 1 */ mortal.kill(); }
}
-
contract Base2 is mortal {
- function kill() { /* do cleanup 2 */ mortal.kill(); }
+ function kill() public { /* do cleanup 2 */ mortal.kill(); }
}
-
contract Final is Base1, Base2 {
}
@@ -799,32 +919,35 @@ derived override, but this function will bypass
pragma solidity ^0.4.0;
+ contract owned {
+ function owned() public { owner = msg.sender; }
+ address owner;
+ }
+
contract mortal is owned {
- function kill() {
+ function kill() public {
if (msg.sender == owner) selfdestruct(owner);
}
}
-
contract Base1 is mortal {
- function kill() { /* do cleanup 1 */ super.kill(); }
+ function kill() public { /* do cleanup 1 */ super.kill(); }
}
contract Base2 is mortal {
- function kill() { /* do cleanup 2 */ super.kill(); }
+ function kill() public { /* do cleanup 2 */ super.kill(); }
}
-
- contract Final is Base2, Base1 {
+ contract Final is Base1, Base2 {
}
-If ``Base1`` calls a function of ``super``, it does not simply
-call this function on one of its base contracts. Rather, it
+If ``Base2`` calls a function of ``super``, it does not simply
+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
+inheritance graph, so it will call ``Base1.kill()`` (note that
the final inheritance sequence is -- starting with the most
-derived contract: Final, Base1, Base2, mortal, owned).
+derived contract: Final, Base2, Base1, mortal, owned).
The actual function that is called when using super is
not known in the context of the class where it is used,
although its type is known. This is similar for ordinary
@@ -842,12 +965,11 @@ the base constructors. This can be done in two ways::
contract Base {
uint x;
- function Base(uint _x) { x = _x; }
+ function Base(uint _x) public { x = _x; }
}
-
contract Derived is Base(7) {
- function Derived(uint _y) Base(_y * _y) {
+ function Derived(uint _y) Base(_y * _y) public {
}
}
@@ -878,6 +1000,8 @@ error "Linearization of inheritance graph impossible".
::
+ // This will not compile
+
pragma solidity ^0.4.0;
contract X {}
@@ -910,15 +1034,21 @@ Contract functions can lack an implementation as in the following example (note
pragma solidity ^0.4.0;
contract Feline {
- function utterance() returns (bytes32);
+ function utterance() public returns (bytes32);
}
-Such contracts cannot be compiled (even if they contain implemented functions alongside non-implemented functions), but they can be used as base contracts::
+Such contracts cannot be compiled (even if they contain
+implemented functions alongside non-implemented functions),
+but they can be used as base contracts::
pragma solidity ^0.4.0;
+ contract Feline {
+ function utterance() public returns (bytes32);
+ }
+
contract Cat is Feline {
- function utterance() returns (bytes32) { return "miaow"; }
+ function utterance() public returns (bytes32) { return "miaow"; }
}
If a contract inherits from an abstract contract and does not implement all non-implemented functions by overriding, it will itself be abstract.
@@ -946,8 +1076,10 @@ Interfaces are denoted by their own keyword:
::
+ pragma solidity ^0.4.11;
+
interface Token {
- function transfer(address recipient, uint amount);
+ function transfer(address recipient, uint amount) public;
}
Contracts can inherit interfaces as they would inherit other contracts.
@@ -968,7 +1100,11 @@ is executed in the context of the calling contract, i.e. ``this`` points to the
calling contract, and especially the storage from the calling contract can be
accessed. As a library is an isolated piece of source code, it can only access
state variables of the calling contract if they are explicitly supplied (it
-would have no way to name them, otherwise).
+would have no way to name them, otherwise). Library functions can only be
+called directly (i.e. without the use of ``DELEGATECALL``) if they do not modify
+the state (i.e. if they are ``view`` or ``pure`` functions),
+because libraries are assumed to be stateless. In particular, it is
+not possible to destroy a library unless Solidity's type system is circumvented.
Libraries can be seen as implicit base contracts of the contracts that use them.
They will not be explicitly visible in the inheritance hierarchy, but calls
@@ -979,7 +1115,7 @@ 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.
To realize this in the EVM, code of internal library functions
-and all functions called from therein will be pulled into the calling
+and all functions called from therein will at compile time be pulled into the calling
contract, and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``.
.. index:: using for, set
@@ -990,7 +1126,7 @@ more advanced example to implement a set).
::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.16;
library Set {
// We define a new struct datatype that will be used to
@@ -1001,9 +1137,10 @@ more advanced example to implement a set).
// reference" and thus only its storage address and not
// its contents is passed as part of the call. This is a
// special feature of library functions. It is idiomatic
- // to call the first parameter 'self', if the function can
+ // to call the first parameter `self`, if the function can
// be seen as a method of that object.
function insert(Data storage self, uint value)
+ public
returns (bool)
{
if (self.flags[value])
@@ -1013,6 +1150,7 @@ more advanced example to implement a set).
}
function remove(Data storage self, uint value)
+ public
returns (bool)
{
if (!self.flags[value])
@@ -1022,17 +1160,18 @@ more advanced example to implement a set).
}
function contains(Data storage self, uint value)
+ public
+ view
returns (bool)
{
return self.flags[value];
}
}
-
contract C {
Set.Data knownValues;
- function register(uint value) {
+ function register(uint value) public {
// The library functions can be called without a
// specific instance of the library, since the
// "instance" will be the current contract.
@@ -1042,7 +1181,7 @@ more advanced example to implement a set).
}
Of course, you do not have to follow this way to use
-libraries - they can also be used without defining struct
+libraries: they can also be used without defining struct
data types. Functions also work without any storage
reference parameters, and they can have multiple storage reference
parameters and in any position.
@@ -1052,7 +1191,7 @@ are all compiled as calls (``DELEGATECALL``) to an external
contract/library. If you use libraries, take care that an
actual external function call is performed.
``msg.sender``, ``msg.value`` and ``this`` will retain their values
-in this call, though (prior to Homestead, because of the use of `CALLCODE`, ``msg.sender`` and
+in this call, though (prior to Homestead, because of the use of ``CALLCODE``, ``msg.sender`` and
``msg.value`` changed, though).
The following example shows how to use memory types and
@@ -1061,19 +1200,19 @@ custom types without the overhead of external function calls:
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
library BigInt {
struct bigint {
uint[] limbs;
}
- function fromUint(uint x) internal returns (bigint r) {
+ function fromUint(uint x) internal pure returns (bigint r) {
r.limbs = new uint[](1);
r.limbs[0] = x;
}
- function add(bigint _a, bigint _b) internal returns (bigint r) {
+ function add(bigint _a, bigint _b) internal pure returns (bigint r) {
r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
uint carry = 0;
for (uint i = 0; i < r.limbs.length; ++i) {
@@ -1095,20 +1234,19 @@ custom types without the overhead of external function calls:
}
}
- function limb(bigint _a, uint _limb) internal returns (uint) {
+ function limb(bigint _a, uint _limb) internal pure returns (uint) {
return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
}
- function max(uint a, uint b) private returns (uint) {
+ function max(uint a, uint b) private pure returns (uint) {
return a > b ? a : b;
}
}
-
contract C {
using BigInt for BigInt.bigint;
- function f() {
+ function f() public pure {
var x = BigInt.fromUint(7);
var y = BigInt.fromUint(uint(-1));
var z = x.add(y);
@@ -1134,6 +1272,30 @@ Restrictions for libraries in comparison to contracts:
(These might be lifted at a later point.)
+Call Protection For Libraries
+=============================
+
+As mentioned in the introduction, if a library's code is executed
+using a ``CALL`` instead of a ``DELEGATECALL`` or ``CALLCODE``,
+it will revert unless a ``view`` or ``pure`` function is called.
+
+The EVM does not provide a direct way for a contract to detect
+whether it was called using ``CALL`` or not, but a contract
+can use the ``ADDRESS`` opcode to find out "where" it is
+currently running. The generated code compares this address
+to the address used at construction time to determine the mode
+of calling.
+
+More specifically, the runtime code of a library always starts
+with a push instruction, which is a zero of 20 bytes at
+compilation time. When the deploy code runs, this constant
+is replaced in memory by the current address and this
+modified code is stored in the contract. At runtime,
+this causes the deploy time address to be the first
+constant to be pushed onto the stack and the dispatcher
+code compares the current address against this constant
+for any non-view and non-pure function.
+
.. index:: ! using for, library
.. _using-for:
@@ -1166,13 +1328,14 @@ available without having to add further code.
Let us rewrite the set example from the
:ref:`libraries` in this way::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.16;
// This is the same code as before, just without comments
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
+ public
returns (bool)
{
if (self.flags[value])
@@ -1182,6 +1345,7 @@ Let us rewrite the set example from the
}
function remove(Data storage self, uint value)
+ public
returns (bool)
{
if (!self.flags[value])
@@ -1191,48 +1355,52 @@ Let us rewrite the set example from the
}
function contains(Data storage self, uint value)
+ public
+ view
returns (bool)
{
return self.flags[value];
}
}
-
contract C {
using Set for Set.Data; // this is the crucial change
Set.Data knownValues;
- function register(uint value) {
+ function register(uint value) public {
// Here, all variables of type Set.Data have
// corresponding member functions.
// The following function call is identical to
- // Set.insert(knownValues, value)
+ // `Set.insert(knownValues, value)`
require(knownValues.insert(value));
}
}
It is also possible to extend elementary types in that way::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
library Search {
- function indexOf(uint[] storage self, uint value) returns (uint) {
+ function indexOf(uint[] storage self, uint value)
+ public
+ view
+ returns (uint)
+ {
for (uint i = 0; i < self.length; i++)
if (self[i] == value) return i;
return uint(-1);
}
}
-
contract C {
using Search for uint[];
uint[] data;
- function append(uint value) {
+ function append(uint value) public {
data.push(value);
}
- function replace(uint _old, uint _new) {
+ function replace(uint _old, uint _new) public {
// This performs the library function call
uint index = data.indexOf(_old);
if (index == uint(-1))
diff --git a/docs/contributing.rst b/docs/contributing.rst
index 1f869dbb..a5efba8b 100644
--- a/docs/contributing.rst
+++ b/docs/contributing.rst
@@ -50,8 +50,10 @@ and instead, ``git rebase`` your branch.
Additionally, if you are writing a new feature, please ensure you write appropriate
Boost test cases and place them under ``test/``.
-However, if you are making a larger change, please consult with the Gitter
-channel, first.
+However, if you are making a larger change, please consult with the `Solidity Development Gitter channel
+<https://gitter.im/ethereum/solidity-dev>`_ (different from the one mentioned above, this on is
+focused on compiler and language development instead of language use) first.
+
Finally, please make sure you respect the `coding standards
<https://raw.githubusercontent.com/ethereum/cpp-ethereum/develop/CodingStandards.txt>`_
@@ -64,13 +66,39 @@ Running the compiler tests
==========================
Solidity includes different types of tests. They are included in the application
-called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode.
+called ``soltest``. Some of them require the ``cpp-ethereum`` client in testing mode,
+some others require ``libz3`` to be installed.
+
+To disable the z3 tests, use ``./build/test/soltest -- --no-smt`` and
+to run a subset of the tests that do not require ``cpp-ethereum``, use ``./build/test/soltest -- --no-ipc``.
-To run ``cpp-ethereum`` in testing mode: ``eth --test -d /tmp/testeth``.
+For all other tests, you need to install `cpp-ethereum <https://github.com/ethereum/cpp-ethereum/releases/download/solidityTester/eth>`_ and run it in testing mode: ``eth --test -d /tmp/testeth``.
-To run the tests: ``soltest -- --ipcpath /tmp/testeth/geth.ipc``.
+Then you run the actual tests: ``./build/test/soltest -- --ipcpath /tmp/testeth/geth.ipc``.
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.
+Alternatively, there is a testing script at ``scripts/test.sh`` which executes all tests and runs
+``cpp-ethereum`` automatically if it is in the path (but does not download it).
+
+Travis CI even runs some additional tests (including ``solc-js`` and testing third party Solidity frameworks) that require compiling the Emscripten target.
+
+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 a2d34274..7be92cfa 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -20,8 +20,10 @@ For example, suppose we want our contract to
accept one kind of external calls with two integers, we would write
something like::
+ pragma solidity ^0.4.16;
+
contract Simple {
- function taker(uint _a, uint _b) {
+ function taker(uint _a, uint _b) public pure {
// do something with _a and _b.
}
}
@@ -34,8 +36,14 @@ The output parameters can be declared with the same syntax after the
the sum and the product of the two given integers, then we would
write::
+ pragma solidity ^0.4.16;
+
contract Simple {
- function arithmetics(uint _a, uint _b) returns (uint o_sum, uint o_product) {
+ function arithmetics(uint _a, uint _b)
+ public
+ pure
+ returns (uint o_sum, uint o_product)
+ {
o_sum = _a + _b;
o_product = _a * _b;
}
@@ -91,9 +99,11 @@ Internal Function Calls
Functions of the current contract can be called directly ("internally"), also recursively, as seen in
this nonsensical example::
+ pragma solidity ^0.4.16;
+
contract C {
- function g(uint a) returns (uint ret) { return f(); }
- function f() returns (uint ret) { return g(7) + f(); }
+ function g(uint a) public pure returns (uint ret) { return f(); }
+ function f() internal pure returns (uint ret) { return g(7) + f(); }
}
These function calls are translated into simple jumps inside the EVM. This has
@@ -116,15 +126,16 @@ 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 with special options ``.value()`` and ``.gas()``, respectively::
+ pragma solidity ^0.4.0;
+
contract InfoFeed {
- function info() payable returns (uint ret) { return 42; }
+ function info() public payable returns (uint ret) { return 42; }
}
-
contract Consumer {
InfoFeed feed;
- function setFeed(address addr) { feed = InfoFeed(addr); }
- function callFeed() { feed.info.value(10).gas(800)(); }
+ function setFeed(address addr) public { feed = InfoFeed(addr); }
+ function callFeed() public { feed.info.value(10).gas(800)(); }
}
The modifier ``payable`` has to be used for ``info``, because otherwise, the `.value()`
@@ -173,9 +184,11 @@ parameters from the function declaration, but can be in arbitrary order.
pragma solidity ^0.4.0;
contract C {
- function f(uint key, uint value) { ... }
+ function f(uint key, uint value) public {
+ // ...
+ }
- function g() {
+ function g() public {
// named arguments
f({value: 2, key: 3});
}
@@ -185,19 +198,19 @@ Omitted Function Parameter Names
--------------------------------
The names of unused parameters (especially return parameters) can be omitted.
-Those names will still be present on the stack, but they are inaccessible.
+Those parameters will still be present on the stack, but they are inaccessible.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract C {
// omitted name for parameter
- function func(uint k, uint) returns(uint) {
+ function func(uint k, uint) public pure returns(uint) {
return k;
}
}
-
+
.. index:: ! new, contracts;creating
@@ -216,29 +229,29 @@ creation-dependencies are not possible.
contract D {
uint x;
- function D(uint a) payable {
+ function D(uint a) public payable {
x = a;
}
}
-
contract C {
D d = new D(4); // will be executed as part of C's constructor
- function createD(uint arg) {
+ function createD(uint arg) public {
D newD = new D(arg);
}
- function createAndEndowD(uint arg, uint amount) {
+ function createAndEndowD(uint arg, uint amount) public payable {
// Send ether along with the creation
D newD = (new D).value(amount)(arg);
}
}
-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.
+As seen in the example, it is possible to forward Ether while creating
+an instance of ``D`` 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.
Order of Evaluation of Expressions
==================================
@@ -261,14 +274,16 @@ Destructuring Assignments and Returning Multiple Values
Solidity internally allows tuple types, i.e. a list of objects of potentially different types whose size is a constant at compile-time. Those tuples can be used to return multiple values at the same time and also assign them to multiple variables (or LValues in general) at the same time::
+ pragma solidity ^0.4.16;
+
contract C {
uint[] data;
- function f() returns (uint, bool, uint) {
+ function f() public pure returns (uint, bool, uint) {
return (7, true, 2);
}
- function g() {
+ function g() public {
// Declares and assigns the variables. Specifying the type explicitly is not possible.
var (x, b, y) = f();
// Assigns to a pre-existing variable.
@@ -280,6 +295,7 @@ Solidity internally allows tuple types, i.e. a list of objects of potentially di
// the rest of the values are discarded.
(data.length,) = f(); // Sets the length to 7
// The same can be done on the left side.
+ // If the tuple begins in an empty component, the beginning values are discarded.
(,data[3]) = f(); // Sets data[3] to 2
// Components can only be left out at the left-hand-side of assignments, with
// one exception:
@@ -313,10 +329,12 @@ This happens because Solidity inherits its scoping rules from JavaScript.
This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block.
As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``::
- pragma solidity ^0.4.0;
+ // This will not compile
+
+ pragma solidity ^0.4.16;
contract ScopingErrors {
- function scoping() {
+ function scoping() public {
uint i = 0;
while (i++ < 1) {
@@ -328,7 +346,7 @@ As a result, the following code is illegal and cause the compiler to throw an er
}
}
- function minimalScoping() {
+ function minimalScoping() public {
{
uint same2 = 0;
}
@@ -338,7 +356,7 @@ As a result, the following code is illegal and cause the compiler to throw an er
}
}
- function forLoopScoping() {
+ function forLoopScoping() public {
for (uint same3 = 0; same3 < 1; same3++) {
}
@@ -350,66 +368,91 @@ As a result, the following code is illegal and cause the compiler to throw an er
In addition to this, if a variable is declared, it will be initialized at the beginning of the function to its default value.
As a result, the following code is legal, despite being poorly written::
- function foo() returns (uint) {
- // baz is implicitly initialized as 0
- uint bar = 5;
- if (true) {
- bar += baz;
- } else {
- uint baz = 10;// never executes
+ pragma solidity ^0.4.0;
+
+ contract C {
+ function foo() public pure returns (uint) {
+ // baz is implicitly initialized as 0
+ uint bar = 5;
+ if (true) {
+ bar += baz;
+ } else {
+ uint baz = 10;// never executes
+ }
+ return bar;// returns 5
}
- return bar;// returns 5
}
-.. index:: ! exception, ! throw
+.. index:: ! exception, ! throw, ! assert, ! require, ! revert
-Exceptions
-==========
+Error handling: Assert, Require, Revert and Exceptions
+======================================================
-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).
+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 ``assert`` function should only be used to test for internal errors, and to check invariants.
+The ``require`` function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts.
+If used properly, analysis tools can evaluate your contract to identify the conditions and function calls which will reach a failing ``assert``. Properly functioning code should never reach a failing assert statement; if this happens there is a bug in your contract which you should fix.
+
+There are two other ways to trigger exceptions: 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()``.
+
+.. note::
+ From version 0.4.13 the ``throw`` keyword is deprecated and will be phased out in the future.
+
+When exceptions happen in a sub-call, they "bubble up" (i.e. exceptions are rethrown) automatically. Exceptions to this rule are ``send``
+and the low-level functions ``call``, ``delegatecall`` and ``callcode`` -- those return ``false`` in case
+of an exception instead of "bubbling up".
+
+.. warning::
+ The low-level ``call``, ``delegatecall`` and ``callcode`` will return success if the called account is non-existent, as part of the design of EVM. Existence must be checked prior to calling if desired.
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
+ function sendHalf(address addr) public payable returns (uint balance) {
+ 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, Solidity automatically generates a runtime exception in the following situations:
+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 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 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 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 you call a zero-initialized variable of internal function type.
-#. If a ``.transfer()`` fails.
#. If you call ``assert`` with an argument that evaluates to false.
-While a user-provided exception is generated in the following situations:
+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``) when a user-provided exception is thrown or the condition of
-a ``require`` call is not met. In contrast, it performs an invalid operation
-(instruction ``0xfe``) if a runtime exception is encountered or the condition of an ``assert`` call is not met. In both cases, this 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
+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.
-
-If contracts are written so that ``assert`` is only used to test internal conditions and ``require``
-is used in case of malformed input, a formal analysis tool that verifies that the invalid
-opcode can never be reached can be used to check for the absence of errors assuming valid inputs.
+(or at least call) without effect. Note that ``assert``-style exceptions consume all gas available to the call, while
+``require``-style exceptions will not consume any gas starting from the Metropolis release.
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 03ee8388..a6bead29 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -39,12 +39,13 @@ This is just the bytecode "data" sent along with the request.
Is there a decompiler available?
================================
-There is no decompiler to Solidity. This is in principle possible
-to some degree, but for example variable names will be lost and
-great effort will be necessary to make it look similar to
-the original source code.
+There is no exact decompiler to Solidity, but
+`Porosity <https://github.com/comaeio/porosity>`_ is close.
+Because some information like variable names, comments, and
+source code formatting is lost in the compilation process,
+it is not possible to completely recover the original source code.
-Bytecode can be decompiled to opcodes, a service that is provided by
+Bytecode can be disassembled to opcodes, a service that is provided by
several blockchain explorers.
Contracts on the blockchain should have their original source
@@ -103,11 +104,6 @@ This is a limitation of the EVM and will be solved with the next protocol update
Returning variably-sized data as part of an external transaction or call is fine.
-How do you represent ``double``/``float`` in Solidity?
-======================================================
-
-This is not yet possible.
-
Is it possible to in-line initialize an array like so: ``string[] myarray = ["a", "b"];``
=========================================================================================
@@ -116,31 +112,15 @@ array in the return statement. Pretty cool, huh?
Example::
+ pragma solidity ^0.4.16;
+
contract C {
- function f() returns (uint8[5]) {
+ function f() public pure returns (uint8[5]) {
string[4] memory adaArr = ["This", "is", "an", "array"];
return ([1, 2, 3, 4, 5]);
}
}
-Are timestamps (``now,`` ``block.timestamp``) reliable?
-=======================================================
-
-This depends on what you mean by "reliable".
-In general, they are supplied by miners and are therefore vulnerable.
-
-Unless someone really messes up the blockchain or the clock on
-your computer, you can make the following assumptions:
-
-You publish a transaction at a time X, this transaction contains same
-code that calls ``now`` and is included in a block whose timestamp is Y
-and this block is included into the canonical chain (published) at a time Z.
-
-The value of ``now`` will be identical to Y and X <= Y <= Z.
-
-Never use ``now`` or ``block.hash`` as a source of randomness, unless you know
-what you are doing!
-
Can a contract function return a ``struct``?
============================================
@@ -153,37 +133,6 @@ Enums are not supported by the ABI, they are just supported by Solidity.
You have to do the mapping yourself for now, we might provide some help
later.
-What is the deal with ``function () { ... }`` inside Solidity contracts? How can a function not have a name?
-============================================================================================================
-
-This function is called "fallback function" and it
-is called when someone just sent Ether to the contract without
-providing any data or if someone messed up the types so that they tried to
-call a function that does not exist.
-
-The default behaviour (if no fallback function is explicitly given) in
-these situations is to throw an exception.
-
-If the contract is meant to receive Ether with simple transfers, you
-should implement the fallback function as
-
-``function() payable { }``
-
-Another use of the fallback function is to e.g. register that your
-contract received ether by using an event.
-
-*Attention*: If you implement the fallback function take care that it uses as
-little gas as possible, because ``send()`` will only supply a limited amount.
-
-Is it possible to pass arguments to the fallback function?
-==========================================================
-
-The fallback function cannot take parameters.
-
-Under special circumstances, you can send data. If you take care
-that none of the other functions is invoked, you can access the data
-by ``msg.data``.
-
Can state variables be initialized in-line?
===========================================
@@ -192,6 +141,8 @@ should be noted that you must declare them as static memory arrays.
Examples::
+ pragma solidity ^0.4.0;
+
contract C {
struct S {
uint a;
@@ -200,10 +151,9 @@ Examples::
S public x = S(1, 2);
string name = "Ada";
- string[4] memory adaArr = ["This", "is", "an", "array"];
+ string[4] adaArr = ["This", "is", "an", "array"];
}
-
contract D {
C c = new C();
}
@@ -227,13 +177,6 @@ Better use ``for (uint i = 0; i < a.length...``
See `struct_and_for_loop_tester.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/65_struct_and_for_loop_tester.sol>`_.
-What character set does Solidity use?
-=====================================
-
-Solidity is character set agnostic concerning strings in the source code, although
-UTF-8 is recommended. Identifiers (variables, functions, ...) can only use
-ASCII.
-
What are some examples of basic string manipulation (``substring``, ``indexOf``, ``charAt``, etc)?
==================================================================================================
@@ -243,14 +186,16 @@ which will be extended in the future. In addition, Arachnid has written `solidit
For now, if you want to modify a string (even when you only want to know its length),
you should always convert it to a ``bytes`` first::
+ pragma solidity ^0.4.0;
+
contract C {
string s;
- function append(byte c) {
+ function append(byte c) public {
bytes(s).push(c);
}
- function set(uint i, byte c) {
+ function set(uint i, byte c) public {
bytes(s)[i] = c;
}
}
@@ -288,10 +233,14 @@ situation.
If you do not want to throw, you can return a pair::
+ pragma solidity ^0.4.16;
+
contract C {
uint[] counters;
function getCounter(uint index)
+ public
+ view
returns (uint counter, bool error) {
if (index >= counters.length)
return (0, true);
@@ -299,12 +248,12 @@ If you do not want to throw, you can return a pair::
return (counters[index], false);
}
- function checkCounter(uint index) {
+ function checkCounter(uint index) public view {
var (counter, error) = getCounter(index);
if (error) {
- ...
+ // ...
} else {
- ...
+ // ...
}
}
}
@@ -358,24 +307,27 @@ There are defaults for the storage location depending on which type
of variable it concerns:
* state variables are always in storage
-* function arguments are always in memory
-* local variables always reference storage
+* function arguments are in memory by default
+* local variables of struct, array or mapping type reference storage by default
+* local variables of value type (i.e. neither array, nor struct nor mapping) are stored in the stack
Example::
+ pragma solidity ^0.4.0;
+
contract C {
uint[] data1;
uint[] data2;
- function appendOne() {
+ function appendOne() public {
append(data1);
}
- function appendTwo() {
+ function appendTwo() public {
append(data2);
}
- function append(uint[] storage d) {
+ function append(uint[] storage d) internal {
d.push(1);
}
}
@@ -393,11 +345,14 @@ A common mistake is to declare a local variable and assume that it will
be created in memory, although it will be created in storage::
/// THIS CONTRACT CONTAINS AN ERROR
+
+ pragma solidity ^0.4.0;
+
contract C {
uint someVariable;
uint[] data;
- function f() {
+ function f() public {
uint[] x;
x.push(2);
data = x;
@@ -417,33 +372,18 @@ slot ``0``) is modified by ``x.push(2)``.
The correct way to do this is the following::
+ pragma solidity ^0.4.0;
+
contract C {
uint someVariable;
uint[] data;
- function f() {
+ function f() public {
uint[] x = data;
x.push(2);
}
}
-What is the difference between ``bytes`` and ``byte[]``?
-========================================================
-
-``bytes`` is usually more efficient: When used as arguments to functions (i.e. in
-CALLDATA) or in memory, every single element of a ``byte[]`` is padded to 32
-bytes which wastes 31 bytes per element.
-
-Is it possible to send a value while calling an overloaded function?
-====================================================================
-
-It's a known missing feature. https://www.pivotaltracker.com/story/show/92020468
-as part of https://www.pivotaltracker.com/n/projects/1189488
-
-Best solution currently see is to introduce a special case for gas and value and
-just re-check whether they are present at the point of overload resolution.
-
-
******************
Advanced Questions
******************
@@ -489,36 +429,19 @@ Note2: Optimizing storage access can pull the gas costs down considerably, becau
currently do not work across loops and also have a problem with bounds checking.
You might get much better results in the future, though.
-What does ``p.recipient.call.value(p.amount)(p.data)`` do?
-==========================================================
-
-Every external function call in Solidity can be modified in two ways:
-
-1. You can add Ether together with the call
-2. You can limit the amount of gas available to the call
-
-This is done by "calling a function on the function":
-
-``f.gas(2).value(20)()`` calls the modified function ``f`` and thereby sending 20
-Wei and limiting the gas to 2 (so this function call will most likely go out of
-gas and return your 20 Wei).
-
-In the above example, the low-level function ``call`` is used to invoke another
-contract with ``p.data`` as payload and ``p.amount`` Wei is sent with that call.
-
What happens to a ``struct``'s mapping when copying over a ``struct``?
======================================================================
This is a very interesting question. Suppose that we have a contract field set up like such::
- struct user {
- mapping(string => address) usedContracts;
+ struct User {
+ mapping(string => string) comments;
}
- function somefunction {
- user user1;
- user1.usedContracts["Hello"] = "World";
- user user2 = user1;
+ function somefunction public {
+ User user1;
+ user1.comments["Hello"] = "World";
+ User user2 = user1;
}
In this case, the mapping of the struct being copied over into the userList is ignored as there is no "list of mapped keys".
@@ -533,15 +456,16 @@ In the case of a ``contract A`` calling a new instance of ``contract B``, parent
You will need to make sure that you have both contracts aware of each other's presence and that ``contract B`` has a ``payable`` constructor.
In this example::
+ pragma solidity ^0.4.0;
+
contract B {
- function B() payable {}
+ function B() public payable {}
}
-
contract A {
address child;
- function test() {
+ function test() public {
child = (new B).value(10)(); //construct a new B with 10 wei
}
}
@@ -580,19 +504,21 @@ Can a contract pass an array (static size) or string or ``bytes`` (dynamic size)
Sure. Take care that if you cross the memory / storage boundary,
independent copies will be created::
+ pragma solidity ^0.4.16;
+
contract C {
uint[20] x;
- function f() {
+ function f() public {
g(x);
h(x);
}
- function g(uint[20] y) {
+ function g(uint[20] y) internal pure {
y[2] = 3;
}
- function h(uint[20] storage y) {
+ function h(uint[20] storage y) internal {
y[3] = 4;
}
}
@@ -641,7 +567,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 getter function for a public state variable of array type only returns
+The automatic :ref:`getter function<getter-functions>` 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.
diff --git a/docs/grammar.txt b/docs/grammar.txt
index 09e492f3..e700c946 100644
--- a/docs/grammar.txt
+++ b/docs/grammar.txt
@@ -16,22 +16,30 @@ ContractPart = StateVariableDeclaration | UsingForDeclaration
InheritanceSpecifier = UserDefinedTypeName ( '(' Expression ( ',' Expression )* ')' )?
-StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' )? Identifier ('=' Expression)? ';'
+StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' | 'constant' )? 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' )*
+ ( ModifierInvocation | StateMutability | 'external' | 'public' | 'internal' | 'private' )*
( 'returns' ParameterList )? ( ';' | Block )
-EventDefinition = 'event' Identifier IndexedParameterList 'anonymous'? ';'
+EventDefinition = 'event' Identifier EventParameterList 'anonymous'? ';'
EnumValue = Identifier
EnumDefinition = 'enum' Identifier '{' EnumValue? (',' EnumValue)* '}'
-IndexedParameterList = '(' ( TypeName 'indexed'? Identifier? (',' TypeName 'indexed'? Identifier?)* )? ')'
-ParameterList = '(' ( TypeName Identifier? (',' TypeName Identifier?)* )? ')'
-TypeNameList = '(' ( TypeName (',' TypeName )* )? ')'
+ParameterList = '(' ( Parameter (',' Parameter)* )? ')'
+Parameter = TypeName StorageLocation? Identifier?
+
+EventParameterList = '(' ( EventParameter (',' EventParameter )* )? ')'
+EventParameter = TypeName 'indexed'? Identifier?
+
+FunctionTypeParameterList = '(' ( FunctionTypeParameter (',' FunctionTypeParameter )* )? ')'
+FunctionTypeParameter = TypeName StorageLocation?
// semantic restriction: mappings and structs (recursively) containing mappings
// are not allowed in argument lists
@@ -47,9 +55,10 @@ UserDefinedTypeName = Identifier ( '.' Identifier )*
Mapping = 'mapping' '(' ElementaryTypeName '=>' TypeName ')'
ArrayTypeName = TypeName '[' Expression? ']'
-FunctionTypeName = 'function' TypeNameList ( 'internal' | 'external' | 'constant' | 'payable' )*
- ( 'returns' TypeNameList )?
+FunctionTypeName = 'function' FunctionTypeParameterList ( 'internal' | 'external' | StateMutability )*
+ ( 'returns' FunctionTypeParameterList )?
StorageLocation = 'memory' | 'storage'
+StateMutability = 'pure' | 'constant' | 'view' | 'payable'
Block = '{' Statement* '}'
Statement = IfStatement | WhileStatement | ForStatement | Block | InlineAssemblyStatement |
@@ -72,8 +81,13 @@ VariableDefinition = ('var' IdentifierList | VariableDeclaration) ( '=' Expressi
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
@@ -88,20 +102,20 @@ Expression =
| Expression '||' Expression
| Expression '?' Expression ':' Expression
| Expression ('=' | '|=' | '^=' | '&=' | '<<=' | '>>=' | '+=' | '-=' | '*=' | '/=' | '%=') Expression
- | Expression? (',' Expression)
| PrimaryExpression
-PrimaryExpression = Identifier
- | BooleanLiteral
+PrimaryExpression = BooleanLiteral
| NumberLiteral
| HexLiteral
| StringLiteral
+ | TupleExpression
+ | Identifier
| ElementaryTypeNameExpression
ExpressionList = Expression ( ',' Expression )*
NameValueList = Identifier ':' Expression ( ',' Identifier ':' Expression )*
-FunctionCall = ( PrimaryExpression | NewExpression | TypeName ) ( ( '.' Identifier ) | ( '[' Expression ']' ) )* '(' FunctionCallArguments ')'
+FunctionCall = Expression '(' FunctionCallArguments ')'
FunctionCallArguments = '{' NameValueList? '}'
| ExpressionList?
@@ -118,7 +132,10 @@ StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]*
HexNumber = '0x' [0-9a-fA-F]+
-DecimalNumber = [0-9]+
+DecimalNumber = [0-9]+ ( '.' [0-9]* )? ( [eE] [0-9]+ )?
+
+TupleExpression = '(' ( Expression? ( ',' Expression? )* )? ')'
+ | '[' ( Expression ( ',' Expression )* )? ']'
ElementaryTypeNameExpression = ElementaryTypeName
@@ -131,9 +148,9 @@ Uint = 'uint' | 'uint8' | 'uint16' | 'uint24' | 'uint32' | 'uint40' | 'uint48' |
Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | 'bytes6' | 'bytes7' | 'bytes8' | 'bytes9' | 'bytes10' | 'bytes11' | 'bytes12' | 'bytes13' | 'bytes14' | 'bytes15' | 'bytes16' | 'bytes17' | 'bytes18' | 'bytes19' | 'bytes20' | 'bytes21' | 'bytes22' | 'bytes23' | 'bytes24' | 'bytes25' | 'bytes26' | 'bytes27' | 'bytes28' | 'bytes29' | 'bytes30' | 'bytes31' | 'bytes32'
-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'
+Fixed = 'fixed' | ( 'fixed' [0-9]+ 'x' [0-9]+ )
-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'
+Ufixed = 'ufixed' | ( 'ufixed' [0-9]+ 'x' [0-9]+ )
InlineAssemblyBlock = '{' AssemblyItem* '}'
diff --git a/docs/index.rst b/docs/index.rst
index 3cdda62d..3df0af3c 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -6,8 +6,9 @@ Solidity
: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 (EVM).
+Solidity is a contract-oriented, high-level language for implementing smart contracts.
+It was influenced by C++, Python and JavaScript
+and is designed to target the Ethereum Virtual Machine (EVM).
Solidity is statically typed, supports inheritance, libraries and complex
user-defined types among other features.
@@ -20,6 +21,23 @@ crowdfunding, blind auctions, multi-signature wallets and more.
`Remix <https://remix.ethereum.org/>`_
(it can take a while to load, please be patient).
+.. warning::
+ Since software is written by humans, it can have bugs. Thus, also
+ smart contracts should be created following well-known best-practices in
+ software development. This includes code review, testing, audits and correctness proofs.
+ Also note that users are sometimes more confident in code than its authors.
+ Finally, blockchains have their own things to watch out for, so please take
+ a look at the section :ref:`security_considerations`.
+
+Translations
+------------
+
+This documentation is translated into several languages by community volunteers, but the English version stands as a reference.
+
+* `Spanish <https://solidity-es.readthedocs.io>`_
+* `Russian <https://github.com/ethereum/wiki/wiki/%5BRussian%5D-%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity>`_ (rather outdated)
+
+
Useful links
------------
@@ -41,9 +59,6 @@ Available Solidity Integrations
* `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)
@@ -63,7 +78,10 @@ Available Solidity Integrations
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>`_.
+ Linter to identify and fix style and security issues in Solidity.
+
+* `Solhint <https://github.com/protofire/solhint>`_
+ Solidity linter that provides security, style guide and best practice rules for smart contract validation.
* `Visual Studio Code extension <http://juan.blanco.ws/solidity-contracts-in-visual-studio-code/>`_
Solidity plugin for Microsoft Visual Studio Code that includes syntax highlighting and the Solidity compiler.
@@ -82,6 +100,8 @@ Discontinued:
* `Mix IDE <https://github.com/ethereum/mix/>`_
Qt based IDE for designing, debugging and testing solidity smart contracts.
+* `Ethereum Studio <https://live.ether.camp/>`_
+ Specialized web IDE that also provides shell access to a complete Ethereum environment.
Solidity Tools
--------------
@@ -129,8 +149,6 @@ If you still have questions, you can try searching or asking on the
site, or come to our `gitter channel <https://gitter.im/ethereum/solidity/>`_.
Ideas for improving Solidity or this documentation are always welcome!
-See also `Russian version (русский перевод) <https://github.com/ethereum/wiki/wiki/%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity>`_.
-
Contents
========
@@ -145,7 +163,9 @@ Contents
solidity-in-depth.rst
security-considerations.rst
using-the-compiler.rst
+ metadata.rst
abi-spec.rst
+ julia.rst
style-guide.rst
common-patterns.rst
bugs.rst
diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst
index 08160dad..8f30f199 100644
--- a/docs/installing-solidity.rst
+++ b/docs/installing-solidity.rst
@@ -2,9 +2,9 @@
.. _installing-solidity:
-###################
-Installing Solidity
-###################
+################################
+Installing the Solidity Compiler
+################################
Versioning
==========
@@ -18,30 +18,38 @@ will use the latest release.
Remix
=====
-If you just want to try Solidity for small contracts, you
-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.
+*We recommend Remix for small contracts and for quickly learning Solidity.*
+
+`Access Remix online <https://remix.ethereum.org/>`_, you don't need to install anything.
+If you want to use it without connection to the Internet, go to
+https://github.com/ethereum/browser-solidity/tree/gh-pages and download the .ZIP file as
+explained on that page.
+
+Further options on this page detail installing commandline Solidity compiler software
+on your computer. Choose a commandline compiler if you are working on a larger contract
+or if you require more compilation options.
npm / Node.js
=============
-This is probably the most portable and most convenient way to install Solidity locally.
+Use `npm` for a convenient and portable way to install `solcjs`, a Solidity compiler. The
+`solcjs` program has less features than all options further down this page. Our
+`Using the compiler <using-the-compiler.html>` documentation assumes you are using
+the full-featured compiler, `solc`. So if you install `solcjs` from `npm` then you will
+stop reading the documentation here and then continue to <https://github.com/ethereum/solc-js>,
-A platform-independent JavaScript library is provided by compiling the C++ source
-into JavaScript using Emscripten. It can be used in projects directly (such as Remix).
+Note: The `solc-js <https://github.com/ethereum/solc-js>` project is derived from the C++
+`solc` by using Emscripten. `solc-js` can be used in JavaScript projects directly (such as Remix).
Please refer to the `solc-js <https://github.com/ethereum/solc-js>`_ repository for instructions.
-It also contains a commandline tool called `solcjs`, which can be installed via npm:
-
.. code:: bash
npm install -g solc
.. note::
+ The commandline is named `solcjs`.
+
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`.
@@ -56,14 +64,14 @@ repository contains potentially unstable changes in the develop branch.
docker run ethereum/solc:stable solc --version
-Currenty, the docker image only contains the compiler executable,
+Currently, the docker image only contains the compiler executable,
so you have to do some additional work to link in the source and
output directories.
Binary Packages
===============
-Binary packages of Solidity available at
+Binary packages of Solidity are available at
`solidity/releases <https://github.com/ethereum/solidity/releases>`_.
We also have PPAs for Ubuntu. For the latest stable version.
@@ -82,12 +90,24 @@ If you want to use the cutting edge developer version:
sudo add-apt-repository ppa:ethereum/ethereum-dev
sudo apt-get update
sudo apt-get install solc
+
+We are also releasing a `snap package <https://snapcraft.io/>`_, which is installable in all the `supported Linux distros <https://snapcraft.io/docs/core/install>`_. To install the latest stable version of solc:
+
+.. code:: bash
+
+ sudo snap install solc
+
+Or if you want to help testing the unstable solc with the most recent changes from the development branch:
+
+.. code:: bash
+
+ sudo snap install solc --edge
Arch Linux also has packages, albeit limited to the latest development version:
.. code:: bash
- pacman -S solidity-git
+ pacman -S solidity
Homebrew is missing pre-built bottles at the time of writing,
following a Jenkins to TravisCI migration, but Homebrew
@@ -123,7 +143,7 @@ Gentoo Linux also provides a solidity package that can be installed using ``emer
.. code:: bash
- demerge ev-lang/solidity
+ emerge dev-lang/solidity
.. _building-from-source:
@@ -218,6 +238,9 @@ Or, on Windows:
Command-Line Build
------------------
+**Be sure to install External Dependencies (see above) before build.**
+
+Solidity project uses CMake to configure the build.
Building Solidity is quite similar on Linux, macOS and other Unices:
.. code:: bash
@@ -252,6 +275,11 @@ Alternatively, you can build for Windows on the command-line, like so:
cmake --build . --config RelWithDebInfo
+CMake options
+=============
+
+If you are interested what CMake options are available run ``cmake .. -LH``.
+
The version string in detail
============================
@@ -267,7 +295,7 @@ 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 relase example: ``0.4.8+commit.60cc1668.Emscripten.clang``.
+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``
diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst
index dc7c6cc9..c297a8ad 100644
--- a/docs/introduction-to-smart-contracts.rst
+++ b/docs/introduction-to-smart-contracts.rst
@@ -21,11 +21,11 @@ Storage
contract SimpleStorage {
uint storedData;
- function set(uint x) {
+ function set(uint x) public {
storedData = x;
}
- function get() constant returns (uint) {
+ function get() public constant returns (uint) {
return storedData;
}
}
@@ -35,7 +35,7 @@ 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. 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>`_). .
+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
data (its *state*) that resides at a specific address on the Ethereum
@@ -57,6 +57,14 @@ 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
so that only you can alter the number.
+.. note::
+ All identifiers (contract names, function names and variable names) are restricted to
+ the ASCII character set. It is possible to store UTF-8 encoded data in string variables.
+
+.. warning::
+ Be careful with using Unicode text as similarly looking (or even identical) characters can
+ have different code points and as such will be encoded as a different byte array.
+
.. index:: ! subcurrency
Subcurrency Example
@@ -86,16 +94,16 @@ registering with username and password - all you need is an Ethereum keypair.
// This is the constructor whose code is
// run only when the contract is created.
- function Coin() {
+ function Coin() public {
minter = msg.sender;
}
- function mint(address receiver, uint amount) {
+ function mint(address receiver, uint amount) public {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
- function send(address receiver, uint amount) {
+ function send(address receiver, uint amount) public {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
@@ -110,9 +118,11 @@ that is publicly accessible. The ``address`` type is a 160-bit value
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.
+allows you to access the current value of the state variable
+from outside of the contract.
Without this keyword, other contracts have no way to access the variable.
-The function will look something like this::
+The code of the function generated by the compiler is roughly equivalent
+to the following::
function minter() returns (address) { return minter; }
@@ -133,11 +143,11 @@ 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 getter function created by the ``public`` keyword
+like this one. The :ref:`getter function<getter-functions>` created by the ``public`` keyword
is a bit more complex in this case. It roughly looks like the
following::
- function balances(address _account) returns (uint) {
+ function balances(address _account) public view returns (uint) {
return balances[_account];
}
diff --git a/docs/julia.rst b/docs/julia.rst
new file mode 100644
index 00000000..9e961a9d
--- /dev/null
+++ b/docs/julia.rst
@@ -0,0 +1,571 @@
+#################################################
+Joyfully Universal Language for (Inline) Assembly
+#################################################
+
+.. _julia:
+
+.. index:: ! assembly, ! asm, ! evmasm, ! julia
+
+JULIA is an intermediate language that can compile to various different backends
+(EVM 1.0, EVM 1.5 and eWASM are planned).
+Because of that, it is designed to be a usable common denominator of all three
+platforms.
+It can already be used for "inline assembly" inside Solidity and
+future versions of the Solidity compiler will even use JULIA as intermediate
+language. It should also be easy to build high-level optimizer stages for JULIA.
+
+.. note::
+
+ Note that the flavour used for "inline assembly" does not have types
+ (everything is ``u256``) and the built-in functions are identical
+ to the EVM opcodes. Please resort to the inline assembly documentation
+ for details.
+
+The core components of JULIA are functions, blocks, variables, literals,
+for-loops, if-statements, switch-statements, expressions and assignments to variables.
+
+JULIA is typed, both variables and literals must specify the type with postfix
+notation. The supported types are ``bool``, ``u8``, ``s8``, ``u32``, ``s32``,
+``u64``, ``s64``, ``u128``, ``s128``, ``u256`` and ``s256``.
+
+JULIA in itself does not even provide operators. If the EVM is targeted,
+opcodes will be available as built-in functions, but they can be reimplemented
+if the backend changes. For a list of mandatory built-in functions, see the section below.
+
+The following example program assumes that the EVM opcodes ``mul``, ``div``
+and ``mod`` are available either natively or as functions and computes exponentiation.
+
+.. code::
+
+ {
+ function power(base:u256, exponent:u256) -> result:u256
+ {
+ switch exponent
+ case 0:u256 { result := 1:u256 }
+ case 1:u256 { result := base }
+ default:
+ {
+ result := power(mul(base, base), div(exponent, 2:u256))
+ switch mod(exponent, 2:u256)
+ case 1:u256 { result := mul(base, result) }
+ }
+ }
+ }
+
+It is also possible to implement the same function using a for-loop
+instead of with recursion. Here, we need the EVM opcodes ``lt`` (less-than)
+and ``add`` to be available.
+
+.. code::
+
+ {
+ function power(base:u256, exponent:u256) -> result:u256
+ {
+ result := 1:u256
+ for { let i := 0:u256 } lt(i, exponent) { i := add(i, 1:u256) }
+ {
+ result := mul(result, base)
+ }
+ }
+ }
+
+Specification of JULIA
+======================
+
+JULIA code is described in this chapter. JULIA code is usually placed into a JULIA object, which is described in the following chapter.
+
+Grammar::
+
+ Block = '{' Statement* '}'
+ Statement =
+ Block |
+ FunctionDefinition |
+ VariableDeclaration |
+ Assignment |
+ Expression |
+ Switch |
+ ForLoop |
+ BreakContinue
+ FunctionDefinition =
+ 'function' Identifier '(' TypedIdentifierList? ')'
+ ( '->' TypedIdentifierList )? Block
+ VariableDeclaration =
+ 'let' TypedIdentifierList ( ':=' Expression )?
+ Assignment =
+ IdentifierList ':=' Expression
+ Expression =
+ FunctionCall | Identifier | Literal
+ If =
+ 'if' Expression Block
+ Switch =
+ 'switch' Expression Case* ( 'default' Block )?
+ Case =
+ 'case' Literal Block
+ ForLoop =
+ 'for' Block Expression Block Block
+ BreakContinue =
+ 'break' | 'continue'
+ FunctionCall =
+ Identifier '(' ( Expression ( ',' Expression )* )? ')'
+ Identifier = [a-zA-Z_$] [a-zA-Z_0-9]*
+ IdentifierList = Identifier ( ',' Identifier)*
+ TypeName = Identifier | BuiltinTypeName
+ BuiltinTypeName = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )
+ TypedIdentifierList = Identifier ':' TypeName ( ',' Identifier ':' TypeName )*
+ Literal =
+ (NumberLiteral | StringLiteral | HexLiteral | TrueLiteral | FalseLiteral) ':' TypeName
+ NumberLiteral = HexNumber | DecimalNumber
+ HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
+ StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
+ TrueLiteral = 'true'
+ FalseLiteral = 'false'
+ HexNumber = '0x' [0-9a-fA-F]+
+ DecimalNumber = [0-9]+
+
+Restrictions on the Grammar
+---------------------------
+
+Switches must have at least one case (including the default case).
+If all possible values of the expression is covered, the default case should
+not be allowed (i.e. a switch with a ``bool`` expression and having both a
+true and false case should not allow a default case).
+
+Every expression evaluates to zero or more values. Identifiers and Literals
+evaluate to exactly
+one value and function calls evaluate to a number of values equal to the
+number of return values of the function called.
+
+In variable declarations and assignments, the right-hand-side expression
+(if present) has to evaluate to a number of values equal to the number of
+variables on the left-hand-side.
+This is the only situation where an expression evaluating
+to more than one value is allowed.
+
+Expressions that are also statements (i.e. at the block level) have to
+evaluate to zero values.
+
+In all other situations, expressions have to evaluate to exactly one value.
+
+The ``continue`` and ``break`` statements can only be used inside loop bodies
+and have to be in the same function as the loop (or both have to be at the
+top level).
+The condition part of the for-loop has to evaluate to exactly one value.
+
+Literals cannot be larger than the their type. The largest type defined is 256-bit wide.
+
+Scoping Rules
+-------------
+
+Scopes in JULIA are tied to Blocks (exceptions are functions and the for loop
+as explained below) and all declarations
+(``FunctionDefinition``, ``VariableDeclaration``)
+introduce new identifiers into these scopes.
+
+Identifiers are visible in
+the block they are defined in (including all sub-nodes and sub-blocks).
+As an exception, identifiers defined in the "init" part of the for-loop
+(the first block) are visible in all other parts of the for-loop
+(but not outside of the loop).
+Identifiers declared in the other parts of the for loop respect the regular
+syntatical scoping rules.
+The parameters and return parameters of functions are visible in the
+function body and their names cannot overlap.
+
+Variables can only be referenced after their declaration. In particular,
+variables cannot be referenced in the right hand side of their own variable
+declaration.
+Functions can be referenced already before their declaration (if they are visible).
+
+Shadowing is disallowed, i.e. you cannot declare an identifier at a point
+where another identifier with the same name is also visible, even if it is
+not accessible.
+
+Inside functions, it is not possible to access a variable that was declared
+outside of that function.
+
+Formal Specification
+--------------------
+
+We formally specify JULIA by providing an evaluation function E overloaded
+on the various nodes of the AST. Any functions can have side effects, so
+E takes two state objects and the AST node and returns two new
+state objects and a variable number of other values.
+The two state objects are the global state object
+(which in the context of the EVM is the memory, storage and state of the
+blockchain) and the local state object (the state of local variables, i.e. a
+segment of the stack in the EVM).
+If the AST node is a statement, E returns the two state objects and a "mode",
+which is used for the ``break`` and ``continue`` statements.
+If the AST node is an expression, E returns the two state objects and
+as many values as the expression evaluates to.
+
+
+The exact nature of the global state is unspecified for this high level
+description. The local state ``L`` is a mapping of identifiers ``i`` to values ``v``,
+denoted as ``L[i] = v``.
+
+For an identifier ``v``, let ``$v`` be the name of the identifier.
+
+We will use a destructuring notation for the AST nodes.
+
+.. code::
+
+ E(G, L, <{St1, ..., Stn}>: Block) =
+ let G1, L1, mode = E(G, L, St1, ..., Stn)
+ let L2 be a restriction of L1 to the identifiers of L
+ G1, L2, mode
+ E(G, L, St1, ..., Stn: Statement) =
+ if n is zero:
+ G, L, regular
+ else:
+ let G1, L1, mode = E(G, L, St1)
+ if mode is regular then
+ E(G1, L1, St2, ..., Stn)
+ otherwise
+ G1, L1, mode
+ E(G, L, FunctionDefinition) =
+ G, L, regular
+ E(G, L, <let var1, ..., varn := rhs>: VariableDeclaration) =
+ E(G, L, <var1, ..., varn := rhs>: Assignment)
+ E(G, L, <let var1, ..., varn>: VariableDeclaration) =
+ let L1 be a copy of L where L1[$vari] = 0 for i = 1, ..., n
+ G, L1, regular
+ E(G, L, <var1, ..., varn := rhs>: Assignment) =
+ let G1, L1, v1, ..., vn = E(G, L, rhs)
+ let L2 be a copy of L1 where L2[$vari] = vi for i = 1, ..., n
+ G, L2, regular
+ E(G, L, <for { i1, ..., in } condition post body>: ForLoop) =
+ if n >= 1:
+ let G1, L1, mode = E(G, L, i1, ..., in)
+ // mode has to be regular due to the syntactic restrictions
+ let G2, L2, mode = E(G1, L1, for {} condition post body)
+ // mode has to be regular due to the syntactic restrictions
+ let L3 be the restriction of L2 to only variables of L
+ G2, L3, regular
+ else:
+ let G1, L1, v = E(G, L, condition)
+ if v is false:
+ G1, L1, regular
+ else:
+ let G2, L2, mode = E(G1, L, body)
+ if mode is break:
+ G2, L2, regular
+ else:
+ G3, L3, mode = E(G2, L2, post)
+ E(G3, L3, for {} condition post body)
+ E(G, L, break: BreakContinue) =
+ G, L, break
+ E(G, L, continue: BreakContinue) =
+ G, L, continue
+ E(G, L, <if condition body>: If) =
+ let G0, L0, v = E(G, L, condition)
+ if v is true:
+ E(G0, L0, body)
+ else:
+ G0, L0, regular
+ E(G, L, <switch condition case l1:t1 st1 ... case ln:tn stn>: Switch) =
+ E(G, L, switch condition case l1:t1 st1 ... case ln:tn stn default {})
+ E(G, L, <switch condition case l1:t1 st1 ... case ln:tn stn default st'>: Switch) =
+ let G0, L0, v = E(G, L, condition)
+ // i = 1 .. n
+ // Evaluate literals, context doesn't matter
+ let _, _, v1 = E(G0, L0, l1)
+ ...
+ let _, _, vn = E(G0, L0, ln)
+ if there exists smallest i such that vi = v:
+ E(G0, L0, sti)
+ else:
+ E(G0, L0, st')
+
+ E(G, L, <name>: Identifier) =
+ G, L, L[$name]
+ E(G, L, <fname(arg1, ..., argn)>: FunctionCall) =
+ G1, L1, vn = E(G, L, argn)
+ ...
+ G(n-1), L(n-1), v2 = E(G(n-2), L(n-2), arg2)
+ Gn, Ln, v1 = E(G(n-1), L(n-1), arg1)
+ Let <function fname (param1, ..., paramn) -> ret1, ..., retm block>
+ be the function of name $fname visible at the point of the call.
+ Let L' be a new local state such that
+ L'[$parami] = vi and L'[$reti] = 0 for all i.
+ Let G'', L'', mode = E(Gn, L', block)
+ G'', Ln, L''[$ret1], ..., L''[$retm]
+ E(G, L, l: HexLiteral) = G, L, hexString(l),
+ where hexString decodes l from hex and left-aligns it into 32 bytes
+ E(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l),
+ where utf8EncodeLeftAligned performs a utf8 encoding of l
+ and aligns it left into 32 bytes
+ E(G, L, n: HexNumber) = G, L, hex(n)
+ where hex is the hexadecimal decoding function
+ E(G, L, n: DecimalNumber) = G, L, dec(n),
+ where dec is the decimal decoding function
+
+Type Conversion Functions
+-------------------------
+
+JULIA has no support for implicit type conversion and therefore functions exists to provide explicit conversion.
+When converting a larger type to a shorter type a runtime exception can occur in case of an overflow.
+
+The following type conversion functions must be available:
+- ``u32tobool(x:u32) -> y:bool``
+- ``booltou32(x:bool) -> y:u32``
+- ``u32tou64(x:u32) -> y:u64``
+- ``u64tou32(x:u64) -> y:u32``
+- etc. (TBD)
+
+Low-level Functions
+-------------------
+
+The following functions must be available:
+
++---------------------------------------------------------------------------------------------------------------+
+| *Arithmetics* |
++---------------------------------------------------------------------------------------------------------------+
+| addu256(x:u256, y:u256) -> z:u256 | x + y |
++---------------------------------------------------------------------------------------------------------------+
+| subu256(x:u256, y:u256) -> z:u256 | x - y |
++---------------------------------------------------------------------------------------------------------------+
+| mulu256(x:u256, y:u256) -> z:u256 | x * y |
++---------------------------------------------------------------------------------------------------------------+
+| divu256(x:u256, y:u256) -> z:u256 | x / y |
++---------------------------------------------------------------------------------------------------------------+
+| divs256(x:s256, y:s256) -> z:s256 | x / y, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| modu256(x:u256, y:u256) -> z:u256 | x % y |
++---------------------------------------------------------------------------------------------------------------+
+| mods256(x:s256, y:s256) -> z:s256 | x % y, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| signextendu256(i:u256, x:u256) -> z:u256 | sign extend from (i*8+7)th bit counting from least significant |
++---------------------------------------------------------------------------------------------------------------+
+| expu256(x:u256, y:u256) -> z:u256 | x to the power of y |
++---------------------------------------------------------------------------------------------------------------+
+| addmodu256(x:u256, y:u256, m:u256) -> z:u256| (x + y) % m with arbitrary precision arithmetics |
++---------------------------------------------------------------------------------------------------------------+
+| mulmodu256(x:u256, y:u256, m:u256) -> z:u256| (x * y) % m with arbitrary precision arithmetics |
++---------------------------------------------------------------------------------------------------------------+
+| ltu256(x:u256, y:u256) -> z:bool | 1 if x < y, 0 otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| gtu256(x:u256, y:u256) -> z:bool | 1 if x > y, 0 otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| sltu256(x:s256, y:s256) -> z:bool | 1 if x < y, 0 otherwise, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| sgtu256(x:s256, y:s256) -> z:bool | 1 if x > y, 0 otherwise, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| equ256(x:u256, y:u256) -> z:bool | 1 if x == y, 0 otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| notu256(x:u256) -> z:u256 | ~x, every bit of x is negated |
++---------------------------------------------------------------------------------------------------------------+
+| andu256(x:u256, y:u256) -> z:u256 | bitwise and of x and y |
++---------------------------------------------------------------------------------------------------------------+
+| oru256(x:u256, y:u256) -> z:u256 | bitwise or of x and y |
++---------------------------------------------------------------------------------------------------------------+
+| xoru256(x:u256, y:u256) -> z:u256 | bitwise xor of x and y |
++---------------------------------------------------------------------------------------------------------------+
+| shlu256(x:u256, y:u256) -> z:u256 | logical left shift of x by y |
++---------------------------------------------------------------------------------------------------------------+
+| shru256(x:u256, y:u256) -> z:u256 | logical right shift of x by y |
++---------------------------------------------------------------------------------------------------------------+
+| saru256(x:u256, y:u256) -> z:u256 | arithmetic right shift of x by y |
++---------------------------------------------------------------------------------------------------------------+
+| byte(n:u256, x:u256) -> v:u256 | nth byte of x, where the most significant byte is the 0th byte |
+| Cannot this be just replaced by and256(shr256(n, x), 0xff) and let it be optimised out by the EVM backend? |
++---------------------------------------------------------------------------------------------------------------+
+| *Memory and storage* |
++---------------------------------------------------------------------------------------------------------------+
+| mload(p:u256) -> v:u256 | mem[p..(p+32)) |
++---------------------------------------------------------------------------------------------------------------+
+| mstore(p:u256, v:u256) | mem[p..(p+32)) := v |
++---------------------------------------------------------------------------------------------------------------+
+| mstore8(p:u256, v:u256) | mem[p] := v & 0xff - only modifies a single byte |
++---------------------------------------------------------------------------------------------------------------+
+| sload(p:u256) -> v:u256 | storage[p] |
++---------------------------------------------------------------------------------------------------------------+
+| sstore(p:u256, v:u256) | storage[p] := v |
++---------------------------------------------------------------------------------------------------------------+
+| msize() -> size:u256 | size of memory, i.e. largest accessed memory index, albeit due |
+| | due to the memory extension function, which extends by words, |
+| | this will always be a multiple of 32 bytes |
++---------------------------------------------------------------------------------------------------------------+
+| *Execution control* |
++---------------------------------------------------------------------------------------------------------------+
+| create(v:u256, p:u256, s:u256) | create new contract with code mem[p..(p+s)) and send v wei |
+| | and return the new address |
++---------------------------------------------------------------------------------------------------------------+
+| call(g:u256, a:u256, v:u256, in:u256, | call contract at address a with input mem[in..(in+insize)) |
+| insize:u256, out:u256, | providing g gas and v wei and output area |
+| outsize:u256) | mem[out..(out+outsize)) returning 0 on error (eg. out of gas) |
+| -> r:u256 | and 1 on success |
++---------------------------------------------------------------------------------------------------------------+
+| callcode(g:u256, a:u256, v:u256, in:u256, | identical to ``call`` but only use the code from a |
+| insize:u256, out:u256, | and stay in the context of the |
+| outsize:u256) -> r:u256 | current contract otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| delegatecall(g:u256, a:u256, in:u256, | identical to ``callcode``, |
+| insize:u256, out:u256, | but also keep ``caller`` |
+| outsize:u256) -> r:u256 | and ``callvalue`` |
++---------------------------------------------------------------------------------------------------------------+
+| stop() | stop execution, identical to return(0,0) |
+| Perhaps it would make sense retiring this as it equals to return(0,0). It can be an optimisation by the EVM |
+| backend. |
++---------------------------------------------------------------------------------------------------------------+
+| abort() | abort (equals to invalid instruction on EVM) |
++---------------------------------------------------------------------------------------------------------------+
+| return(p:u256, s:u256) | end execution, return data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| revert(p:u256, s:u256) | end execution, revert state changes, return data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| selfdestruct(a:u256) | end execution, destroy current contract and send funds to a |
++---------------------------------------------------------------------------------------------------------------+
+| log0(p:u256, s:u256) | log without topics and data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| log1(p:u256, s:u256, t1:u256) | log with topic t1 and data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| log2(p:u256, s:u256, t1:u256, t2:u256) | log with topics t1, t2 and data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| log3(p:u256, s:u256, t1:u256, t2:u256, | log with topics t, t2, t3 and data mem[p..(p+s)) |
+| t3:u256) | |
++---------------------------------------------------------------------------------------------------------------+
+| log4(p:u256, s:u256, t1:u256, t2:u256, | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) |
+| t3:u256, t4:u256) | |
++---------------------------------------------------------------------------------------------------------------+
+| *State queries* |
++---------------------------------------------------------------------------------------------------------------+
+| blockcoinbase() -> address:u256 | current mining beneficiary |
++---------------------------------------------------------------------------------------------------------------+
+| blockdifficulty() -> difficulty:u256 | difficulty of the current block |
++---------------------------------------------------------------------------------------------------------------+
+| blockgaslimit() -> limit:u256 | block gas limit of the current block |
++---------------------------------------------------------------------------------------------------------------+
+| blockhash(b:u256) -> hash:u256 | hash of block nr b - only for last 256 blocks excluding current |
++---------------------------------------------------------------------------------------------------------------+
+| blocknumber() -> block:u256 | current block number |
++---------------------------------------------------------------------------------------------------------------+
+| blocktimestamp() -> timestamp:u256 | timestamp of the current block in seconds since the epoch |
++---------------------------------------------------------------------------------------------------------------+
+| txorigin() -> address:u256 | transaction sender |
++---------------------------------------------------------------------------------------------------------------+
+| txgasprice() -> price:u256 | gas price of the transaction |
++---------------------------------------------------------------------------------------------------------------+
+| gasleft() -> gas:u256 | gas still available to execution |
++---------------------------------------------------------------------------------------------------------------+
+| balance(a:u256) -> v:u256 | wei balance at address a |
++---------------------------------------------------------------------------------------------------------------+
+| this() -> address:u256 | address of the current contract / execution context |
++---------------------------------------------------------------------------------------------------------------+
+| caller() -> address:u256 | call sender (excluding delegatecall) |
++---------------------------------------------------------------------------------------------------------------+
+| callvalue() -> v:u256 | wei sent together with the current call |
++---------------------------------------------------------------------------------------------------------------+
+| calldataload(p:u256) -> v:u256 | call data starting from position p (32 bytes) |
++---------------------------------------------------------------------------------------------------------------+
+| calldatasize() -> v:u256 | size of call data in bytes |
++---------------------------------------------------------------------------------------------------------------+
+| calldatacopy(t:u256, f:u256, s:u256) | copy s bytes from calldata at position f to mem at position t |
++---------------------------------------------------------------------------------------------------------------+
+| codesize() -> size:u256 | size of the code of the current contract / execution context |
++---------------------------------------------------------------------------------------------------------------+
+| codecopy(t:u256, f:u256, s:u256) | copy s bytes from code at position f to mem at position t |
++---------------------------------------------------------------------------------------------------------------+
+| extcodesize(a:u256) -> size:u256 | size of the code at address a |
++---------------------------------------------------------------------------------------------------------------+
+| extcodecopy(a:u256, t:u256, f:u256, s:u256) | like codecopy(t, f, s) but take code at address a |
++---------------------------------------------------------------------------------------------------------------+
+| *Others* |
++---------------------------------------------------------------------------------------------------------------+
+| discardu256(unused:u256) | discard value |
++---------------------------------------------------------------------------------------------------------------+
+| splitu256tou64(x:u256) -> (x1:u64, x2:u64, | split u256 to four u64's |
+| x3:u64, x4:u64) | |
++---------------------------------------------------------------------------------------------------------------+
+| combineu64tou256(x1:u64, x2:u64, x3:u64, | combine four u64's into a single u256 |
+| x4:u64) -> (x:u256) | |
++---------------------------------------------------------------------------------------------------------------+
+| sha3(p:u256, s:u256) -> v:u256 | keccak(mem[p...(p+s))) |
++---------------------------------------------------------------------------------------------------------------+
+
+Backends
+--------
+
+Backends or targets are the translators from JULIA to a specific bytecode. Each of the backends can expose functions
+prefixed with the name of the backend. We reserve ``evm_`` and ``ewasm_`` prefixes for the two proposed backends.
+
+Backend: EVM
+------------
+
+The EVM target will have all the underlying EVM opcodes exposed with the `evm_` prefix.
+
+Backend: "EVM 1.5"
+------------------
+
+TBD
+
+Backend: eWASM
+--------------
+
+TBD
+
+Specification of JULIA Object
+=============================
+
+Grammar::
+
+ TopLevelObject = 'object' '{' Code? ( Object | Data )* '}'
+ Object = 'object' StringLiteral '{' Code? ( Object | Data )* '}'
+ Code = 'code' Block
+ Data = 'data' StringLiteral HexLiteral
+ HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
+ StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
+
+Above, ``Block`` refers to ``Block`` in the JULIA code grammar explained in the previous chapter.
+
+An example JULIA Object is shown below:
+
+..code::
+
+ // Code consists of a single object. A single "code" node is the code of the object.
+ // Every (other) named object or data section is serialized and
+ // made accessible to the special built-in functions datacopy / dataoffset / datasize
+ object {
+ code {
+ let size = datasize("runtime")
+ let offset = allocate(size)
+ // This will turn into a memory->memory copy for eWASM and
+ // a codecopy for EVM
+ datacopy(dataoffset("runtime"), offset, size)
+ // this is a constructor and the runtime code is returned
+ return(offset, size)
+ }
+
+ data "Table2" hex"4123"
+
+ object "runtime" {
+ code {
+ // runtime code
+
+ let size = datasize("Contract2")
+ let offset = allocate(size)
+ // This will turn into a memory->memory copy for eWASM and
+ // a codecopy for EVM
+ datacopy(dataoffset("Contract2"), offset, size)
+ // constructor parameter is a single number 0x1234
+ mstore(add(offset, size), 0x1234)
+ create(offset, add(size, 32))
+ }
+
+ // Embedded object. Use case is that the outside is a factory contract,
+ // and Contract2 is the code to be created by the factory
+ object "Contract2" {
+ code {
+ // code here ...
+ }
+
+ object "runtime" {
+ code {
+ // code here ...
+ }
+ }
+
+ data "Table1" hex"4123"
+ }
+ }
+ }
diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst
index e4b403f6..f9d197b7 100644
--- a/docs/layout-of-source-files.rst
+++ b/docs/layout-of-source-files.rst
@@ -197,17 +197,16 @@ for the two input parameters and two returned values.
pragma solidity ^0.4.0;
- /** @title Shape calculator.*/
- contract shapeCalculator{
- /**@dev Calculates a rectangle's surface and perimeter.
- * @param w Width of the rectangle.
- * @param h Height of the rectangle.
- * @return s The calculated surface.
- * @return p The calculated perimeter.
- */
- function rectangle(uint w, uint h) returns (uint s, uint p) {
- s = w * h;
- p = 2 * (w + h);
- }
- }
-
+ /** @title Shape calculator. */
+ contract shapeCalculator {
+ /** @dev Calculates a rectangle's surface and perimeter.
+ * @param w Width of the rectangle.
+ * @param h Height of the rectangle.
+ * @return s The calculated surface.
+ * @return p The calculated perimeter.
+ */
+ function rectangle(uint w, uint h) returns (uint s, uint p) {
+ s = w * h;
+ p = 2 * (w + h);
+ }
+ }
diff --git a/docs/metadata.rst b/docs/metadata.rst
new file mode 100644
index 00000000..5e37219e
--- /dev/null
+++ b/docs/metadata.rst
@@ -0,0 +1,146 @@
+#################
+Contract Metadata
+#################
+
+.. index:: metadata, contract verification
+
+The Solidity compiler automatically generates a JSON file, the
+contract metadata, that contains information about the current contract.
+It can be used to query the compiler version, the sources used, the ABI
+and NatSpec documentation in order to more safely interact with the contract
+and to verify its source code.
+
+The compiler appends a Swarm hash of the metadata file to the end of the
+bytecode (for details, see below) of each contract, so that you can retrieve
+the file in an authenticated way without having to resort to a centralized
+data provider.
+
+Of course, you have to publish the metadata file to Swarm (or some other service)
+so that others can access it. The file can be output by using ``solc --metadata``
+and the file will be called ``ContractName_meta.json``.
+It will contain Swarm references to the source code, so you have to upload
+all source files and the metadata file.
+
+The metadata file has the following format. The example below is presented in a
+human-readable way. Properly formatted metadata should use quotes correctly,
+reduce whitespace to a minimum and sort the keys of all objects to arrive at a
+unique formatting.
+Comments are of course also not permitted and used here only for explanatory purposes.
+
+.. code-block:: none
+
+ {
+ // Required: The version of the metadata format
+ version: "1",
+ // Required: Source code language, basically selects a "sub-version"
+ // of the specification
+ language: "Solidity",
+ // Required: Details about the compiler, contents are specific
+ // to the language.
+ compiler: {
+ // Required for Solidity: Version of the compiler
+ version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
+ // Optional: Hash of the compiler binary which produced this output
+ keccak256: "0x123..."
+ },
+ // Required: Compilation source files/source units, keys are file names
+ sources:
+ {
+ "myFile.sol": {
+ // Required: keccak256 hash of the source file
+ "keccak256": "0x123...",
+ // 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
+ "keccak256": "0x234...",
+ // Required (unless "url" is used): literal contents of the source file
+ "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
+ }
+ },
+ // Required: Compiler settings
+ settings:
+ {
+ // Required for Solidity: Sorted list of remappings
+ remappings: [ ":g/dir" ],
+ // Optional: Optimizer settings (enabled defaults to false)
+ optimizer: {
+ enabled: true,
+ runs: 500
+ },
+ // Required for Solidity: File and name of the contract or library this
+ // metadata is created for.
+ compilationTarget: {
+ "myFile.sol": "MyContract"
+ },
+ // Required for Solidity: Addresses for libraries used
+ libraries: {
+ "MyLib": "0x123123..."
+ }
+ },
+ // Required: Generated information about the contract.
+ output:
+ {
+ // Required: ABI definition of the contract
+ abi: [ ... ],
+ // Required: NatSpec user documentation of the contract
+ userdoc: [ ... ],
+ // Required: NatSpec developer documentation of the contract
+ devdoc: [ ... ],
+ }
+ }
+
+.. 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
+=============================================
+
+Because we might support other ways to retrieve the metadata file in the future,
+the mapping ``{"bzzr0": <Swarm hash>}`` is stored
+`CBOR <https://tools.ietf.org/html/rfc7049>`_-encoded. Since the beginning of that
+encoding is not easy to find, its length is added in a two-byte big-endian
+encoding. The current version of the Solidity compiler thus adds the following
+to the end of the deployed bytecode::
+
+ 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
+
+So in order to retrieve the data, the end of the deployed bytecode can be checked
+to match that pattern and use the Swarm hash to retrieve the file.
+
+Usage for Automatic Interface Generation and NatSpec
+====================================================
+
+The metadata is used in the following way: A component that wants to interact
+with a contract (e.g. Mist) retrieves the code of the contract, from that
+the Swarm hash of a file which is then retrieved.
+That file is JSON-decoded into a structure like above.
+
+The component can then use the ABI to automatically generate a rudimentary
+user interface for the contract.
+
+Furthermore, Mist can use the userdoc to display a confirmation message to the user
+whenever they interact with the contract.
+
+Additional information about Ethereum Natural Specification (NatSpec) can be found `here <https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format>`_.
+
+Usage for Source Code Verification
+==================================
+
+In order to verify the compilation, sources can be retrieved from Swarm
+via the link in the metadata file.
+The compiler of the correct version (which is checked to be part of the "official" compilers)
+is invoked on that input with the specified settings. The resulting
+bytecode is compared to the data of the creation transaction or ``CREATE`` opcode data.
+This automatically verifies the metadata since its hash is part of the bytecode.
+Excess data corresponds to the constructor input data, which should be decoded
+according to the interface and presented to the user.
diff --git a/docs/miscellaneous.rst b/docs/miscellaneous.rst
index 2e0ccf45..328ec6ea 100644
--- a/docs/miscellaneous.rst
+++ b/docs/miscellaneous.rst
@@ -48,6 +48,8 @@ non-elementary type, the positions are found by adding an offset of ``keccak256(
So for the following contract snippet::
+ pragma solidity ^0.4.0;
+
contract C {
struct s { uint a; uint b; }
uint x;
@@ -82,10 +84,8 @@ Layout of Call Data
*******************
When a Solidity contract is deployed and when it is called from an
-account, the input data is assumed to be in the format in `the ABI
-specification
-<https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI>`_. The
-ABI specification requires arguments to be padded to multiples of 32
+account, the input data is assumed to be in the format in :ref:`the ABI
+specification <ABI>`. The ABI specification requires arguments to be padded to multiples of 32
bytes. The internal function calls use a different convention.
@@ -143,13 +143,13 @@ Different types have different rules for cleaning up invalid values:
Internals - The Optimizer
*************************
-The Solidity optimizer operates on assembly, so it can be and also is used by other languages. It splits the sequence of instructions into basic blocks at JUMPs and JUMPDESTs. Inside these blocks, the instructions are analysed and every modification to the stack, to memory or storage is recorded as an expression which consists of an instruction and a list of arguments which are essentially pointers to other expressions. The main idea is now to find expressions that are always equal (on every input) and combine them into an expression class. The optimizer first tries to find each new expression in a list of already known expressions. If this does not work, the expression is simplified according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is done recursively, we can also apply the latter rule if the second factor is a more complex expression where we know that it will always evaluate to one. Modifications to storage and memory locations have to erase knowledge about storage and memory locations which are not known to be different: If we first write to location x and then to location y and both are input variables, the second could overwrite the first, so we actually do not know what is stored at x after we wrote to y. On the other hand, if a simplification of the expression x - y evaluates to a non-zero constant, we know that we can keep our knowledge about what is stored at x.
+The Solidity optimizer operates on assembly, so it can be and also is used by other languages. It splits the sequence of instructions into basic blocks at ``JUMPs`` and ``JUMPDESTs``. Inside these blocks, the instructions are analysed and every modification to the stack, to memory or storage is recorded as an expression which consists of an instruction and a list of arguments which are essentially pointers to other expressions. The main idea is now to find expressions that are always equal (on every input) and combine them into an expression class. The optimizer first tries to find each new expression in a list of already known expressions. If this does not work, the expression is simplified according to rules like ``constant + constant = sum_of_constants`` or ``X * 1 = X``. Since this is done recursively, we can also apply the latter rule if the second factor is a more complex expression where we know that it will always evaluate to one. Modifications to storage and memory locations have to erase knowledge about storage and memory locations which are not known to be different: If we first write to location x and then to location y and both are input variables, the second could overwrite the first, so we actually do not know what is stored at x after we wrote to y. On the other hand, if a simplification of the expression x - y evaluates to a non-zero constant, we know that we can keep our knowledge about what is stored at x.
-At the end of this process, we know which expressions have to be on the stack in the end and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all JUMP and JUMPI instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown JUMP. If a JUMPI is found whose condition evaluates to a constant, it is transformed to an unconditional jump.
+At the end of this process, we know which expressions have to be on the stack in the end and have a list of modifications to memory and storage. This information is stored together with the basic blocks and is used to link them. Furthermore, knowledge about the stack, storage and memory configuration is forwarded to the next block(s). If we know the targets of all ``JUMP`` and ``JUMPI`` instructions, we can build a complete control flow graph of the program. If there is only one target we do not know (this can happen as in principle, jump targets can be computed from inputs), we have to erase all knowledge about the input state of a block as it can be the target of the unknown ``JUMP``. If a ``JUMPI`` is found whose condition evaluates to a constant, it is transformed to an unconditional jump.
As the last step, the code in each block is completely re-generated. A dependency graph is created from the expressions on the stack at the end of the block and every operation that is not part of this graph is essentially dropped. Now code is generated that applies the modifications to memory and storage in the order they were made in the original code (dropping modifications which were found not to be needed) and finally, generates all values that are required to be on the stack in the correct place.
-These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a JUMPI and during the analysis, the condition evaluates to a constant, the JUMPI is replaced depending on the value of the constant, and thus code like
+These steps are applied to each basic block and the newly generated code is used as replacement if it is smaller. If a basic block is split at a ``JUMPI`` and during the analysis, the condition evaluates to a constant, the ``JUMPI`` is replaced depending on the value of the constant, and thus code like
::
@@ -221,156 +221,12 @@ This means the following source mappings represent the same information:
``1:2:1;:9;2::2;;``
-*****************
-Contract Metadata
-*****************
-
-The Solidity compiler automatically generates a JSON file, the
-contract metadata, that contains information about the current contract.
-It can be used to query the compiler version, the sources used, the ABI
-and NatSpec documentation in order to more safely interact with the contract
-and to verify its source code.
-
-The compiler appends a Swarm hash of the metadata file to the end of the
-bytecode (for details, see below) of each contract, so that you can retrieve
-the file in an authenticated way without having to resort to a centralized
-data provider.
-
-Of course, you have to publish the metadata file to Swarm (or some other service)
-so that others can access it. The file can be output by using ``solc --metadata``
-and the file will be called ``ContractName_meta.json``.
-It will contain Swarm references to the source code, so you have to upload
-all source files and the metadata file.
-
-The metadata file has the following format. The example below is presented in a
-human-readable way. Properly formatted metadata should use quotes correctly,
-reduce whitespace to a minimum and sort the keys of all objects to arrive at a
-unique formatting.
-Comments are of course also not permitted and used here only for explanatory purposes.
-
-.. code-block:: none
-
- {
- // Required: The version of the metadata format
- version: "1",
- // Required: Source code language, basically selects a "sub-version"
- // of the specification
- language: "Solidity",
- // Required: Details about the compiler, contents are specific
- // to the language.
- compiler: {
- // Required for Solidity: Version of the compiler
- version: "0.4.6+commit.2dabbdf0.Emscripten.clang",
- // Optional: Hash of the compiler binary which produced this output
- keccak256: "0x123..."
- },
- // Required: Compilation source files/source units, keys are file names
- sources:
- {
- "myFile.sol": {
- // Required: keccak256 hash of the source file
- "keccak256": "0x123...",
- // 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
- "keccak256": "0x234...",
- // Required (unless "url" is used): literal contents of the source file
- "content": "contract mortal is owned { function kill() { if (msg.sender == owner) selfdestruct(owner); } }"
- }
- },
- // Required: Compiler settings
- settings:
- {
- // Required for Solidity: Sorted list of remappings
- remappings: [ ":g/dir" ],
- // Optional: Optimizer settings (enabled defaults to false)
- optimizer: {
- enabled: true,
- runs: 500
- },
- // Required for Solidity: File and name of the contract or library this
- // metadata is created for.
- compilationTarget: {
- "myFile.sol": "MyContract"
- },
- // Required for Solidity: Addresses for libraries used
- libraries: {
- "MyLib": "0x123123..."
- }
- },
- // Required: Generated information about the contract.
- output:
- {
- // Required: ABI definition of the contract
- abi: [ ... ],
- // Required: NatSpec user documentation of the contract
- userdoc: [ ... ],
- // Required: NatSpec developer documentation of the contract
- devdoc: [ ... ],
- }
- }
-
-.. 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
-=============================================
-
-Because we might support other ways to retrieve the metadata file in the future,
-the mapping ``{"bzzr0": <Swarm hash>}`` is stored
-[CBOR](https://tools.ietf.org/html/rfc7049)-encoded. Since the beginning of that
-encoding is not easy to find, its length is added in a two-byte big-endian
-encoding. The current version of the Solidity compiler thus adds the following
-to the end of the deployed bytecode::
-
- 0xa1 0x65 'b' 'z' 'z' 'r' '0' 0x58 0x20 <32 bytes swarm hash> 0x00 0x29
-
-So in order to retrieve the data, the end of the deployed bytecode can be checked
-to match that pattern and use the Swarm hash to retrieve the file.
-
-Usage for Automatic Interface Generation and NatSpec
-====================================================
-
-The metadata is used in the following way: A component that wants to interact
-with a contract (e.g. Mist) retrieves the code of the contract, from that
-the Swarm hash of a file which is then retrieved.
-That file is JSON-decoded into a structure like above.
-
-The component can then use the ABI to automatically generate a rudimentary
-user interface for the contract.
-
-Furthermore, Mist can use the userdoc to display a confirmation message to the user
-whenever they interact with the contract.
-
-Usage for Source Code Verification
-==================================
-
-In order to verify the compilation, sources can be retrieved from Swarm
-via the link in the metadata file.
-The compiler of the correct version (which is checked to be part of the "official" compilers)
-is invoked on that input with the specified settings. The resulting
-bytecode is compared to the data of the creation transaction or CREATE opcode data.
-This automatically verifies the metadata since its hash is part of the bytecode.
-Excess data corresponds to the constructor input data, which should be decoded
-according to the interface and presented to the user.
-
-
***************
Tips and Tricks
***************
* Use ``delete`` on arrays to delete all its elements.
-* Use shorter types for struct elements and sort them such that short types are grouped together. This can lower the gas costs as multiple SSTORE operations might be combined into a single (SSTORE costs 5000 or 20000 gas, so this is what you want to optimise). Use the gas price estimator (with optimiser enabled) to check!
+* Use shorter types for struct elements and sort them such that short types are grouped together. This can lower the gas costs as multiple ``SSTORE`` operations might be combined into a single (``SSTORE`` costs 5000 or 20000 gas, so this is what you want to optimise). Use the gas price estimator (with optimiser enabled) to check!
* Make your state variables public - the compiler will create :ref:`getters <visibility-and-getters>` for you automatically.
* If you end up checking conditions on input or state a lot at the beginning of your functions, try using :ref:`modifiers`.
* If your contract has a function called ``send`` but you want to use the built-in send-function, use ``address(contractVariable).send(amount)``.
@@ -394,12 +250,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 | ``++``, ``--`` |
@@ -462,18 +320,19 @@ Global Variables
- ``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)
+- ``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
-- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the (tightly packed) arguments
+- ``keccak256(...) returns (bytes32)``: compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
+- ``sha3(...) returns (bytes32)``: an alias to ``keccak256``
+- ``sha256(...) returns (bytes32)``: compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
+- ``ripemd160(...) returns (bytes20)``: compute the RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
- ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error
-- ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``
-- ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``
+- ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0.
+- ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0.
- ``this`` (current contract's type): the current contract, explicitly convertible to ``address``
- ``super``: the contract one level higher in the inheritance hierarchy
- ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address
+- ``suicide(address recipient)``: an alias to ``selfdestruct``
- ``<address>.balance`` (``uint256``): balance of the :ref:`address` in Wei
- ``<address>.send(uint256 amount) returns (bool)``: send given amount of Wei to :ref:`address`, returns ``false`` on failure
- ``<address>.transfer(uint256 amount)``: send given amount of Wei to :ref:`address`, throws on failure
@@ -489,30 +348,32 @@ Function Visibility Specifiers
return true;
}
-- ``public``: visible externally and internally (creates getter function for storage/state variables)
+- ``public``: visible externally and internally (creates a :ref:`getter function<getter-functions>` 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
-.. index:: modifiers, constant, anonymous, indexed
+.. index:: modifiers, pure, view, payable, constant, anonymous, indexed
Modifiers
=========
+- ``pure`` for functions: Disallows modification or access of state - this is not enforced yet.
+- ``view`` for functions: Disallows modification of state - this is not enforced yet.
+- ``payable`` for functions: Allows them to receive Ether together with a call.
- ``constant`` for state variables: Disallows assignment (except initialisation), does not occupy storage slot.
-- ``constant`` for functions: Disallows modification of state - this is not enforced yet.
+- ``constant`` for functions: Same as ``view``.
- ``anonymous`` for events: Does not store event signature as topic.
- ``indexed`` for event parameters: Stores the parameter as topic.
-- ``payable`` for functions: Allows them to receive Ether together with a call.
Reserved Keywords
=================
These keywords are reserved in Solidity. They might become part of the syntax in the future:
-``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``interface``, ``let``, ``match``, ``null``,
-``of``, ``pure``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``, ``view``.
+``abstract``, ``after``, ``case``, ``catch``, ``default``, ``final``, ``in``, ``inline``, ``let``, ``match``, ``null``,
+``of``, ``relocatable``, ``static``, ``switch``, ``try``, ``type``, ``typeof``.
Language Grammar
================
diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst
index 33c613d8..49fd7ea4 100644
--- a/docs/security-considerations.rst
+++ b/docs/security-considerations.rst
@@ -14,7 +14,7 @@ the source code is often available.
Of course you always have to consider how much is at stake:
You can compare a smart contract with a web service that is open to the
-public (and thus, also to malicous actors) and perhaps even open source.
+public (and thus, also to malicious actors) and perhaps even open source.
If you only store your grocery list on that web service, you might not have
to take too much care, but if you manage your bank account using that web service,
you should be more careful.
@@ -55,42 +55,59 @@ complete contract):
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- // THIS CONTRACT CONTAINS A BUG - DO NOT USE
- contract Fund {
- /// Mapping of ether shares of the contract.
- mapping(address => uint) shares;
- /// Withdraw your share.
- function withdraw() {
- if (msg.sender.send(shares[msg.sender]))
- shares[msg.sender] = 0;
- }
- }
+ // THIS CONTRACT CONTAINS A BUG - DO NOT USE
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() public {
+ if (msg.sender.send(shares[msg.sender]))
+ shares[msg.sender] = 0;
+ }
+ }
The problem is not too serious here because of the limited gas as part
-of ``send``, but it still exposes a weakness: Ether transfer always
-includes code execution, so the recipient could be a contract that calls
+of ``send``, but it still exposes a weakness: Ether transfer can always
+include code execution, so the recipient could be a contract that calls
back into ``withdraw``. This would let it get multiple refunds and
-basically retrieve all the Ether in the contract.
+basically retrieve all the Ether in the contract. In particular, the
+following contract will allow an attacker to refund multiple times
+as it uses ``call`` which forwards all remaining gas by default:
+
+::
+
+ pragma solidity ^0.4.0;
+
+ // THIS CONTRACT CONTAINS A BUG - DO NOT USE
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() public {
+ if (msg.sender.call.value(shares[msg.sender])())
+ shares[msg.sender] = 0;
+ }
+ }
To avoid re-entrancy, you can use the Checks-Effects-Interactions pattern as
outlined further below:
::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.11;
- contract Fund {
- /// Mapping of ether shares of the contract.
- mapping(address => uint) shares;
- /// Withdraw your share.
- function withdraw() {
- var share = shares[msg.sender];
- shares[msg.sender] = 0;
- msg.sender.transfer(share);
- }
- }
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() public {
+ var share = shares[msg.sender];
+ shares[msg.sender] = 0;
+ msg.sender.transfer(share);
+ }
+ }
Note that re-entrancy is not only an effect of Ether transfer but of any
function call on another contract. Furthermore, you also have to take
@@ -113,7 +130,7 @@ Sending and Receiving Ether
- Neither contracts nor "external accounts" are currently able to prevent that someone sends them Ether.
Contracts can react on and reject a regular transfer, but there are ways
to move Ether without creating a message call. One way is to simply "mine to"
- the contract address and the second way is using ``selfdestruct(x)``.
+ the contract address and the second way is using ``selfdestruct(x)``.
- If a contract receives Ether (without a function being called), the fallback function is executed.
If it does not have a fallback function, the Ether will be rejected (by throwing an exception).
@@ -169,11 +186,11 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like
contract TxUserWallet {
address owner;
- function TxUserWallet() {
+ function TxUserWallet() public {
owner = msg.sender;
}
- function transferTo(address dest, uint amount) {
+ function transferTo(address dest, uint amount) public {
require(tx.origin == owner);
dest.transfer(amount);
}
@@ -183,16 +200,20 @@ Now someone tricks you into sending ether to the address of this attack wallet:
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.11;
+
+ interface TxUserWallet {
+ function transferTo(address dest, uint amount) public;
+ }
contract TxAttackWallet {
address owner;
- function TxAttackWallet() {
+ function TxAttackWallet() public {
owner = msg.sender;
}
- function() {
+ function() public {
TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
}
}
@@ -278,8 +299,7 @@ Formal Verification
Using formal verification, it is possible to perform an automated mathematical
proof that your source code fulfills a certain formal specification.
The specification is still formal (just as the source code), but usually much
-simpler. There is a prototype in Solidity that performs formal verification and
-it will be better documented soon.
+simpler.
Note that formal verification itself can only help you understand the
difference between what you did (the specification) and how you did it
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 993e2c18..b663083c 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -36,7 +36,7 @@ of votes.
::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.16;
/// @title Voting with delegation.
contract Ballot {
@@ -66,7 +66,7 @@ of votes.
Proposal[] public proposals;
/// Create a new ballot to choose one of `proposalNames`.
- function Ballot(bytes32[] proposalNames) {
+ function Ballot(bytes32[] proposalNames) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
@@ -86,7 +86,7 @@ of votes.
// Give `voter` the right to vote on this ballot.
// May only be called by `chairperson`.
- function giveRightToVote(address voter) {
+ function giveRightToVote(address voter) public {
// If the argument of `require` evaluates to `false`,
// it terminates and reverts all changes to
// the state and to Ether balances. It is often
@@ -94,14 +94,14 @@ of votes.
// 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);
+ require((msg.sender == chairperson) && !voters[voter].voted && (voters[voter].weight == 0));
voters[voter].weight = 1;
}
/// Delegate your vote to the voter `to`.
- function delegate(address to) {
+ function delegate(address to) public {
// assigns reference
- Voter sender = voters[msg.sender];
+ Voter storage sender = voters[msg.sender];
require(!sender.voted);
// Self-delegation is not allowed.
@@ -126,7 +126,7 @@ of votes.
// modifies `voters[msg.sender].voted`
sender.voted = true;
sender.delegate = to;
- Voter delegate = voters[to];
+ Voter storage delegate = voters[to];
if (delegate.voted) {
// If the delegate already voted,
// directly add to the number of votes
@@ -140,8 +140,8 @@ of votes.
/// Give your vote (including votes delegated to you)
/// to proposal `proposals[proposal].name`.
- function vote(uint proposal) {
- Voter sender = voters[msg.sender];
+ function vote(uint proposal) public {
+ Voter storage sender = voters[msg.sender];
require(!sender.voted);
sender.voted = true;
sender.vote = proposal;
@@ -154,7 +154,7 @@ of votes.
/// @dev Computes the winning proposal taking all
/// previous votes into account.
- function winningProposal() constant
+ function winningProposal() public view
returns (uint winningProposal)
{
uint winningVoteCount = 0;
@@ -165,11 +165,11 @@ 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
- function winnerName() constant
+ function winnerName() public view
returns (bytes32 winnerName)
{
winnerName = proposals[winningProposal()].name;
@@ -221,8 +221,7 @@ activate themselves.
// absolute unix timestamps (seconds since 1970-01-01)
// or time periods in seconds.
address public beneficiary;
- uint public auctionStart;
- uint public biddingTime;
+ uint public auctionEnd;
// Current state of the auction.
address public highestBidder;
@@ -249,17 +248,16 @@ activate themselves.
function SimpleAuction(
uint _biddingTime,
address _beneficiary
- ) {
+ ) public {
beneficiary = _beneficiary;
- auctionStart = now;
- biddingTime = _biddingTime;
+ auctionEnd = now + _biddingTime;
}
/// Bid on the auction with the value sent
/// together with this transaction.
/// The value will only be refunded if the
/// auction is not won.
- function bid() payable {
+ function bid() public payable {
// No arguments are necessary, all
// information is already part of
// the transaction. The keyword payable
@@ -268,18 +266,18 @@ activate themselves.
// Revert the call if the bidding
// period is over.
- require(now <= (auctionStart + biddingTime));
+ require(now <= auctionEnd);
// 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 recipients withdraw their money themselves.
+ // because it could execute an untrusted contract.
+ // It is always safer to let the recipients
+ // withdraw their money themselves.
pendingReturns[highestBidder] += highestBid;
}
highestBidder = msg.sender;
@@ -288,15 +286,15 @@ activate themselves.
}
/// Withdraw a bid that was overbid.
- function withdraw() returns (bool) {
- var amount = pendingReturns[msg.sender];
+ function withdraw() public returns (bool) {
+ uint amount = pendingReturns[msg.sender];
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
// before `send` returns.
pendingReturns[msg.sender] = 0;
- if (!msg.sender.send(amount)) {
+ if (!msg.sender.send(amount)) {
// No need to call throw here, just reset the amount owing
pendingReturns[msg.sender] = amount;
return false;
@@ -307,7 +305,7 @@ activate themselves.
/// End the auction and send the highest bid
/// to the beneficiary.
- function auctionEnd() {
+ function auctionEnd() public {
// It is a good guideline to structure functions that interact
// with other contracts (i.e. they call functions or send Ether)
// into three phases:
@@ -322,7 +320,7 @@ activate themselves.
// external contracts.
// 1. Conditions
- require(now >= (auctionStart + biddingTime)); // auction did not yet end
+ require(now >= auctionEnd); // auction did not yet end
require(!ended); // this function has already been called
// 2. Effects
@@ -362,8 +360,8 @@ together with the bid. Since value transfers cannot
be blinded in Ethereum, anyone can see the value.
The following contract solves this problem by
-accepting any value that is at least as large as
-the bid. Since this can of course only be checked during
+accepting any value that is larger than the highest
+bid. Since this can of course only be checked during
the reveal phase, some bids might be **invalid**, and
this is on purpose (it even provides an explicit
flag to place invalid bids with high value transfers):
@@ -382,7 +380,6 @@ high or low invalid bids.
}
address public beneficiary;
- uint public auctionStart;
uint public biddingEnd;
uint public revealEnd;
bool public ended;
@@ -408,9 +405,8 @@ high or low invalid bids.
uint _biddingTime,
uint _revealTime,
address _beneficiary
- ) {
+ ) public {
beneficiary = _beneficiary;
- auctionStart = now;
biddingEnd = now + _biddingTime;
revealEnd = biddingEnd + _revealTime;
}
@@ -425,6 +421,7 @@ high or low invalid bids.
/// still make the required deposit. The same address can
/// place multiple bids.
function bid(bytes32 _blindedBid)
+ public
payable
onlyBefore(biddingEnd)
{
@@ -442,6 +439,7 @@ high or low invalid bids.
bool[] _fake,
bytes32[] _secret
)
+ public
onlyAfter(biddingEnd)
onlyBefore(revealEnd)
{
@@ -467,7 +465,7 @@ high or low invalid bids.
}
// Make it impossible for the sender to re-claim
// the same deposit.
- bid.blindedBid = 0;
+ bid.blindedBid = bytes32(0);
}
msg.sender.transfer(refund);
}
@@ -491,38 +489,33 @@ high or low invalid bids.
}
/// Withdraw a bid that was overbid.
- function withdraw() returns (bool) {
- var amount = pendingReturns[msg.sender];
+ function withdraw() public {
+ uint amount = pendingReturns[msg.sender];
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
- // before `send` returns (see the remark above about
+ // before `transfer` returns (see the remark above about
// conditions -> effects -> interaction).
pendingReturns[msg.sender] = 0;
- if (!msg.sender.send(amount)){
- // No need to call throw here, just reset the amount owing
- pendingReturns[msg.sender] = amount;
- return false;
- }
+ msg.sender.transfer(amount);
}
- return true;
}
/// End the auction and send the highest bid
/// to the beneficiary.
function auctionEnd()
+ public
onlyAfter(revealEnd)
{
require(!ended);
AuctionEnded(highestBidder, highestBid);
ended = true;
- // We send all the money we have, because some
- // of the refunds might have failed.
- beneficiary.transfer(this.balance);
+ beneficiary.transfer(highestBid);
}
}
+
.. index:: purchase, remote purchase, escrow
********************
@@ -540,7 +533,10 @@ Safe Remote Purchase
enum State { Created, Locked, Inactive }
State public state;
- function Purchase() payable {
+ // Ensure that `msg.value` is an even number.
+ // Division will truncate if it is an odd number.
+ // Check via multiplication that it wasn't an odd number.
+ function Purchase() public payable {
seller = msg.sender;
value = msg.value / 2;
require((2 * value) == msg.value);
@@ -574,6 +570,7 @@ Safe Remote Purchase
/// Can only be called by the seller before
/// the contract is locked.
function abort()
+ public
onlySeller
inState(State.Created)
{
@@ -587,6 +584,7 @@ Safe Remote Purchase
/// The ether will be locked until confirmReceived
/// is called.
function confirmPurchase()
+ public
inState(State.Created)
condition(msg.value == (2 * value))
payable
@@ -599,6 +597,7 @@ Safe Remote Purchase
/// Confirm that you (the buyer) received the item.
/// This will release the locked ether.
function confirmReceived()
+ public
onlyBuyer
inState(State.Locked)
{
diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst
index 224eb368..a9a7ed52 100644
--- a/docs/structure-of-a-contract.rst
+++ b/docs/structure-of-a-contract.rst
@@ -8,7 +8,7 @@ Structure of a Contract
Contracts in Solidity are similar to classes in object-oriented languages.
Each contract can contain declarations of :ref:`structure-state-variables`, :ref:`structure-functions`,
-:ref:`structure-function-modifiers`, :ref:`structure-events`, :ref:`structure-structs-types` and :ref:`structure-enum-types`.
+:ref:`structure-function-modifiers`, :ref:`structure-events`, :ref:`structure-struct-types` and :ref:`structure-enum-types`.
Furthermore, contracts can inherit from other contracts.
.. _structure-state-variables:
@@ -20,12 +20,12 @@ State variables are values which are permanently stored in contract storage.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract SimpleStorage {
- uint storedData; // State variable
- // ...
- }
+ contract SimpleStorage {
+ uint storedData; // State variable
+ // ...
+ }
See the :ref:`types` section for valid state variable types and
:ref:`visibility-and-getters` for possible choices for
@@ -40,13 +40,13 @@ Functions are the executable units of code within a contract.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract SimpleAuction {
- function bid() payable { // Function
- // ...
- }
- }
+ contract SimpleAuction {
+ function bid() public payable { // Function
+ // ...
+ }
+ }
:ref:`function-calls` can happen internally or externally
and have different levels of visibility (:ref:`visibility-and-getters`)
@@ -62,20 +62,20 @@ Function modifiers can be used to amend the semantics of functions in a declarat
::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.11;
- contract Purchase {
- address public seller;
+ contract Purchase {
+ address public seller;
- modifier onlySeller() { // Modifier
- require(msg.sender == seller);
- _;
- }
+ modifier onlySeller() { // Modifier
+ require(msg.sender == seller);
+ _;
+ }
- function abort() onlySeller { // Modifier usage
- // ...
- }
- }
+ function abort() public onlySeller { // Modifier usage
+ // ...
+ }
+ }
.. _structure-events:
@@ -86,23 +86,23 @@ Events are convenience interfaces with the EVM logging facilities.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract SimpleAuction {
- event HighestBidIncreased(address bidder, uint amount); // Event
+ contract SimpleAuction {
+ event HighestBidIncreased(address bidder, uint amount); // Event
- function bid() payable {
- // ...
- HighestBidIncreased(msg.sender, msg.value); // Triggering event
- }
- }
+ function bid() public payable {
+ // ...
+ HighestBidIncreased(msg.sender, msg.value); // Triggering event
+ }
+ }
See :ref:`events` in contracts section for information on how events are declared
and can be used from within a dapp.
-.. _structure-structs-types:
+.. _structure-struct-types:
-Structs Types
+Struct Types
=============
Structs are custom defined types that can group several variables (see
@@ -110,16 +110,16 @@ Structs are custom defined types that can group several variables (see
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract Ballot {
- struct Voter { // Struct
- uint weight;
- bool voted;
- address delegate;
- uint vote;
- }
- }
+ contract Ballot {
+ struct Voter { // Struct
+ uint weight;
+ bool voted;
+ address delegate;
+ uint vote;
+ }
+ }
.. _structure-enum-types:
@@ -131,8 +131,8 @@ Enums can be used to create custom types with a finite set of values (see
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract Purchase {
- enum State { Created, Locked, Inactive } // Enum
- }
+ contract Purchase {
+ enum State { Created, Locked, Inactive } // Enum
+ }
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index 0742d2e9..ab1af13d 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -25,7 +25,7 @@ solidity code. The goal of this guide is *consistency*. A quote from python's
captures this concept well.
A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.
- But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask!
+ But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgement. Look at other examples and decide what looks best. And don't hesitate to ask!
***********
@@ -86,17 +86,17 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu
Yes::
contract A {
- function spam();
- function ham();
+ function spam() public;
+ function ham() public;
}
contract B is A {
- function spam() {
+ function spam() public {
...
}
- function ham() {
+ function ham() public {
...
}
}
@@ -104,10 +104,10 @@ Yes::
No::
contract A {
- function spam() {
+ function spam() public {
...
}
- function ham() {
+ function ham() public {
...
}
}
@@ -169,26 +169,26 @@ Within a grouping, place the ``constant`` functions last.
Yes::
contract A {
- function A() {
+ function A() public {
...
}
-
- function() {
+
+ function() public {
...
}
-
+
// External functions
// ...
-
+
// External functions that are constant
// ...
-
+
// Public functions
// ...
-
+
// Internal functions
// ...
-
+
// Private functions
// ...
}
@@ -196,7 +196,7 @@ Yes::
No::
contract A {
-
+
// External functions
// ...
@@ -206,16 +206,16 @@ No::
// Public functions
// ...
- function A() {
+ function A() public {
...
}
-
- function() {
+
+ function() public {
...
}
// Internal functions
- // ...
+ // ...
}
Whitespace in Expressions
@@ -223,7 +223,7 @@ Whitespace in Expressions
Avoid extraneous whitespace in the following situations:
-Immediately inside parenthesis, brackets or braces, with the exception of single-line function declarations.
+Immediately inside parenthesis, brackets or braces, with the exception of single line function declarations.
Yes::
@@ -235,17 +235,17 @@ No::
Exception::
- function singleLine() { spam(); }
+ function singleLine() public { spam(); }
Immediately before a comma, semicolon:
Yes::
- function spam(uint i, Coin coin);
+ function spam(uint i, Coin coin) public;
No::
- function spam(uint i , Coin coin) ;
+ function spam(uint i , Coin coin) public ;
More than one space around an assignment or other operator to align with
another:
@@ -266,13 +266,13 @@ Don't include a whitespace in the fallback function:
Yes::
- function() {
+ function() public {
...
}
No::
-
- function () {
+
+ function () public {
...
}
@@ -395,30 +395,30 @@ The opening brace should be preceeded by a single space.
Yes::
- function increment(uint x) returns (uint) {
+ function increment(uint x) public pure returns (uint) {
return x + 1;
}
- function increment(uint x) public onlyowner returns (uint) {
+ function increment(uint x) public pure onlyowner returns (uint) {
return x + 1;
}
No::
- function increment(uint x) returns (uint)
+ function increment(uint x) public pure returns (uint)
{
return x + 1;
}
- function increment(uint x) returns (uint){
+ function increment(uint x) public pure returns (uint){
return x + 1;
}
- function increment(uint x) returns (uint) {
+ function increment(uint x) public pure returns (uint) {
return x + 1;
}
- function increment(uint x) returns (uint) {
+ function increment(uint x) public pure returns (uint) {
return x + 1;}
The visibility modifiers for a function should come before any custom
@@ -450,14 +450,16 @@ Yes::
address d,
address e,
address f
- ) {
+ )
+ public
+ {
doSomething();
}
No::
function thisFunctionHasLotsOfArguments(address a, address b, address c,
- address d, address e, address f) {
+ address d, address e, address f) public {
doSomething();
}
@@ -466,7 +468,7 @@ No::
address c,
address d,
address e,
- address f) {
+ address f) public {
doSomething();
}
@@ -476,12 +478,12 @@ No::
address c,
address d,
address e,
- address f) {
+ address f) public {
doSomething();
}
If a long function declaration has modifiers, then each modifier should be
-dropped to it's own line.
+dropped to its own line.
Yes::
@@ -542,6 +544,7 @@ Yes::
B(param1)
C(param2, param3)
D(param4)
+ public
{
// do something with param5
}
@@ -554,6 +557,7 @@ No::
B(param1)
C(param2, param3)
D(param4)
+ public
{
// do something with param5
}
@@ -563,7 +567,8 @@ No::
function A(uint param1, uint param2, uint param3, uint param4, uint param5)
B(param1)
C(param2, param3)
- D(param4) {
+ D(param4)
+ public {
// do something with param5
}
}
@@ -572,7 +577,7 @@ When declaring short functions with a single statement, it is permissible to do
Permissible::
- function shortFunction() { doSomething(); }
+ function shortFunction() public { doSomething(); }
These guidelines for function declarations are intended to improve readability.
Authors should use their best judgement as this guide does not try to cover all
@@ -679,7 +684,7 @@ naming styles.
* ``mixedCase`` (differs from CapitalizedWords by initial lowercase character!)
* ``Capitalized_Words_With_Underscores``
-.. note:: When using abbreviations in CapWords, capitalize all the letters of the abbreviation. Thus HTTPServerError is better than HttpServerError.
+.. note:: When using initialisms in CapWords, capitalize all the letters of the initialisms. Thus HTTPServerError is better than HttpServerError. When using initialisms is mixedCase, capitalize all the letters of the initialisms, except keep the first one lower case if it is the beginning of the name. Thus xmlHTTPRequest is better than XMLHTTPRequest.
Names to Avoid
@@ -696,49 +701,63 @@ indistinguishable from the numerals one and zero.
Contract and Library Names
==========================
-Contracts and libraries should be named using the CapWords style.
+Contracts and libraries should be named using the CapWords style. Examples: ``SimpleToken``, ``SmartBank``, ``CertificateHashRepository``, ``Player``.
-Events
-======
+Struct Names
+==========================
+
+Structs should be named using the CapWords style. Examples: ``MyCoin``, ``Position``, ``PositionXY``.
+
+
+Event Names
+===========
-Events should be named using the CapWords style.
+Events should be named using the CapWords style. Examples: ``Deposit``, ``Transfer``, ``Approval``, ``BeforeTransfer``, ``AfterTransfer``.
Function Names
==============
-Functions should use mixedCase.
+Functions other than constructors should use mixedCase. Examples: ``getBalance``, ``transfer``, ``verifyOwner``, ``addMember``, ``changeOwner``.
-Function Arguments
-==================
+Function Argument Names
+=======================
+
+Function arguments should use mixedCase. Examples: ``initialSupply``, ``account``, ``recipientAddress``, ``senderAddress``, ``newOwner``.
When writing library functions that operate on a custom struct, the struct
should be the first argument and should always be named ``self``.
-Local and State Variables
-=========================
+Local and State Variable Names
+==============================
-Use mixedCase.
+Use mixedCase. Examples: ``totalSupply``, ``remainingSupply``, ``balancesOf``, ``creatorAddress``, ``isPreSale``, ``tokenExchangeRate``.
Constants
=========
Constants should be named with all capital letters with underscores separating
-words. (for example:``MAX_BLOCKS``)
+words. Examples: ``MAX_BLOCKS``, `TOKEN_NAME`, ``TOKEN_TICKER``, ``CONTRACT_VERSION``.
-Modifiers
-=========
+Modifier Names
+==============
+
+Use mixedCase. Examples: ``onlyBy``, ``onlyAfter``, ``onlyDuringThePreSale``.
-Use mixedCase.
+Enums
+=====
-Avoiding Collisions
-===================
+Enums, in the style of simple type declarations, should be named using the CapWords style. Examples: ``TokenGroup``, ``Frame``, ``HashStyle``, ``CharacterLocation``.
+
+
+Avoiding Naming Collisions
+==========================
* ``single_trailing_underscore_``
diff --git a/docs/types.rst b/docs/types.rst
index 0a0bffea..55eaa69a 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -54,13 +54,13 @@ Operators:
* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation)
* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder), ``**`` (exponentiation), ``<<`` (left shift), ``>>`` (right shift)
-Division always truncates (it just is compiled to the DIV opcode of the EVM), but it does not truncate if both
+Division always truncates (it is just compiled to the ``DIV`` opcode of the EVM), but it does not truncate if both
operators are :ref:`literals<rational_literals>` (or literal expressions).
Division by zero and modulus with zero throws a runtime exception.
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
+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.
@@ -70,6 +70,30 @@ sign extends. Shifting by a negative amount throws a runtime exception.
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:: ! ufixed, ! fixed, ! fixed point number
+
+Fixed Point Numbers
+-------------------
+
+.. warning::
+ Fixed point numbers are not fully supported by Solidity yet. They can be declared, but
+ cannot be assigned to or from.
+
+``fixed`` / ``ufixed``: Signed and unsigned fixed point number of various sizes. Keywords ``ufixedMxN`` and ``fixedMxN``, where ``M`` represents the number of bits taken by
+the type and ``N`` represents how many decimal points are available. ``M`` must be divisible by 8 and goes from 8 to 256 bits. ``N`` must be between 0 and 80, inclusive.
+``ufixed`` and ``fixed`` are aliases for ``ufixed128x19`` and ``fixed128x19``, respectively.
+
+Operators:
+
+* Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``)
+* Arithmetic operators: ``+``, ``-``, unary ``-``, unary ``+``, ``*``, ``/``, ``%`` (remainder)
+
+.. note::
+ The main difference between floating point (``float`` and ``double`` in many languages, more precisely IEEE 754 numbers) and fixed point numbers is
+ that the number of bits used for the integer and the fractional part (the part after the decimal dot) is flexible in the former, while it is strictly
+ defined in the latter. Generally, in floating point almost the entire space is used to represent the number, while only a small number of bits define
+ where the decimal point is.
+
.. index:: address, balance, send, call, callcode, delegatecall, transfer
.. _address:
@@ -77,12 +101,17 @@ sign extends. Shifting by a negative amount throws a runtime exception.
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:
* ``<=``, ``<``, ``==``, ``!=``, ``>=`` and ``>``
+.. note::
+ Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address.
+
+.. _members-of-addresses:
+
Members of Addresses
^^^^^^^^^^^^^^^^^^^^
@@ -100,7 +129,7 @@ and to send Ether (in units of wei) to an address using the ``transfer`` functio
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 ``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.
+ 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 feature 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``
@@ -125,7 +154,25 @@ 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.
+It is possible to adjust the supplied gas with the ``.gas()`` modifier::
+
+ namReg.call.gas(1000000)("register", "MyName");
+
+Similarly, the supplied Ether value can be controlled too::
+
+ nameReg.call.value(1 ether)("register", "MyName");
+
+Lastly, these modifiers can be combined. Their order does not matter::
+
+ nameReg.call.gas(1000000).value(1 ether)("register", "MyName");
+
+.. note::
+ It is not yet possible to use the gas or value modifiers on overloaded functions.
+
+ A workaround is to introduce a special case for gas and value and just re-check
+ whether they are present at the point of overload resolution.
+
+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.
@@ -135,6 +182,9 @@ The ``.gas()`` option is available on all three methods, while the ``.value()``
All contracts inherit the members of address, so it is possible to query the balance of the
current contract using ``this.balance``.
+.. note::
+ The use of ``callcode`` is discouraged and will be removed in the future.
+
.. warning::
All these functions are low-level functions and should be used with care.
Specifically, any unknown contract might be malicious and if you call it, you
@@ -164,6 +214,10 @@ Members:
* ``.length`` yields the fixed length of the byte array (read-only).
+.. note::
+ It is possible to use an array of bytes as ``byte[]``, but it is wasting a lot of space, 31 bytes every element,
+ to be exact, when passing in calls. It is better to use ``bytes``.
+
Dynamically-sized byte array
----------------------------
@@ -176,13 +230,6 @@ As a rule of thumb, use ``bytes`` for arbitrary-length raw byte data and ``strin
for arbitrary-length string (UTF-8) data. If you can limit the length to a certain
number of bytes, always use one of ``bytes1`` to ``bytes32`` because they are much cheaper.
-.. index:: ! ufixed, ! fixed, ! fixed point number
-
-Fixed Point Numbers
--------------------
-
-**COMING SOON...**
-
.. index:: address, literal;address
.. _address_literals:
@@ -196,6 +243,9 @@ 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.
+.. note::
+ The mixed-case address checksum format is defined in `EIP-55 <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md>`_.
+
.. index:: literal, literal;rational
.. _rational_literals:
@@ -222,14 +272,6 @@ For example, ``(2**800 + 1) - 2**800`` results in the constant ``1`` (of type ``
although intermediate results would not even fit the machine word size. Furthermore, ``.5 * 8`` results
in the integer ``4`` (although non-integers were used in between).
-If the result is not an integer,
-an appropriate ``ufixed`` or ``fixed`` type is used whose number of fractional bits is as large as
-required (approximating the rational number in the worst case).
-
-In ``var x = 1/4;``, ``x`` will receive the type ``ufixed0x8`` while in ``var x = 1/3`` it will receive
-the type ``ufixed0x256`` because ``1/3`` is not finitely representable in binary and will thus be
-approximated.
-
Any operator that can be applied to integers can also be applied to number literal expressions as
long as the operands are integers. If any of the two is fractional, bit operations are disallowed
and exponentiation is disallowed if the exponent is fractional (because that might result in
@@ -243,20 +285,14 @@ a non-rational number).
types. So the number literal expressions ``1 + 2`` and ``2 + 1`` both
belong to the same number literal type for the rational number three.
-.. note::
- Most finite decimal fractions like ``5.3743`` are not finitely representable in binary. The correct type
- for ``5.3743`` is ``ufixed8x248`` because that allows to best approximate the number. If you want to
- use the number together with types like ``ufixed`` (i.e. ``ufixed128x128``), you have to explicitly
- specify the desired precision: ``x + ufixed(5.3743)``.
-
.. warning::
Division on integer literals used to truncate in earlier versions, but it will now convert into a rational number, i.e. ``5 / 2`` is not equal to ``2``, but to ``2.5``.
.. note::
Number literal expressions are converted into a non-literal type as soon as they are used with non-literal
expressions. Even though we know that the value of the
- expression assigned to ``b`` in the following example evaluates to an integer, it still
- uses fixed point types (and not rational number literals) in between and so the code
+ expression assigned to ``b`` in the following example evaluates to
+ an integer, but the partial expression ``2.5 + a`` does not type check so the code
does not compile
::
@@ -295,14 +331,14 @@ check the value ranges at runtime and a failure causes an exception. Enums need
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract test {
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
ActionChoices choice;
ActionChoices constant defaultChoice = ActionChoices.GoStraight;
- function setGoStraight() {
+ function setGoStraight() public {
choice = ActionChoices.GoStraight;
}
@@ -311,11 +347,11 @@ check the value ranges at runtime and a failure causes an exception. Enums need
// for all matters external to Solidity. The integer type used is just
// large enough to hold all enum values, i.e. if you have more values,
// `uint16` will be used and so on.
- function getChoice() returns (ActionChoices) {
+ function getChoice() public view returns (ActionChoices) {
return choice;
}
- function getDefaultChoice() returns (uint) {
+ function getDefaultChoice() public pure returns (uint) {
return uint(defaultChoice);
}
}
@@ -332,7 +368,7 @@ can be assigned from functions and function parameters of function type
can be used to pass functions to and return functions from function calls.
Function types come in two flavours - *internal* and *external* functions:
-Internal functions can only be used inside the current contract (more specifically,
+Internal functions can only be called inside the current contract (more specifically,
inside the current code unit, which also includes internal library functions
and inherited functions) because they cannot be executed outside of the
context of the current contract. Calling an internal function is realized
@@ -344,14 +380,15 @@ be passed via and returned from external function calls.
Function types are notated as follows::
- function (<parameter types>) {internal|external} [constant] [payable] [returns (<return types>)]
+ function (<parameter types>) {internal|external} [pure|constant|view|payable] [returns (<return types>)]
In contrast to the parameter types, the return types cannot be empty - if the
function type should not return anything, the whole ``returns (<return types>)``
part has to be omitted.
By default, function types are internal, so the ``internal`` keyword can be
-omitted.
+omitted. In contrast, contract functions themselves are public by default,
+only when used as the name of a type, the default is internal.
There are two ways to access a function in the current contract: Either directly
by its name, ``f``, or using ``this.f``. The former will result in an internal
@@ -369,15 +406,27 @@ Note that public functions of the current contract can be used both as an
internal and as an external function. To use ``f`` as an internal function,
just use ``f``, if you want to use its external form, use ``this.f``.
+Additionally, public (or external) functions also have a special member called ``selector``,
+which returns the :ref:`ABI function selector <abi_function_selector>`::
+
+ pragma solidity ^0.4.16;
+
+ contract Selector {
+ function f() public view returns (bytes4) {
+ return this.f.selector;
+ }
+ }
+
Example that shows how to use internal function types::
- pragma solidity ^0.4.5;
+ pragma solidity ^0.4.16;
library ArrayUtils {
// internal functions can be used in internal library functions because
// they will be part of the same code context
- function map(uint[] memory self, function (uint) returns (uint) f)
+ function map(uint[] memory self, function (uint) pure returns (uint) f)
internal
+ pure
returns (uint[] memory r)
{
r = new uint[](self.length);
@@ -387,9 +436,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) pure returns (uint) f
)
internal
+ pure
returns (uint r)
{
r = self[0];
@@ -397,23 +447,23 @@ Example that shows how to use internal function types::
r = f(r, self[i]);
}
}
- function range(uint length) internal returns (uint[] memory r) {
+ function range(uint length) internal pure returns (uint[] memory r) {
r = new uint[](length);
for (uint i = 0; i < r.length; i++) {
r[i] = i;
}
}
}
-
+
contract Pyramid {
using ArrayUtils for *;
- function pyramid(uint l) returns (uint) {
+ function pyramid(uint l) public pure returns (uint) {
return ArrayUtils.range(l).map(square).reduce(sum);
}
- function square(uint x) internal returns (uint) {
+ function square(uint x) internal pure returns (uint) {
return x * x;
}
- function sum(uint x, uint y) internal returns (uint) {
+ function sum(uint x, uint y) internal pure returns (uint) {
return x + y;
}
}
@@ -429,11 +479,11 @@ Another example that uses external function types::
}
Request[] requests;
event NewRequest(uint);
- function query(bytes data, function(bytes memory) external callback) {
+ function query(bytes data, function(bytes memory) external callback) public {
requests.push(Request(data, callback));
NewRequest(requests.length - 1);
}
- function reply(uint requestID, bytes response) {
+ function reply(uint requestID, bytes response) public {
// Here goes the check that the reply comes from a trusted source
requests[requestID].callback(response);
}
@@ -444,13 +494,14 @@ Another example that uses external function types::
function buySomething() {
oracle.query("USD", this.oracleResponse);
}
- function oracleResponse(bytes response) {
+ function oracleResponse(bytes response) public {
require(msg.sender == address(oracle));
// Use the data
}
}
-Note that lambda or inline functions are planned but not yet supported.
+.. note::
+ Lambda or inline functions are planned but not yet supported.
.. index:: ! type;reference, ! reference type, storage, memory, location, array, struct
@@ -472,19 +523,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.
+(not return parameters) of external functions are forced to ``calldata`` and
+behave mostly like ``memory``.
Data locations are important because they change how assignments behave:
-Assignments between storage and memory and also to a state variable (even from other state variables)
+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.
::
@@ -494,7 +545,7 @@ memory-stored reference type does not create a copy.
uint[] x; // the data location of x is storage
// the data location of memoryArray is memory
- function f(uint[] memoryArray) {
+ function f(uint[] memoryArray) public {
x = memoryArray; // works, copies the whole array to storage
var y = x; // works, assigns a pointer, data location of y is storage
y[7]; // fine, returns the 8th element
@@ -511,7 +562,7 @@ memory-stored reference type does not create a copy.
}
function g(uint[] storage storageArray) internal {}
- function h(uint[] memoryArray) {}
+ function h(uint[] memoryArray) public {}
}
Summary
@@ -557,7 +608,7 @@ 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 a getter.
+It is possible to mark arrays ``public`` and have Solidity create a :ref:`getter <visibility-and-getters>`.
The numeric index will become a required parameter for the getter.
.. index:: ! array;allocating, new
@@ -571,10 +622,10 @@ the ``.length`` member.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract C {
- function f(uint len) {
+ function f(uint len) public pure {
uint[] memory a = new uint[](7);
bytes memory b = new bytes(len);
// Here we have a.length == 7 and b.length == len
@@ -592,13 +643,13 @@ assigned to a variable right away.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract C {
- function f() {
+ function f() public pure {
g([uint(1), 2, 3]);
}
- function g(uint[3] _data) {
+ function g(uint[3] _data) public pure {
// ...
}
}
@@ -613,13 +664,16 @@ possible:
::
+ // This will not compile.
+
pragma solidity ^0.4.0;
contract C {
- function f() {
+ function f() public {
// The next line creates a type error because uint[3] memory
// cannot be converted to uint[] memory.
uint[] x = [uint(1), 3, 4];
+ }
}
It is planned to remove this restriction in the future but currently creates
@@ -651,7 +705,7 @@ Members
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.16;
contract ArrayContract {
uint[2**20] m_aLotOfIntegers;
@@ -660,23 +714,23 @@ Members
bool[2][] m_pairsOfFlags;
// newPairs is stored in memory - the default for function arguments
- function setAllFlagPairs(bool[2][] newPairs) {
+ function setAllFlagPairs(bool[2][] newPairs) public {
// assignment to a storage array replaces the complete array
m_pairsOfFlags = newPairs;
}
- function setFlagPair(uint index, bool flagA, bool flagB) {
+ function setFlagPair(uint index, bool flagA, bool flagB) public {
// access to a non-existing index will throw an exception
m_pairsOfFlags[index][0] = flagA;
m_pairsOfFlags[index][1] = flagB;
}
- function changeFlagArraySize(uint newSize) {
+ function changeFlagArraySize(uint newSize) public {
// if the new size is smaller, removed array elements will be cleared
m_pairsOfFlags.length = newSize;
}
- function clear() {
+ function clear() public {
// these clear the arrays completely
delete m_pairsOfFlags;
delete m_aLotOfIntegers;
@@ -686,20 +740,20 @@ Members
bytes m_byteData;
- function byteArrays(bytes data) {
+ function byteArrays(bytes data) public {
// byte arrays ("bytes") are different as they are stored without padding,
// but can be treated identical to "uint8[]"
m_byteData = data;
m_byteData.length += 7;
- m_byteData[3] = 8;
+ m_byteData[3] = byte(8);
delete m_byteData[2];
}
- function addFlag(bool[2] flag) returns (uint) {
+ function addFlag(bool[2] flag) public returns (uint) {
return m_pairsOfFlags.push(flag);
}
- function createMemoryArray(uint size) returns (bytes) {
+ function createMemoryArray(uint size) public pure returns (bytes) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
// Create a dynamic byte array:
@@ -743,14 +797,14 @@ shown in the following example:
uint numCampaigns;
mapping (uint => Campaign) campaigns;
- function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
+ function newCampaign(address beneficiary, uint goal) public returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID is return variable
// Creates new struct and saves in storage. We leave out the mapping type.
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
}
- function contribute(uint campaignID) payable {
- Campaign c = campaigns[campaignID];
+ function contribute(uint campaignID) public payable {
+ Campaign storage c = campaigns[campaignID];
// Creates a new temporary memory struct, initialised with the given values
// and copies it over to storage.
// Note that you can also use Funder(msg.sender, msg.value) to initialise.
@@ -758,8 +812,8 @@ shown in the following example:
c.amount += msg.value;
}
- function checkGoalReached(uint campaignID) returns (bool reached) {
- Campaign c = campaigns[campaignID];
+ function checkGoalReached(uint campaignID) public returns (bool reached) {
+ Campaign storage c = campaigns[campaignID];
if (c.amount < c.fundingGoal)
return false;
uint amount = c.amount;
@@ -806,7 +860,7 @@ 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 a getter.
+It is possible to mark mappings ``public`` and have Solidity create a :ref:`getter <visibility-and-getters>`.
The ``_KeyType`` will become a required parameter for the getter and it will
return ``_ValueType``.
@@ -820,14 +874,16 @@ for each ``_KeyType``, recursively.
contract MappingExample {
mapping(address => uint) public balances;
- function update(uint newBalance) {
+ function update(uint newBalance) public {
balances[msg.sender] = newBalance;
}
}
contract MappingUser {
- function f() returns (uint) {
- return MappingExample(<address>).balances(this);
+ function f() public returns (uint) {
+ MappingExample m = new MappingExample();
+ m.update(100);
+ return m.balances(this);
}
}
@@ -843,7 +899,7 @@ Operators Involving LValues
If ``a`` is an LValue (i.e. a variable or something that can be assigned to), the following operators are available as shorthands:
-``a += e`` is equivalent to ``a = a + e``. The operators ``-=``, ``*=``, ``/=``, ``%=``, ``a |=``, ``&=`` and ``^=`` are defined accordingly. ``a++`` and ``a--`` are equivalent to ``a += 1`` / ``a -= 1`` but the expression itself still has the previous value of ``a``. In contrast, ``--a`` and ``++a`` have the same effect on ``a`` but return the value after the change.
+``a += e`` is equivalent to ``a = a + e``. The operators ``-=``, ``*=``, ``/=``, ``%=``, ``|=``, ``&=`` and ``^=`` are defined accordingly. ``a++`` and ``a--`` are equivalent to ``a += 1`` / ``a -= 1`` but the expression itself still has the previous value of ``a``. In contrast, ``--a`` and ``++a`` have the same effect on ``a`` but return the value after the change.
delete
------
@@ -862,11 +918,11 @@ It is important to note that ``delete a`` really behaves like an assignment to `
uint data;
uint[] dataArray;
- function f() {
+ function f() public {
uint x = data;
delete x; // sets x to 0, does not affect data
delete data; // sets data to 0, does not affect x which still holds a copy
- uint[] y = dataArray;
+ uint[] storage y = dataArray;
delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also
// y is affected which is an alias to the storage object
// On the other hand: "delete y" is not valid, as assignments to local variables
@@ -936,6 +992,6 @@ parameters or return parameters.
.. warning::
The type is only deduced from the first assignment, so
the loop in the following snippet is infinite, as ``i`` will have the type
- ``uint8`` and any value of this type is smaller than ``2000``.
+ ``uint8`` and the highest value of this type is smaller than ``2000``.
``for (var i = 0; i < 2000; i++) { ... }``
diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst
index 779e3819..8f49c600 100644
--- a/docs/units-and-global-variables.rst
+++ b/docs/units-and-global-variables.rst
@@ -34,8 +34,10 @@ library has to be updated by an external oracle.
These suffixes cannot be applied to variables. If you want to
interpret some input variable in e.g. days, you can do it in the following way::
- function f(uint start, uint daysAfter) {
- if (now >= start + daysAfter * 1 days) { ... }
+ function f(uint start, uint daysAfter) public {
+ if (now >= start + daysAfter * 1 days) {
+ // ...
+ }
}
Special Variables and Functions
@@ -70,39 +72,55 @@ Block and Transaction Properties
``msg.value`` can change for every **external** function call.
This includes calls to library functions.
- If you want to implement access restrictions in library functions using
- ``msg.sender``, you have to manually supply the value of
- ``msg.sender`` as an argument.
+.. note::
+ Do not rely on ``block.timestamp``, ``now`` and ``block.blockhash`` as a source of randomness,
+ unless you know what you are doing.
+
+ Both the timestamp and the block hash can be influenced by miners to some degree.
+ Bad actors in the mining community can for example run a casino payout function on a chosen hash
+ and just retry a different hash if they did not receive any money.
+
+ The current block timestamp must be strictly larger than the timestamp of the last block,
+ but the only guarantee is that it will be somewhere between the timestamps of two
+ consecutive blocks in the canonical chain.
.. note::
The block hashes are not available for all blocks for scalability reasons.
You can only access the hashes of the most recent 256 blocks, all other
values will be zero.
-.. index:: assert, revert, 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
----------------------------------------
-``assert(bool condition)``:
- throws if the condition is not met.
``addmod(uint x, uint y, uint k) returns (uint)``:
- compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``.
+ compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0.
``mulmod(uint x, uint y, uint k) returns (uint)``:
- compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``.
+ compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``. Assert that ``k != 0`` starting from version 0.5.0.
``keccak256(...) returns (bytes32)``:
- compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments
-``sha3(...) returns (bytes32)``:
- alias to ``keccak256()``
+ compute the Ethereum-SHA-3 (Keccak-256) hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
``sha256(...) returns (bytes32)``:
- compute the SHA-256 hash of the (tightly packed) arguments
+ compute the SHA-256 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
+``sha3(...) returns (bytes32)``:
+ alias to ``keccak256``
``ripemd160(...) returns (bytes20)``:
- compute RIPEMD-160 hash of the (tightly packed) arguments
+ compute RIPEMD-160 hash of the :ref:`(tightly packed) arguments <abi_packed_mode>`
``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>`_)
-``revert()``:
- abort execution and revert state changes
In the above, "tightly packed" means that the arguments are concatenated without padding.
This means that the following are all identical::
@@ -122,6 +140,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
@@ -148,6 +167,9 @@ For more information, see the section on :ref:`address`.
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.
+.. note::
+ The use of ``callcode`` is discouraged and will be removed in the future.
+
.. index:: this, selfdestruct
Contract Related
@@ -159,5 +181,8 @@ Contract Related
``selfdestruct(address recipient)``:
destroy the current contract, sending its funds to the given :ref:`address`
+``suicide(address recipient)``:
+ alias to ``selfdestruct``
+
Furthermore, all functions of the current contract are callable directly including the current function.
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index 7f82df70..42cc807a 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -138,7 +138,7 @@ Input Description
// 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.
+ // target part of that output. Additionally, `*` can be used as a wildcard to request everything.
//
outputSelection: {
// Enable the metadata and bytecode outputs of every single contract.
@@ -147,11 +147,11 @@ Input Description
},
// Enable the abi and opcodes output of MyContract defined in file def.
"def": {
- "MyContract": [ "abi", "evm.opcodes" ]
+ "MyContract": [ "abi", "evm.bytecode.opcodes" ]
},
// Enable the source map output of every single contract.
"*": {
- "*": [ "evm.sourceMap" ]
+ "*": [ "evm.bytecode.sourceMap" ]
},
// Enable the legacy AST output of every single file.
"*": {
@@ -177,7 +177,8 @@ Output Description
start: 0,
end: 100
],
- // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc
+ // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
+ // See below for complete list of types.
type: "TypeError",
// Mandatory: Component where the error originated, such as "general", "ewasm", etc.
component: "general",
@@ -273,3 +274,21 @@ Output Description
}
}
}
+
+
+Error types
+~~~~~~~~~~~
+
+1. ``JSONError``: JSON input doesn't conform to the required format, e.g. input is not a JSON object, the language is not supported, etc.
+2. ``IOError``: IO and import processing errors, such as unresolvable URL or hash mismatch in supplied sources.
+3. ``ParserError``: Source code doesn't conform to the language rules.
+4. ``DocstringParsingError``: The NatSpec tags in the comment block cannot be parsed.
+5. ``SyntaxError``: Syntactical error, such as ``continue`` is used outside of a ``for`` loop.
+6. ``DeclarationError``: Invalid, unresolvable or clashing identifier names. e.g. ``Identifier not found``
+7. ``TypeError``: Error within the type system, such as invalid type conversions, invalid assignments, etc.
+8. ``UnimplementedFeatureError``: Feature is not supported by the compiler, but is expected to be supported in future versions.
+9. ``InternalCompilerError``: Internal bug triggered in the compiler - this should be reported as an issue.
+10. ``Exception``: Unknown failure during compilation - this should be reported as an issue.
+11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue.
+12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue.
+13. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible.
diff --git a/docs/utils/SolidityLexer.py b/docs/utils/SolidityLexer.py
index 1dc99159..50f51cf4 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': [
@@ -56,8 +56,8 @@ class SolidityLexer(RegexLexer):
(r'[})\].]', Punctuation),
(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'private|pure|return|returns|storage|super|this|throw|using|view|while)\b', Keyword, 'slashstartsregex'),
+ (r'(var|function|event|modifier|struct|enum|contract|library|interface)\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,15 +67,15 @@ class SolidityLexer(RegexLexer):
['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'(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'(abstract|after|case|catch|default|final|in|inline|let|match|'
+ r'null|of|relocatable|static|switch|try|type|typeof)\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'sha256|ecrecover|ripemd160|assert|revert|require)', 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'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?', Number.Float),
(r'0x[0-9a-fA-F]+', Number.Hex),
- (r'[0-9]+', Number.Integer),
+ (r'[0-9]+([eE][0-9]+)?', Number.Integer),
(r'"(\\\\|\\"|[^"])*"', String.Double),
(r"'(\\\\|\\'|[^'])*'", String.Single),
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment