aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/abi-spec.rst45
-rw-r--r--docs/assembly.rst59
-rw-r--r--docs/bugs_by_version.json4
-rw-r--r--docs/contracts.rst143
-rw-r--r--docs/control-structures.rst22
-rw-r--r--docs/grammar.txt10
-rw-r--r--docs/index.rst17
-rw-r--r--docs/julia.rst564
-rw-r--r--docs/metadata.rst2
-rw-r--r--docs/security-considerations.rst73
-rw-r--r--docs/solidity-by-example.rst7
-rw-r--r--docs/structure-of-a-contract.rst86
-rw-r--r--docs/style-guide.rst6
-rw-r--r--docs/types.rst2
-rw-r--r--docs/units-and-global-variables.rst5
-rw-r--r--docs/using-the-compiler.rst23
-rw-r--r--docs/utils/SolidityLexer.py10
17 files changed, 887 insertions, 191 deletions
diff --git a/docs/abi-spec.rst b/docs/abi-spec.rst
index 77d15026..e968fb06 100644
--- a/docs/abi-spec.rst
+++ b/docs/abi-spec.rst
@@ -330,15 +330,15 @@ For example,
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract Test {
- function Test(){ b = 0x12345678901234567890123456789012; }
- event Event(uint indexed a, bytes32 b);
- event Event2(uint indexed a, bytes32 b);
- function foo(uint a) { Event(a, b); }
- bytes32 b;
- }
+ contract Test {
+ function Test(){ b = 0x12345678901234567890123456789012; }
+ event Event(uint indexed a, bytes32 b);
+ event Event2(uint indexed a, bytes32 b);
+ function foo(uint a) { Event(a, b); }
+ bytes32 b;
+ }
would result in the JSON:
@@ -377,11 +377,15 @@ As an example, the code
::
- contract Test {
- struct S { uint a; uint[] b; T[] c; }
- struct T { uint x; uint y; }
- function f(S s, T t, uint a) { }
- }
+ pragma solidity ^0.4.19;
+ pragma experimental ABIEncoderV2;
+
+ contract Test {
+ struct S { uint a; uint[] b; T[] c; }
+ struct T { uint x; uint y; }
+ function f(S s, T t, uint a) { }
+ function g() returns (S s, T t, uint a) {}
+ }
would result in the JSON:
@@ -451,13 +455,18 @@ Non-standard Packed Mode
Solidity supports a non-standard packed mode where:
- no :ref:`function selector <abi_function_selector>` is encoded,
-- short types are not zero padded and
+- 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 ``uint1, bytes1, uint8, string`` with values ``1, 0x42, 0x2424, "Hello, world!"`` results in ::
+As an example encoding ``int1, bytes1, uint16, string`` with values ``-1, 0x42, 0x2424, "Hello, world!"`` results in ::
- 0x0142242448656c6c6f2c20776f726c6421
- ^^ uint1(1)
+ 0xff42242448656c6c6f2c20776f726c6421
+ ^^ int1(-1)
^^ bytes1(0x42)
- ^^^^ uint8(0x2424)
+ ^^^^ uint16(0x2424)
^^^^^^^^^^^^^^^^^^^^^^^^^^ string("Hello, world!") without a length field
+
+More specifically, each statically-sized type takes as many bytes as its range has
+and dynamically-sized types like ``string``, ``bytes`` or ``uint[]`` are encoded without
+their length field. This means that the encoding is ambiguous as soon as there are two
+dynamically-sized elements.
diff --git a/docs/assembly.rst b/docs/assembly.rst
index f5abcdc8..a4fa88c6 100644
--- a/docs/assembly.rst
+++ b/docs/assembly.rst
@@ -9,11 +9,6 @@ This assembly language can also be used as "inline assembly" inside Solidity
source code. We start with describing how to use inline assembly and how it
differs from standalone assembly and then specify assembly itself.
-.. note::
- TODO: Write about how scoping rules of inline assembly are a bit different
- and the complications that arise when for example using internal functions
- of libraries. Furthermore, write about the symbols defined by the compiler.
-
.. _inline-assembly:
Inline Assembly
@@ -31,6 +26,7 @@ arising when writing manual assembly by the following features:
* access to external variables: ``function f(uint x) { assembly { x := sub(x, 1) } }``
* labels: ``let x := 10 repeat: x := sub(x, 1) jumpi(repeat, eq(x, 0))``
* loops: ``for { let i := 0 } lt(i, x) { i := add(i, 1) } { y := mul(2, y) }``
+* if statements: ``if slt(x, 0) { x := sub(0, x) }``
* switch statements: ``switch x case 0 { y := mul(x, 2) } default { y := 0 }``
* function calls: ``function f(x) -> y { switch x case 0 { y := 1 } default { y := mul(x, f(sub(x, 1))) } }``
@@ -41,6 +37,11 @@ We now want to describe the inline assembly language in detail.
at a low level. This discards several important safety
features of Solidity.
+.. note::
+ TODO: Write about how scoping rules of inline assembly are a bit different
+ and the complications that arise when for example using internal functions
+ of libraries. Furthermore, write about the symbols defined by the compiler.
+
Example
-------
@@ -400,7 +401,7 @@ Labels
Another problem in EVM assembly is that ``jump`` and ``jumpi`` use absolute addresses
which can change easily. Solidity inline assembly provides labels to make the use of
jumps easier. Note that labels are a low-level feature and it is possible to write
-efficient assembly without labels, just using assembly functions, loops and switch instructions
+efficient assembly without labels, just using assembly functions, loops, if and switch instructions
(see below). The following code computes an element in the Fibonacci series.
.. code::
@@ -446,31 +447,6 @@ will have a wrong impression about the stack height at label ``two``:
three:
}
-This problem can be fixed by manually adjusting the stack height for the
-assembler - you can provide a stack height delta that is added
-to the stack height just prior to the label.
-Note that you will not have to care about these things if you just use
-loops and assembly-level functions.
-
-As an example how this can be done in extreme cases, please see the following.
-
-.. code::
-
- {
- let x := 8
- jump(two)
- 0 // This code is unreachable but will adjust the stack height correctly
- one:
- x := 9 // Now x can be accessed properly.
- jump(three)
- pop // Similar negative correction.
- two:
- 7 // push something onto the stack
- jump(one)
- three:
- pop // We have to pop the manually pushed value here again.
- }
-
Declaring Assembly-Local Variables
----------------------------------
@@ -523,6 +499,21 @@ 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
}
+If
+--
+
+The if statement can be used for conditionally executing code.
+There is no "else" part, consider using "switch" (see below) if
+you need multiple alternatives.
+
+.. code::
+
+ {
+ if eq(value, 0) { revert(0, 0) }
+ }
+
+The curly braces for the body are required.
+
Switch
------
@@ -622,7 +613,7 @@ Things to Avoid
---------------
Inline assembly might have a quite high-level look, but it actually is extremely
-low-level. Function calls, loops and switches are converted by simple
+low-level. Function calls, loops, ifs and switches are converted by simple
rewriting rules and after that, the only thing the assembler does for you is re-arranging
functional-style opcodes, managing jump labels, counting stack height for
variable access and removing stack slots for assembly-local variables when the end
@@ -669,7 +660,7 @@ for the Solidity compiler. In this form, it tries to achieve several goals:
3. Control flow should be easy to detect to help in formal verification and optimization.
In order to achieve the first and last goal, assembly provides high-level constructs
-like ``for`` loops, ``switch`` statements and function calls. It should be possible
+like ``for`` loops, ``if`` and ``switch`` statements and function calls. It should be possible
to write assembly programs that do not make use of explicit ``SWAP``, ``DUP``,
``JUMP`` and ``JUMPI`` statements, because the first two obfuscate the data flow
and the last two obfuscate control flow. Furthermore, functional statements of
@@ -875,6 +866,7 @@ Grammar::
FunctionalAssemblyAssignment |
AssemblyAssignment |
LabelDefinition |
+ AssemblyIf |
AssemblySwitch |
AssemblyFunctionDefinition |
AssemblyFor |
@@ -891,6 +883,7 @@ Grammar::
IdentifierList = Identifier ( ',' Identifier)*
AssemblyAssignment = '=:' Identifier
LabelDefinition = Identifier ':'
+ AssemblyIf = 'if' FunctionalAssemblyExpression AssemblyBlock
AssemblySwitch = 'switch' FunctionalAssemblyExpression AssemblyCase*
( 'default' AssemblyBlock )?
AssemblyCase = 'case' FunctionalAssemblyExpression AssemblyBlock
diff --git a/docs/bugs_by_version.json b/docs/bugs_by_version.json
index cca45428..3a8ff9a1 100644
--- a/docs/bugs_by_version.json
+++ b/docs/bugs_by_version.json
@@ -397,6 +397,10 @@
"bugs": [],
"released": "2017-10-18"
},
+ "0.4.19": {
+ "bugs": [],
+ "released": "2017-11-30"
+ },
"0.4.2": {
"bugs": [
"ZeroFunctionSelector",
diff --git a/docs/contracts.rst b/docs/contracts.rst
index cdc92315..ca4e79c0 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -198,7 +198,6 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
function compute(uint a, uint b) internal returns (uint) { return a+b; }
}
-
contract D {
function readData() {
C c = new C();
@@ -209,11 +208,10 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
}
}
-
contract E is C {
function g() {
C c = new C();
- uint val = compute(3, 5); // acces to internal member (from derivated to parent contract)
+ uint val = compute(3, 5); // access to internal member (from derived to parent contract)
}
}
@@ -238,7 +236,6 @@ be done at declaration.
uint public data = 42;
}
-
contract Caller {
C c = new C();
function f() {
@@ -321,7 +318,6 @@ inheritable properties of contracts and may be overridden by derived contracts.
}
}
-
contract mortal is owned {
// This contract inherits the "onlyOwner"-modifier from
// "owned" and applies it to the "close"-function, which
@@ -332,7 +328,6 @@ inheritable properties of contracts and may be overridden by derived contracts.
}
}
-
contract priced {
// Modifiers can receive arguments:
modifier costs(uint price) {
@@ -342,7 +337,6 @@ inheritable properties of contracts and may be overridden by derived contracts.
}
}
-
contract Register is priced, owned {
mapping (address => bool) registeredAddresses;
uint price;
@@ -432,12 +426,20 @@ value types and strings.
bytes32 constant myHash = keccak256("abc");
}
+.. index:: ! functions
+
+.. _functions:
+
+*********
+Functions
+*********
+
+.. index:: ! view function, function;view
.. _view-functions:
-**************
View Functions
-**************
+==============
Functions can be declared ``view`` in which case they promise not to modify the state.
@@ -471,11 +473,12 @@ The following statements are considered modifying the state:
.. warning::
The compiler does not enforce yet that a ``view`` method is not modifying state.
+.. index:: ! pure function, function;pure
+
.. _pure-functions:
-**************
Pure Functions
-**************
+==============
Functions can be declared ``pure`` in which case they promise not to read from or modify the state.
@@ -504,9 +507,8 @@ In addition to the list of state modifying statements explained above, the follo
.. _fallback-function:
-*****************
Fallback Function
-*****************
+=================
A contract can have exactly one unnamed function. This function cannot have
arguments and cannot return anything.
@@ -570,7 +572,6 @@ Please ensure you test your fallback function thoroughly to ensure the execution
function() payable { }
}
-
contract Caller {
function callTest(Test test) {
test.call(0xabcdef01); // hash does not exist
@@ -584,6 +585,85 @@ Please ensure you test your fallback function thoroughly to ensure the execution
}
}
+.. index:: ! overload
+
+.. _overload-function:
+
+Function Overloading
+====================
+
+A Contract can have multiple functions of the same name but with different arguments.
+This also applies to inherited functions. The following example shows overloading of the
+``f`` function in the scope of contract ``A``.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(uint _in) public pure returns (uint out) {
+ out = 1;
+ }
+
+ function f(uint _in, bytes32 _key) public pure returns (uint out) {
+ out = 2;
+ }
+ }
+
+Overloaded functions are also present in the external interface. It is an error if two
+externally visible functions differ by their Solidity types but not by their external types.
+
+::
+
+ // This will not compile
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(B _in) public pure returns (B out) {
+ out = _in;
+ }
+
+ function f(address _in) public pure returns (address out) {
+ out = _in;
+ }
+ }
+
+ contract B {
+ }
+
+
+Both ``f`` function overloads above end up accepting the address type for the ABI although
+they are considered different inside Solidity.
+
+Overload resolution and Argument matching
+-----------------------------------------
+
+Overloaded functions are selected by matching the function declarations in the current scope
+to the arguments supplied in the function call. Functions are selected as overload candidates
+if all arguments can be implicitly converted to the expected types. If there is not exactly one
+candidate, resolution fails.
+
+.. note::
+ Return parameters are not taken into account for overload resolution.
+
+::
+
+ pragma solidity ^0.4.16;
+
+ contract A {
+ function f(uint8 _in) public pure returns (uint8 out) {
+ out = _in;
+ }
+
+ function f(uint256 _in) public pure returns (uint256 out) {
+ out = _in;
+ }
+ }
+
+Calling ``f(50)`` would create a type error since ``250`` can be implicitly converted both to ``uint8``
+and ``uint256`` types. On another hand ``f(256)`` would resolve to ``f(uint256)`` overload as ``256`` cannot be implicitly
+converted to ``uint8``.
+
.. index:: ! event
.. _events:
@@ -687,12 +767,19 @@ as topics. The event call above can be performed in the same way as
::
- log3(
- msg.value,
- 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20,
- msg.sender,
- _id
- );
+ pragma solidity ^0.4.10;
+
+ contract C {
+ function f() {
+ bytes32 _id = 0x420042;
+ log3(
+ bytes32(msg.value),
+ bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
+ bytes32(msg.sender),
+ _id
+ );
+ }
+ }
where the long hexadecimal number is equal to
``keccak256("Deposit(address,hash256,uint256)")``, the signature of the event.
@@ -734,7 +821,6 @@ Details are given in the following example.
address owner;
}
-
// Use "is" to derive from another contract. Derived
// contracts can access all non-private members including
// internal functions and state variables. These cannot be
@@ -745,7 +831,6 @@ Details are given in the following example.
}
}
-
// These abstract contracts are only provided to make the
// interface known to the compiler. Note the function
// without body. If a contract does not implement all
@@ -754,13 +839,11 @@ Details are given in the following example.
function lookup(uint id) returns (address adr);
}
-
contract NameReg {
function register(bytes32 name);
function unregister();
}
-
// Multiple inheritance is possible. Note that "owned" is
// also a base class of "mortal", yet there is only a single
// instance of "owned" (as for virtual inheritance in C++).
@@ -786,7 +869,6 @@ Details are given in the following example.
}
}
-
// If a constructor takes an argument, it needs to be
// provided in the header (or modifier-invocation-style at
// the constructor of the derived contract (see below)).
@@ -821,12 +903,10 @@ seen in the following example::
function kill() { /* do cleanup 1 */ mortal.kill(); }
}
-
contract Base2 is mortal {
function kill() { /* do cleanup 2 */ mortal.kill(); }
}
-
contract Final is Base1, Base2 {
}
@@ -848,7 +928,6 @@ derived override, but this function will bypass
}
}
-
contract Base1 is mortal {
function kill() { /* do cleanup 1 */ super.kill(); }
}
@@ -858,12 +937,11 @@ derived override, but this function will bypass
function kill() { /* do cleanup 2 */ super.kill(); }
}
-
contract Final is Base2, Base1 {
}
If ``Base1`` calls a function of ``super``, it does not simply
-call this function on one of its base contracts. Rather, it
+call this function on one of its base contracts. Rather, it
calls this function on the next base contract in the final
inheritance graph, so it will call ``Base2.kill()`` (note that
the final inheritance sequence is -- starting with the most
@@ -888,7 +966,6 @@ the base constructors. This can be done in two ways::
function Base(uint _x) { x = _x; }
}
-
contract Derived is Base(7) {
function Derived(uint _y) Base(_y * _y) {
}
@@ -1081,7 +1158,6 @@ more advanced example to implement a set).
}
}
-
contract C {
Set.Data knownValues;
@@ -1157,7 +1233,6 @@ custom types without the overhead of external function calls:
}
}
-
contract C {
using BigInt for BigInt.bigint;
@@ -1250,7 +1325,6 @@ Let us rewrite the set example from the
}
}
-
contract C {
using Set for Set.Data; // this is the crucial change
Set.Data knownValues;
@@ -1276,7 +1350,6 @@ It is also possible to extend elementary types in that way::
}
}
-
contract C {
using Search for uint[];
uint[] data;
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 0497365b..bcb597cf 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -194,7 +194,7 @@ Omitted Function Parameter Names
--------------------------------
The names of unused parameters (especially return parameters) can be omitted.
-Those names will still be present on the stack, but they are inaccessible.
+Those parameters will still be present on the stack, but they are inaccessible.
::
@@ -363,15 +363,19 @@ As a result, the following code is illegal and cause the compiler to throw an er
In addition to this, if a variable is declared, it will be initialized at the beginning of the function to its default value.
As a result, the following code is legal, despite being poorly written::
- function foo() returns (uint) {
- // baz is implicitly initialized as 0
- uint bar = 5;
- if (true) {
- bar += baz;
- } else {
- uint baz = 10;// never executes
+ pragma solidity ^0.4.0;
+
+ contract C {
+ function foo() returns (uint) {
+ // baz is implicitly initialized as 0
+ uint bar = 5;
+ if (true) {
+ bar += baz;
+ } else {
+ uint baz = 10;// never executes
+ }
+ return bar;// returns 5
}
- return bar;// returns 5
}
.. index:: ! exception, ! throw, ! assert, ! require, ! revert
diff --git a/docs/grammar.txt b/docs/grammar.txt
index 72364b7c..ce3fd3ad 100644
--- a/docs/grammar.txt
+++ b/docs/grammar.txt
@@ -127,10 +127,10 @@ StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
Identifier = [a-zA-Z_$] [a-zA-Z_$0-9]*
HexNumber = '0x' [0-9a-fA-F]+
-DecimalNumber = [0-9]+
+DecimalNumber = [0-9]+ ( '.' [0-9]* )? ( [eE] [0-9]+ )?
-TupleExpression = '(' ( Expression ( ',' Expression )* )? ')'
- | '[' ( Expression ( ',' Expression )* )? ']'
+TupleExpression = '(' ( Expression? ( ',' Expression? )* )? ')'
+ | '[' ( Expression ( ',' Expression )* )? ']'
ElementaryTypeNameExpression = ElementaryTypeName
@@ -143,9 +143,9 @@ Uint = 'uint' | 'uint8' | 'uint16' | 'uint24' | 'uint32' | 'uint40' | 'uint48' |
Byte = 'byte' | 'bytes' | 'bytes1' | 'bytes2' | 'bytes3' | 'bytes4' | 'bytes5' | 'bytes6' | 'bytes7' | 'bytes8' | 'bytes9' | 'bytes10' | 'bytes11' | 'bytes12' | 'bytes13' | 'bytes14' | 'bytes15' | 'bytes16' | 'bytes17' | 'bytes18' | 'bytes19' | 'bytes20' | 'bytes21' | 'bytes22' | 'bytes23' | 'bytes24' | 'bytes25' | 'bytes26' | 'bytes27' | 'bytes28' | 'bytes29' | 'bytes30' | 'bytes31' | 'bytes32'
-Fixed = 'fixed' | ( 'fixed' DecimalNumber 'x' DecimalNumber )
+Fixed = 'fixed' | ( 'fixed' [0-9]+ 'x' [0-9]+ )
-Ufixed = 'ufixed' | ( 'ufixed' DecimalNumber 'x' DecimalNumber )
+Ufixed = 'ufixed' | ( 'ufixed' [0-9]+ 'x' [0-9]+ )
InlineAssemblyBlock = '{' AssemblyItem* '}'
diff --git a/docs/index.rst b/docs/index.rst
index 351f8ad7..3c617d36 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -6,8 +6,9 @@ Solidity
:alt: Solidity logo
:align: center
-Solidity is a contract-oriented, high-level language whose syntax is similar to that of JavaScript
-and it is designed to target the Ethereum Virtual Machine (EVM).
+Solidity is a contract-oriented, high-level language for implementing smart contracts.
+It was influenced by C++, Python and JavaScript
+and is designed to target the Ethereum Virtual Machine (EVM).
Solidity is statically typed, supports inheritance, libraries and complex
user-defined types among other features.
@@ -20,6 +21,15 @@ crowdfunding, blind auctions, multi-signature wallets and more.
`Remix <https://remix.ethereum.org/>`_
(it can take a while to load, please be patient).
+Translations
+------------
+
+This documentation is translated into several languages by community volunteers, but the English version stands as a reference.
+
+* `Spanish <https://solidity-es.readthedocs.io>`_
+* `Russian <https://github.com/ethereum/wiki/wiki/%5BRussian%5D-%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity>`_ (rather outdated)
+
+
Useful links
------------
@@ -131,8 +141,6 @@ If you still have questions, you can try searching or asking on the
site, or come to our `gitter channel <https://gitter.im/ethereum/solidity/>`_.
Ideas for improving Solidity or this documentation are always welcome!
-See also `Russian version (русский перевод) <https://github.com/ethereum/wiki/wiki/%5BRussian%5D-%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE-%D0%BF%D0%BE-Solidity>`_.
-
Contents
========
@@ -149,6 +157,7 @@ Contents
using-the-compiler.rst
metadata.rst
abi-spec.rst
+ julia.rst
style-guide.rst
common-patterns.rst
bugs.rst
diff --git a/docs/julia.rst b/docs/julia.rst
new file mode 100644
index 00000000..309e6b36
--- /dev/null
+++ b/docs/julia.rst
@@ -0,0 +1,564 @@
+#################################################
+Joyfully Universal Language for (Inline) Assembly
+#################################################
+
+.. _julia:
+
+.. index:: ! assembly, ! asm, ! evmasm, ! julia
+
+JULIA is an intermediate language that can compile to various different backends
+(EVM 1.0, EVM 1.5 and eWASM are planned).
+Because of that, it is designed to be a usable common denominator of all three
+platforms.
+It can already be used for "inline assembly" inside Solidity and
+future versions of the Solidity compiler will even use JULIA as intermediate
+language. It should also be easy to build high-level optimizer stages for JULIA.
+
+The core components of JULIA are functions, blocks, variables, literals,
+for-loops, if-statements, switch-statements, expressions and assignments to variables.
+
+JULIA is typed, both variables and literals must specify the type with postfix
+notation. The supported types are ``bool``, ``u8``, ``s8``, ``u32``, ``s32``,
+``u64``, ``s64``, ``u128``, ``s128``, ``u256`` and ``s256``.
+
+JULIA in itself does not even provide operators. If the EVM is targeted,
+opcodes will be available as built-in functions, but they can be reimplemented
+if the backend changes. For a list of mandatory built-in functions, see the section below.
+
+The following example program assumes that the EVM opcodes ``mul``, ``div``
+and ``mod`` are available either natively or as functions and computes exponentiation.
+
+.. code::
+
+ {
+ function power(base:u256, exponent:u256) -> result:u256
+ {
+ switch exponent
+ case 0:u256 { result := 1:u256 }
+ case 1:u256 { result := base }
+ default:
+ {
+ result := power(mul(base, base), div(exponent, 2:u256))
+ switch mod(exponent, 2:u256)
+ case 1:u256 { result := mul(base, result) }
+ }
+ }
+ }
+
+It is also possible to implement the same function using a for-loop
+instead of with recursion. Here, we need the EVM opcodes ``lt`` (less-than)
+and ``add`` to be available.
+
+.. code::
+
+ {
+ function power(base:u256, exponent:u256) -> result:u256
+ {
+ result := 1:u256
+ for { let i := 0:u256 } lt(i, exponent) { i := add(i, 1:u256) }
+ {
+ result := mul(result, base)
+ }
+ }
+ }
+
+Specification of JULIA
+======================
+
+JULIA code is described in this chapter. JULIA code is usually placed into a JULIA object, which is described in the following chapter.
+
+Grammar::
+
+ Block = '{' Statement* '}'
+ Statement =
+ Block |
+ FunctionDefinition |
+ VariableDeclaration |
+ Assignment |
+ Expression |
+ Switch |
+ ForLoop |
+ BreakContinue
+ FunctionDefinition =
+ 'function' Identifier '(' TypedIdentifierList? ')'
+ ( '->' TypedIdentifierList )? Block
+ VariableDeclaration =
+ 'let' TypedIdentifierList ( ':=' Expression )?
+ Assignment =
+ IdentifierList ':=' Expression
+ Expression =
+ FunctionCall | Identifier | Literal
+ If =
+ 'if' Expression Block
+ Switch =
+ 'switch' Expression Case* ( 'default' Block )?
+ Case =
+ 'case' Literal Block
+ ForLoop =
+ 'for' Block Expression Block Block
+ BreakContinue =
+ 'break' | 'continue'
+ FunctionCall =
+ Identifier '(' ( Expression ( ',' Expression )* )? ')'
+ Identifier = [a-zA-Z_$] [a-zA-Z_0-9]*
+ IdentifierList = Identifier ( ',' Identifier)*
+ TypeName = Identifier | BuiltinTypeName
+ BuiltinTypeName = 'bool' | [us] ( '8' | '32' | '64' | '128' | '256' )
+ TypedIdentifierList = Identifier ':' TypeName ( ',' Identifier ':' TypeName )*
+ Literal =
+ (NumberLiteral | StringLiteral | HexLiteral | TrueLiteral | FalseLiteral) ':' TypeName
+ NumberLiteral = HexNumber | DecimalNumber
+ HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
+ StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
+ TrueLiteral = 'true'
+ FalseLiteral = 'false'
+ HexNumber = '0x' [0-9a-fA-F]+
+ DecimalNumber = [0-9]+
+
+Restrictions on the Grammar
+---------------------------
+
+Switches must have at least one case (including the default case).
+If all possible values of the expression is covered, the default case should
+not be allowed (i.e. a switch with a ``bool`` expression and having both a
+true and false case should not allow a default case).
+
+Every expression evaluates to zero or more values. Identifiers and Literals
+evaluate to exactly
+one value and function calls evaluate to a number of values equal to the
+number of return values of the function called.
+
+In variable declarations and assignments, the right-hand-side expression
+(if present) has to evaluate to a number of values equal to the number of
+variables on the left-hand-side.
+This is the only situation where an expression evaluating
+to more than one value is allowed.
+
+Expressions that are also statements (i.e. at the block level) have to
+evaluate to zero values.
+
+In all other situations, expressions have to evaluate to exactly one value.
+
+The ``continue`` and ``break`` statements can only be used inside loop bodies
+and have to be in the same function as the loop (or both have to be at the
+top level).
+The condition part of the for-loop has to evaluate to exactly one value.
+
+Literals cannot be larger than the their type. The largest type defined is 256-bit wide.
+
+Scoping Rules
+-------------
+
+Scopes in JULIA are tied to Blocks (exceptions are functions and the for loop
+as explained below) and all declarations
+(``FunctionDefinition``, ``VariableDeclaration``)
+introduce new identifiers into these scopes.
+
+Identifiers are visible in
+the block they are defined in (including all sub-nodes and sub-blocks).
+As an exception, identifiers defined in the "init" part of the for-loop
+(the first block) are visible in all other parts of the for-loop
+(but not outside of the loop).
+Identifiers declared in the other parts of the for loop respect the regular
+syntatical scoping rules.
+The parameters and return parameters of functions are visible in the
+function body and their names cannot overlap.
+
+Variables can only be referenced after their declaration. In particular,
+variables cannot be referenced in the right hand side of their own variable
+declaration.
+Functions can be referenced already before their declaration (if they are visible).
+
+Shadowing is disallowed, i.e. you cannot declare an identifier at a point
+where another identifier with the same name is also visible, even if it is
+not accessible.
+
+Inside functions, it is not possible to access a variable that was declared
+outside of that function.
+
+Formal Specification
+--------------------
+
+We formally specify JULIA by providing an evaluation function E overloaded
+on the various nodes of the AST. Any functions can have side effects, so
+E takes two state objects and the AST node and returns two new
+state objects and a variable number of other values.
+The two state objects are the global state object
+(which in the context of the EVM is the memory, storage and state of the
+blockchain) and the local state object (the state of local variables, i.e. a
+segment of the stack in the EVM).
+If the AST node is a statement, E returns the two state objects and a "mode",
+which is used for the ``break`` and ``continue`` statements.
+If the AST node is an expression, E returns the two state objects and
+as many values as the expression evaluates to.
+
+
+The exact nature of the global state is unspecified for this high level
+description. The local state ``L`` is a mapping of identifiers ``i`` to values ``v``,
+denoted as ``L[i] = v``.
+
+For an identifier ``v``, let ``$v`` be the name of the identifier.
+
+We will use a destructuring notation for the AST nodes.
+
+.. code::
+
+ E(G, L, <{St1, ..., Stn}>: Block) =
+ let G1, L1, mode = E(G, L, St1, ..., Stn)
+ let L2 be a restriction of L1 to the identifiers of L
+ G1, L2, mode
+ E(G, L, St1, ..., Stn: Statement) =
+ if n is zero:
+ G, L, regular
+ else:
+ let G1, L1, mode = E(G, L, St1)
+ if mode is regular then
+ E(G1, L1, St2, ..., Stn)
+ otherwise
+ G1, L1, mode
+ E(G, L, FunctionDefinition) =
+ G, L, regular
+ E(G, L, <let var1, ..., varn := rhs>: VariableDeclaration) =
+ E(G, L, <var1, ..., varn := rhs>: Assignment)
+ E(G, L, <let var1, ..., varn>: VariableDeclaration) =
+ let L1 be a copy of L where L1[$vari] = 0 for i = 1, ..., n
+ G, L1, regular
+ E(G, L, <var1, ..., varn := rhs>: Assignment) =
+ let G1, L1, v1, ..., vn = E(G, L, rhs)
+ let L2 be a copy of L1 where L2[$vari] = vi for i = 1, ..., n
+ G, L2, regular
+ E(G, L, <for { i1, ..., in } condition post body>: ForLoop) =
+ if n >= 1:
+ let G1, L1, mode = E(G, L, i1, ..., in)
+ // mode has to be regular due to the syntactic restrictions
+ let G2, L2, mode = E(G1, L1, for {} condition post body)
+ // mode has to be regular due to the syntactic restrictions
+ let L3 be the restriction of L2 to only variables of L
+ G2, L3, regular
+ else:
+ let G1, L1, v = E(G, L, condition)
+ if v is false:
+ G1, L1, regular
+ else:
+ let G2, L2, mode = E(G1, L, body)
+ if mode is break:
+ G2, L2, regular
+ else:
+ G3, L3, mode = E(G2, L2, post)
+ E(G3, L3, for {} condition post body)
+ E(G, L, break: BreakContinue) =
+ G, L, break
+ E(G, L, continue: BreakContinue) =
+ G, L, continue
+ E(G, L, <if condition body>: If) =
+ let G0, L0, v = E(G, L, condition)
+ if v is true:
+ E(G0, L0, body)
+ else:
+ G0, L0, regular
+ E(G, L, <switch condition case l1:t1 st1 ... case ln:tn stn>: Switch) =
+ E(G, L, switch condition case l1:t1 st1 ... case ln:tn stn default {})
+ E(G, L, <switch condition case l1:t1 st1 ... case ln:tn stn default st'>: Switch) =
+ let G0, L0, v = E(G, L, condition)
+ // i = 1 .. n
+ // Evaluate literals, context doesn't matter
+ let _, _, v1 = E(G0, L0, l1)
+ ...
+ let _, _, vn = E(G0, L0, ln)
+ if there exists smallest i such that vi = v:
+ E(G0, L0, sti)
+ else:
+ E(G0, L0, st')
+
+ E(G, L, <name>: Identifier) =
+ G, L, L[$name]
+ E(G, L, <fname(arg1, ..., argn)>: FunctionCall) =
+ G1, L1, vn = E(G, L, argn)
+ ...
+ G(n-1), L(n-1), v2 = E(G(n-2), L(n-2), arg2)
+ Gn, Ln, v1 = E(G(n-1), L(n-1), arg1)
+ Let <function fname (param1, ..., paramn) -> ret1, ..., retm block>
+ be the function of name $fname visible at the point of the call.
+ Let L' be a new local state such that
+ L'[$parami] = vi and L'[$reti] = 0 for all i.
+ Let G'', L'', mode = E(Gn, L', block)
+ G'', Ln, L''[$ret1], ..., L''[$retm]
+ E(G, L, l: HexLiteral) = G, L, hexString(l),
+ where hexString decodes l from hex and left-aligns it into 32 bytes
+ E(G, L, l: StringLiteral) = G, L, utf8EncodeLeftAligned(l),
+ where utf8EncodeLeftAligned performs a utf8 encoding of l
+ and aligns it left into 32 bytes
+ E(G, L, n: HexNumber) = G, L, hex(n)
+ where hex is the hexadecimal decoding function
+ E(G, L, n: DecimalNumber) = G, L, dec(n),
+ where dec is the decimal decoding function
+
+Type Conversion Functions
+-------------------------
+
+JULIA has no support for implicit type conversion and therefore functions exists to provide explicit conversion.
+When converting a larger type to a shorter type a runtime exception can occur in case of an overflow.
+
+The following type conversion functions must be available:
+- ``u32tobool(x:u32) -> y:bool``
+- ``booltou32(x:bool) -> y:u32``
+- ``u32tou64(x:u32) -> y:u64``
+- ``u64tou32(x:u64) -> y:u32``
+- etc. (TBD)
+
+Low-level Functions
+-------------------
+
+The following functions must be available:
+
++---------------------------------------------------------------------------------------------------------------+
+| *Arithmetics* |
++---------------------------------------------------------------------------------------------------------------+
+| addu256(x:u256, y:u256) -> z:u256 | x + y |
++---------------------------------------------------------------------------------------------------------------+
+| subu256(x:u256, y:u256) -> z:u256 | x - y |
++---------------------------------------------------------------------------------------------------------------+
+| mulu256(x:u256, y:u256) -> z:u256 | x * y |
++---------------------------------------------------------------------------------------------------------------+
+| divu256(x:u256, y:u256) -> z:u256 | x / y |
++---------------------------------------------------------------------------------------------------------------+
+| divs256(x:s256, y:s256) -> z:s256 | x / y, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| modu256(x:u256, y:u256) -> z:u256 | x % y |
++---------------------------------------------------------------------------------------------------------------+
+| mods256(x:s256, y:s256) -> z:s256 | x % y, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| signextendu256(i:u256, x:u256) -> z:u256 | sign extend from (i*8+7)th bit counting from least significant |
++---------------------------------------------------------------------------------------------------------------+
+| expu256(x:u256, y:u256) -> z:u256 | x to the power of y |
++---------------------------------------------------------------------------------------------------------------+
+| addmodu256(x:u256, y:u256, m:u256) -> z:u256| (x + y) % m with arbitrary precision arithmetics |
++---------------------------------------------------------------------------------------------------------------+
+| mulmodu256(x:u256, y:u256, m:u256) -> z:u256| (x * y) % m with arbitrary precision arithmetics |
++---------------------------------------------------------------------------------------------------------------+
+| ltu256(x:u256, y:u256) -> z:bool | 1 if x < y, 0 otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| gtu256(x:u256, y:u256) -> z:bool | 1 if x > y, 0 otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| sltu256(x:s256, y:s256) -> z:bool | 1 if x < y, 0 otherwise, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| sgtu256(x:s256, y:s256) -> z:bool | 1 if x > y, 0 otherwise, for signed numbers in two's complement |
++---------------------------------------------------------------------------------------------------------------+
+| equ256(x:u256, y:u256) -> z:bool | 1 if x == y, 0 otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| notu256(x:u256) -> z:u256 | ~x, every bit of x is negated |
++---------------------------------------------------------------------------------------------------------------+
+| andu256(x:u256, y:u256) -> z:u256 | bitwise and of x and y |
++---------------------------------------------------------------------------------------------------------------+
+| oru256(x:u256, y:u256) -> z:u256 | bitwise or of x and y |
++---------------------------------------------------------------------------------------------------------------+
+| xoru256(x:u256, y:u256) -> z:u256 | bitwise xor of x and y |
++---------------------------------------------------------------------------------------------------------------+
+| shlu256(x:u256, y:u256) -> z:u256 | logical left shift of x by y |
++---------------------------------------------------------------------------------------------------------------+
+| shru256(x:u256, y:u256) -> z:u256 | logical right shift of x by y |
++---------------------------------------------------------------------------------------------------------------+
+| saru256(x:u256, y:u256) -> z:u256 | arithmetic right shift of x by y |
++---------------------------------------------------------------------------------------------------------------+
+| byte(n:u256, x:u256) -> v:u256 | nth byte of x, where the most significant byte is the 0th byte |
+| Cannot this be just replaced by and256(shr256(n, x), 0xff) and let it be optimised out by the EVM backend? |
++---------------------------------------------------------------------------------------------------------------+
+| *Memory and storage* |
++---------------------------------------------------------------------------------------------------------------+
+| mload(p:u256) -> v:u256 | mem[p..(p+32)) |
++---------------------------------------------------------------------------------------------------------------+
+| mstore(p:u256, v:u256) | mem[p..(p+32)) := v |
++---------------------------------------------------------------------------------------------------------------+
+| mstore8(p:u256, v:u256) | mem[p] := v & 0xff - only modifies a single byte |
++---------------------------------------------------------------------------------------------------------------+
+| sload(p:u256) -> v:u256 | storage[p] |
++---------------------------------------------------------------------------------------------------------------+
+| sstore(p:u256, v:u256) | storage[p] := v |
++---------------------------------------------------------------------------------------------------------------+
+| msize() -> size:u256 | size of memory, i.e. largest accessed memory index, albeit due |
+| | due to the memory extension function, which extends by words, |
+| | this will always be a multiple of 32 bytes |
++---------------------------------------------------------------------------------------------------------------+
+| *Execution control* |
++---------------------------------------------------------------------------------------------------------------+
+| create(v:u256, p:u256, s:u256) | create new contract with code mem[p..(p+s)) and send v wei |
+| | and return the new address |
++---------------------------------------------------------------------------------------------------------------+
+| call(g:u256, a:u256, v:u256, in:u256, | call contract at address a with input mem[in..(in+insize)) |
+| insize:u256, out:u256, | providing g gas and v wei and output area |
+| outsize:u256) | mem[out..(out+outsize)) returning 0 on error (eg. out of gas) |
+| -> r:u256 | and 1 on success |
++---------------------------------------------------------------------------------------------------------------+
+| callcode(g:u256, a:u256, v:u256, in:u256, | identical to ``call`` but only use the code from a |
+| insize:u256, out:u256, | and stay in the context of the |
+| outsize:u256) -> r:u256 | current contract otherwise |
++---------------------------------------------------------------------------------------------------------------+
+| delegatecall(g:u256, a:u256, in:u256, | identical to ``callcode``, |
+| insize:u256, out:u256, | but also keep ``caller`` |
+| outsize:u256) -> r:u256 | and ``callvalue`` |
++---------------------------------------------------------------------------------------------------------------+
+| stop() | stop execution, identical to return(0,0) |
+| Perhaps it would make sense retiring this as it equals to return(0,0). It can be an optimisation by the EVM |
+| backend. |
++---------------------------------------------------------------------------------------------------------------+
+| abort() | abort (equals to invalid instruction on EVM) |
++---------------------------------------------------------------------------------------------------------------+
+| return(p:u256, s:u256) | end execution, return data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| revert(p:u256, s:u256) | end execution, revert state changes, return data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| selfdestruct(a:u256) | end execution, destroy current contract and send funds to a |
++---------------------------------------------------------------------------------------------------------------+
+| log0(p:u256, s:u256) | log without topics and data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| log1(p:u256, s:u256, t1:u256) | log with topic t1 and data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| log2(p:u256, s:u256, t1:u256, t2:u256) | log with topics t1, t2 and data mem[p..(p+s)) |
++---------------------------------------------------------------------------------------------------------------+
+| log3(p:u256, s:u256, t1:u256, t2:u256, | log with topics t, t2, t3 and data mem[p..(p+s)) |
+| t3:u256) | |
++---------------------------------------------------------------------------------------------------------------+
+| log4(p:u256, s:u256, t1:u256, t2:u256, | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) |
+| t3:u256, t4:u256) | |
++---------------------------------------------------------------------------------------------------------------+
+| *State queries* |
++---------------------------------------------------------------------------------------------------------------+
+| blockcoinbase() -> address:u256 | current mining beneficiary |
++---------------------------------------------------------------------------------------------------------------+
+| blockdifficulty() -> difficulty:u256 | difficulty of the current block |
++---------------------------------------------------------------------------------------------------------------+
+| blockgaslimit() -> limit:u256 | block gas limit of the current block |
++---------------------------------------------------------------------------------------------------------------+
+| blockhash(b:u256) -> hash:u256 | hash of block nr b - only for last 256 blocks excluding current |
++---------------------------------------------------------------------------------------------------------------+
+| blocknumber() -> block:u256 | current block number |
++---------------------------------------------------------------------------------------------------------------+
+| blocktimestamp() -> timestamp:u256 | timestamp of the current block in seconds since the epoch |
++---------------------------------------------------------------------------------------------------------------+
+| txorigin() -> address:u256 | transaction sender |
++---------------------------------------------------------------------------------------------------------------+
+| txgasprice() -> price:u256 | gas price of the transaction |
++---------------------------------------------------------------------------------------------------------------+
+| gasleft() -> gas:u256 | gas still available to execution |
++---------------------------------------------------------------------------------------------------------------+
+| balance(a:u256) -> v:u256 | wei balance at address a |
++---------------------------------------------------------------------------------------------------------------+
+| this() -> address:u256 | address of the current contract / execution context |
++---------------------------------------------------------------------------------------------------------------+
+| caller() -> address:u256 | call sender (excluding delegatecall) |
++---------------------------------------------------------------------------------------------------------------+
+| callvalue() -> v:u256 | wei sent together with the current call |
++---------------------------------------------------------------------------------------------------------------+
+| calldataload(p:u256) -> v:u256 | call data starting from position p (32 bytes) |
++---------------------------------------------------------------------------------------------------------------+
+| calldatasize() -> v:u256 | size of call data in bytes |
++---------------------------------------------------------------------------------------------------------------+
+| calldatacopy(t:u256, f:u256, s:u256) | copy s bytes from calldata at position f to mem at position t |
++---------------------------------------------------------------------------------------------------------------+
+| codesize() -> size:u256 | size of the code of the current contract / execution context |
++---------------------------------------------------------------------------------------------------------------+
+| codecopy(t:u256, f:u256, s:u256) | copy s bytes from code at position f to mem at position t |
++---------------------------------------------------------------------------------------------------------------+
+| extcodesize(a:u256) -> size:u256 | size of the code at address a |
++---------------------------------------------------------------------------------------------------------------+
+| extcodecopy(a:u256, t:u256, f:u256, s:u256) | like codecopy(t, f, s) but take code at address a |
++---------------------------------------------------------------------------------------------------------------+
+| *Others* |
++---------------------------------------------------------------------------------------------------------------+
+| discardu256(unused:u256) | discard value |
++---------------------------------------------------------------------------------------------------------------+
+| splitu256tou64(x:u256) -> (x1:u64, x2:u64, | split u256 to four u64's |
+| x3:u64, x4:u64) | |
++---------------------------------------------------------------------------------------------------------------+
+| combineu64tou256(x1:u64, x2:u64, x3:u64, | combine four u64's into a single u256 |
+| x4:u64) -> (x:u256) | |
++---------------------------------------------------------------------------------------------------------------+
+| sha3(p:u256, s:u256) -> v:u256 | keccak(mem[p...(p+s))) |
++---------------------------------------------------------------------------------------------------------------+
+
+Backends
+--------
+
+Backends or targets are the translators from JULIA to a specific bytecode. Each of the backends can expose functions
+prefixed with the name of the backend. We reserve ``evm_`` and ``ewasm_`` prefixes for the two proposed backends.
+
+Backend: EVM
+------------
+
+The EVM target will have all the underlying EVM opcodes exposed with the `evm_` prefix.
+
+Backend: "EVM 1.5"
+------------------
+
+TBD
+
+Backend: eWASM
+--------------
+
+TBD
+
+Specification of JULIA Object
+=============================
+
+Grammar::
+
+ TopLevelObject = 'object' '{' Code? ( Object | Data )* '}'
+ Object = 'object' StringLiteral '{' Code? ( Object | Data )* '}'
+ Code = 'code' Block
+ Data = 'data' StringLiteral HexLiteral
+ HexLiteral = 'hex' ('"' ([0-9a-fA-F]{2})* '"' | '\'' ([0-9a-fA-F]{2})* '\'')
+ StringLiteral = '"' ([^"\r\n\\] | '\\' .)* '"'
+
+Above, ``Block`` refers to ``Block`` in the JULIA code grammar explained in the previous chapter.
+
+An example JULIA Object is shown below:
+
+..code::
+
+ // Code consists of a single object. A single "code" node is the code of the object.
+ // Every (other) named object or data section is serialized and
+ // made accessible to the special built-in functions datacopy / dataoffset / datasize
+ object {
+ code {
+ let size = datasize("runtime")
+ let offset = allocate(size)
+ // This will turn into a memory->memory copy for eWASM and
+ // a codecopy for EVM
+ datacopy(dataoffset("runtime"), offset, size)
+ // this is a constructor and the runtime code is returned
+ return(offset, size)
+ }
+
+ data "Table2" hex"4123"
+
+ object "runtime" {
+ code {
+ // runtime code
+
+ let size = datasize("Contract2")
+ let offset = allocate(size)
+ // This will turn into a memory->memory copy for eWASM and
+ // a codecopy for EVM
+ datacopy(dataoffset("Contract2"), offset, size)
+ // constructor parameter is a single number 0x1234
+ mstore(add(offset, size), 0x1234)
+ create(offset, add(size, 32))
+ }
+
+ // Embedded object. Use case is that the outside is a factory contract,
+ // and Contract2 is the code to be created by the factory
+ object "Contract2" {
+ code {
+ // code here ...
+ }
+
+ object "runtime" {
+ code {
+ // code here ...
+ }
+ }
+
+ data "Table1" hex"4123"
+ }
+ }
+ }
diff --git a/docs/metadata.rst b/docs/metadata.rst
index dbde87e8..5e37219e 100644
--- a/docs/metadata.rst
+++ b/docs/metadata.rst
@@ -131,6 +131,8 @@ user interface for the contract.
Furthermore, Mist can use the userdoc to display a confirmation message to the user
whenever they interact with the contract.
+Additional information about Ethereum Natural Specification (NatSpec) can be found `here <https://github.com/ethereum/wiki/wiki/Ethereum-Natural-Specification-Format>`_.
+
Usage for Source Code Verification
==================================
diff --git a/docs/security-considerations.rst b/docs/security-considerations.rst
index 6586cb5f..1e2138fa 100644
--- a/docs/security-considerations.rst
+++ b/docs/security-considerations.rst
@@ -55,42 +55,59 @@ complete contract):
::
- pragma solidity ^0.4.0;
-
- // THIS CONTRACT CONTAINS A BUG - DO NOT USE
- contract Fund {
- /// Mapping of ether shares of the contract.
- mapping(address => uint) shares;
- /// Withdraw your share.
- function withdraw() {
- if (msg.sender.send(shares[msg.sender]))
- shares[msg.sender] = 0;
- }
- }
+ pragma solidity ^0.4.0;
+
+ // THIS CONTRACT CONTAINS A BUG - DO NOT USE
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() {
+ if (msg.sender.send(shares[msg.sender]))
+ shares[msg.sender] = 0;
+ }
+ }
The problem is not too serious here because of the limited gas as part
-of ``send``, but it still exposes a weakness: Ether transfer always
-includes code execution, so the recipient could be a contract that calls
+of ``send``, but it still exposes a weakness: Ether transfer can always
+include code execution, so the recipient could be a contract that calls
back into ``withdraw``. This would let it get multiple refunds and
-basically retrieve all the Ether in the contract.
+basically retrieve all the Ether in the contract. In particular, the
+following contract will allow an attacker to refund multiple times
+as it uses ``call`` which forwards all remaining gas by default:
+
+::
+
+ pragma solidity ^0.4.0;
+
+ // THIS CONTRACT CONTAINS A BUG - DO NOT USE
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() {
+ if (msg.sender.call.value(shares[msg.sender])())
+ shares[msg.sender] = 0;
+ }
+ }
To avoid re-entrancy, you can use the Checks-Effects-Interactions pattern as
outlined further below:
::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.11;
- contract Fund {
- /// Mapping of ether shares of the contract.
- mapping(address => uint) shares;
- /// Withdraw your share.
- function withdraw() {
- var share = shares[msg.sender];
- shares[msg.sender] = 0;
- msg.sender.transfer(share);
- }
- }
+ contract Fund {
+ /// Mapping of ether shares of the contract.
+ mapping(address => uint) shares;
+ /// Withdraw your share.
+ function withdraw() {
+ var share = shares[msg.sender];
+ shares[msg.sender] = 0;
+ msg.sender.transfer(share);
+ }
+ }
Note that re-entrancy is not only an effect of Ether transfer but of any
function call on another contract. Furthermore, you also have to take
@@ -179,7 +196,9 @@ Never use tx.origin for authorization. Let's say you have a wallet contract like
}
}
-Now someone tricks you into sending ether to the address of this attack wallet::
+Now someone tricks you into sending ether to the address of this attack wallet:
+
+::
pragma solidity ^0.4.11;
diff --git a/docs/solidity-by-example.rst b/docs/solidity-by-example.rst
index 59ab7962..9489665e 100644
--- a/docs/solidity-by-example.rst
+++ b/docs/solidity-by-example.rst
@@ -492,7 +492,7 @@ high or low invalid bids.
if (amount > 0) {
// It is important to set this to zero because the recipient
// can call this function again as part of the receiving call
- // before `send` returns (see the remark above about
+ // before `transfer` returns (see the remark above about
// conditions -> effects -> interaction).
pendingReturns[msg.sender] = 0;
@@ -508,12 +508,11 @@ high or low invalid bids.
require(!ended);
AuctionEnded(highestBidder, highestBid);
ended = true;
- // We send all the money we have, because some
- // of the refunds might have failed.
- beneficiary.transfer(this.balance);
+ beneficiary.transfer(highestBid);
}
}
+
.. index:: purchase, remote purchase, escrow
********************
diff --git a/docs/structure-of-a-contract.rst b/docs/structure-of-a-contract.rst
index 224eb368..0b554800 100644
--- a/docs/structure-of-a-contract.rst
+++ b/docs/structure-of-a-contract.rst
@@ -20,12 +20,12 @@ State variables are values which are permanently stored in contract storage.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract SimpleStorage {
- uint storedData; // State variable
- // ...
- }
+ contract SimpleStorage {
+ uint storedData; // State variable
+ // ...
+ }
See the :ref:`types` section for valid state variable types and
:ref:`visibility-and-getters` for possible choices for
@@ -40,13 +40,13 @@ Functions are the executable units of code within a contract.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract SimpleAuction {
- function bid() payable { // Function
- // ...
- }
- }
+ contract SimpleAuction {
+ function bid() payable { // Function
+ // ...
+ }
+ }
:ref:`function-calls` can happen internally or externally
and have different levels of visibility (:ref:`visibility-and-getters`)
@@ -62,20 +62,20 @@ Function modifiers can be used to amend the semantics of functions in a declarat
::
- pragma solidity ^0.4.11;
+ pragma solidity ^0.4.11;
- contract Purchase {
- address public seller;
+ contract Purchase {
+ address public seller;
- modifier onlySeller() { // Modifier
- require(msg.sender == seller);
- _;
- }
+ modifier onlySeller() { // Modifier
+ require(msg.sender == seller);
+ _;
+ }
- function abort() onlySeller { // Modifier usage
- // ...
- }
- }
+ function abort() onlySeller { // Modifier usage
+ // ...
+ }
+ }
.. _structure-events:
@@ -86,16 +86,16 @@ Events are convenience interfaces with the EVM logging facilities.
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract SimpleAuction {
- event HighestBidIncreased(address bidder, uint amount); // Event
+ contract SimpleAuction {
+ event HighestBidIncreased(address bidder, uint amount); // Event
- function bid() payable {
- // ...
- HighestBidIncreased(msg.sender, msg.value); // Triggering event
- }
- }
+ function bid() payable {
+ // ...
+ HighestBidIncreased(msg.sender, msg.value); // Triggering event
+ }
+ }
See :ref:`events` in contracts section for information on how events are declared
and can be used from within a dapp.
@@ -110,16 +110,16 @@ Structs are custom defined types that can group several variables (see
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract Ballot {
- struct Voter { // Struct
- uint weight;
- bool voted;
- address delegate;
- uint vote;
- }
- }
+ contract Ballot {
+ struct Voter { // Struct
+ uint weight;
+ bool voted;
+ address delegate;
+ uint vote;
+ }
+ }
.. _structure-enum-types:
@@ -131,8 +131,8 @@ Enums can be used to create custom types with a finite set of values (see
::
- pragma solidity ^0.4.0;
+ pragma solidity ^0.4.0;
- contract Purchase {
- enum State { Created, Locked, Inactive } // Enum
- }
+ contract Purchase {
+ enum State { Created, Locked, Inactive } // Enum
+ }
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
index a438b3d0..5b6f42a2 100644
--- a/docs/style-guide.rst
+++ b/docs/style-guide.rst
@@ -739,6 +739,12 @@ Modifier Names
Use mixedCase. Examples: ``onlyBy``, ``onlyAfter``, ``onlyDuringThePreSale``.
+Enums
+=====
+
+Enums, in the style of simple type declarations, should be named using the CapWords style. Examples: ``TokenGroup``, ``Frame``, ``HashStyle``, ``CharacterLocation``.
+
+
Avoiding Naming Collisions
==========================
diff --git a/docs/types.rst b/docs/types.rst
index 0be8255e..c716b95e 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -990,6 +990,6 @@ parameters or return parameters.
.. warning::
The type is only deduced from the first assignment, so
the loop in the following snippet is infinite, as ``i`` will have the type
- ``uint8`` and any value of this type is smaller than ``2000``.
+ ``uint8`` and the highest value of this type is smaller than ``2000``.
``for (var i = 0; i < 2000; i++) { ... }``
diff --git a/docs/units-and-global-variables.rst b/docs/units-and-global-variables.rst
index 7af97376..8261bdde 100644
--- a/docs/units-and-global-variables.rst
+++ b/docs/units-and-global-variables.rst
@@ -85,11 +85,6 @@ Block and Transaction Properties
consecutive blocks in the canonical chain.
.. note::
- If you want to implement access restrictions in library functions using
- ``msg.sender``, you have to manually supply the value of
- ``msg.sender`` as an argument.
-
-.. note::
The block hashes are not available for all blocks for scalability reasons.
You can only access the hashes of the most recent 256 blocks, all other
values will be zero.
diff --git a/docs/using-the-compiler.rst b/docs/using-the-compiler.rst
index 7f82df70..f1f13b82 100644
--- a/docs/using-the-compiler.rst
+++ b/docs/using-the-compiler.rst
@@ -138,7 +138,7 @@ Input Description
// ewasm.wasm - eWASM binary format (not supported atm)
//
// Note that using a using `evm`, `evm.bytecode`, `ewasm`, etc. will select every
- // target part of that output.
+ // target part of that output. Additionally, `*` can be used as a wildcard to request everything.
//
outputSelection: {
// Enable the metadata and bytecode outputs of every single contract.
@@ -177,7 +177,8 @@ Output Description
start: 0,
end: 100
],
- // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc
+ // Mandatory: Error type, such as "TypeError", "InternalCompilerError", "Exception", etc.
+ // See below for complete list of types.
type: "TypeError",
// Mandatory: Component where the error originated, such as "general", "ewasm", etc.
component: "general",
@@ -273,3 +274,21 @@ Output Description
}
}
}
+
+
+Error types
+~~~~~~~~~~~
+
+1. ``JSONError``: JSON input doesn't conform to the required format, e.g. input is not a JSON object, the language is not supported, etc.
+2. ``IOError``: IO and import processing errors, such as unresolvable URL or hash mismatch in supplied sources.
+3. ``ParserError``: Source code doesn't conform to the language rules.
+4. ``DocstringParsingError``: The NatSpec tags in the comment block cannot be parsed.
+5. ``SyntaxError``: Syntactical error, such as ``continue`` is used outside of a ``for`` loop.
+6. ``DeclarationError``: Invalid, unresolvable or clashing identifier names. e.g. ``Identifier not found``
+7. ``TypeError``: Error within the type system, such as invalid type conversions, invalid assignments, etc.
+8. ``UnimplementedFeatureError``: Feature is not supported by the compiler, but is expected to be supported in future versions.
+9. ``InternalCompilerError``: Internal bug triggered in the compiler - this should be reported as an issue.
+10. ``Exception``: Unknown failure during compilation - this should be reported as an issue.
+11. ``CompilerError``: Invalid use of the compiler stack - this should be reported as an issue.
+12. ``FatalError``: Fatal error not processed correctly - this should be reported as an issue.
+13. ``Warning``: A warning, which didn't stop the compilation, but should be addressed if possible.
diff --git a/docs/utils/SolidityLexer.py b/docs/utils/SolidityLexer.py
index a828146f..50f51cf4 100644
--- a/docs/utils/SolidityLexer.py
+++ b/docs/utils/SolidityLexer.py
@@ -56,7 +56,7 @@ class SolidityLexer(RegexLexer):
(r'[})\].]', Punctuation),
(r'(anonymous|as|assembly|break|constant|continue|do|delete|else|external|for|hex|if|'
r'indexed|internal|import|is|mapping|memory|new|payable|public|pragma|'
- r'private|return|returns|storage|super|this|throw|using|while)\b', Keyword, 'slashstartsregex'),
+ r'private|pure|return|returns|storage|super|this|throw|using|view|while)\b', Keyword, 'slashstartsregex'),
(r'(var|function|event|modifier|struct|enum|contract|library|interface)\b', Keyword.Declaration, 'slashstartsregex'),
(r'(bytes|string|address|uint|int|bool|byte|' +
'|'.join(
@@ -67,15 +67,15 @@ class SolidityLexer(RegexLexer):
['fixed%dx%d' % ((i), (j + 8)) for i in range(0, 256, 8) for j in range(0, 256 - i, 8)]
) + r')\b', Keyword.Type, 'slashstartsregex'),
(r'(wei|szabo|finney|ether|seconds|minutes|hours|days|weeks|years)\b', Keyword.Type, 'slashstartsregex'),
- (r'(abstract|after|case|catch|default|final|in|inline|interface|let|match|'
- r'null|of|pure|relocatable|static|switch|try|type|typeof|view)\b', Keyword.Reserved),
+ (r'(abstract|after|case|catch|default|final|in|inline|let|match|'
+ r'null|of|relocatable|static|switch|try|type|typeof)\b', Keyword.Reserved),
(r'(true|false)\b', Keyword.Constant),
(r'(block|msg|tx|now|suicide|selfdestruct|addmod|mulmod|sha3|keccak256|log[0-4]|'
r'sha256|ecrecover|ripemd160|assert|revert|require)', Name.Builtin),
(r'[$a-zA-Z_][a-zA-Z0-9_]*', Name.Other),
- (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?[fd]?', Number.Float),
+ (r'[0-9][0-9]*\.[0-9]+([eE][0-9]+)?', Number.Float),
(r'0x[0-9a-fA-F]+', Number.Hex),
- (r'[0-9]+', Number.Integer),
+ (r'[0-9]+([eE][0-9]+)?', Number.Integer),
(r'"(\\\\|\\"|[^"])*"', String.Double),
(r"'(\\\\|\\'|[^'])*'", String.Single),
]