diff options
author | chriseth <chris@ethereum.org> | 2018-05-16 20:43:57 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-16 20:43:57 +0800 |
commit | e67f0147998a9e3835ed3ce8bf6a0a0c634216c5 (patch) | |
tree | b9c0b7d41cd9f78ae3404704a888da30e767edbe /docs | |
parent | 124ca40dc525a987a88176c6e5170978e82fa290 (diff) | |
parent | 1e45d3ab2e0ca688c2ae48ab657f11496ccebc12 (diff) | |
download | dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.tar dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.tar.gz dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.tar.bz2 dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.tar.lz dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.tar.xz dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.tar.zst dexon-solidity-e67f0147998a9e3835ed3ce8bf6a0a0c634216c5.zip |
Merge pull request #4148 from ethereum/develop
Merge develop into release for 0.4.24
Diffstat (limited to 'docs')
-rw-r--r-- | docs/abi-spec.rst | 16 | ||||
-rw-r--r-- | docs/assembly.rst | 272 | ||||
-rw-r--r-- | docs/bugs_by_version.json | 4 | ||||
-rw-r--r-- | docs/conf.py | 5 | ||||
-rw-r--r-- | docs/contracts.rst | 46 | ||||
-rw-r--r-- | docs/control-structures.rst | 31 | ||||
-rw-r--r-- | docs/frequently-asked-questions.rst | 4 | ||||
-rw-r--r-- | docs/grammar.txt | 4 | ||||
-rw-r--r-- | docs/installing-solidity.rst | 43 | ||||
-rw-r--r-- | docs/introduction-to-smart-contracts.rst | 2 | ||||
-rw-r--r-- | docs/julia.rst | 56 | ||||
-rw-r--r-- | docs/requirements.txt | 1 | ||||
-rw-r--r-- | docs/security-considerations.rst | 2 | ||||
-rw-r--r-- | docs/solidity-by-example.rst | 18 | ||||
-rw-r--r-- | docs/structure-of-a-contract.rst | 2 | ||||
-rw-r--r-- | docs/style-guide.rst | 9 | ||||
-rw-r--r-- | docs/units-and-global-variables.rst | 9 | ||||
-rw-r--r-- | docs/using-the-compiler.rst | 11 |
18 files changed, 177 insertions, 358 deletions
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst index 98301fdc..8591a07f 100644 --- a/docs/abi-spec.rst +++ b/docs/abi-spec.rst @@ -62,7 +62,7 @@ The following elementary types exist: The following (fixed-size) array type exists: -- ``<type>[M]``: a fixed-length array of ``M`` elements, ``M > 0``, of the given type. +- ``<type>[M]``: a fixed-length array of ``M`` elements, ``M >= 0``, of the given type. The following non-fixed-size types exist: @@ -77,7 +77,7 @@ of them inside parentheses, separated by commas: - ``(T1,T2,...,Tn)``: tuple consisting of the types ``T1``, ..., ``Tn``, ``n >= 0`` -It is possible to form tuples of tuples, arrays of tuples and so on. +It is possible to form tuples of tuples, arrays of tuples and so on. It is also possible to form zero-tuples (where ``n == 0``). .. note:: Solidity supports all the types presented above with the same names with the exception of tuples. The ABI tuple type is utilised for encoding Solidity ``structs``. @@ -101,8 +101,8 @@ We distinguish static and dynamic types. Static types are encoded in-place and d * ``bytes`` * ``string`` * ``T[]`` for any ``T`` -* ``T[k]`` for any dynamic ``T`` and any ``k > 0`` -* ``(T1,...,Tk)`` if any ``Ti`` is dynamic for ``1 <= i <= k`` +* ``T[k]`` for any dynamic ``T`` and any ``k >= 0`` +* ``(T1,...,Tk)`` if ``Ti`` is dynamic for some ``1 <= i <= k`` All other types are called "static". @@ -117,16 +117,16 @@ on the type of ``X`` being - ``(T1,...,Tk)`` for ``k >= 0`` and any types ``T1``, ..., ``Tk`` - ``enc(X) = head(X(1)) ... head(X(k-1)) tail(X(0)) ... tail(X(k-1))`` + ``enc(X) = head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(k))`` - where ``X(i)`` is the ``ith`` component of the value, and + where ``X = (X(1), ..., X(k))`` and ``head`` and ``tail`` are defined for ``Ti`` being a static type as ``head(X(i)) = enc(X(i))`` and ``tail(X(i)) = ""`` (the empty string) and as - ``head(X(i)) = enc(len(head(X(0)) ... head(X(k-1)) tail(X(0)) ... tail(X(i-1))))`` + ``head(X(i)) = enc(len(head(X(1)) ... head(X(k)) tail(X(1)) ... tail(X(i-1)) ))`` ``tail(X(i)) = enc(X(i))`` otherwise, i.e. if ``Ti`` is a dynamic type. @@ -144,7 +144,7 @@ on the type of ``X`` being - ``T[]`` where ``X`` has ``k`` elements (``k`` is assumed to be of type ``uint256``): - ``enc(X) = enc(k) enc([X[1], ..., X[k]])`` + ``enc(X) = enc(k) enc([X[0], ..., X[k-1]])`` i.e. it is encoded as if it were an array of static size ``k``, prefixed with the number of elements. diff --git a/docs/assembly.rst b/docs/assembly.rst index 978e71e3..443cb7da 100644 --- a/docs/assembly.rst +++ b/docs/assembly.rst @@ -418,6 +418,9 @@ changes during the call, and thus references to local variables will be wrong. Labels ------ +.. note:: + Labels are deprecated. Please use functions, loops, if or switch statements instead. + Another problem in EVM assembly is that ``jump`` and ``jumpi`` use absolute addresses which can change easily. Solidity inline assembly provides labels to make the use of jumps easier. Note that labels are a low-level feature and it is possible to write @@ -519,6 +522,10 @@ is performed by replacing the variable's value on the stack by the new value. =: v // instruction style assignment, puts the result of sload(10) into v } +.. note:: + Instruction-style assignment is deprecated. + + If -- @@ -693,9 +700,9 @@ the form ``mul(add(x, y), 7)`` are preferred over pure opcode statements like ``7 y x add mul`` because in the first form, it is much easier to see which operand is used for which opcode. -The second goal is achieved by introducing a desugaring phase that only removes -the higher level constructs in a very regular way and still allows inspecting -the generated low-level assembly code. The only non-local operation performed +The second goal is achieved by compiling the +higher level constructs to bytecode in a very regular way. +The only non-local operation performed by the assembler is name lookup of user-defined identifiers (functions, variables, ...), which follow very simple and regular scoping rules and cleanup of local variables from the stack. @@ -716,8 +723,6 @@ keep track of the current so-called stack height. Since all local variables are removed at the end of a block, the stack height before and after the block should be the same. If this is not the case, a warning is issued. -Why do we use higher-level constructs like ``switch``, ``for`` and functions: - Using ``switch``, ``for`` and functions, it should be possible to write complex code without using ``jump`` or ``jumpi`` manually. This makes it much easier to analyze the control flow, which allows for improved formal @@ -726,13 +731,11 @@ verification and optimization. Furthermore, if manual jumps are allowed, computing the stack height is rather complicated. The position of all local variables on the stack needs to be known, otherwise neither references to local variables nor removing local variables automatically -from the stack at the end of a block will work properly. The desugaring -mechanism correctly inserts operations at unreachable blocks that adjust the -stack height properly in case of jumps that do not have a continuing control flow. +from the stack at the end of a block will work properly. Example: -We will follow an example compilation from Solidity to desugared assembly. +We will follow an example compilation from Solidity to assembly. We consider the runtime bytecode of the following Solidity program:: pragma solidity ^0.4.16; @@ -772,99 +775,9 @@ The following assembly will be generated:: } } -After the desugaring phase it looks as follows:: - - { - mstore(0x40, 0x60) - { - let $0 := div(calldataload(0), exp(2, 226)) - jumpi($case1, eq($0, 0xb3de648b)) - jump($caseDefault) - $case1: - { - // the function call - we put return label and arguments on the stack - $ret1 calldataload(4) jump(f) - // This is unreachable code. Opcodes are added that mirror the - // effect of the function on the stack height: Arguments are - // removed and return values are introduced. - pop pop - let r := 0 - $ret1: // the actual return point - $ret2 0x20 jump($allocate) - pop pop let ret := 0 - $ret2: - mstore(ret, r) - return(ret, 0x20) - // although it is useless, the jump is automatically inserted, - // since the desugaring process is a purely syntactic operation that - // does not analyze control-flow - jump($endswitch) - } - $caseDefault: - { - revert(0, 0) - jump($endswitch) - } - $endswitch: - } - jump($afterFunction) - allocate: - { - // we jump over the unreachable code that introduces the function arguments - jump($start) - let $retpos := 0 let size := 0 - $start: - // output variables live in the same scope as the arguments and is - // actually allocated. - let pos := 0 - { - pos := mload(0x40) - mstore(0x40, add(pos, size)) - } - // This code replaces the arguments by the return values and jumps back. - swap1 pop swap1 jump - // Again unreachable code that corrects stack height. - 0 0 - } - f: - { - jump($start) - let $retpos := 0 let x := 0 - $start: - let y := 0 - { - let i := 0 - $for_begin: - jumpi($for_end, iszero(lt(i, x))) - { - y := mul(2, y) - } - $for_continue: - { i := add(i, 1) } - jump($for_begin) - $for_end: - } // Here, a pop instruction will be inserted for i - swap1 pop swap1 jump - 0 0 - } - $afterFunction: - stop - } - - -Assembly happens in four stages: -1. Parsing -2. Desugaring (removes switch, for and functions) -3. Opcode stream generation -4. Bytecode generation - -We will specify steps one to three in a pseudo-formal way. More formal -specifications will follow. - - -Parsing / Grammar ------------------ +Assembly Grammar +---------------- The tasks of the parser are the following: @@ -922,160 +835,3 @@ Grammar:: StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"' HexNumber = '0x' [0-9a-fA-F]+ DecimalNumber = [0-9]+ - - -Desugaring ----------- - -An AST transformation removes for, switch and function constructs. The result -is still parseable by the same parser, but it will not use certain constructs. -If jumpdests are added that are only jumped to and not continued at, information -about the stack content is added, unless no local variables of outer scopes are -accessed or the stack height is the same as for the previous instruction. - -Pseudocode:: - - desugar item: AST -> AST = - match item { - AssemblyFunctionDefinition('function' name '(' arg1, ..., argn ')' '->' ( '(' ret1, ..., retm ')' body) -> - <name>: - { - jump($<name>_start) - let $retPC := 0 let argn := 0 ... let arg1 := 0 - $<name>_start: - let ret1 := 0 ... let retm := 0 - { desugar(body) } - swap and pop items so that only ret1, ... retm, $retPC are left on the stack - jump - 0 (1 + n times) to compensate removal of arg1, ..., argn and $retPC - } - AssemblyFor('for' { init } condition post body) -> - { - init // cannot be its own block because we want variable scope to extend into the body - // find I such that there are no labels $forI_* - $forI_begin: - jumpi($forI_end, iszero(condition)) - { body } - $forI_continue: - { post } - jump($forI_begin) - $forI_end: - } - 'break' -> - { - // find nearest enclosing scope with label $forI_end - pop all local variables that are defined at the current point - but not at $forI_end - jump($forI_end) - 0 (as many as variables were removed above) - } - 'continue' -> - { - // find nearest enclosing scope with label $forI_continue - pop all local variables that are defined at the current point - but not at $forI_continue - jump($forI_continue) - 0 (as many as variables were removed above) - } - AssemblySwitch(switch condition cases ( default: defaultBlock )? ) -> - { - // find I such that there is no $switchI* label or variable - let $switchI_value := condition - for each of cases match { - case val: -> jumpi($switchI_caseJ, eq($switchI_value, val)) - } - if default block present: -> - { defaultBlock jump($switchI_end) } - for each of cases match { - case val: { body } -> $switchI_caseJ: { body jump($switchI_end) } - } - $switchI_end: - } - FunctionalAssemblyExpression( identifier(arg1, arg2, ..., argn) ) -> - { - if identifier is function <name> with n args and m ret values -> - { - // find I such that $funcallI_* does not exist - $funcallI_return argn ... arg2 arg1 jump(<name>) - pop (n + 1 times) - if the current context is `let (id1, ..., idm) := f(...)` -> - let id1 := 0 ... let idm := 0 - $funcallI_return: - else -> - 0 (m times) - $funcallI_return: - turn the functional expression that leads to the function call - into a statement stream - } - else -> desugar(children of node) - } - default node -> - desugar(children of node) - } - -Opcode Stream Generation ------------------------- - -During opcode stream generation, we keep track of the current stack height -in a counter, -so that accessing stack variables by name is possible. The stack height is modified with every opcode -that modifies the stack and with every label that is annotated with a stack -adjustment. Every time a new -local variable is introduced, it is registered together with the current -stack height. If a variable is accessed (either for copying its value or for -assignment), the appropriate ``DUP`` or ``SWAP`` instruction is selected depending -on the difference between the current stack height and the -stack height at the point the variable was introduced. - -Pseudocode:: - - codegen item: AST -> opcode_stream = - match item { - AssemblyBlock({ items }) -> - join(codegen(item) for item in items) - if last generated opcode has continuing control flow: - POP for all local variables registered at the block (including variables - introduced by labels) - warn if the stack height at this point is not the same as at the start of the block - Identifier(id) -> - lookup id in the syntactic stack of blocks - match type of id - Local Variable -> - DUPi where i = 1 + stack_height - stack_height_of_identifier(id) - Label -> - // reference to be resolved during bytecode generation - PUSH<bytecode position of label> - SubAssembly -> - PUSH<bytecode position of subassembly data> - FunctionalAssemblyExpression(id ( arguments ) ) -> - join(codegen(arg) for arg in arguments.reversed()) - id (which has to be an opcode, might be a function name later) - AssemblyLocalDefinition(let (id1, ..., idn) := expr) -> - register identifiers id1, ..., idn as locals in current block at current stack height - codegen(expr) - assert that expr returns n items to the stack - FunctionalAssemblyAssignment((id1, ..., idn) := expr) -> - lookup id1, ..., idn in the syntactic stack of blocks, assert that they are variables - codegen(expr) - for j = n, ..., i: - SWAPi where i = 1 + stack_height - stack_height_of_identifier(idj) - POP - AssemblyAssignment(=: id) -> - look up id in the syntactic stack of blocks, assert that it is a variable - SWAPi where i = 1 + stack_height - stack_height_of_identifier(id) - POP - LabelDefinition(name:) -> - JUMPDEST - NumberLiteral(num) -> - PUSH<num interpreted as decimal and right-aligned> - HexLiteral(lit) -> - PUSH32<lit interpreted as hex and left-aligned> - StringLiteral(lit) -> - PUSH32<lit utf-8 encoded and left-aligned> - SubAssembly(assembly <name> block) -> - append codegen(block) at the end of the code - dataSize(<name>) -> - assert that <name> is a subassembly -> - PUSH32<size of code generated from subassembly <name>> - linkerSymbol(<lit>) -> - PUSH32<zeros> and append position to linker table - } diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json index d96bfde3..2fe1d226 100644 --- a/docs/bugs_by_version.json +++ b/docs/bugs_by_version.json @@ -432,6 +432,10 @@ "bugs": [], "released": "2018-04-19" }, + "0.4.24": { + "bugs": [], + "released": "2018-05-16" + }, "0.4.3": { "bugs": [ "ZeroFunctionSelector", diff --git a/docs/conf.py b/docs/conf.py index ca8c0fec..7e107f2a 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,8 @@ import re # documentation root, use os.path.abspath to make it absolute, like shown here. def setup(sphinx): - sys.path.insert(0, os.path.abspath('./utils')) + thisdir = os.path.dirname(os.path.realpath(__file__)) + sys.path.insert(0, thisdir + '/utils') from SolidityLexer import SolidityLexer sphinx.add_lexer('Solidity', SolidityLexer()) @@ -50,7 +51,7 @@ master_doc = 'index' # General information about the project. project = 'Solidity' -copyright = '2016-2017, Ethereum' +copyright = '2016-2018, Ethereum' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/docs/contracts.rst b/docs/contracts.rst index a1f2895c..b73fe2ca 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -24,8 +24,8 @@ Creating contracts programatically on Ethereum is best done via using the JavaSc As of today it has a method called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_ to facilitate contract creation. -When a contract is created, its constructor (a function with the same -name as the contract) is executed once. +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. @@ -473,7 +473,7 @@ The following statements are considered modifying the state: } .. note:: - ``constant`` on functions is an alias to ``view``, but this is deprecated and is planned to be dropped in version 0.5.0. + ``constant`` on functions is an alias to ``view``, but this is deprecated and will be dropped in version 0.5.0. .. note:: Getter methods are marked ``view``. @@ -841,10 +841,10 @@ Details are given in the following example. :: - pragma solidity ^0.4.16; + pragma solidity ^0.4.22; contract owned { - function owned() { owner = msg.sender; } + constructor() { owner = msg.sender; } address owner; } @@ -875,7 +875,7 @@ Details are given in the following example. // also a base class of `mortal`, yet there is only a single // instance of `owned` (as for virtual inheritance in C++). contract named is owned, mortal { - function named(bytes32 name) { + constructor(bytes32 name) { Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); NameReg(config.lookup(1)).register(name); } @@ -913,10 +913,10 @@ Note that above, we call ``mortal.kill()`` to "forward" the destruction request. The way this is done is problematic, as seen in the following example:: - pragma solidity ^0.4.0; + pragma solidity ^0.4.22; contract owned { - function owned() public { owner = msg.sender; } + constructor() public { owner = msg.sender; } address owner; } @@ -942,10 +942,10 @@ derived override, but this function will bypass ``Base1.kill``, basically because it does not even know about ``Base1``. The way around this is to use ``super``:: - pragma solidity ^0.4.0; + pragma solidity ^0.4.22; contract owned { - function owned() public { owner = msg.sender; } + constructor() public { owner = msg.sender; } address owner; } @@ -982,7 +982,7 @@ virtual method lookup. Constructors ============ -A constructor is an optional function declared with the ``constructor`` keyword which is executed upon contract creation. +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 {}``. @@ -1030,10 +1030,11 @@ A constructor set as ``internal`` causes the contract to be marked as :ref:`abst Arguments for Base Constructors =============================== -Derived contracts need to provide all arguments needed for -the base constructors. This can be done in two ways:: +The constructors of all the base contracts will be called following the +linearization rules explained below. If the base constructors have arguments, +derived contracts need to specify all of them. This can be done in two ways:: - pragma solidity ^0.4.0; + pragma solidity ^0.4.22; contract Base { uint x; @@ -1059,6 +1060,9 @@ derived contract. Arguments have to be given either in the inheritance list or in modifier-style in the derived constuctor. Specifying arguments in both places is an error. +If a derived contract doesn't specify the arguments to all of its base +contracts' constructors, it will be abstract. + .. index:: ! inheritance;multiple, ! linearization, ! C3 linearization Multiple Inheritance and Linearization @@ -1066,12 +1070,15 @@ Multiple Inheritance and Linearization Languages that allow multiple inheritance have to deal with several problems. One is the `Diamond Problem <https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem>`_. -Solidity follows the path of Python and uses "`C3 Linearization <https://en.wikipedia.org/wiki/C3_linearization>`_" +Solidity is similar to Python in that it uses "`C3 Linearization <https://en.wikipedia.org/wiki/C3_linearization>`_" to force a specific order in the DAG of base classes. This results in the desirable property of monotonicity but disallows some inheritance graphs. Especially, the order in which the base classes are given in the ``is`` directive is -important. In the following code, Solidity will give the +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. +In the following code, Solidity will give the error "Linearization of inheritance graph impossible". :: @@ -1089,9 +1096,6 @@ The reason for this is that ``C`` requests ``X`` to override ``A`` requests to override ``X``, which is a contradiction that cannot be resolved. -A simple rule to remember is to specify the base classes in -the order from "most base-like" to "most derived". - Inheriting Different Kinds of Members of the Same Name ====================================================== @@ -1139,8 +1143,10 @@ Example of a Function Type (a variable declaration, where the variable is of typ function(address) external returns (address) foo; -Abstract contracts decouple the definition of a contract from its implementation providing better extensibility and self-documentation and +Abstract contracts decouple the definition of a contract from its implementation providing better extensibility and self-documentation and facilitating patterns like the `Template method <https://en.wikipedia.org/wiki/Template_method_pattern>`_ and removing code duplication. +Abstract contracts are useful in the same way that defining methods in an interface is useful. It is a way for the designer of the abstract contract to say "any child of mine must implement this method". + .. index:: ! contract;interface, ! interface contract diff --git a/docs/control-structures.rst b/docs/control-structures.rst index f3c351dd..7849d15a 100644 --- a/docs/control-structures.rst +++ b/docs/control-structures.rst @@ -272,9 +272,12 @@ Assignment Destructuring Assignments and Returning Multiple Values ------------------------------------------------------- -Solidity internally allows tuple types, i.e. a list of objects of potentially different types whose size is a constant at compile-time. Those tuples can be used to return multiple values at the same time and also assign them to multiple variables (or LValues in general) at the same time:: +Solidity internally allows tuple types, i.e. a list of objects of potentially different types whose size is a constant at compile-time. Those tuples can be used to return multiple values at the same time. +These can then either be assigned to newly declared variables or to pre-existing variables (or LValues in general): - pragma solidity ^0.4.16; +:: + + pragma solidity >0.4.23 <0.5.0; contract C { uint[] data; @@ -284,21 +287,12 @@ Solidity internally allows tuple types, i.e. a list of objects of potentially di } function g() public { - // Variables declared with type - uint x; - bool b; - uint y; - // Tuple values can be assigned to these pre-existing variables - (x, b, y) = f(); + // Variables declared with type and assigned from the returned tuple. + (uint x, bool b, 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). - // If the tuple ends in an empty component, - // the rest of the values are discarded. - (data.length,) = f(); // Sets the length to 7 - // The same can be done on the left side. - // If the tuple begins in an empty component, the beginning values are discarded. - (,data[3]) = f(); // Sets data[3] to 2 + (data.length,,) = f(); // Sets the length to 7 // Components can only be left out at the left-hand-side of assignments, with // one exception: (x,) = (1,); @@ -307,6 +301,11 @@ Solidity internally allows tuple types, i.e. a list of objects of potentially di } } +.. note:: + Prior to version 0.4.24 it was possible to assign to tuples of smaller size, either + filling up on the left or on the right side (which ever was empty). This is + now deprecated, both sides have to have the same number of components. + Complications for Arrays and Structs ------------------------------------ @@ -330,7 +329,9 @@ A variable declared anywhere within a function will be in scope for the *entire (this will change soon, see below). This happens because Solidity inherits its scoping rules from JavaScript. This is in contrast to many languages where variables are only scoped where they are declared until the end of the semantic block. -As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``:: +As a result, the following code is illegal and cause the compiler to throw an error, ``Identifier already declared``: + +:: // This will not compile diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst index 6a2fe685..ca5a1aee 100644 --- a/docs/frequently-asked-questions.rst +++ b/docs/frequently-asked-questions.rst @@ -203,7 +203,7 @@ situation. If you do not want to throw, you can return a pair:: - pragma solidity ^0.4.16; + pragma solidity >0.4.23 <0.5.0; contract C { uint[] counters; @@ -219,7 +219,7 @@ If you do not want to throw, you can return a pair:: } function checkCounter(uint index) public view { - var (counter, error) = getCounter(index); + (uint counter, bool error) = getCounter(index); if (error) { // ... } else { diff --git a/docs/grammar.txt b/docs/grammar.txt index b4ca5ca9..0dda4f49 100644 --- a/docs/grammar.txt +++ b/docs/grammar.txt @@ -16,7 +16,7 @@ ContractPart = StateVariableDeclaration | UsingForDeclaration InheritanceSpecifier = UserDefinedTypeName ( '(' Expression ( ',' Expression )* ')' )? -StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' | 'constant' )? Identifier ('=' Expression)? ';' +StateVariableDeclaration = TypeName ( 'public' | 'internal' | 'private' | 'constant' )* Identifier ('=' Expression)? ';' UsingForDeclaration = 'using' Identifier 'for' ('*' | TypeName) ';' StructDefinition = 'struct' Identifier '{' ( VariableDeclaration ';' (VariableDeclaration ';')* ) '}' @@ -78,7 +78,7 @@ Break = 'break' Return = 'return' Expression? Throw = 'throw' EmitStatement = 'emit' FunctionCall -VariableDefinition = ('var' IdentifierList | VariableDeclaration) ( '=' Expression )? +VariableDefinition = ('var' IdentifierList | VariableDeclaration | '(' VariableDeclaration? (',' VariableDeclaration? )* ')' ) ( '=' Expression )? IdentifierList = '(' ( Identifier? ',' )* Identifier? ')' // Precedence by order (see github.com/ethereum/solidity/pull/732) diff --git a/docs/installing-solidity.rst b/docs/installing-solidity.rst index 6726ded9..05ee0748 100644 --- a/docs/installing-solidity.rst +++ b/docs/installing-solidity.rst @@ -35,7 +35,7 @@ npm / Node.js ============= Use `npm` for a convenient and portable way to install `solcjs`, a Solidity compiler. The -`solcjs` program has less features than all options further down this page. Our +`solcjs` program has fewer features than all options further down this page. Our :ref:`commandline-compiler` documentation assumes you are using the full-featured compiler, `solc`. So if you install `solcjs` from `npm` then you will stop reading the documentation here and then continue to `solc-js <https://github.com/ethereum/solc-js>`_. @@ -203,19 +203,38 @@ Prerequisites - Windows You will need to install the following dependencies for Windows builds of Solidity: -+------------------------------+-------------------------------------------------------+ -| Software | Notes | -+==============================+=======================================================+ -| `Git for Windows`_ | Command-line tool for retrieving source from Github. | -+------------------------------+-------------------------------------------------------+ -| `CMake`_ | Cross-platform build file generator. | -+------------------------------+-------------------------------------------------------+ -| `Visual Studio 2015`_ | C++ compiler and dev environment. | -+------------------------------+-------------------------------------------------------+ ++-----------------------------------+-------------------------------------------------------+ +| Software | Notes | ++===================================+=======================================================+ +| `Git for Windows`_ | Command-line tool for retrieving source from Github. | ++-----------------------------------+-------------------------------------------------------+ +| `CMake`_ | Cross-platform build file generator. | ++-----------------------------------+-------------------------------------------------------+ +| `Visual Studio 2017 Build Tools`_ | C++ compiler | ++-----------------------------------+-------------------------------------------------------+ +| `Visual Studio 2017`_ (Optional) | C++ compiler and dev environment. | ++-----------------------------------+-------------------------------------------------------+ + +If you've already had one IDE and only need compiler and libraries, +you could install Visual Studio 2017 Build Tools. + +Visual Studio 2017 provides both IDE and necessary compiler and libraries. +So if you have not got an IDE and prefer to develop solidity, Visual Studio 2017 +may be an choice for you to get everything setup easily. + +Here is the list of components that should be installed +in Visual Studio 2017 Build Tools or Visual Studio 2017: + +* Visual Studio C++ core features +* VC++ 2017 v141 toolset (x86,x64) +* Windows Universal CRT SDK +* Windows 8.1 SDK +* C++/CLI support .. _Git for Windows: https://git-scm.com/download/win .. _CMake: https://cmake.org/download/ -.. _Visual Studio 2015: https://www.visualstudio.com/products/vs-2015-product-editions +.. _Visual Studio 2017: https://www.visualstudio.com/vs/ +.. _Visual Studio 2017 Build Tools: https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017 External Dependencies @@ -263,7 +282,7 @@ And even for Windows: mkdir build cd build - cmake -G "Visual Studio 14 2015 Win64" .. + cmake -G "Visual Studio 15 2017 Win64" .. This latter set of instructions should result in the creation of **solidity.sln** in that build directory. Double-clicking on that file diff --git a/docs/introduction-to-smart-contracts.rst b/docs/introduction-to-smart-contracts.rst index 84b1fff8..d1789c44 100644 --- a/docs/introduction-to-smart-contracts.rst +++ b/docs/introduction-to-smart-contracts.rst @@ -25,7 +25,7 @@ Storage storedData = x; } - function get() public constant returns (uint) { + function get() public view returns (uint) { return storedData; } } diff --git a/docs/julia.rst b/docs/julia.rst index 078bc55b..c9b73db2 100644 --- a/docs/julia.rst +++ b/docs/julia.rst @@ -306,12 +306,20 @@ Type Conversion Functions JULIA has no support for implicit type conversion and therefore functions exists to provide explicit conversion. When converting a larger type to a shorter type a runtime exception can occur in case of an overflow. -The following type conversion functions must be available: -- ``u32tobool(x:u32) -> y:bool`` -- ``booltou32(x:bool) -> y:u32`` -- ``u32tou64(x:u32) -> y:u64`` -- ``u64tou32(x:u64) -> y:u32`` -- etc. (TBD) +Truncating conversions are supported between the following types: + - ``bool`` + - ``u32`` + - ``u64`` + - ``u256`` + - ``s256`` + +For each of these a type conversion function exists having the prototype in the form of ``<input_type>to<output_type>(x:<input_type>) -> y:<output_type>``, +such as ``u32tobool(x:u32) -> y:bool``, ``u256tou32(x:u256) -> y:u32`` or ``s256tou256(x:s256) -> y:u256``. + +.. note:: + + ``u32tobool(x:u32) -> y:bool`` can be implemented as ``y := not(iszerou256(x))`` and + ``booltou32(x:bool) -> y:u32`` can be implemented as ``switch x case true:bool { y := 1:u32 } case false:bool { y := 0:u32 }`` Low-level Functions ------------------- @@ -319,6 +327,16 @@ Low-level Functions The following functions must be available: +---------------------------------------------------------------------------------------------------------------+ +| *Logic* | ++---------------------------------------------+-----------------------------------------------------------------+ +| not(x:bool) -> z:bool | logical not | ++---------------------------------------------+-----------------------------------------------------------------+ +| and(x:bool, y:bool) -> z:bool | logical and | ++---------------------------------------------+-----------------------------------------------------------------+ +| or(x:bool, y:bool) -> z:bool | logical or | ++---------------------------------------------+-----------------------------------------------------------------+ +| xor(x:bool, y:bool) -> z:bool | xor | ++---------------------------------------------+-----------------------------------------------------------------+ | *Arithmetics* | +---------------------------------------------+-----------------------------------------------------------------+ | addu256(x:u256, y:u256) -> z:u256 | x + y | @@ -343,15 +361,19 @@ The following functions must be available: +---------------------------------------------+-----------------------------------------------------------------+ | mulmodu256(x:u256, y:u256, m:u256) -> z:u256| (x * y) % m with arbitrary precision arithmetics | +---------------------------------------------+-----------------------------------------------------------------+ -| ltu256(x:u256, y:u256) -> z:bool | 1 if x < y, 0 otherwise | +| ltu256(x:u256, y:u256) -> z:bool | true if x < y, false otherwise | +---------------------------------------------+-----------------------------------------------------------------+ -| gtu256(x:u256, y:u256) -> z:bool | 1 if x > y, 0 otherwise | +| gtu256(x:u256, y:u256) -> z:bool | true if x > y, false otherwise | +---------------------------------------------+-----------------------------------------------------------------+ -| sltu256(x:s256, y:s256) -> z:bool | 1 if x < y, 0 otherwise, for signed numbers in two's complement | +| sltu256(x:s256, y:s256) -> z:bool | true if x < y, false otherwise | +| | (for signed numbers in two's complement) | +---------------------------------------------+-----------------------------------------------------------------+ -| sgtu256(x:s256, y:s256) -> z:bool | 1 if x > y, 0 otherwise, for signed numbers in two's complement | +| sgtu256(x:s256, y:s256) -> z:bool | true if x > y, false otherwise | +| | (for signed numbers in two's complement) | +---------------------------------------------+-----------------------------------------------------------------+ -| equ256(x:u256, y:u256) -> z:bool | 1 if x == y, 0 otherwise | +| equ256(x:u256, y:u256) -> z:bool | true if x == y, false otherwise | ++---------------------------------------------+-----------------------------------------------------------------+ +| iszerou256(x:u256) -> z:bool | true if x == 0, false otherwise | +---------------------------------------------+-----------------------------------------------------------------+ | notu256(x:u256) -> z:u256 | ~x, every bit of x is negated | +---------------------------------------------+-----------------------------------------------------------------+ @@ -405,10 +427,6 @@ The following functions must be available: | insize:u256, out:u256, | but also keep ``caller`` | | outsize:u256) -> r:u256 | and ``callvalue`` | +---------------------------------------------+-----------------------------------------------------------------+ -| stop() | stop execution, identical to return(0,0) | -| | Perhaps it would make sense retiring this as it equals to | -| | return(0,0). It can be an optimisation by the EVM backend. | -+---------------------------------------------+-----------------------------------------------------------------+ | abort() | abort (equals to invalid instruction on EVM) | +---------------------------------------------+-----------------------------------------------------------------+ | return(p:u256, s:u256) | end execution, return data mem[p..(p+s)) | @@ -473,15 +491,17 @@ The following functions must be available: +---------------------------------------------+-----------------------------------------------------------------+ | *Others* | +---------------------------------------------+-----------------------------------------------------------------+ +| discard(unused:bool) | discard value | ++---------------------------------------------+-----------------------------------------------------------------+ | discardu256(unused:u256) | discard value | +---------------------------------------------+-----------------------------------------------------------------+ | splitu256tou64(x:u256) -> (x1:u64, x2:u64, | split u256 to four u64's | -| x3:u64, x4:u64) | | +| x3:u64, x4:u64) | | +---------------------------------------------+-----------------------------------------------------------------+ | combineu64tou256(x1:u64, x2:u64, x3:u64, | combine four u64's into a single u256 | -| x4:u64) -> (x:u256) | | +| x4:u64) -> (x:u256) | | +---------------------------------------------+-----------------------------------------------------------------+ -| sha3(p:u256, s:u256) -> v:u256 | keccak(mem[p...(p+s))) | +| keccak256(p:u256, s:u256) -> v:u256 | keccak(mem[p...(p+s))) | +---------------------------------------------+-----------------------------------------------------------------+ Backends diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..0607b1ef --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +sphinx_rtd_theme>=0.3.1 diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst index 3e1c3a12..4133edb1 100644 --- a/docs/security-considerations.rst +++ b/docs/security-considerations.rst @@ -120,7 +120,7 @@ Gas Limit and Loops Loops that do not have a fixed number of iterations, for example, loops that depend on storage values, have to be used carefully: Due to the block gas limit, transactions can only consume a certain amount of gas. Either explicitly or just due to normal operation, the number of iterations in a loop can grow beyond the block gas limit which can cause the complete -contract to be stalled at a certain point. This may not apply to ``constant`` functions that are only executed +contract to be stalled at a certain point. This may not apply to ``view`` functions that are only executed to read data from the blockchain. Still, such functions may be called by other contracts as part of on-chain operations and stall those. Please be explicit about such cases in the documentation of your contracts. diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst index 546767e4..2b3d4b48 100644 --- a/docs/solidity-by-example.rst +++ b/docs/solidity-by-example.rst @@ -66,7 +66,7 @@ of votes. Proposal[] public proposals; /// Create a new ballot to choose one of `proposalNames`. - function Ballot(bytes32[] proposalNames) public { + constructor(bytes32[] proposalNames) public { chairperson = msg.sender; voters[chairperson].weight = 1; @@ -256,7 +256,7 @@ activate themselves. /// Create a simple auction with `_biddingTime` /// seconds bidding time on behalf of the /// beneficiary address `_beneficiary`. - function SimpleAuction( + constructor( uint _biddingTime, address _beneficiary ) public { @@ -388,7 +388,7 @@ high or low invalid bids. :: - pragma solidity ^0.4.22; + pragma solidity >0.4.23 <0.5.0; contract BlindAuction { struct Bid { @@ -418,7 +418,7 @@ high or low invalid bids. modifier onlyBefore(uint _time) { require(now < _time); _; } modifier onlyAfter(uint _time) { require(now > _time); _; } - function BlindAuction( + constructor( uint _biddingTime, uint _revealTime, address _beneficiary @@ -467,8 +467,8 @@ high or low invalid bids. uint refund; for (uint i = 0; i < length; i++) { - var bid = bids[msg.sender][i]; - var (value, fake, secret) = + Bid storage bid = bids[msg.sender][i]; + (uint value, bool fake, bytes32 secret) = (_values[i], _fake[i], _secret[i]); if (bid.blindedBid != keccak256(value, fake, secret)) { // Bid was not actually revealed. @@ -553,7 +553,7 @@ Safe Remote Purchase // Ensure that `msg.value` is an even number. // Division will truncate if it is an odd number. // Check via multiplication that it wasn't an odd number. - function Purchase() public payable { + constructor() public payable { seller = msg.sender; value = msg.value / 2; require((2 * value) == msg.value, "Value has to be even."); @@ -602,7 +602,7 @@ Safe Remote Purchase { emit Aborted(); state = State.Inactive; - seller.transfer(this.balance); + seller.transfer(address(this).balance); } /// Confirm the purchase as buyer. @@ -637,7 +637,7 @@ Safe Remote Purchase // block the refund - the withdraw pattern should be used. buyer.transfer(value); - seller.transfer(this.balance); + seller.transfer(address(this).balance); } } diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst index d57f1703..7a6317eb 100644 --- a/docs/structure-of-a-contract.rst +++ b/docs/structure-of-a-contract.rst @@ -129,7 +129,7 @@ Structs are custom defined types that can group several variables (see Enum Types ========== -Enums can be used to create custom types with a finite set of values (see +Enums can be used to create custom types with a finite set of 'constant values' (see :ref:`enums` in types section). :: diff --git a/docs/style-guide.rst b/docs/style-guide.rst index ee1ea4bd..6b28f2ab 100644 --- a/docs/style-guide.rst +++ b/docs/style-guide.rst @@ -117,7 +117,7 @@ No:: Maximum Line Length =================== -Keeping lines under the `PEP 8 recommendation <https://www.python.org/dev/peps/pep-0008/#maximum-line-length>`_ of 79 (or 99) +Keeping lines under the `PEP 8 recommendation <https://www.python.org/dev/peps/pep-0008/#maximum-line-length>`_ to a maximum of 79 (or 99) characters helps readers easily parse the code. Wrapped lines should conform to the following guidelines. @@ -269,7 +269,7 @@ Functions should be grouped according to their visibility and ordered: - internal - private -Within a grouping, place the ``constant`` functions last. +Within a grouping, place the ``view`` and ``pure`` functions last. Yes:: @@ -285,7 +285,10 @@ Yes:: // External functions // ... - // External functions that are constant + // External functions that are view + // ... + + // External functions that are pure // ... // Public functions diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst index 51f7b9f3..a6f8ca87 100644 --- a/docs/units-and-global-variables.rst +++ b/docs/units-and-global-variables.rst @@ -31,6 +31,9 @@ because of `leap seconds <https://en.wikipedia.org/wiki/Leap_second>`_. Due to the fact that leap seconds cannot be predicted, an exact calendar library has to be updated by an external oracle. +.. note:: + The suffix ``years`` has been deprecated due to the reasons above. + These suffixes cannot be applied to variables. If you want to interpret some input variable in e.g. days, you can do it in the following way:: @@ -117,11 +120,11 @@ Error Handling -------------- ``assert(bool condition)``: - throws if the condition is not met - to be used for internal errors. + invalidates the transaction if the condition is not met - to be used for internal errors. ``require(bool condition)``: - throws if the condition is not met - to be used for errors in inputs or external components. + reverts if the condition is not met - to be used for errors in inputs or external components. ``require(bool condition, string message)``: - throws if the condition is not met - to be used for errors in inputs or external components. Also provides an error message. + reverts if the condition is not met - to be used for errors in inputs or external components. Also provides an error message. ``revert()``: abort execution and revert state changes ``revert(string reason)``: diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst index df30b6b4..1d7cb97b 100644 --- a/docs/using-the-compiler.rst +++ b/docs/using-the-compiler.rst @@ -14,7 +14,9 @@ Using the Commandline Compiler One of the build targets of the Solidity repository is ``solc``, the solidity commandline compiler. Using ``solc --help`` provides you with an explanation of all options. The compiler can produce various outputs, ranging from simple binaries and assembly over an abstract syntax tree (parse tree) to estimations of gas usage. -If you only want to compile a single file, you run it as ``solc --bin sourceFile.sol`` and it will print the binary. Before you deploy your contract, activate the optimizer while compiling using ``solc --optimize --bin sourceFile.sol``. If you want to get some of the more advanced output variants of ``solc``, it is probably better to tell it to output everything to separate files using ``solc -o outputDirectory --bin --ast --asm sourceFile.sol``. +If you only want to compile a single file, you run it as ``solc --bin sourceFile.sol`` and it will print the binary. If you want to get some of the more advanced output variants of ``solc``, it is probably better to tell it to output everything to separate files using ``solc -o outputDirectory --bin --ast --asm sourceFile.sol``. + +Before you deploy your contract, activate the optimizer while compiling using ``solc --optimize --bin sourceFile.sol``. By default, the optimizer will optimize the contract for 200 runs. If you want to optimize for initial contract deployment and get the smallest output, set it to ``--runs=1``. If you expect many transactions and don't care for higher deployment cost and output size, set ``--runs`` to a high number. The commandline compiler will automatically read imported files from the filesystem, but it is also possible to provide path redirects using ``prefix=path`` in the following way: @@ -96,10 +98,13 @@ Input Description { // Optional: Sorted list of remappings remappings: [ ":g/dir" ], - // Optional: Optimizer settings (enabled defaults to false) + // Optional: Optimizer settings optimizer: { + // disabled by default enabled: true, - runs: 500 + // Optimize for how many times you intend to run the code. + // Lower values will optimize more for initial deployment cost, higher values will optimize more for high-frequency usage. + runs: 200 }, evmVersion: "byzantium", // Version of the EVM to compile for. Affects type checking and code generation. Can be homestead, tangerineWhistle, spuriousDragon, byzantium or constantinople // Metadata settings (optional) |