Merge pull request #580 from Denton-L/docs-whitespace

Corrections to Documentation Spacing
This commit is contained in:
chriseth 2016-05-18 21:59:24 +02:00
commit ec061b09a3
12 changed files with 615 additions and 556 deletions

View File

@ -179,6 +179,7 @@ function finishes.
AreWeDoneYet,
Finished
}
// This is the current stage.
Stages public stage = Stages.AcceptingBlindedBids;
@ -188,9 +189,11 @@ function finishes.
if (stage != _stage) throw;
_
}
function nextStage() internal {
stage = Stages(uint(stage) + 1);
}
// Perform timed transitions. Be sure to mention
// this modifier first, otherwise the guards
// will not take the new stage into account.
@ -211,6 +214,7 @@ function finishes.
{
// We will not implement that here
}
function reveal()
timedTransitions
atStage(Stages.RevealBids)
@ -227,6 +231,7 @@ function finishes.
_
nextStage();
}
function g()
timedTransitions
atStage(Stages.AnotherStage)
@ -235,12 +240,14 @@ function finishes.
// If you want to use `return` here,
// you have to call `nextStage()` manually.
}
function h()
timedTransitions
atStage(Stages.AreWeDoneYet)
transitionNext
{
}
function i()
timedTransitions
atStage(Stages.Finished)

View File

