diff options
Diffstat (limited to 'docs')
-rw-r--r-- | docs/_static/css/custom.css (renamed from docs/docs-css/custom.css) | 6 | ||||
-rw-r--r-- | docs/abi-spec.rst | 114 | ||||
-rw-r--r-- | docs/assembly.rst | 18 | ||||
-rw-r--r-- | docs/common-patterns.rst | 2 | ||||
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | docs/contracts.rst | 66 | ||||
-rw-r--r-- | docs/control-structures.rst | 44 | ||||
-rw-r--r-- | docs/frequently-asked-questions.rst | 13 | ||||
-rw-r--r-- | docs/installing-solidity.rst | 42 | ||||
-rw-r--r-- | docs/layout-of-source-files.rst | 13 | ||||
-rw-r--r-- | docs/solidity-by-example.rst | 10 | ||||
-rw-r--r-- | docs/structure-of-a-contract.rst | 2 | ||||
-rw-r--r-- | docs/style-guide.rst | 123 | ||||
-rw-r--r-- | docs/types.rst | 78 | ||||
-rw-r--r-- | docs/using-the-compiler.rst | 11 |
15 files changed, 319 insertions, 225 deletions
diff --git a/docs/docs-css/custom.css b/docs/_static/css/custom.css index 970148ed..fd506203 100644 --- a/docs/docs-css/custom.css +++ b/docs/_static/css/custom.css @@ -7,8 +7,8 @@ pre { } .wy-table-responsive table td, .wy-table-responsive table th { - white-space: pre-wrap; + white-space: normal; } -.wy-table-responsive table td, .wy-table-responsive table th { - white-space: pre-wrap; +.rst-content table.docutils td { + vertical-align: top; } diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index be645b5c..92af8f0c 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -151,8 +151,8 @@ on the type of ``X`` being - ``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. + ``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``: @@ -205,7 +205,9 @@ Thus for our ``Foo`` example if we wanted to call ``baz`` with the parameters `` - ``0x0000000000000000000000000000000000000000000000000000000000000045``: the first parameter, a uint32 value ``69`` padded to 32 bytes - ``0x0000000000000000000000000000000000000000000000000000000000000001``: the second parameter - boolean ``true``, padded to 32 bytes -In total:: +In total: + +.. code-block:: none 0xcdcd77c000000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001 @@ -217,7 +219,9 @@ If we wanted to call ``bar`` with the argument ``["abc", "def"]``, we would pass - ``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:: +In total: + +.. code-block:: none 0xfce353f661626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000 @@ -234,7 +238,9 @@ If we wanted to call ``sam`` with the arguments ``"dave"``, ``true`` and ``[1,2, - ``0x0000000000000000000000000000000000000000000000000000000000000002``: the second entry of the third parameter. - ``0x0000000000000000000000000000000000000000000000000000000000000003``: the third entry of the third parameter. -In total:: +In total: + +.. code-block:: none 0xa5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003 @@ -264,7 +270,7 @@ Finally, we encode the data part of the second dynamic argument, ``"Hello, world All together, the encoding is (newline after function selector and each 32-bytes for clarity): -:: +.. code-block:: none 0x8be65246 0000000000000000000000000000000000000000000000000000000000000123 @@ -292,15 +298,15 @@ Then we encode the length and data of the second embedded dynamic array ``[3]`` Then we need to find the offsets ``a`` and ``b`` for their respective dynamic arrays ``[1, 2]`` and ``[3]``. To calculate the offsets we can take a look at the encoded data of the first root array ``[[1, 2], [3]]`` enumerating each line in the encoding: -:: +.. code-block:: none - 0 - a - offset of [1, 2] - 1 - b - offset of [3] - 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] - 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 - 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 - 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] - 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 + 0 - a - offset of [1, 2] + 1 - b - offset of [3] + 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] + 3 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 + 4 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 + 5 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] + 6 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 Offset ``a`` points to the start of the content of the array ``[1, 2]`` which is line 2 (64 bytes); thus ``a = 0x0000000000000000000000000000000000000000000000000000000000000040``. @@ -318,17 +324,17 @@ Then we encode the embedded strings of the second root array: In parallel to the first root array, since strings are dynamic elements we need to find their offsets ``c``, ``d`` and ``e``: -:: +.. code-block:: none - 0 - c - offset for "one" - 1 - d - offset for "two" - 2 - e - offset for "three" - 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" - 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" - 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" - 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" - 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" - 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" + 0 - c - offset for "one" + 1 - d - offset for "two" + 2 - e - offset for "three" + 3 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" + 4 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" + 5 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" + 6 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" + 7 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" + 8 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" Offset ``c`` points to the start of the content of the string ``"one"`` which is line 3 (96 bytes); thus ``c = 0x0000000000000000000000000000000000000000000000000000000000000060``. @@ -349,29 +355,29 @@ Then we encode the length of the second root array: Finally we find the offsets ``f`` and ``g`` for their respective root dynamic arrays ``[[1, 2], [3]]`` and ``["one", "two", "three"]``, and assemble parts in the correct order: -:: - - 0x2289b18c - function signature - 0 - f - offset of [[1, 2], [3]] - 1 - g - offset of ["one", "two", "three"] - 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]] - 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2] - 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3] - 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] - 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 - 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 - 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] - 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 - 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"] - 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one" - 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two" - 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three" - 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" - 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" - 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" - 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" - 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" - 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" +.. code-block:: none + + 0x2289b18c - function signature + 0 - f - offset of [[1, 2], [3]] + 1 - g - offset of ["one", "two", "three"] + 2 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [[1, 2], [3]] + 3 - 0000000000000000000000000000000000000000000000000000000000000040 - offset of [1, 2] + 4 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset of [3] + 5 - 0000000000000000000000000000000000000000000000000000000000000002 - count for [1, 2] + 6 - 0000000000000000000000000000000000000000000000000000000000000001 - encoding of 1 + 7 - 0000000000000000000000000000000000000000000000000000000000000002 - encoding of 2 + 8 - 0000000000000000000000000000000000000000000000000000000000000001 - count for [3] + 9 - 0000000000000000000000000000000000000000000000000000000000000003 - encoding of 3 + 10 - 0000000000000000000000000000000000000000000000000000000000000003 - count for ["one", "two", "three"] + 11 - 0000000000000000000000000000000000000000000000000000000000000060 - offset for "one" + 12 - 00000000000000000000000000000000000000000000000000000000000000a0 - offset for "two" + 13 - 00000000000000000000000000000000000000000000000000000000000000e0 - offset for "three" + 14 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "one" + 15 - 6f6e650000000000000000000000000000000000000000000000000000000000 - encoding of "one" + 16 - 0000000000000000000000000000000000000000000000000000000000000003 - count for "two" + 17 - 74776f0000000000000000000000000000000000000000000000000000000000 - encoding of "two" + 18 - 0000000000000000000000000000000000000000000000000000000000000005 - count for "three" + 19 - 7468726565000000000000000000000000000000000000000000000000000000 - encoding of "three" Offset ``f`` points to the start of the content of the array ``[[1, 2], [3]]`` which is line 2 (64 bytes); thus ``f = 0x0000000000000000000000000000000000000000000000000000000000000040``. @@ -444,7 +450,7 @@ For example, pragma solidity >0.4.24; contract Test { - constructor() public { b = 0x12345678901234567890123456789012; } + constructor() public { b = hex"12345678901234567890123456789012"; } event Event(uint indexed a, bytes32 b); event Event2(uint indexed a, bytes32 b); function foo(uint a) public { emit Event(a, b); } @@ -453,7 +459,7 @@ For example, would result in the JSON: -.. code:: json +.. code-block:: json [{ "type":"event", @@ -494,13 +500,13 @@ As an example, the code contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } - function f(S memory s, T memory t, uint a) public { } - function g() public returns (S memory s, T memory t, uint a) {} + function f(S memory s, T memory t, uint a) public; + function g() public returns (S memory s, T memory t, uint a); } would result in the JSON: -.. code:: json +.. code-block:: json [ { @@ -568,7 +574,9 @@ Through ``abi.encodePacked()``, Solidity supports a non-standard packed mode whe - 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 ``int8, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in :: +As an example encoding ``int8, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in: + +.. code-block:: none 0xff42242448656c6c6f2c20776f726c6421 ^^ int8(-1) diff --git a/docs/assembly.rst b/docs/assembly.rst index 91ba076a..2cbad06f 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -82,7 +82,7 @@ you really know what you are doing. library VectorSum { // This function is less efficient because the optimizer currently fails to // remove the bounds checks in array access. - function sumSolidity(uint[] memory _data) public view returns (uint o_sum) { + function sumSolidity(uint[] memory _data) public pure returns (uint o_sum) { for (uint i = 0; i < _data.length; ++i) o_sum += _data[i]; } @@ -90,7 +90,7 @@ 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[] memory _data) public view returns (uint o_sum) { + function sumAsm(uint[] memory _data) public pure returns (uint o_sum) { for (uint i = 0; i < _data.length; ++i) { assembly { o_sum := add(o_sum, mload(add(add(_data, 0x20), mul(i, 0x20)))) @@ -99,7 +99,7 @@ you really know what you are doing. } // Same as above, but accomplish the entire code within inline assembly. - function sumPureAsm(uint[] memory _data) public view returns (uint o_sum) { + function sumPureAsm(uint[] memory _data) public pure returns (uint o_sum) { assembly { // Load the length (first 32 bytes) let len := mload(_data) @@ -378,23 +378,13 @@ used ``x_slot`` and to retrieve the byte-offset you used ``x_offset``. In assignments (see below), we can even use local Solidity variables to assign to. -Functions external to inline assembly can also be accessed: The assembly will -push their entry label (with virtual function resolution applied). The calling semantics -in solidity are: - - - the caller pushes ``return label``, ``arg1``, ``arg2``, ..., ``argn`` - - the call returns with ``ret1``, ``ret2``, ..., ``retm`` - -This feature is still a bit cumbersome to use, because the stack offset essentially -changes during the call, and thus references to local variables will be wrong. - .. code:: pragma solidity ^0.4.11; contract C { uint b; - function f(uint x) public returns (uint r) { + function f(uint x) public view returns (uint r) { assembly { r := mul(x, sload(b_slot)) // ignore the offset, we know it is zero } diff --git a/docs/common-patterns.rst b/docs/common-patterns.rst index bc8286b2..6b061bf7 100644 --- a/docs/common-patterns.rst +++ b/docs/common-patterns.rst @@ -198,7 +198,7 @@ restrictions highly readable. ); _; if (msg.value > _amount) - msg.sender.send(msg.value - _amount); + msg.sender.transfer(msg.value - _amount); } function forceOwnerChange(address _newOwner) diff --git a/docs/conf.py b/docs/conf.py index 55f4f1a8..233ff7b6 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -143,7 +143,7 @@ html_theme = 'sphinx_rtd_theme' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [] +html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied diff --git a/docs/contracts.rst b/docs/contracts.rst index 561d2f97..ca15d814 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -110,12 +110,11 @@ This means that cyclic creation dependencies are impossible. function isTokenTransferOK(address currentOwner, address newOwner) public - view + pure returns (bool ok) { // Check some arbitrary condition. - address tokenAddress = msg.sender; - return (keccak256(abi.encodePacked(newOwner)) & 0xff) == (bytes20(tokenAddress) & 0xff); + return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; } } @@ -138,16 +137,16 @@ Functions have to be specified as being ``external``, For state variables, ``external`` is not possible. ``external``: - External functions are part of the contract - interface, which means they can be called from other contracts and + External functions are part of the contract interface, + which means they can be called from other contracts and via transactions. An external function ``f`` cannot be called internally (i.e. ``f()`` does not work, but ``this.f()`` works). External functions are sometimes more efficient when they receive large arrays of data. ``public``: - Public functions are part of the contract - interface and can be either called internally or via + Public functions are part of the contract interface + and can be either called internally or via messages. For public state variables, an automatic getter function (see below) is generated. @@ -188,8 +187,6 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value :: - // This will not compile - pragma solidity ^0.4.0; contract C { @@ -201,6 +198,7 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value function compute(uint a, uint b) internal pure returns (uint) { return a + b; } } + // This will not compile contract D { function readData() public { C c = new C(); @@ -228,8 +226,8 @@ The compiler automatically creates getter functions for all **public** state variables. For the contract given below, the compiler will generate a function called ``data`` that does not take any arguments and returns a ``uint``, the value of the state -variable ``data``. The initialization of state variables can -be done at declaration. +variable ``data``. State variables can be initialized +when they are declared. :: @@ -241,8 +239,8 @@ be done at declaration. contract Caller { C c = new C(); - function f() public { - uint local = c.data(); + function f() public view returns (uint) { + return c.data(); } } @@ -257,9 +255,9 @@ it is evaluated as a state variable. If it is accessed externally contract C { uint public data; - function x() public { + function x() public returns (uint) { data = 3; // internal access - uint val = this.data(); // external access + return this.data(); // external access } } @@ -616,14 +614,13 @@ Like any function, the fallback function can execute complex operations as long } contract Caller { - function callTest(Test test) public { - address(test).call(abi.encodeWithSignature("nonExistingFunction()")); + function callTest(Test test) public returns (bool) { + require(address(test).call(abi.encodeWithSignature("nonExistingFunction()"))); // results in test.x becoming == 1. // If someone sends ether to that contract, - // the transaction will fail and reject the - // Ether. - address(test).send(2 ether); + // the transfer will fail, i.e. this returns false here. + return address(test).send(2 ether); } } @@ -634,9 +631,11 @@ Like any function, the fallback function can execute complex operations as long 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``. +A contract can have multiple functions of the same name but with different parameter +types. +This process is called "overloading" and also applies to inherited functions. +The following example shows overloading of the function +``f`` in the scope of contract ``A``. :: @@ -644,11 +643,12 @@ This also applies to inherited functions. The following example shows overloadin contract A { function f(uint _in) public pure returns (uint out) { - out = 1; + out = _in; } - function f(uint _in, bytes32 _key) public pure returns (uint out) { - out = 2; + function f(uint _in, bool _really) public pure returns (uint out) { + if (_really) + out = _in; } } @@ -657,9 +657,9 @@ externally visible functions differ by their Solidity types but not by their ext :: - // This will not compile pragma solidity ^0.4.16; + // This will not compile contract A { function f(B _in) public pure returns (B out) { out = _in; @@ -811,12 +811,12 @@ as topics. The event call above can be performed in the same way as contract C { function f() public payable { - bytes32 _id = 0x420042; + uint256 _id = 0x420042; log3( bytes32(msg.value), bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), bytes32(uint256(msg.sender)), - _id + bytes32(_id) ); } } @@ -1038,10 +1038,12 @@ derived contracts need to specify all of them. This can be done in two ways:: constructor(uint _x) public { x = _x; } } + // Either directly specify in the inheritance list... contract Derived1 is Base(7) { - constructor(uint _y) public {} + constructor() public {} } + // or through a "modifier" of the derived constructor. contract Derived2 is Base { constructor(uint _y) Base(_y * _y) public {} } @@ -1080,12 +1082,11 @@ error "Linearization of inheritance graph impossible". :: - // This will not compile - pragma solidity ^0.4.0; contract X {} contract A is X {} + // This will not compile contract C is A, X {} The reason for this is that ``C`` requests ``X`` to override ``A`` @@ -1343,6 +1344,7 @@ custom types without the overhead of external function calls: BigInt.bigint memory x = BigInt.fromUint(7); BigInt.bigint memory y = BigInt.fromUint(uint(-1)); BigInt.bigint memory z = x.add(y); + assert(z.limb(1) > 0); } } diff --git a/docs/control-structures.rst b/docs/control-structures.rst index 9fd017db..def75132 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -23,8 +23,9 @@ something like:: pragma solidity ^0.4.16; contract Simple { - function taker(uint _a, uint _b) public pure { - // do something with _a and _b. + uint sum; + function taker(uint _a, uint _b) public { + sum = _a + _b; } } @@ -102,7 +103,7 @@ this nonsensical example:: pragma solidity ^0.4.16; contract C { - function g(uint a) public pure returns (uint ret) { return f(); } + function g(uint a) public pure returns (uint ret) { return a + f(); } function f() internal pure returns (uint ret) { return g(7) + f(); } } @@ -158,8 +159,8 @@ throws an exception or goes out of gas. .. warning:: Any interaction with another contract imposes a potential danger, especially - if the source code of the contract is not known in advance. The current - contract hands over control to the called contract and that may potentially + if the source code of the contract is not known in advance. The + current contract hands over control to the called contract and that may potentially do just about anything. Even if the called contract inherits from a known parent contract, the inheriting contract is only required to have a correct interface. The implementation of the contract, however, can be completely arbitrary and thus, @@ -184,14 +185,16 @@ parameters from the function declaration, but can be in arbitrary order. pragma solidity ^0.4.0; contract C { - function f(uint key, uint value) public { - // ... + mapping(uint => uint) data; + + function f() public { + set({value: 2, key: 3}); } - function g() public { - // named arguments - f({value: 2, key: 3}); + function set(uint key, uint value) public { + data[key] = value; } + } Omitted Function Parameter Names @@ -228,7 +231,7 @@ creation-dependencies are not possible. pragma solidity >0.4.24; contract D { - uint x; + uint public x; constructor(uint a) public payable { x = a; } @@ -239,11 +242,13 @@ creation-dependencies are not possible. function createD(uint arg) public { D newD = new D(arg); + newD.x(); } function createAndEndowD(uint arg, uint amount) public payable { // Send ether along with the creation D newD = (new D).value(amount)(arg); + newD.x(); } } @@ -287,12 +292,13 @@ These can then either be assigned to newly declared variables or to pre-existing } function g() public { - // Variables declared with type and assigned from the returned tuple. - (uint x, bool b, uint y) = f(); + // Variables declared with type and assigned from the returned tuple, + // not all elements have to be specified (but the number must match). + (uint x, , uint y) = f(); // Common trick to swap values -- does not work for non-value storage types. (x, y) = (y, x); // Components can be left out (also for variable declarations). - (data.length,,) = f(); // Sets the length to 7 + (data.length, , ) = f(); // Sets the length to 7 } } @@ -338,11 +344,13 @@ the two variables have the same name but disjoint scopes. contract C { function minimalScoping() pure public { { - uint same2 = 0; + uint same; + same = 1; } { - uint same2 = 0; + uint same; + same = 3; } } } @@ -354,6 +362,7 @@ In any case, you will get a warning about the outer variable being shadowed. :: pragma solidity >0.4.24; + // This will report a warning contract C { function f() pure public returns (uint) { uint x = 1; @@ -372,9 +381,8 @@ In any case, you will get a warning about the outer variable being shadowed. :: - // This will not compile - pragma solidity >0.4.24; + // This will not compile contract C { function f() pure public returns (uint) { x = 2; diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 786c3341..b26ff527 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -62,7 +62,8 @@ Example:: contract C { function f() public pure returns (uint8[5] memory) { string[4] memory adaArr = ["This", "is", "an", "array"]; - return ([1, 2, 3, 4, 5]); + adaArr[0] = "That"; + return [1, 2, 3, 4, 5]; } } @@ -186,9 +187,10 @@ If you do not want to throw, you can return a pair:: function checkCounter(uint index) public view { (uint counter, bool error) = getCounter(index); if (error) { - // ... + // Handle the error } else { - // ... + // Do something with counter. + require(counter > 7, "Invalid counter value"); } } } @@ -372,15 +374,14 @@ contract level) with ``arrayname.length = <some new length>;``. If you get the :: - // This will not compile - pragma solidity ^0.4.18; + // This will not compile contract C { int8[] dynamicStorageArray; int8[5] fixedStorageArray; - function f() { + function f() public { int8[] memory memArr; // Case 1 memArr.length++; // illegal diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 41204bba..910f80cf 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -44,7 +44,7 @@ Note: The 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 repository for instructions. -.. code:: bash +.. code-block:: bash npm install -g solc @@ -62,7 +62,7 @@ We provide up to date docker builds for the compiler. The ``stable`` repository contains released versions while the ``nightly`` repository contains potentially unstable changes in the develop branch. -.. code:: bash +.. code-block:: bash docker run ethereum/solc:stable --version @@ -78,7 +78,7 @@ Binary packages of Solidity are available at We also have PPAs for Ubuntu. For the latest stable version. -.. code:: bash +.. code-block:: bash sudo add-apt-repository ppa:ethereum/ethereum sudo apt-get update @@ -86,7 +86,7 @@ We also have PPAs for Ubuntu. For the latest stable version. If you want to use the cutting edge developer version: -.. code:: bash +.. code-block:: bash sudo add-apt-repository ppa:ethereum/ethereum sudo add-apt-repository ppa:ethereum/ethereum-dev @@ -95,19 +95,19 @@ If you want to use the cutting edge developer version: 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 +.. code-block:: 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 +.. code-block:: bash sudo snap install solc --edge Arch Linux also has packages, albeit limited to the latest development version: -.. code:: bash +.. code-block:: bash pacman -S solidity @@ -116,7 +116,7 @@ following a Jenkins to TravisCI migration, but Homebrew should still work just fine as a means to build-from-source. We will re-add the pre-built bottles soon. -.. code:: bash +.. code-block:: bash brew update brew upgrade @@ -134,7 +134,7 @@ specific commit of ``solidity.rb``. Install it using ``brew``: -.. code:: bash +.. code-block:: bash brew unlink solidity # Install 0.4.8 @@ -142,7 +142,7 @@ Install it using ``brew``: Gentoo Linux also provides a solidity package that can be installed using ``emerge``: -.. code:: bash +.. code-block:: bash emerge dev-lang/solidity @@ -156,7 +156,7 @@ Clone the Repository To clone the source code, execute the following command: -.. code:: bash +.. code-block:: bash git clone --recursive https://github.com/ethereum/solidity.git cd solidity @@ -164,14 +164,14 @@ To clone the source code, execute the following command: If you want to help developing Solidity, you should fork Solidity and add your personal fork as a second remote: -.. code:: bash +.. code-block:: bash cd solidity git remote add personal git@github.com:[username]/solidity.git Solidity has git submodules. Ensure they are properly loaded: -.. code:: bash +.. code-block:: bash git submodule update --init --recursive @@ -187,7 +187,7 @@ If you are installing Xcode for the first time, or have just installed a new version then you will need to agree to the license before you can do command-line builds: -.. code:: bash +.. code-block:: bash sudo xcodebuild -license accept @@ -244,13 +244,13 @@ We now have a "one button" script which installs all required external dependenc on macOS, Windows and on numerous Linux distros. This used to be a multi-step manual process, but is now a one-liner: -.. code:: bash +.. code-block:: bash ./scripts/install_deps.sh Or, on Windows: -.. code:: bat +.. code-block:: bat scripts\install_deps.bat @@ -263,7 +263,7 @@ Command-Line Build Solidity project uses CMake to configure the build. Building Solidity is quite similar on Linux, macOS and other Unices: -.. code:: bash +.. code-block:: bash mkdir build cd build @@ -271,14 +271,14 @@ Building Solidity is quite similar on Linux, macOS and other Unices: or even easier: -.. code:: bash +.. code-block:: bash #note: this will install binaries solc and soltest at usr/local/bin ./scripts/build.sh And even for Windows: -.. code:: bash +.. code-block:: bash mkdir build cd build @@ -291,7 +291,7 @@ should result in Visual Studio firing up. We suggest building Alternatively, you can build for Windows on the command-line, like so: -.. code:: bash +.. code-block:: bash cmake --build . --config RelWithDebInfo @@ -310,7 +310,7 @@ they are found in the system. Each solver can be disabled by a `cmake` option. Inside the build folder you can disable them, since they are enabled by default: -.. code:: bash +.. code-block:: bash # disables only Z3 SMT Solver. cmake .. -DUSE_Z3=OFF diff --git a/docs/layout-of-source-files.rst b/docs/layout-of-source-files.rst index 46ef3d57..5cbb6cff 100644 --- a/docs/layout-of-source-files.rst +++ b/docs/layout-of-source-files.rst @@ -100,11 +100,10 @@ When the compiler is invoked, it is not only possible to specify how to discover the first element of a path, but it is possible to specify path prefix remappings so that e.g. ``github.com/ethereum/dapp-bin/library`` is remapped to ``/usr/local/dapp-bin/library`` and the compiler will read the files from there. -If multiple remappings can be applied, the one with the longest key is tried first. This -allows for a "fallback-remapping" with e.g. ``""`` maps to -``"/usr/local/include/solidity"``. Furthermore, these remappings can -depend on the context, which allows you to configure packages to -import e.g. different versions of a library of the same name. +If multiple remappings can be applied, the one with the longest key is tried first. +An empty prefix is not allowed. Furthermore, these remappings can depend on the context, +which allows you to configure packages to import e.g. different versions of a library +of the same name. **solc**: @@ -148,7 +147,7 @@ Note that solc only allows you to include files from certain directories: They have to be in the directory (or subdirectory) of one of the explicitly specified source files or in the directory (or subdirectory) of a remapping target. If you want to allow direct absolute includes, just add the -remapping ``=/``. +remapping ``/=/``. If there are multiple remappings that lead to a valid file, the remapping with the longest common prefix is chosen. @@ -205,7 +204,7 @@ for the two input parameters and two returned values. * @return s The calculated surface. * @return p The calculated perimeter. */ - function rectangle(uint w, uint h) public returns (uint s, uint p) { + function rectangle(uint w, uint h) public pure returns (uint s, uint p) { s = w * h; p = 2 * (w + h); } diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 3f054297..7d325746 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -467,22 +467,22 @@ high or low invalid bids. uint refund; for (uint i = 0; i < length; i++) { - Bid storage bid = bids[msg.sender][i]; + Bid storage bidToCheck = bids[msg.sender][i]; (uint value, bool fake, bytes32 secret) = (_values[i], _fake[i], _secret[i]); - if (bid.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) { + if (bidToCheck.blindedBid != keccak256(abi.encodePacked(value, fake, secret))) { // Bid was not actually revealed. // Do not refund deposit. continue; } - refund += bid.deposit; - if (!fake && bid.deposit >= value) { + refund += bidToCheck.deposit; + if (!fake && bidToCheck.deposit >= value) { if (placeBid(msg.sender, value)) refund -= value; } // Make it impossible for the sender to re-claim // the same deposit. - bid.blindedBid = bytes32(0); + bidToCheck.blindedBid = bytes32(0); } msg.sender.transfer(refund); } diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index 7a6317eb..ae349055 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -75,7 +75,7 @@ Function modifiers can be used to amend the semantics of functions in a declarat _; } - function abort() public onlySeller { // Modifier usage + function abort() public view onlySeller { // Modifier usage // ... } } diff --git a/docs/style-guide.rst b/docs/style-guide.rst index 53e126b4..d2de5287 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -52,31 +52,35 @@ Surround top level declarations in solidity source with two blank lines. Yes:: + pragma solidity ^0.4.0; + contract A { - ... + // ... } contract B { - ... + // ... } contract C { - ... + // ... } No:: + pragma solidity ^0.4.0; + contract A { - ... + // ... } contract B { - ... + // ... } contract C { - ... + // ... } Within a contract surround function declarations with a single blank line. @@ -85,30 +89,34 @@ Blank lines may be omitted between groups of related one-liners (such as stub fu Yes:: + pragma solidity ^0.4.0; + contract A { - function spam() public; - function ham() public; + function spam() public pure; + function ham() public pure; } contract B is A { - function spam() public { - ... + function spam() public pure { + // ... } - function ham() public { - ... + function ham() public pure { + // ... } } No:: + pragma solidity ^0.4.0; + contract A { - function spam() public { - ... + function spam() public pure { + // ... } - function ham() public { - ... + function ham() public pure { + // ... } } @@ -229,22 +237,24 @@ Import statements should always be placed at the top of the file. Yes:: - import "./Owned.sol"; + pragma solidity ^0.4.0; + import "./Owned.sol"; contract A { - ... + // ... } - contract B is Owned { - ... + // ... } No:: + pragma solidity ^0.4.0; + contract A { - ... + // ... } @@ -252,7 +262,7 @@ No:: contract B is Owned { - ... + // ... } Order of Functions @@ -273,13 +283,15 @@ Within a grouping, place the ``view`` and ``pure`` functions last. Yes:: + pragma solidity ^0.4.0; + contract A { constructor() public { - ... + // ... } function() external { - ... + // ... } // External functions @@ -303,13 +315,15 @@ Yes:: No:: + pragma solidity ^0.4.0; + contract A { // External functions // ... function() external { - ... + // ... } // Private functions @@ -319,7 +333,7 @@ No:: // ... constructor() public { - ... + // ... } // Internal functions @@ -397,6 +411,8 @@ should: Yes:: + pragma solidity ^0.4.0; + contract Coin { struct Bank { address owner; @@ -406,6 +422,8 @@ Yes:: No:: + pragma solidity ^0.4.0; + contract Coin { struct Bank { @@ -705,7 +723,25 @@ manner as modifiers if the function declaration is long or hard to read. Yes:: + pragma solidity ^0.4.0; + + // Base contracts just to make this compile + contract B { + constructor(uint) public { + } + } + contract C { + constructor(uint, uint) public { + } + } + contract D { + constructor(uint) public { + } + } + contract A is B, C, D { + uint x; + constructor(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) @@ -713,29 +749,50 @@ Yes:: public { // do something with param5 + x = param5; } } No:: + pragma solidity ^0.4.0; + + // Base contracts just to make this compile + contract B { + constructor(uint) public { + } + } + contract C { + constructor(uint, uint) public { + } + } + contract D { + constructor(uint) public { + } + } + contract A is B, C, D { + uint x; + constructor(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { - // do something with param5 + x = param5; } } - contract A is B, C, D { + contract X is B, C, D { + uint x; + constructor(uint param1, uint param2, uint param3, uint param4, uint param5) B(param1) C(param2, param3) D(param4) public { - // do something with param5 + x = param5; } } @@ -875,6 +932,8 @@ As shown in the example below, if the contract name is `Congress` and the librar Yes:: + pragma solidity ^0.4.0; + // Owned.sol contract Owned { address public owner; @@ -897,11 +956,13 @@ Yes:: import "./Owned.sol"; contract Congress is Owned, TokenRecipient { - ... + //... } No:: + pragma solidity ^0.4.0; + // owned.sol contract owned { address public owner; @@ -924,7 +985,7 @@ No:: import "./owned.sol"; contract Congress is owned, tokenRecipient { - ... + //... } diff --git a/docs/types.rst b/docs/types.rst index 208966be..c216fd83 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -134,7 +134,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 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. + If ``x`` is a contract address, its code (more specifically: its :ref:`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`` @@ -200,25 +200,38 @@ The ``.gas()`` option is available on all three methods, while the ``.value()`` .. note:: The use of ``callcode`` is discouraged and will be removed in the future. +.. index:: ! contract type, ! type; contract + +.. _contract_types: + Contract Types -------------- -Every :ref:`contract<contracts>` defines its own type. Contracts can be implicitly converted -to contracts they inherit from. They can be explicitly converted from and to ``address`` types. +Every :ref:`contract<contracts>` defines its own type. +You can implicitly convert contracts to contracts they inherit from, +and explicitly convert them to and from the ``address`` type. -The data representation of a contract is identical to that of the ``address`` type and -this type is also used in the :ref:`ABI<ABI>`. +.. note:: + Starting with version 0.5.0 contracts do not derive from the address type, + but can still be explicitly converted to address. -Contracts do not support any operators. +If you declare a local variable of contract type (`MyContract c`), you can call +functions on that contract. Take care to assign it from somewhere that is the +same contract type. -The members of contract types are the external functions of the contract including -public state variables. +You can also instantiate contracts (which means they are newly created). You +can find more details in the :ref:`'Contracts via new'<creating-contracts>` +section. -.. note:: - Starting with version 0.5.0 contracts do not derive from the address type, but can still be explicitly converted to address. +The data representation of a contract is identical to that of the ``address`` +type and this type is also used in the :ref:`ABI<ABI>`. -.. index:: byte array, bytes32 +Contracts do not support any operators. +The members of contract types are the external functions of the contract +including public state variables. + +.. index:: byte array, bytes32 Fixed-size byte arrays ---------------------- @@ -434,7 +447,7 @@ which returns the :ref:`ABI function selector <abi_function_selector>`:: pragma solidity ^0.4.16; contract Selector { - function f() public view returns (bytes4) { + function f() public pure returns (bytes4) { return this.f.selector; } } @@ -497,15 +510,15 @@ Another example that uses external function types:: contract Oracle { struct Request { bytes data; - function(bytes memory) external callback; + function(uint) external callback; } Request[] requests; event NewRequest(uint); - function query(bytes memory data, function(bytes memory) external callback) public { + function query(bytes memory data, function(uint) external callback) public { requests.push(Request(data, callback)); emit NewRequest(requests.length - 1); } - function reply(uint requestID, bytes memory response) public { + function reply(uint requestID, uint response) public { // Here goes the check that the reply comes from a trusted source requests[requestID].callback(response); } @@ -513,15 +526,16 @@ Another example that uses external function types:: contract OracleUser { Oracle constant oracle = Oracle(0x1234567); // known contract + uint exchangeRate; function buySomething() public { oracle.query("USD", this.oracleResponse); } - function oracleResponse(bytes memory response) public { + function oracleResponse(uint response) public { require( msg.sender == address(oracle), "Only oracle can call this." ); - // Use the data + exchangeRate = response; } } @@ -588,8 +602,8 @@ memory-stored reference type do not create a copy. h(x); // calls h and creates an independent, temporary copy in memory } - function g(uint[] storage storageArray) internal {} - function h(uint[] memory memoryArray) public {} + function g(uint[] storage) internal pure {} + function h(uint[] memory) public pure {} } Summary @@ -646,8 +660,9 @@ Allocating Memory Arrays ^^^^^^^^^^^^^^^^^^^^^^^^ Creating arrays with variable length in memory can be done using the ``new`` keyword. -As opposed to storage arrays, it is **not** possible to resize memory arrays by assigning to -the ``.length`` member. +As opposed to storage arrays, it is **not** possible to resize memory arrays (e.g. by assigning to +the ``.length`` member). You either have to calculate the required size in advance +or create a new memory array and copy every element. :: @@ -657,7 +672,8 @@ the ``.length`` member. 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 + assert(a.length == 7); + assert(b.length == len); a[6] = 8; } } @@ -678,7 +694,7 @@ assigned to a variable right away. function f() public pure { g([uint(1), 2, 3]); } - function g(uint[3] memory _data) public pure { + function g(uint[3] memory) public pure { // ... } } @@ -693,10 +709,9 @@ possible: :: - // This will not compile. - pragma solidity ^0.4.0; + // This will not compile. contract C { function f() public { // The next line creates a type error because uint[3] memory @@ -739,9 +754,12 @@ Members uint[2**20] m_aLotOfIntegers; // Note that the following is not a pair of dynamic arrays but a // dynamic array of pairs (i.e. of fixed size arrays of length two). + // Because of that, T[] is always a dynamic array of T, even if T + // itself is an array. bool[2][] m_pairsOfFlags; - // newPairs is stored in memory - the default for function arguments + // newPairs is stored in memory - the only possibility + // for public function arguments function setAllFlagPairs(bool[2][] memory newPairs) public { // assignment to a storage array replaces the complete array m_pairsOfFlags = newPairs; @@ -773,7 +791,7 @@ Members // but can be treated identical to "uint8[]" m_byteData = data; m_byteData.length += 7; - m_byteData[3] = byte(8); + m_byteData[3] = 0x08; delete m_byteData[2]; } @@ -784,6 +802,11 @@ Members function createMemoryArray(uint size) public pure returns (bytes memory) { // Dynamic memory arrays are created using `new`: uint[2][] memory arrayOfPairs = new uint[2][](size); + + // Inline arrays are always statically-sized and if you only + // use literals, you have to provide at least one type. + arrayOfPairs[0] = [uint(1), 2]; + // Create a dynamic byte array: bytes memory b = new bytes(200); for (uint i = 0; i < b.length; i++) @@ -955,6 +978,7 @@ It is important to note that ``delete a`` really behaves like an assignment to ` // 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 // referencing storage objects can only be made from existing storage objects. + assert(y.length == 0); } } diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index 1d7cb97b..b286e1a3 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -23,14 +23,15 @@ it is also possible to provide path redirects using ``prefix=path`` in the follo :: - solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ =/usr/local/lib/fallback file.sol + solc github.com/ethereum/dapp-bin/=/usr/local/lib/dapp-bin/ file.sol This essentially instructs the compiler to search for anything starting with -``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin`` and if it does not -find the file there, it will look at ``/usr/local/lib/fallback`` (the empty prefix -always matches). ``solc`` will not read files from the filesystem that lie outside of +``github.com/ethereum/dapp-bin/`` under ``/usr/local/lib/dapp-bin``. +``solc`` will not read files from the filesystem that lie outside of the remapping targets and outside of the directories where explicitly specified source -files reside, so things like ``import "/etc/passwd";`` only work if you add ``=/`` as a remapping. +files reside, so things like ``import "/etc/passwd";`` only work if you add ``/=/`` as a remapping. + +An empty remapping prefix is not allowed. If there are multiple matches due to remappings, the one with the longest common prefix is selected. |