diff options
author | Anurag Dashputre <anurag4u80@gmail.com> | 2018-08-23 14:26:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-08-23 14:26:45 +0800 |
commit | 8497dcd721ff0a113374c0c1e1778d44265398a6 (patch) | |
tree | 2833ab7b3c7513647c0476d0e5d33dc11fcd6951 /docs | |
parent | 55524788e2829b3a2b9c6c513f78ba2074aa3385 (diff) | |
parent | 410d288dfc2e08c42df58c7e01ad5c332ce92727 (diff) | |
download | dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.tar dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.tar.gz dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.tar.bz2 dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.tar.lz dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.tar.xz dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.tar.zst dexon-solidity-8497dcd721ff0a113374c0c1e1778d44265398a6.zip |
Merge branch 'develop' into anurag_issue_3667
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 | 110 | ||||
-rw-r--r-- | docs/assembly.rst | 18 | ||||
-rw-r--r-- | docs/bugs.json | 17 | ||||
-rw-r--r-- | docs/bugs.rst | 8 | ||||
-rw-r--r-- | docs/bugs_by_version.json | 62 | ||||
-rw-r--r-- | docs/common-patterns.rst | 2 | ||||
-rw-r--r-- | docs/conf.py | 2 | ||||
-rw-r--r-- | docs/contracts.rst | 147 | ||||
-rw-r--r-- | docs/control-structures.rst | 50 | ||||
-rw-r--r-- | docs/frequently-asked-questions.rst | 61 | ||||
-rw-r--r-- | docs/index.rst | 68 | ||||
-rw-r--r-- | docs/layout-of-source-files.rst | 13 | ||||
-rw-r--r-- | docs/miscellaneous.rst | 13 | ||||
-rw-r--r-- | docs/security-considerations.rst | 3 | ||||
-rw-r--r-- | docs/solidity-by-example.rst | 58 | ||||
-rw-r--r-- | docs/structure-of-a-contract.rst | 2 | ||||
-rw-r--r-- | docs/style-guide.rst | 123 | ||||
-rw-r--r-- | docs/types.rst | 229 | ||||
-rw-r--r-- | docs/units-and-global-variables.rst | 11 | ||||
-rw-r--r-- | docs/using-the-compiler.rst | 11 |
21 files changed, 673 insertions, 341 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 3c593e54..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); } @@ -494,8 +500,8 @@ 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: @@ -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/bugs.json b/docs/bugs.json index b464be18..839ea128 100644 --- a/docs/bugs.json +++ b/docs/bugs.json @@ -1,4 +1,21 @@ [ + { + "name": "EventStructWrongData", + "summary": "Using structs in events logged wrong data.", + "description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.", + "introduced": "0.4.17", + "fixed": "0.5.0", + "severity": "very low" + }, + { + "name": "NestedArrayFunctionCallDecoder", + "summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.", + "description": "If Solidity code calls a function that returns a multi-dimensional fixed-size array, array elements are incorrectly interpreted as memory pointers and thus can cause memory corruption if the return values are accessed. Calling functions with multi-dimensional fixed-size arrays is unaffected as is returning fixed-size arrays from function calls. The regular expression only checks if such functions are present, not if they are called, which is required for the contract to be affected.", + "introduced": "0.1.4", + "fixed": "0.4.22", + "severity": "medium", + "check": {"regex-source": "returns[^;{]*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\]\\s*\\[\\s*[^\\] \\t\\r\\n\\v\\f][^\\]]*\\][^{;]*[;{]"} + }, { "name": "OneOfTwoConstructorsSkipped", "summary": "If a contract has both a new-style constructor (using the constructor keyword) and an old-style constructor (a function with the same name as the contract) at the same time, one of them will be ignored.", diff --git a/docs/bugs.rst b/docs/bugs.rst index 7629830d..6f315a65 100644 --- a/docs/bugs.rst +++ b/docs/bugs.rst @@ -56,6 +56,14 @@ conditions is an object that can contain a boolean value ``optimizer``, which means that the optimizer has to be switched on to enable the bug. If no conditions are given, assume that the bug is present. +check + This field contains JavaScript regular expressions that are to be matched + against the source code ("source-regex") to find out if the + smart contract contains the bug or not. If there is no match, + then the bug is very likely not present. If there is a match, + the bug might be present. For improved accuracy, the regular + expression should be applied to the source code after stripping + comments. .. literalinclude:: bugs.json :language: js diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index 2fe1d226..560b6fa9 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -69,6 +69,7 @@ }, "0.1.4": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -86,6 +87,7 @@ }, "0.1.5": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -103,6 +105,7 @@ }, "0.1.6": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -121,6 +124,7 @@ }, "0.1.7": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -139,6 +143,7 @@ }, "0.2.0": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -157,6 +162,7 @@ }, "0.2.1": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -175,6 +181,7 @@ }, "0.2.2": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "ECRecoverMalformedInput", "SkipEmptyStringLiteral", @@ -193,6 +200,7 @@ }, "0.3.0": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -211,6 +219,7 @@ }, "0.3.1": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -228,6 +237,7 @@ }, "0.3.2": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -245,6 +255,7 @@ }, "0.3.3": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -261,6 +272,7 @@ }, "0.3.4": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -277,6 +289,7 @@ }, "0.3.5": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -293,6 +306,7 @@ }, "0.3.6": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -307,6 +321,7 @@ }, "0.4.0": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -321,6 +336,7 @@ }, "0.4.1": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -335,6 +351,7 @@ }, "0.4.10": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -345,6 +362,7 @@ }, "0.4.11": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -354,6 +372,7 @@ }, "0.4.12": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -362,6 +381,7 @@ }, "0.4.13": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput" @@ -370,6 +390,7 @@ }, "0.4.14": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue" ], @@ -377,32 +398,43 @@ }, "0.4.15": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-08-08" }, "0.4.16": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-08-24" }, "0.4.17": { "bugs": [ + "EventStructWrongData", + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector" ], "released": "2017-09-21" }, "0.4.18": { - "bugs": [], + "bugs": [ + "EventStructWrongData", + "NestedArrayFunctionCallDecoder" + ], "released": "2017-10-18" }, "0.4.19": { - "bugs": [], + "bugs": [ + "EventStructWrongData", + "NestedArrayFunctionCallDecoder" + ], "released": "2017-11-30" }, "0.4.2": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -415,29 +447,41 @@ "released": "2016-09-17" }, "0.4.20": { - "bugs": [], + "bugs": [ + "EventStructWrongData", + "NestedArrayFunctionCallDecoder" + ], "released": "2018-02-14" }, "0.4.21": { - "bugs": [], + "bugs": [ + "EventStructWrongData", + "NestedArrayFunctionCallDecoder" + ], "released": "2018-03-07" }, "0.4.22": { "bugs": [ + "EventStructWrongData", "OneOfTwoConstructorsSkipped" ], "released": "2018-04-16" }, "0.4.23": { - "bugs": [], + "bugs": [ + "EventStructWrongData" + ], "released": "2018-04-19" }, "0.4.24": { - "bugs": [], + "bugs": [ + "EventStructWrongData" + ], "released": "2018-05-16" }, "0.4.3": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -450,6 +494,7 @@ }, "0.4.4": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -461,6 +506,7 @@ }, "0.4.5": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -473,6 +519,7 @@ }, "0.4.6": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -484,6 +531,7 @@ }, "0.4.7": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -494,6 +542,7 @@ }, "0.4.8": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", @@ -504,6 +553,7 @@ }, "0.4.9": { "bugs": [ + "NestedArrayFunctionCallDecoder", "ZeroFunctionSelector", "DelegateCallReturnValue", "ECRecoverMalformedInput", 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..669a374f 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -26,8 +26,8 @@ Creating contracts programmatically on Ethereum is best done via using the JavaS 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 declared with the -``constructor`` keyword) is executed once. +When a contract is created, its constructor_ (a function declared with the ``constructor`` keyword) is executed once. + A constructor is optional. Only one constructor is allowed, and this means overloading is not supported. @@ -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,13 +255,43 @@ 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 } } -The next example is a bit more complex: +If you have a `public` state variable of array type, then you can only retrieve +single elements of the array via the generated getter function. This mechanism +exists to avoid high gas costs when returning an entire array. You can use +arguments to specify which individual element to return, for example +``data(0)``. If you want to return an entire array in one call, then you need +to write a function, for example: + +:: + + pragma solidity ^0.4.0; + contract arrayExample { + // public state variable + uint[] public myArray; + + // Getter function generated by the compiler + /* + function myArray(uint i) returns (uint) { + return myArray[i]; + } + */ + + // function that returns entire array + function getArray() returns (uint[] memory) { + return myArray; + } + } + +Now you can use ``getArray()`` to retrieve the entire array, instead of +``myArray(i)``, which returns a single element per call. + +The next example is more complex: :: @@ -278,16 +306,16 @@ The next example is a bit more complex: mapping (uint => mapping(bool => Data[])) public data; } -It will generate a function of the following form:: +It generates a function of the following form. The mapping in the struct is omitted +because there is no good way to provide the key for the mapping: + +:: 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; } -Note that the mapping in the struct is omitted because there -is no good way to provide the key for the mapping. - .. index:: ! function;modifier .. _modifiers: @@ -616,14 +644,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 +661,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 +673,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 +687,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 +841,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) ); } } @@ -842,13 +872,14 @@ Solidity supports multiple inheritance by copying code including polymorphism. All function calls are virtual, which means that the most derived function is called, except when the contract name is explicitly given. -When a contract inherits from multiple contracts, only a single +When a contract inherits from other contracts, only a single contract is created on the blockchain, and the code from all the base contracts is copied into the created contract. The general inheritance system is very similar to `Python's <https://docs.python.org/3/tutorial/classes.html#inheritance>`_, -especially concerning multiple inheritance. +especially concerning multiple inheritance, but there are also +some :ref:`differences <multi-inheritance>`. Details are given in the following example. @@ -993,12 +1024,26 @@ virtual method lookup. .. index:: ! constructor +.. _constructor: + Constructors ============ -A constructor is an optional function declared with the ``constructor`` keyword which is executed upon contract creation. -Constructor functions can be either ``public`` or ``internal``. If there is no constructor, the contract will assume the -default constructor: ``contructor() public {}``. +A constructor is an optional function declared with the ``constructor`` keyword +which is executed upon contract creation, and where you can run contract +initialisation code. + +Before the constructor code is executed, state variables are initialised to +their specified value if you initialise them inline, or zero if you do not. + +After the final code of the contract is returned. The final deployment of +the code costs additional gas linear to the length of the code. If you did not +supply enough gas to initiate the state variables declared in the constructor, +then an "out of gas" exception is generated. + +Constructor functions can be either ``public`` or ``internal``. If there is no +constructor, the contract will assume the default constructor, which is +equivalent to ``constructor() public {}``. For example: :: @@ -1038,10 +1083,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 {} } @@ -1062,6 +1109,8 @@ contracts' constructors, it will be abstract. .. index:: ! inheritance;multiple, ! linearization, ! C3 linearization +.. _multi-inheritance: + Multiple Inheritance and Linearization ====================================== @@ -1074,18 +1123,23 @@ disallows some inheritance graphs. Especially, the order in which the base classes are given in the ``is`` directive is important: You have to list the direct base contracts in the order from "most base-like" to "most derived". -Note that this order is different from the one used in Python. +Note that this order is the reverse of the one used in Python. + +Another simplifying way to explain this is that when a function is called that +is defined multiple times in different contracts, the given bases +are searched from right to left (left to right in Python) in a depth-first manner, +stopping at the first match. If a base contract has already been searched, it is skipped. + In the following code, Solidity will give the 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`` @@ -1093,6 +1147,8 @@ The reason for this is that ``C`` requests ``X`` to override ``A`` requests to override ``X``, which is a contradiction that cannot be resolved. + + Inheriting Different Kinds of Members of the Same Name ====================================================== @@ -1343,6 +1399,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..d0e58908 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; @@ -404,11 +412,11 @@ The deprecated keyword ``throw`` can also be used as an alternative to ``revert( 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 +and the low-level functions ``call``, ``delegatecall``, ``callcode`` and ``staticcall`` -- 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. + The low-level ``call``, ``delegatecall``, ``callcode`` and ``staticcall`` 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. @@ -447,7 +455,7 @@ 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 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``, ``callcode`` or ``staticcall`` 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). diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 786c3341..d2b7de9c 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"); } } } @@ -236,13 +238,6 @@ The key point is that the calling contract needs to know about the function it i See `ping.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_ping.sol>`_ and `pong.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_pong.sol>`_. -Get contract to do something when it is first mined -=================================================== - -Use the constructor. Anything inside it will be executed when the contract is first mined. - -See `replicator.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/50_replicator.sol>`_. - How do you create 2-dimensional arrays? ======================================= @@ -372,15 +367,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 @@ -409,28 +403,6 @@ Is it possible to return an array of strings (``string[]``) from a Solidity func Not yet, as this requires two levels of dynamic arrays (``string`` is a dynamic array itself). -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 :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. - - -What could have happened if an account has storage value(s) but no code? Example: http://test.ether.camp/account/5f740b3a43fbb99724ce93a879805f4dc89178b5 -========================================================================================================================================================== - -The last thing a constructor does is returning the code of the contract. -The gas costs for this depend on the length of the code and it might be -that the supplied gas is not enough. This situation is the only one -where an "out of gas" exception does not revert changes to the state, -i.e. in this case the initialisation of the state variables. - -https://github.com/ethereum/wiki/wiki/Subtleties - -After a successful CREATE operation's sub-execution, if the operation returns x, 5 * len(x) gas is subtracted from the remaining gas before the contract is created. If the remaining gas is less than 5 * len(x), then no gas is subtracted, the code of the created contract becomes the empty string, but this is not treated as an exceptional condition - no reverts happen. - - What does the following strange check do in the Custom Token contract? ====================================================================== @@ -445,6 +417,25 @@ does not fit inside this range, it is truncated. These truncations can have above is necessary to avoid certain attacks. +Why are explicit conversions between fixed-size bytes types and integer types failing? +====================================================================================== + +Since version 0.5.0 explicit conversions between fixed-size byte arrays and integers are only allowed, +if both types have the same size. This prevents unexpected behaviour when truncating or padding. +Such conversions are still possible, but intermediate casts are required that make the desired +truncation and padding convention explicit. See :ref:`types-conversion-elementary-types` for a full +explanation and examples. + + +Why can number literals not be converted to fixed-size bytes types? +=================================================================== + +Since version 0.5.0 only hexadecimal number literals can be converted to fixed-size bytes +types and only if the number of hex digits matches the size of the type. See :ref:`types-conversion-literals` +for a full explanation and examples. + + + More Questions? =============== diff --git a/docs/index.rst b/docs/index.rst index 53d44f08..d59d476e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -60,44 +60,55 @@ Useful links Available Solidity Integrations ------------------------------- -* `Remix <https://remix.ethereum.org/>`_ - Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. +* Generic: -* `IntelliJ IDEA plugin <https://plugins.jetbrains.com/plugin/9475-intellij-solidity>`_ - Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs) + * `Remix <https://remix.ethereum.org/>`_ + Browser-based IDE with integrated compiler and Solidity runtime environment without server-side components. -* `Visual Studio Extension <https://visualstudiogallery.msdn.microsoft.com/96221853-33c4-4531-bdd5-d2ea5acc4799/>`_ - Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler. + * `Solium <https://github.com/duaraghav8/Solium/>`_ + 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. + +* Atom: + + * `Etheratom <https://github.com/0mkara/etheratom>`_ + Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible). + + * `Atom Solidity Linter <https://atom.io/packages/linter-solidity>`_ + Plugin for the Atom editor that provides Solidity linting. -* `Package for SublimeText — Solidity language syntax <https://packagecontrol.io/packages/Ethereum/>`_ - Solidity syntax highlighting for SublimeText editor. + * `Atom Solium Linter <https://atom.io/packages/linter-solium>`_ + Configurable Solidty linter for Atom using Solium as a base. -* `Etheratom <https://github.com/0mkara/etheratom>`_ - Plugin for the Atom editor that features syntax highlighting, compilation and a runtime environment (Backend node & VM compatible). +* Emacs: -* `Atom Solidity Linter <https://atom.io/packages/linter-solidity>`_ - Plugin for the Atom editor that provides Solidity linting. + * `Emacs Solidity <https://github.com/ethereum/emacs-solidity/>`_ + Plugin for the Emacs editor providing syntax highlighting and compilation error reporting. -* `Atom Solium Linter <https://atom.io/packages/linter-solium>`_ - Configurable Solidty linter for Atom using Solium as a base. +* IntelliJ: -* `Solium <https://github.com/duaraghav8/Solium/>`_ - Linter to identify and fix style and security issues in Solidity. + * `IntelliJ IDEA plugin <https://plugins.jetbrains.com/plugin/9475-intellij-solidity>`_ + Solidity plugin for IntelliJ IDEA (and all other JetBrains IDEs) -* `Solhint <https://github.com/protofire/solhint>`_ - Solidity linter that provides security, style guide and best practice rules for smart contract validation. +* Sublime: -* `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. + * `Package for SublimeText — Solidity language syntax <https://packagecontrol.io/packages/Ethereum/>`_ + Solidity syntax highlighting for SublimeText editor. -* `Emacs Solidity <https://github.com/ethereum/emacs-solidity/>`_ - Plugin for the Emacs editor providing syntax highlighting and compilation error reporting. +* Vim: -* `Vim Solidity <https://github.com/tomlion/vim-solidity/>`_ - Plugin for the Vim editor providing syntax highlighting. + * `Vim Solidity <https://github.com/tomlion/vim-solidity/>`_ + Plugin for the Vim editor providing syntax highlighting. -* `Vim Syntastic <https://github.com/scrooloose/syntastic>`_ - Plugin for the Vim editor providing compile checking. + * `Vim Syntastic <https://github.com/scrooloose/syntastic>`_ + Plugin for the Vim editor providing compile checking. + +* Visual Studio Code: + + * `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. Discontinued: @@ -107,10 +118,13 @@ Discontinued: * `Ethereum Studio <https://live.ether.camp/>`_ Specialized web IDE that also provides shell access to a complete Ethereum environment. +* `Visual Studio Extension <https://visualstudiogallery.msdn.microsoft.com/96221853-33c4-4531-bdd5-d2ea5acc4799/>`_ + Solidity plugin for Microsoft Visual Studio that includes the Solidity compiler. + Solidity Tools -------------- -* `Dapp <https://dapp.readthedocs.io>`_ +* `Dapp <https://dapp.tools/dapp/>`_ Build tool, package manager, and deployment assistant for Solidity. * `Solidity REPL <https://github.com/raineorshine/solidity-repl>`_ 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/miscellaneous.rst b/docs/miscellaneous.rst index c0c7cb1b..87041be6 100644 --- a/docs/miscellaneous.rst +++ b/docs/miscellaneous.rst @@ -87,10 +87,14 @@ Solidity always places new objects at the free memory pointer and memory is neve 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 :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. +The input data for a function call is assumed to be in the format defined by the :ref:`ABI +specification <ABI>`. Among others, the ABI specification requires arguments to be padded to multiples of 32 +bytes. The internal function calls use a different convention. + +Arguments for the constructor of a contract are directly appended at the end of the +contract's code, also in ABI encoding. The constructor will access them through a hard-coded offset, and +not by using the ``codesize`` opcode, since this of course changes when appending +data to the code. .. index: variable cleanup @@ -318,6 +322,7 @@ The following is the order of precedence for operators, listed in order of evalu Global Variables ================ +- ``abi.decode(bytes encodedData, (...)) returns (...)``: :ref:`ABI <ABI>`-decodes the provided data. The types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` - ``abi.encode(...) returns (bytes)``: :ref:`ABI <ABI>`-encodes the given arguments - ``abi.encodePacked(...) returns (bytes)``: Performs :ref:`packed encoding <abi_packed_mode>` of the given arguments - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: :ref:`ABI <ABI>`-encodes the given arguments diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 5bb3d81d..066a31ea 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -171,7 +171,8 @@ before they interact with your contract. Note that ``.send()`` does **not** throw an exception if the call stack is depleted but rather returns ``false`` in that case. The low-level functions -``.call()``, ``.callcode()`` and ``.delegatecall()`` behave in the same way. +``.call()``, ``.callcode()``, ``.delegatecall()`` and ``.staticcall()`` behave +in the same way. tx.origin ========= diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 3f054297..72b3581b 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -90,7 +90,7 @@ of votes. // If the first argument of `require` evaluates // to `false`, execution terminates and all // changes to the state and to Ether balances - // are reverted. + // are reverted. // This used to consume all gas in old EVM versions, but // not anymore. // It is often a good idea to use `require` to check if @@ -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); } @@ -708,7 +708,7 @@ For a contract that fulfills payments, the signed message must include: A replay attack is when a signed message is reused to claim authorization for a second action. To avoid replay attacks we will use the same as in Ethereum transactions -themselves, a so-called nonce, which is the number of transactions sent by an +themselves, a so-called nonce, which is the number of transactions sent by an account. The smart contract will check if a nonce is used multiple times. @@ -731,7 +731,7 @@ Packing arguments Now that we have identified what information to include in the signed message, we are ready to put the message together, hash it, and sign it. For simplicity, we just concatenate the data. -The +The `ethereumjs-abi <https://github.com/ethereumjs/ethereumjs-abi>`_ library provides a function called ``soliditySHA3`` that mimics the behavior of Solidity's ``keccak256`` function applied to arguments encoded @@ -750,7 +750,7 @@ creates the proper signature for the ``ReceiverPays`` example: ["address", "uint256", "uint256", "address"], [recipient, amount, nonce, contractAddress] ).toString("hex"); - + web3.personal.sign(hash, web3.eth.defaultAccount, callback); } @@ -779,7 +779,7 @@ at the end of this chapter). Computing the Message Hash -------------------------- - + The smart contract needs to know exactly what parameters were signed, and so it must recreate the message from the parameters and use that for signature verification. The functions ``prefixed`` and @@ -801,7 +801,7 @@ The full contract constructor() public payable {} - function claimPayment(uint256 amount, uint256 nonce, bytes signature) public { + function claimPayment(uint256 amount, uint256 nonce, bytes memory signature) public { require(!usedNonces[nonce]); usedNonces[nonce] = true; @@ -820,7 +820,7 @@ The full contract } /// signature methods. - function splitSignature(bytes sig) + function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) @@ -839,7 +839,7 @@ The full contract return (v, r, s); } - function recoverSigner(bytes32 message, bytes sig) + function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) @@ -874,7 +874,7 @@ two parties (Alice and Bob). Using it involves three steps: 1. Alice funds a smart contract with Ether. This "opens" the payment channel. 2. Alice signs messages that specify how much of that Ether is owed to the recipient. This step is repeated for each payment. 3. Bob "closes" the payment channel, withdrawing their portion of the Ether and sending the remainder back to the sender. - + Not ethat only steps 1 and 3 require Ethereum transactions, step 2 means that the sender transmits a cryptographically signed message to the recipient via off chain ways (e.g. email). This means only two transactions are required to support any number of transfers. @@ -906,8 +906,8 @@ Each message includes the following information: * The smart contract's address, used to prevent cross-contract replay attacks. * The total amount of Ether that is owed the recipient so far. - -A payment channel is closed just once, at the of a series of transfers. + +A payment channel is closed just once, at the end of a series of transfers. Because of this, only one of the messages sent will be redeemed. This is why each message specifies a cumulative total amount of Ether owed, rather than the amount of the individual micropayment. The recipient will naturally choose to @@ -926,7 +926,7 @@ Here is the modified javascript code to cryptographically sign a message from th [contractAddress, amount] ); } - + function signMessage(message, callback) { web3.personal.sign( "0x" + message.toString("hex"), @@ -934,10 +934,10 @@ Here is the modified javascript code to cryptographically sign a message from th callback ); } - + // contractAddress is used to prevent cross-contract replay attacks. // amount, in wei, specifies how much Ether should be sent. - + function signPayment(contractAddress, amount, callback) { var message = constructPaymentMessage(contractAddress, amount); signMessage(message, callback); @@ -1003,7 +1003,7 @@ The full contract expiration = now + duration; } - function isValidSignature(uint256 amount, bytes signature) + function isValidSignature(uint256 amount, bytes memory signature) internal view returns (bool) @@ -1017,7 +1017,7 @@ The full contract /// the recipient can close the channel at any time by presenting a /// signed amount from the sender. the recipient will be sent that amount, /// and the remainder will go back to the sender - function close(uint256 amount, bytes signature) public { + function close(uint256 amount, bytes memory signature) public { require(msg.sender == recipient); require(isValidSignature(amount, signature)); @@ -1043,7 +1043,7 @@ The full contract /// All functions below this are just taken from the chapter /// 'creating and verifying signatures' chapter. - function splitSignature(bytes sig) + function splitSignature(bytes memory sig) internal pure returns (uint8 v, bytes32 r, bytes32 s) @@ -1058,11 +1058,11 @@ The full contract // final byte (first byte of the next 32 bytes) v := byte(0, mload(add(sig, 96))) } - + return (v, r, s); } - - function recoverSigner(bytes32 message, bytes sig) + + function recoverSigner(bytes32 message, bytes memory sig) internal pure returns (address) @@ -1083,7 +1083,7 @@ Note: The function ``splitSignature`` is very simple and does not use all securi A real implementation should use a more rigorously tested library, such as openzepplin's `version <https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/ECRecovery.sol>`_ of this code. - + Verifying Payments ------------------ @@ -1101,7 +1101,7 @@ The recipient should verify each message using the following process: 2. Verify that the new total is the expected amount. 3. Verify that the new total does not exceed the amount of Ether escrowed. 4. Verify that the signature is valid and comes from the payment channel sender. - + We'll use the `ethereumjs-util <https://github.com/ethereumjs/ethereumjs-util>`_ library to write this verifications. The final step can be done a number of ways, but if it's being done in **JavaScript**. @@ -1117,14 +1117,14 @@ above: ["\x19Ethereum Signed Message:\n32", hash] ); } - + function recoverSigner(message, signature) { var split = ethereumjs.Util.fromRpcSig(signature); var publicKey = ethereumjs.Util.ecrecover(message, split.v, split.r, split.s); var signer = ethereumjs.Util.pubToAddress(publicKey).toString("hex"); return signer; } - + function isValidSignature(contractAddress, amount, signature, expectedSigner) { var message = prefixed(constructPaymentMessage(contractAddress, amount)); var signer = recoverSigner(message, signature); 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 bcd3ce9c..03fd36d9 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -91,7 +91,7 @@ Operators: 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 +.. index:: address, balance, send, call, callcode, delegatecall, staticcall, transfer .. _address: @@ -146,7 +146,7 @@ Send is the low-level counterpart of ``transfer``. If the execution fails, the c to make safe Ether transfers, always check the return value of ``send``, use ``transfer`` or even better: use a pattern where the recipient withdraws the money. -* ``call``, ``callcode`` and ``delegatecall`` +* ``call``, ``callcode``, ``delegatecall`` and ``staticcall`` Furthermore, to interface with contracts that do not adhere to the ABI, or to get more direct control over the encoding, @@ -189,7 +189,9 @@ Lastly, these modifiers can be combined. Their order does not matter:: 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. +Since byzantium ``staticcall`` can be used as well. This is basically the same as ``call``, but will revert, if the called function modifies the state in any way. + +All four functions ``call``, ``delegatecall``, ``callcode`` and ``staticcall`` are very low-level functions and should only be used as a *last resort* as they break the type-safety of Solidity. The ``.gas()`` option is available on all three methods, while the ``.value()`` option is not supported for ``delegatecall``. @@ -200,25 +202,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 ---------------------- @@ -355,6 +370,10 @@ Enums are one way to create a user-defined type in Solidity. They are explicitly to and from all integer types but implicit conversion is not allowed. The explicit conversions check the value ranges at runtime and a failure causes an exception. Enums needs at least one member. +The data representation is the same as for enums in C: The options are represented by +subsequent unsigned integer values starting from ``0``. + + :: pragma solidity ^0.4.16; @@ -371,7 +390,7 @@ check the value ranges at runtime and a failure causes an exception. Enums need // Since enum types are not part of the ABI, the signature of "getChoice" // will automatically be changed to "getChoice() returns (uint8)" // 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, + // large enough to hold all enum values, i.e. if you have more than 256 values, // `uint16` will be used and so on. function getChoice() public view returns (ActionChoices) { return choice; @@ -413,8 +432,26 @@ 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. In contrast, contract functions themselves are public by default, -only when used as the name of a type, the default is internal. +omitted. Note that this only applies to function types. Visibility has +to be specified explicitly for functions defined in contracts, they +do not have a default. + +A function type ``A`` is implicitly convertible to a function type ``B`` if and only if +their parameter types are identical, their return types are identical, +their internal/external property is identical and the state mutability of ``A`` +is not more restrictive than the state mutability of ``B``. In particular: + + - ``pure`` functions can be converted to ``view`` and ``non-payable`` functions + - ``view`` functions can be converted to ``non-payable`` functions + - ``payable`` functions can be converted to ``non-payable`` functions + +No other conversions are possible. + +The rule about ``payable`` and ``non-payable`` might be a little +confusing, but in essence, if a function is ``payable``, this means that it +also accepts a payment of zero Ether, so it also is ``non-payable``. +On the other hand, a ``non-payable`` function will reject Ether sent to it, +so ``non-payable`` functions cannot be converted to ``payable`` functions. If a function type variable is not initialized, calling it will result in an exception. The same happens if you call a function after using ``delete`` @@ -434,7 +471,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 +534,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 +550,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; } } @@ -544,16 +582,18 @@ variables are held). Data location ------------- + Every complex type, i.e. *arrays* and *structs*, has an additional -annotation, the "data location", about whether it is stored in memory or in storage. Depending on the -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). +annotation, the "data location", about where it is stored. There are three data locations: +``memory``, ``storage`` and ``calldata``. Calldata is only valid for parameters of external contract +functions and is required for this type of parameter. Calldata is a non-modifiable, +non-persistent area where function arguments are stored, and behaves mostly like memory. -There is also a third data location, ``calldata``, which is a non-modifiable, -non-persistent area where function arguments are stored. Function parameters -(not return parameters) of external functions are forced to ``calldata`` and -behave mostly like ``memory``. + +.. note:: + Prior to version 0.5.0 the data location could be omitted, and would default to different locations + depending on the kind of variable, function type, etc., but all complex types must now give an explicit + data location. 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) @@ -588,8 +628,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 @@ -599,10 +639,6 @@ Forced data location: - parameters (not return) of external functions: calldata - state variables: storage -Default data location: - - parameters (also return) of functions: memory - - all other local variables: storage - .. index:: ! array .. _arrays: @@ -646,8 +682,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 +694,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 +716,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 +731,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 +776,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 +813,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 +824,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,11 +1000,14 @@ 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); } } .. index:: ! type;conversion, ! cast +.. _types-conversion-elementary-types: + Conversions between Elementary Types ==================================== @@ -973,9 +1021,7 @@ is possible if it makes sense semantically and no information is lost: ``uint8`` is convertible to ``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256`` (because ``uint256`` cannot hold e.g. ``-1``). -Furthermore, unsigned integers can be converted to bytes of the same or larger -size, but not vice-versa. Any type that can be converted to ``uint160`` can also -be converted to ``address``. +Any integer type that can be converted to ``uint160`` can also be converted to ``address``. Explicit Conversions -------------------- @@ -994,17 +1040,90 @@ a negative ``int8`` to a ``uint``: At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex characters), which is -3 in the two's complement representation of 256 bits. -If a type is explicitly converted to a smaller type, higher-order bits are +If an integer is explicitly converted to a smaller type, higher-order bits are cut off:: uint32 a = 0x12345678; uint16 b = uint16(a); // b will be 0x5678 now -Since 0.5.0 explicit conversions between integers and fixed-size byte arrays -are only allowed, if both have the same size. To convert between integers and -fixed-size byte arrays of different size, they first have to be explicitly -converted to a matching size. This makes alignment and padding explicit:: +If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end). +The result of the conversion will compare equal to the original integer. + + uint16 a = 0x1234; + uint32 b = uint32(a); // b will be 0x00001234 now + assert(a == b); + +Fixed-size bytes types behave differently during conversions. They can be thought of as +sequences of individual bytes and converting to a smaller type will cut off the +sequence:: + + bytes2 a = 0x1234; + bytes1 b = bytes1(a); // b will be 0x12 + +If a fixed-size bytes type is explicitly converted to a larger type, it is padded on +the right. Accessing the byte at a fixed index will result in the same value before and +after the conversion (if the index is still in range):: + + bytes2 a = 0x1234; + bytes4 b = bytes4(a); // b will be 0x12340000 + assert(a[0] == b[0]); + assert(a[1] == b[1]); + +Since integers and fixed-size byte arrays behave differently when truncating or +padding, explicit conversions between integers and fixed-size byte arrays are only allowed, +if both have the same size. If you want to convert between integers and fixed-size byte arrays of +different size, you have to use intermediate conversions that make the desired truncation and padding +rules explicit:: + + bytes2 a = 0x1234; + uint32 b = uint16(a); // b will be 0x00001234 + uint32 c = uint32(bytes4(a)); // c will be 0x12340000 + uint8 d = uint8(uint16(a)); // d will be 0x34 + uint8 e = uint8(bytes1(a)); // d will be 0x12 + +.. _types-conversion-literals: + +Conversions between Literals and Elementary Types +================================================= + +Integer Types +------------- + +Decimal and hexadecimal number literals can be implicitly converted to any integer type +that is large enough to represent it without truncation:: + + uint8 a = 12; // fine + uint32 b = 1234; // fine + uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456 + +Fixed-Size Byte Arrays +---------------------- - uint16 x = 0xffff; - bytes32(uint256(x)); // pad on the left - bytes32(bytes2(x)); // pad on the right +Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal +number literals can be, but only if the number of hex digits exactly fits the size of the bytes +type. As an exception both decimal and hexadecimal literals which have a value of zero can be +converted to any fixed-size bytes type:: + + bytes2 a = 54321; // not allowed + bytes2 b = 0x12; // not allowed + bytes2 c = 0x123; // not allowed + bytes2 d = 0x1234; // fine + bytes2 e = 0x0012; // fine + bytes4 f = 0; // fine + bytes4 g = 0x0; // fine + +String literals and hex string literals can be implicitly converted to fixed-size byte arrays, +if their number of characters matches the size of the bytes type:: + + bytes2 a = hex"1234"; // fine + bytes2 b = "xy"; // fine + bytes2 c = hex"12"; // not allowed + bytes2 d = hex"123"; // not allowed + bytes2 e = "x"; // not allowed + bytes2 f = "xyz"; // not allowed + +Addresses +--------- + +As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum +test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type. diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 6eae2804..28c9e6ab 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -96,13 +96,14 @@ Block and Transaction Properties .. index:: abi, encoding, packed -ABI Encoding Functions ----------------------- +ABI Encoding and Decoding Functions +----------------------------------- +- ``abi.decode(bytes encodedData, (...)) returns (...)``: ABI-decodes the given data, while the types are given in parentheses as second argument. Example: ``(uint a, uint[2] memory b, bytes memory c) = abi.decode(data, (uint, uint[2], bytes))`` - ``abi.encode(...) returns (bytes)``: ABI-encodes the given arguments - ``abi.encodePacked(...) returns (bytes)``: Performs :ref:`packed encoding <abi_packed_mode>` of the given arguments - ``abi.encodeWithSelector(bytes4 selector, ...) returns (bytes)``: ABI-encodes the given arguments starting from the second and prepends the given four-byte selector -- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature)), ...)``` +- ``abi.encodeWithSignature(string signature, ...) returns (bytes)``: Equivalent to ``abi.encodeWithSelector(bytes4(keccak256(bytes(signature))), ...)``` .. note:: These encoding functions can be used to craft data for function calls without actually @@ -152,7 +153,7 @@ Mathematical and Cryptographic Functions 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 +.. index:: balance, send, transfer, call, callcode, delegatecall, staticcall .. _address_related: Address Related @@ -170,6 +171,8 @@ Address Related issue low-level ``CALLCODE`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable ``<address>.delegatecall(bytes memory) returns (bool)``: issue low-level ``DELEGATECALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable +``<address>.staticcall(bytes memory) returns (bool)``: + issue low-level ``STATICCALL`` with the given payload, returns ``false`` on failure, forwards all available gas, adjustable For more information, see the section on :ref:`address`. 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. |