@ -25,27 +25,28 @@ API, this is done as follows::
// The json abi array generated by the compiler
var abiArray = [
{
"inputs":[
{"name":"x","type":"uint256"},
{"name":"y","type":"uint256"}
],
"type":"constructor"
},
{
"constant":true,
"inputs":[],
"name":"x",
"outputs":[{"name":"","type":"bytes32"}],
"type":"function"
}
{
"inputs":[
{"name":"x","type":"uint256"},
{"name":"y","type":"uint256"}
],
"type":"constructor"
},
{
"constant":true,
"inputs":[],
"name":"x",
"outputs":[{"name":"","type":"bytes32"}],
"type":"function"
}
];
var MyContract = web3.eth.contract(abiArray);
// deploy new contract
var contractInstance = MyContract.new(
10, 11,
{from: myAccount, gas: 1000000}
10,
11,
{from: myAccount, gas: 1000000}
);
.. index:: constructor;arguments
@ -84,7 +85,8 @@ This means that cyclic creation dependencies are impossible.
// Only the creator can alter the name --
// the comparison is possible since contracts
// are implicitly convertible to addresses.
if (msg.sender == creator) name = newName;
if (msg.sender == creator)
name = newName;
}
function transfer(address newOwner) {
@ -221,8 +223,12 @@ The next example is a bit more complex:
::
contract complex {
struct Data { uint a; bytes3 b; mapping(uint => uint) map; }
mapping(uint => mapping(bool => Data[])) public data;
struct Data {
uint a;
bytes3 b;
mapping (uint => uint) map;
}
mapping (uint => mapping(bool => Data[])) public data;
}
It will generate a function of the following form::
@ -260,7 +266,11 @@ inheritable properties of contracts and may be overridden by derived contracts.
// This means that if the owner calls this function, the
// function is executed and otherwise, an exception is
// thrown.
modifier onlyowner { if (msg.sender != owner) throw; _ }
modifier onlyowner {
if (msg.sender != owner)
throw;
_
}
}
@ -277,17 +287,24 @@ inheritable properties of contracts and may be overridden by derived contracts.
contract priced {
// Modifiers can receive arguments:
modifier costs(uint price) { if (msg.value >= price) _ }
modifier costs(uint price) {
if (msg.value >= price) {
_
}
}
}
contract Register is priced, owned {
mapping (address => bool) registeredAddresses;
uint price;
function Register(uint initialPrice) { price = initialPrice; }
function register() costs(price) {
registeredAddresses[msg.sender] = true;
}
function changePrice(uint _price) onlyowner {
price = _price;
}
@ -359,13 +376,13 @@ possible.
contract Caller {
function callTest(address testAddress) {
Test(testAddress).call(0xabcdef01); // hash does not exist
// results in Test(testAddress).x becoming == 1.
Rejector r = Rejector(0x123);
r.send(2 ether);
// results in r.balance == 0
}
function callTest(address testAddress) {
Test(testAddress).call(0xabcdef01); // hash does not exist
// results in Test(testAddress).x becoming == 1.
Rejector r = Rejector(0x123);
r.send(2 ether);
// results in r.balance == 0
}
}
.. index:: ! event
@ -820,56 +837,56 @@ custom types without the overhead of external function calls:
::
library bigint {
struct bigint {
uint[] limbs;
}
library bigint {
struct bigint {
uint[] limbs;
}
function fromUint(uint x) internal returns (bigint r) {
r.limbs = new uint[](1);
r.limbs[0] = x;
}
function fromUint(uint x) internal returns (bigint r) {
r.limbs = new uint[](1);
r.limbs[0] = x;
}
function add(bigint _a, bigint _b) internal returns (bigint r) {
r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
uint carry = 0;
for (uint i = 0; i < r.limbs.length; ++i) {
uint a = limb(_a, i);
uint b = limb(_b, i);
r.limbs[i] = a + b + carry;
if (a + b < a || (a + b == uint(-1) && carry > 0))
carry = 1;
else
carry = 0;
}
if (carry > 0) {
// too bad, we have to add a limb
uint[] memory newLimbs = new uint[](r.limbs.length + 1);
for (i = 0; i < r.limbs.length; ++i)
newLimbs[i] = r.limbs[i];
newLimbs[i] = carry;
r.limbs = newLimbs;
}
}
function add(bigint _a, bigint _b) internal returns (bigint r) {
r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
uint carry = 0;
for (uint i = 0; i < r.limbs.length; ++i) {
uint a = limb(_a, i);
uint b = limb(_b, i);
r.limbs[i] = a + b + carry;
if (a + b < a || (a + b == uint(-1) && carry > 0))
carry = 1;
else
carry = 0;
}
if (carry > 0) {
// too bad, we have to add a limb
uint[] memory newLimbs = new uint[](r.limbs.length + 1);
for (i = 0; i < r.limbs.length; ++i)
newLimbs[i] = r.limbs[i];
newLimbs[i] = carry;
r.limbs = newLimbs;
}
}
function limb(bigint _a, uint _limb) internal returns (uint) {
return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
}
function limb(bigint _a, uint _limb) internal returns (uint) {
return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
}
function max(uint a, uint b) private returns (uint) {
return a > b ? a : b;
}
}
function max(uint a, uint b) private returns (uint) {
return a > b ? a : b;
}
}
contract C {
using bigint for bigint.bigint;
function f() {
var x = bigint.fromUint(7);
var y = bigint.fromUint(uint(-1));
var z = x.add(y);
}
}
contract C {
using bigint for bigint.bigint;
function f() {
var x = bigint.fromUint(7);
var y = bigint.fromUint(uint(-1));
var z = x.add(y);
}
}
As the compiler cannot know where the library will be
deployed at, these addresses have to be filled into the

View File

@ -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
@ -53,12 +53,14 @@ 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.

View File

@ -692,11 +692,11 @@ What happens to a struct's mapping when copying over a struct?
This is a very interesting question. Suppose that we have a contract field set up like such::
struct user{
struct user {
mapping(string => address) usedContracts;
}
function somefunction{
function somefunction {
user user1;
user1.usedContracts["Hello"] = "World";
user user2 = user1;
@ -713,7 +713,10 @@ In the case of a `contract A` calling a new instance of `contract B`, parenthese
`new B` because `B.value` would refer to a member of `B` called `value`.
You will need to make sure that you have both contracts aware of each other's presence.
In this example::
contract B {}
contract A {
address child;
@ -757,21 +760,21 @@ Sure. Take care that if you cross the memory / storage boundary,
independent copies will be created::
contract C {
uint[20] x;
uint[20] x;
function f() {
g(x);
h(x);
}
function f() {
g(x);
h(x);
}
function g(uint[20] y) {
y[2] = 3;
}
function g(uint[20] y) {
y[2] = 3;
}
function h(uint[20] storage y) {
y[3] = 4;
}
}
function h(uint[20] storage y) {
y[3] = 4;
}
}
The call to `g(x)` will not have an effect on `x` because it needs
to create an independent copy of the storage value in memory

View File

@ -20,9 +20,11 @@ Storage
contract SimpleStorage {
uint storedData;
function set(uint x) {
storedData = x;
}
function get() constant returns (uint retVal) {
return storedData;
}
@ -88,10 +90,12 @@ registering with username and password - all you need is an Ethereum keypair.
function Coin() {
minter = msg.sender;
}
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;

View File

@ -51,9 +51,11 @@ There are some types in Solidity's type system that have no counterpart in the s
if (useB) f = b;
return f(x);
}
function a(uint x) returns (uint z) {
return x * x;
}
function b(uint x) returns (uint z) {
return 2 * x;
}

View File

@ -292,7 +292,7 @@ activate themselves.
}
Blind Auction
================
=============
The previous open auction is extended to a blind auction
in the following. The advantage of a blind auction is

View File

@ -21,8 +21,8 @@ State variables are values which are permanently stored in contract storage.
::
contract SimpleStorage {
uint storedData; // State variable
// ...
uint storedData; // State variable
// ...
}
See the :ref:`types` section for valid state variable types and
@ -39,9 +39,9 @@ Functions are the executable units of code within a contract.
::
contract SimpleAuction {
function bid() { // Function
// ...
}
function bid() { // Function
// ...
}
}
:ref:`function-calls` can happen internally or externally
@ -59,16 +59,16 @@ Function modifiers can be used to amend the semantics of functions in a declarat
::
contract Purchase {
address public seller;
address public seller;
modifier onlySeller() { // Modifier
if (msg.sender != seller) throw;
_
}
modifier onlySeller() { // Modifier
if (msg.sender != seller) throw;
_
}
function abort() onlySeller { // Modifier usage
// ...
}
function abort() onlySeller { // Modifier usage
// ...
}
}
.. _structure-events:
@ -81,12 +81,12 @@ Events are convenience interfaces with the EVM logging facilities.
::
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() {
// ...
HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
function bid() {
// ...
HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
See :ref:`events` in contracts section for information on how events are declared
@ -103,12 +103,12 @@ Structs are custom defined types that can group several variables (see
::
contract Ballot {
struct Voter { // Struct
uint weight;
bool voted;
address delegate;
uint vote;
}
struct Voter { // Struct
uint weight;
bool voted;
address delegate;
uint vote;
}
}
.. _structure-enum-types:
@ -122,5 +122,5 @@ Enums can be used to create custom types with a finite set of values (see
::
contract Purchase {
enum State { Created, Locked, Inactive } // Enum
enum State { Created, Locked, Inactive } // Enum
}

View File

@ -171,21 +171,21 @@ to and from all integer types but implicit conversion is not allowed.
enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
ActionChoices choice;
ActionChoices constant defaultChoice = ActionChoices.GoStraight;
function setGoStraight()
{
function setGoStraight() {
choice = ActionChoices.GoStraight;
}
// Since enum types are not part of the ABI, the signature of "getChoice"
// will automatically be changed to "getChoice() returns (uint8)"
// for all matters external to Solidity. The integer type used is just
// large enough to hold all enum values, i.e. if you have more values,
// `uint16` will be used and so on.
function getChoice() returns (ActionChoices)
{
function getChoice() returns (ActionChoices) {
return choice;
}
function getDefaultChoice() returns (uint)
{
function getDefaultChoice() returns (uint) {
return uint(defaultChoice);
}
}
@ -226,26 +226,28 @@ memory-stored reference type does not create a copy.
::
contract c {
uint[] x; // the data location of x is storage
// the data location of memoryArray is memory
function f(uint[] memoryArray) {
x = memoryArray; // works, copies the whole array to storage
var y = x; // works, assigns a pointer, data location of y is storage
y[7]; // fine, returns the 8th element
y.length = 2; // fine, modifies x through y
delete x; // fine, clears the array, also modifies y
// The following does not work; it would need to create a new temporary /
// unnamed array in storage, but storage is "statically" allocated:
// y = memoryArray;
// This does not work either, since it would "reset" the pointer, but there
// is no sensible location it could point to.
// delete y;
g(x); // calls g, handing over a reference to x
h(x); // calls h and creates an independent, temporary copy in memory
}
function g(uint[] storage storageArray) internal {}
function h(uint[] memoryArray) {}
contract C {
uint[] x; // the data location of x is storage
// the data location of memoryArray is memory
function f(uint[] memoryArray) {
x = memoryArray; // works, copies the whole array to storage
var y = x; // works, assigns a pointer, data location of y is storage
y[7]; // fine, returns the 8th element
y.length = 2; // fine, modifies x through y
delete x; // fine, clears the array, also modifies y
// The following does not work; it would need to create a new temporary /
// unnamed array in storage, but storage is "statically" allocated:
// y = memoryArray;
// This does not work either, since it would "reset" the pointer, but there
// is no sensible location it could point to.
// delete y;
g(x); // calls g, handing over a reference to x
h(x); // calls h and creates an independent, temporary copy in memory
}
function g(uint[] storage storageArray) internal {}
function h(uint[] memoryArray) {}
}
Summary
@ -303,12 +305,12 @@ the `.length` member.
::
contract C {
function f(uint len) {
uint[] memory a = new uint[](7);
bytes memory b = new bytes(len);
// Here we have a.length == 7 and b.length == len
a[6] = 8;
}
function f(uint len) {
uint[] memory a = new uint[](7);
bytes memory b = new bytes(len);
// Here we have a.length == 7 and b.length == len
a[6] = 8;
}
}
@ -339,51 +341,59 @@ Members
::
contract ArrayContract {
uint[2**20] m_aLotOfIntegers;
// Note that the following is not a pair of arrays but an array of pairs.
bool[2][] m_pairsOfFlags;
// newPairs is stored in memory - the default for function arguments
function setAllFlagPairs(bool[2][] newPairs) {
// assignment to a storage array replaces the complete array
m_pairsOfFlags = newPairs;
}
function setFlagPair(uint index, bool flagA, bool flagB) {
// access to a non-existing index will throw an exception
m_pairsOfFlags[index][0] = flagA;
m_pairsOfFlags[index][1] = flagB;
}
function changeFlagArraySize(uint newSize) {
// if the new size is smaller, removed array elements will be cleared
m_pairsOfFlags.length = newSize;
}
function clear() {
// these clear the arrays completely
delete m_pairsOfFlags;
delete m_aLotOfIntegers;
// identical effect here
m_pairsOfFlags.length = 0;
}
bytes m_byteData;
function byteArrays(bytes data) {
// byte arrays ("bytes") are different as they are stored without padding,
// but can be treated identical to "uint8[]"
m_byteData = data;
m_byteData.length += 7;
m_byteData[3] = 8;
delete m_byteData[2];
}
function addFlag(bool[2] flag) returns (uint) {
return m_pairsOfFlags.push(flag);
}
function createMemoryArray(uint size) returns (bytes) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
b[i] = byte(i);
return b;
}
uint[2**20] m_aLotOfIntegers;
// Note that the following is not a pair of arrays but an array of pairs.
bool[2][] m_pairsOfFlags;
// newPairs is stored in memory - the default for function arguments
function setAllFlagPairs(bool[2][] newPairs) {
// assignment to a storage array replaces the complete array
m_pairsOfFlags = newPairs;
}
function setFlagPair(uint index, bool flagA, bool flagB) {
// access to a non-existing index will throw an exception
m_pairsOfFlags[index][0] = flagA;
m_pairsOfFlags[index][1] = flagB;
}
function changeFlagArraySize(uint newSize) {
// if the new size is smaller, removed array elements will be cleared
m_pairsOfFlags.length = newSize;
}
function clear() {
// these clear the arrays completely
delete m_pairsOfFlags;
delete m_aLotOfIntegers;
// identical effect here
m_pairsOfFlags.length = 0;
}
bytes m_byteData;
function byteArrays(bytes data) {
// byte arrays ("bytes") are different as they are stored without padding,
// but can be treated identical to "uint8[]"
m_byteData = data;
m_byteData.length += 7;
m_byteData[3] = 8;
delete m_byteData[2];
}
function addFlag(bool[2] flag) returns (uint) {
return m_pairsOfFlags.push(flag);
}
function createMemoryArray(uint size) returns (bytes) {
// Dynamic memory arrays are created using `new`:
uint[2][] memory arrayOfPairs = new uint[2][](size);
// Create a dynamic byte array:
bytes memory b = new bytes(200);
for (uint i = 0; i < b.length; i++)
b[i] = byte(i);
return b;
}
}
@ -400,41 +410,46 @@ shown in the following example:
::
contract CrowdFunding {
// Defines a new type with two fields.
struct Funder {
address addr;
uint amount;
}
struct Campaign {
address beneficiary;
uint fundingGoal;
uint numFunders;
uint amount;
mapping (uint => Funder) funders;
}
uint numCampaigns;
mapping (uint => Campaign) campaigns;
function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID is return variable
// Creates new struct and saves in storage. We leave out the mapping type.
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
}
function contribute(uint campaignID) {
Campaign c = campaigns[campaignID];
// Defines a new type with two fields.
struct Funder {
address addr;
uint amount;
}
struct Campaign {
address beneficiary;
uint fundingGoal;
uint numFunders;
uint amount;
mapping (uint => Funder) funders;
}
uint numCampaigns;
mapping (uint => Campaign) campaigns;
function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID is return variable
// Creates new struct and saves in storage. We leave out the mapping type.
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
}
function contribute(uint campaignID) {
Campaign c = campaigns[campaignID];
// Creates a new temporary memory struct, initialised with the given values
// and copies it over to storage.
// Note that you can also use Funder(msg.sender, msg.value) to initialise.
c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
c.amount += msg.value;
}
function checkGoalReached(uint campaignID) returns (bool reached) {
Campaign c = campaigns[campaignID];
if (c.amount < c.fundingGoal)
return false;
c.beneficiary.send(c.amount);
c.amount = 0;
return true;
}
c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
c.amount += msg.value;
}
function checkGoalReached(uint campaignID) returns (bool reached) {
Campaign c = campaigns[campaignID];
if (c.amount < c.fundingGoal)
return false;
c.beneficiary.send(c.amount);
c.amount = 0;
return true;
}
}
The contract does not provide the full functionality of a crowdfunding
@ -495,18 +510,19 @@ It is important to note that `delete a` really behaves like an assignment to `a`
::
contract DeleteExample {
uint data;
uint[] dataArray;
function f() {
uint x = data;
delete x; // sets x to 0, does not affect data
delete data; // sets data to 0, does not affect x which still holds a copy
uint[] y = dataArray;
delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also
// y is affected which is an alias to the storage object
// On the other hand: "delete y" is not valid, as assignments to local variables
// referencing storage objects can only be made from existing storage objects.
}
uint data;
uint[] dataArray;
function f() {
uint x = data;
delete x; // sets x to 0, does not affect data
delete data; // sets data to 0, does not affect x which still holds a copy
uint[] y = dataArray;
delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also
// y is affected which is an alias to the storage object
// On the other hand: "delete y" is not valid, as assignments to local variables
// referencing storage objects can only be made from existing storage objects.
}
}
.. index:: ! type;conversion, ! cast

View File

@ -35,7 +35,7 @@ These suffixes cannot be applied to variables. If you want to
interpret some input variable in e.g. days, you can do it in the following way::
function f(uint start, uint daysAfter) {
if (now >= start + daysAfter * 1 days) { ... }
if (now >= start + daysAfter * 1 days) { ... }
}
Special Variables and Functions