aboutsummaryrefslogtreecommitdiffstats
path: root/docs/control-structures.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/control-structures.rst')
-rw-r--r--docs/control-structures.rst566
1 files changed, 288 insertions, 278 deletions
diff --git a/docs/control-structures.rst b/docs/control-structures.rst
index 1bb0f71a..c26300a3 100644
--- a/docs/control-structures.rst
+++ b/docs/control-structures.rst
@@ -32,8 +32,8 @@ Functions of the current contract can be called directly ("internally"), also re
this nonsensical example::
contract c {
- function g(uint a) returns (uint ret) { return f(); }
- function f() returns (uint ret) { return g(7) + f(); }
+ function g(uint a) returns (uint ret) { return f(); }
+ function f() returns (uint ret) { return g(7) + f(); }
}
These function calls are translated into simple jumps inside the EVM. This has
@@ -51,14 +51,16 @@ all function arguments have to be copied to memory.
When calling functions
of other contracts, the amount of Wei sent with the call and the gas can be specified::
-
+
contract InfoFeed {
- function info() returns (uint ret) { return 42; }
+ function info() returns (uint ret) { return 42; }
}
+
+
contract Consumer {
- InfoFeed feed;
- function setFeed(address addr) { feed = InfoFeed(addr); }
- function callFeed() { feed.info.value(10).gas(800)(); }
+ InfoFeed feed;
+ function setFeed(address addr) { feed = InfoFeed(addr); }
+ function callFeed() { feed.info.value(10).gas(800)(); }
}
Note that the expression `InfoFeed(addr)` performs an explicit type conversion stating
@@ -76,15 +78,17 @@ of unused parameters (especially return parameters) can be omitted.
::
contract c {
- function f(uint key, uint value) { ... }
- function g() {
- // named arguments
- f({value: 2, key: 3});
- }
- // omitted parameters
- function func(uint k, uint) returns(uint) {
- return k;
- }
+ function f(uint key, uint value) { ... }
+
+ function g() {
+ // named arguments
+ f({value: 2, key: 3});
+ }
+
+ // omitted parameters
+ function func(uint k, uint) returns(uint) {
+ return k;
+ }
}
Order of Evaluation of Expressions
@@ -109,29 +113,31 @@ 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::
contract C {
- uint[] data;
- function f() returns (uint, bool, uint) {
- return (7, true, 2);
- }
- function g() {
- // Declares and assigns the variables. Specifying the type explicitly is not possible.
- var (x, b, y) = f();
- // Assigns to a pre-existing variable.
- (x, y) = (2, 7);
- // 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.
- (,data[3]) = f(); // Sets data[3] to 2
- // Components can only be left out at the left-hand-side of assignments, with
- // one exception:
- (x,) = (1,);
- // (1,) is the only way to specify a 1-component tuple, because (1) is
- // equivalent to 1.
- }
+ uint[] data;
+
+ function f() returns (uint, bool, uint) {
+ return (7, true, 2);
+ }
+
+ function g() {
+ // Declares and assigns the variables. Specifying the type explicitly is not possible.
+ var (x, b, y) = f();
+ // Assigns to a pre-existing variable.
+ (x, y) = (2, 7);
+ // 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.
+ (,data[3]) = f(); // Sets data[3] to 2
+ // Components can only be left out at the left-hand-side of assignments, with
+ // one exception:
+ (x,) = (1,);
+ // (1,) is the only way to specify a 1-component tuple, because (1) is
+ // equivalent to 1.
+ }
}
Complications for Arrays and Structs
@@ -210,7 +216,7 @@ In the following example, we show how `throw` can be used to easily revert an Et
contract Sharer {
function sendHalf(address addr) returns (uint balance) {
- if (!addr.send(msg.value/2))
+ if (!addr.send(msg.value / 2))
throw; // also reverts the transfer to Sharer
return this.balance;
}
@@ -244,8 +250,8 @@ arising when writing manual assembly by the following features:
We now want to describe the inline assembly language in detail.
.. warning::
- Inline assembly is still a relatively new feature and might change if it does not prove useful,
- so please try to keep up to date.
+ Inline assembly is still a relatively new feature and might change if it does not prove useful,
+ so please try to keep up to date.
Example
-------
@@ -256,23 +262,23 @@ idea is that assembly libraries will be used to enhance the language in such way
.. code::
- library GetCode {
- function at(address _addr) returns (bytes o_code) {
- assembly {
- // retrieve the size of the code, this needs assembly
- let size := extcodesize(_addr)
- // allocate output byte array - this could also be done without assembly
- // by using o_code = new bytes(size)
- o_code := mload(0x40)
- // new "memory end" including padding
- mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
- // store length in memory
- mstore(o_code, size)
- // actually retrieve the code, this needs assembly
- extcodecopy(_addr, add(o_code, 0x20), 0, size)
- }
- }
- }
+ library GetCode {
+ function at(address _addr) returns (bytes o_code) {
+ assembly {
+ // retrieve the size of the code, this needs assembly
+ let size := extcodesize(_addr)
+ // allocate output byte array - this could also be done without assembly
+ // by using o_code = new bytes(size)
+ o_code := mload(0x40)
+ // new "memory end" including padding
+ mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
+ // store length in memory
+ mstore(o_code, size)
+ // actually retrieve the code, this needs assembly
+ extcodecopy(_addr, add(o_code, 0x20), 0, size)
+ }
+ }
+ }
Inline assemmbly could also be beneficial in cases where the optimizer fails to produce
efficient code. Please be aware that assembly is much more difficult to write because
@@ -281,21 +287,25 @@ you really know what you are doing.
.. code::
- library VectorSum {
- // This function is less efficient because the optimizer currently fails to
- // remove the bounds checks in array access.
- function sumSolidity(uint[] _data) returns (uint o_sum) {
- for (uint i = 0; i < _data.length; ++i)
- o_sum += _data[i];
- }
- // We know that we only access the array in bounds, so we can avoid the check.
- // 0x20 needs to be added to an array because the first slot contains the
- // array length.
- function sumAsm(uint[] _data) returns (uint o_sum) {
- for (uint i = 0; i < _data.length; ++i)
- assembly { o_sum := mload(add(add(_data, 0x20), i)) }
- }
- }
+ library VectorSum {
+ // This function is less efficient because the optimizer currently fails to
+ // remove the bounds checks in array access.
+ function sumSolidity(uint[] _data) returns (uint o_sum) {
+ for (uint i = 0; i < _data.length; ++i)
+ o_sum += _data[i];
+ }
+
+ // We know that we only access the array in bounds, so we can avoid the check.
+ // 0x20 needs to be added to an array because the first slot contains the
+ // array length.
+ function sumAsm(uint[] _data) returns (uint o_sum) {
+ for (uint i = 0; i < _data.length; ++i) {
+ assembly {
+ o_sum := mload(add(add(_data, 0x20), i))
+ }
+ }
+ }
+ }
Syntax
------
@@ -330,147 +340,147 @@ In the following, `mem[a...b)` signifies the bytes of memory starting at positio
The opcodes `pushi` and `jumpdest` cannot be used directly.
-+-----------------------+------+---------------------------------------------------------------+
-| stop + `-` | stop execution, identical to return(0,0) |
-+-----------------------+------+---------------------------------------------------------------+
-| add(x, y) | | x + y |
-+-----------------------+------+---------------------------------------------------------------+
-| sub(x, y) | | x - y |
-+-----------------------+------+---------------------------------------------------------------+
-| mul(x, y) | | x * y |
-+-----------------------+------+---------------------------------------------------------------+
-| div(x, y) | | x / y |
-+-----------------------+------+---------------------------------------------------------------+
-| sdiv(x, y) | | x / y, for signed numbers in two's complement |
-+-----------------------+------+---------------------------------------------------------------+
-| mod(x, y) | | x % y |
-+-----------------------+------+---------------------------------------------------------------+
-| smod(x, y) | | x % y, for signed numbers in two's complement |
-+-----------------------+------+---------------------------------------------------------------+
-| exp(x, y) | | x to the power of y |
-+-----------------------+------+---------------------------------------------------------------+
-| not(x) | | ~x, every bit of x is negated |
-+-----------------------+------+---------------------------------------------------------------+
-| lt(x, y) | | 1 if x < y, 0 otherwise |
-+-----------------------+------+---------------------------------------------------------------+
-| gt(x, y) | | 1 if x > y, 0 otherwise |
-+-----------------------+------+---------------------------------------------------------------+
-| slt(x, y) | |1 if x < y, 0 otherwise, for signed numbers in two's complement|
-+-----------------------+------+---------------------------------------------------------------+
-| sgt(x, y) | |1 if x > y, 0 otherwise, for signed numbers in two's complement|
-+-----------------------+------+---------------------------------------------------------------+
-| eq(x, y) | | 1 if x == y, 0 otherwise |
-+-----------------------+------+---------------------------------------------------------------+
-| iszero(x) | | 1 if x == 0, 0 otherwise |
-+-----------------------+------+---------------------------------------------------------------+
-| and(x, y) | | bitwise and of x and y |
-+-----------------------+------+---------------------------------------------------------------+
-| or(x, y) | | bitwise or of x and y |
-+-----------------------+------+---------------------------------------------------------------+
-| xor(x, y) | | bitwise xor of x and y |
-+-----------------------+------+---------------------------------------------------------------+
-| byte(n, x) | | nth byte of x, where the most significant byte is the 0th byte|
-+-----------------------+------+---------------------------------------------------------------+
-| addmod(x, y, m) | | (x + y) % m with arbitrary precision arithmetics |
-+-----------------------+------+---------------------------------------------------------------+
-| mulmod(x, y, m) | | (x * y) % m with arbitrary precision arithmetics |
-+-----------------------+------+---------------------------------------------------------------+
-| signextend(i, x) | | sign extend from (i*8+7)th bit counting from least significant|
-+-----------------------+------+---------------------------------------------------------------+
-| sha3(p, n) | | keccak(mem[p...(p+n))) |
-+-----------------------+------+---------------------------------------------------------------+
-| jump(label) | `-` | jump to label / code position |
-+-----------------------+------+---------------------------------------------------------------+
-| jumpi(label, cond) | `-` | jump to label if cond is nonzero |
-+-----------------------+------+---------------------------------------------------------------+
-| pc | | current position in code |
-+-----------------------+------+---------------------------------------------------------------+
-| pop | `*` | remove topmost stack slot |
-+-----------------------+------+---------------------------------------------------------------+
-| dup1 ... dup16 | | copy ith stack slot to the top (counting from top) |
-+-----------------------+------+---------------------------------------------------------------+
-| swap1 ... swap1 | `*` | swap topmost and ith stack slot below it |
-+-----------------------+------+---------------------------------------------------------------+
-| mload(p) | | mem[p..(p+32)) |
-+-----------------------+------+---------------------------------------------------------------+
-| mstore(p, v) | `-` | mem[p..(p+32)) := v |
-+-----------------------+------+---------------------------------------------------------------+
-| mstore8(p, v) | `-` | mem[p] := v & 0xff - only modifies a single byte |
-+-----------------------+------+---------------------------------------------------------------+
-| sload(p) | | storage[p] |
-+-----------------------+------+---------------------------------------------------------------+
-| sstore(p, v) | `-` | storage[p] := v |
-+-----------------------+------+---------------------------------------------------------------+
-| msize | | size of memory, i.e. largest accessed memory index |
-+-----------------------+------+---------------------------------------------------------------+
-| gas | | gas still available to execution |
-+-----------------------+------+---------------------------------------------------------------+
-| address | | address of the current contract / execution context |
-+-----------------------+------+---------------------------------------------------------------+
-| balance(a) | | wei balance at address a |
-+-----------------------+------+---------------------------------------------------------------+
-| caller | | call sender (excluding delegatecall) |
-+-----------------------+------+---------------------------------------------------------------+
-| callvalue | | wei sent together with the current call |
-+-----------------------+------+---------------------------------------------------------------+
-| calldataload(p) | | call data starting from position p (32 bytes) |
-+-----------------------+------+---------------------------------------------------------------+
-| calldatasize | | size of call data in bytes |
-+-----------------------+------+---------------------------------------------------------------+
-| calldatacopy(t, f, s) | `-` | copy s bytes from calldata at position f to mem at position t |
-+-----------------------+------+---------------------------------------------------------------+
-| codesize | | size of the code of the current contract / execution context |
-+-----------------------+------+---------------------------------------------------------------+
-| codecopy(t, f, s) | `-` | copy s bytes from code at position f to mem at position t |
-+-----------------------+------+---------------------------------------------------------------+
-| extcodesize(a) | | size of the code at address a |
-+-----------------------+------+---------------------------------------------------------------+
-|extcodecopy(a, t, f, s)| `-` | like codecopy(t, f, s) but take code at address a |
-+-----------------------+------+---------------------------------------------------------------+
-| create(v, p, s) | | create new contract with code mem[p..(p+s)) and send v wei |
-| | | and return the new address |
-+-----------------------+------+---------------------------------------------------------------+
-| call(g, a, v, in, | | call contract at address a with input mem[in..(in+insize)] |
-| insize, out, outsize) | | providing g gas and v wei and output area |
-| | | mem[out..(out+outsize)] returting 1 on error (out of gas) |
-+-----------------------+------+---------------------------------------------------------------+
-| callcode(g, a, v, in, | | identical to call but only use the code from a and stay |
-| insize, out, outsize) | | in the context of the current contract otherwise |
-+-----------------------+------+---------------------------------------------------------------+
-| delegatecall(g, a, in,| | identical to callcode but also keep `caller` and `callvalue` |
-| insize, out, outsize) | | |
-+-----------------------+------+---------------------------------------------------------------+
-| return(p, s) | `*` | end execution, return data mem[p..(p+s)) |
-+-----------------------+------+---------------------------------------------------------------+
-| selfdestruct(a) | `*` | end execution, destroy current contract and send funds to a |
-+-----------------------+------+---------------------------------------------------------------+
-| log0(p, s) | `-` | log without topics and data mem[p..(p+s)) |
-+-----------------------+------+---------------------------------------------------------------+
-| log1(p, s, t1) | `-` | log with topic t1 and data mem[p..(p+s)) |
-+-----------------------+------+---------------------------------------------------------------+
-| log2(p, s, t1, t2) | `-` | log with topics t1, t2 and data mem[p..(p+s)) |
-+-----------------------+------+---------------------------------------------------------------+
-| log3(p, s, t1, t2, t3)| `-` | log with topics t1, t2, t3 and data mem[p..(p+s)) |
-+-----------------------+------+---------------------------------------------------------------+
-| log4(p, s, t1, t2, t3,| `-` | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) |
-| t4) | | |
-+-----------------------+------+---------------------------------------------------------------+
-| origin | | transaction sender |
-+-----------------------+------+---------------------------------------------------------------+
-| gasprice | | gas price of the transaction |
-+-----------------------+------+---------------------------------------------------------------+
-| blockhash(b) | |hash of block nr b - only for last 256 blocks excluding current|
-+-----------------------+------+---------------------------------------------------------------+
-| coinbase | | current mining beneficiary |
-+-----------------------+------+---------------------------------------------------------------+
-| timestamp | | timestamp of the current block in seconds since the epoch |
-+-----------------------+------+---------------------------------------------------------------+
-| number | | current block number |
-+-----------------------+------+---------------------------------------------------------------+
-| difficulty | | difficulty of the current block |
-+-----------------------+------+---------------------------------------------------------------+
-| gaslimit | | block gas limit of the current block |
-+-----------------------+------+---------------------------------------------------------------+
++-------------------------+------+-----------------------------------------------------------------+
+| stop + `-` | stop execution, identical to return(0,0) |
++-------------------------+------+-----------------------------------------------------------------+
+| add(x, y) | | x + y |
++-------------------------+------+-----------------------------------------------------------------+
+| sub(x, y) | | x - y |
++-------------------------+------+-----------------------------------------------------------------+
+| mul(x, y) | | x * y |
++-------------------------+------+-----------------------------------------------------------------+
+| div(x, y) | | x / y |
++-------------------------+------+-----------------------------------------------------------------+
+| sdiv(x, y) | | x / y, for signed numbers in two's complement |
++-------------------------+------+-----------------------------------------------------------------+
+| mod(x, y) | | x % y |
++-------------------------+------+-----------------------------------------------------------------+
+| smod(x, y) | | x % y, for signed numbers in two's complement |
++-------------------------+------+-----------------------------------------------------------------+
+| exp(x, y) | | x to the power of y |
++-------------------------+------+-----------------------------------------------------------------+
+| not(x) | | ~x, every bit of x is negated |
++-------------------------+------+-----------------------------------------------------------------+
+| lt(x, y) | | 1 if x < y, 0 otherwise |
++-------------------------+------+-----------------------------------------------------------------+
+| gt(x, y) | | 1 if x > y, 0 otherwise |
++-------------------------+------+-----------------------------------------------------------------+
+| slt(x, y) | | 1 if x < y, 0 otherwise, for signed numbers in two's complement |
++-------------------------+------+-----------------------------------------------------------------+
+| sgt(x, y) | | 1 if x > y, 0 otherwise, for signed numbers in two's complement |
++-------------------------+------+-----------------------------------------------------------------+
+| eq(x, y) | | 1 if x == y, 0 otherwise |
++-------------------------+------+-----------------------------------------------------------------+
+| iszero(x) | | 1 if x == 0, 0 otherwise |
++-------------------------+------+-----------------------------------------------------------------+
+| and(x, y) | | bitwise and of x and y |
++-------------------------+------+-----------------------------------------------------------------+
+| or(x, y) | | bitwise or of x and y |
++-------------------------+------+-----------------------------------------------------------------+
+| xor(x, y) | | bitwise xor of x and y |
++-------------------------+------+-----------------------------------------------------------------+
+| byte(n, x) | | nth byte of x, where the most significant byte is the 0th byte |
++-------------------------+------+-----------------------------------------------------------------+
+| addmod(x, y, m) | | (x + y) % m with arbitrary precision arithmetics |
++-------------------------+------+-----------------------------------------------------------------+
+| mulmod(x, y, m) | | (x * y) % m with arbitrary precision arithmetics |
++-------------------------+------+-----------------------------------------------------------------+
+| signextend(i, x) | | sign extend from (i*8+7)th bit counting from least significant |
++-------------------------+------+-----------------------------------------------------------------+
+| sha3(p, n) | | keccak(mem[p...(p+n))) |
++-------------------------+------+-----------------------------------------------------------------+
+| jump(label) | `-` | jump to label / code position |
++-------------------------+------+-----------------------------------------------------------------+
+| jumpi(label, cond) | `-` | jump to label if cond is nonzero |
++-------------------------+------+-----------------------------------------------------------------+
+| pc | | current position in code |
++-------------------------+------+-----------------------------------------------------------------+
+| pop | `*` | remove topmost stack slot |
++-------------------------+------+-----------------------------------------------------------------+
+| dup1 ... dup16 | | copy ith stack slot to the top (counting from top) |
++-------------------------+------+-----------------------------------------------------------------+
+| swap1 ... swap1 | `*` | swap topmost and ith stack slot below it |
++-------------------------+------+-----------------------------------------------------------------+
+| mload(p) | | mem[p..(p+32)) |
++-------------------------+------+-----------------------------------------------------------------+
+| mstore(p, v) | `-` | mem[p..(p+32)) := v |
++-------------------------+------+-----------------------------------------------------------------+
+| mstore8(p, v) | `-` | mem[p] := v & 0xff - only modifies a single byte |
++-------------------------+------+-----------------------------------------------------------------+
+| sload(p) | | storage[p] |
++-------------------------+------+-----------------------------------------------------------------+
+| sstore(p, v) | `-` | storage[p] := v |
++-------------------------+------+-----------------------------------------------------------------+
+| msize | | size of memory, i.e. largest accessed memory index |
++-------------------------+------+-----------------------------------------------------------------+
+| gas | | gas still available to execution |
++-------------------------+------+-----------------------------------------------------------------+
+| address | | address of the current contract / execution context |
++-------------------------+------+-----------------------------------------------------------------+
+| balance(a) | | wei balance at address a |
++-------------------------+------+-----------------------------------------------------------------+
+| caller | | call sender (excluding delegatecall) |
++-------------------------+------+-----------------------------------------------------------------+
+| callvalue | | wei sent together with the current call |
++-------------------------+------+-----------------------------------------------------------------+
+| calldataload(p) | | call data starting from position p (32 bytes) |
++-------------------------+------+-----------------------------------------------------------------+
+| calldatasize | | size of call data in bytes |
++-------------------------+------+-----------------------------------------------------------------+
+| calldatacopy(t, f, s) | `-` | copy s bytes from calldata at position f to mem at position t |
++-------------------------+------+-----------------------------------------------------------------+
+| codesize | | size of the code of the current contract / execution context |
++-------------------------+------+-----------------------------------------------------------------+
+| codecopy(t, f, s) | `-` | copy s bytes from code at position f to mem at position t |
++-------------------------+------+-----------------------------------------------------------------+
+| extcodesize(a) | | size of the code at address a |
++-------------------------+------+-----------------------------------------------------------------+
+| extcodecopy(a, t, f, s) | `-` | like codecopy(t, f, s) but take code at address a |
++-------------------------+------+-----------------------------------------------------------------+
+| create(v, p, s) | | create new contract with code mem[p..(p+s)) and send v wei |
+| | | and return the new address |
++-------------------------+------+-----------------------------------------------------------------+
+| call(g, a, v, in, | | call contract at address a with input mem[in..(in+insize)] |
+| insize, out, outsize) | | providing g gas and v wei and output area |
+| | | mem[out..(out+outsize)] returting 1 on error (out of gas) |
++-------------------------+------+-----------------------------------------------------------------+
+| callcode(g, a, v, in, | | identical to call but only use the code from a and stay |
+| insize, out, outsize) | | in the context of the current contract otherwise |
++-------------------------+------+-----------------------------------------------------------------+
+| delegatecall(g, a, in, | | identical to callcode but also keep `caller` and `callvalue` |
+| insize, out, outsize) | | |
++-------------------------+------+-----------------------------------------------------------------+
+| return(p, s) | `*` | end execution, return data mem[p..(p+s)) |
++-------------------------+------+-----------------------------------------------------------------+
+| selfdestruct(a) | `*` | end execution, destroy current contract and send funds to a |
++-------------------------+------+-----------------------------------------------------------------+
+| log0(p, s) | `-` | log without topics and data mem[p..(p+s)) |
++-------------------------+------+-----------------------------------------------------------------+
+| log1(p, s, t1) | `-` | log with topic t1 and data mem[p..(p+s)) |
++-------------------------+------+-----------------------------------------------------------------+
+| log2(p, s, t1, t2) | `-` | log with topics t1, t2 and data mem[p..(p+s)) |
++-------------------------+------+-----------------------------------------------------------------+
+| log3(p, s, t1, t2, t3) | `-` | log with topics t1, t2, t3 and data mem[p..(p+s)) |
++-------------------------+------+-----------------------------------------------------------------+
+| log4(p, s, t1, t2, t3, | `-` | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) |
+| t4) | | |
++-------------------------+------+-----------------------------------------------------------------+
+| origin | | transaction sender |
++-------------------------+------+-----------------------------------------------------------------+
+| gasprice | | gas price of the transaction |
++-------------------------+------+-----------------------------------------------------------------+
+| blockhash(b) | | hash of block nr b - only for last 256 blocks excluding current |
++-------------------------+------+-----------------------------------------------------------------+
+| coinbase | | current mining beneficiary |
++-------------------------+------+-----------------------------------------------------------------+
+| timestamp | | timestamp of the current block in seconds since the epoch |
++-------------------------+------+-----------------------------------------------------------------+
+| number | | current block number |
++-------------------------+------+-----------------------------------------------------------------+
+| difficulty | | difficulty of the current block |
++-------------------------+------+-----------------------------------------------------------------+
+| gaslimit | | block gas limit of the current block |
++-------------------------+------+-----------------------------------------------------------------+
Literals
--------
@@ -482,7 +492,7 @@ Strings are stored left-aligned and cannot be longer than 32 bytes.
.. code::
- assembly { 2 3 add "abc" and }
+ assembly { 2 3 add "abc" and }
Functional Style
-----------------
@@ -492,7 +502,7 @@ adding `3` to the contents in memory at position `0x80` would be
.. code::
- 3 0x80 mload add 0x80 mstore
+ 3 0x80 mload add 0x80 mstore
As it is often hard to see what the actual arguments for certain opcodes are,
Solidity inline assembly also provides a "functional style" notation where the same code
@@ -500,7 +510,7 @@ would be written as follows
.. code::
- mstore(0x80, add(mload(0x80), 3))
+ mstore(0x80, add(mload(0x80), 3))
Functional style and instructional style can be mixed, but any opcode inside a
functional style expression has to return exactly one stack slot (most of the opcodes do).
@@ -531,18 +541,18 @@ It is planned that the stack height changes can be specified in inline assembly.
.. code::
- contract c {
- uint b;
- function f(uint x) returns (uint r) {
- assembly {
- b pop // remove the offset, we know it is zero
- sload
- x
- mul
- =: r // assign to return variable r
- }
- }
- }
+ contract c {
+ uint b;
+ function f(uint x) returns (uint r) {
+ assembly {
+ b pop // remove the offset, we know it is zero
+ sload
+ x
+ mul
+ =: r // assign to return variable r
+ }
+ }
+ }
Labels
------
@@ -553,19 +563,19 @@ jumps easier. The following code computes an element in the Fibonacci series.
.. code::
- {
- let n := calldataload(4)
- let a := 1
- let b := a
- loop:
- jumpi(loopend, eq(n, 0))
- a add swap1
- n := sub(n, 1)
- jump(loop)
- loopend:
- mstore(0, a)
- return(0, 0x20)
- }
+ {
+ let n := calldataload(4)
+ let a := 1
+ let b := a
+ loop:
+ jumpi(loopend, eq(n, 0))
+ a add swap1
+ n := sub(n, 1)
+ jump(loop)
+ loopend:
+ mstore(0, a)
+ return(0, 0x20)
+ }
Please note that automatically accessing stack variables can only work if the
assembler knows the current stack height. This fails to work if the jump source
@@ -578,19 +588,19 @@ will have a wrong impression about the stack height at label `two`:
.. code::
- {
- jump(two)
- one:
- // Here the stack height is 1 (because we pushed 7),
- // but the assembler thinks it is 0 because it reads
- // from top to bottom.
- // Accessing stack variables here will lead to errors.
- jump(three)
- two:
- 7 // push something onto the stack
- jump(one)
- three:
- }
+ {
+ jump(two)
+ one:
+ // Here the stack height is 1 (because we pushed 7),
+ // but the assembler thinks it is 0 because it reads
+ // from top to bottom.
+ // Accessing stack variables here will lead to errors.
+ jump(three)
+ two:
+ 7 // push something onto the stack
+ jump(one)
+ three:
+ }
Declaring Assembly-Local Variables
@@ -605,19 +615,19 @@ be just `0`, but it can also be a complex functional-style expression.
.. code::
- contract c {
- function f(uint x) returns (uint b) {
- assembly {
- let v := add(x, 1)
- mstore(0x80, v)
- {
- let y := add(sload(v), 1)
- b := y
- } // y is "deallocated" here
- b := add(b, v)
- } // v is "deallocated" here
- }
- }
+ contract c {
+ function f(uint x) returns (uint b) {
+ assembly {
+ let v := add(x, 1)
+ mstore(0x80, v)
+ {
+ let y := add(sload(v), 1)
+ b := y
+ } // y is "deallocated" here
+ b := add(b, v)
+ } // v is "deallocated" here
+ }
+ }
Assignments
@@ -635,12 +645,12 @@ For both ways, the colon points to the name of the variable.
.. code::
- assembly {
- let v := 0 // functional-style assignment as part of variable declaration
- let g := add(v, 2)
- sload(10)
- =: v // instruction style assignment, puts the result of sload(10) into v
- }
+ assembly {
+ let v := 0 // functional-style assignment as part of variable declaration
+ let g := add(v, 2)
+ sload(10)
+ =: v // instruction style assignment, puts the result of sload(10) into v
+ }
Things to Avoid
@@ -676,6 +686,6 @@ arrays are pointers to memory arrays. The length of a dynamic array is stored at
first slot of the array and then only the array elements follow.
.. warning::
- Statically-sized memory arrays do not have a length field, but it will be added soon
- to allow better convertibility between statically- and dynamically-sized arrays, so
- please do not rely on that.
+ Statically-sized memory arrays do not have a length field, but it will be added soon
+ to allow better convertibility between statically- and dynamically-sized arrays, so
+ please do not rely on that.