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.
@ -203,7 +206,7 @@ function finishes.
nextStage();
// The other stages transition by transaction
}
// Order of the modifiers matters here!
function bid()
timedTransitions
@ -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
@ -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.

View File

@ -139,10 +139,10 @@ with `c.someMethod.sendTransaction({from:eth.accounts[x], gas: 1000000});`
That is, because they can change state, they have to have a gas
payment sent along to get the work done.
Get a contract to return its funds to you (not using selfdestruct(...)).
Get a contract to return its funds to you (not using selfdestruct(...)).
========================================================================
This example demonstrates how to send funds from a contract to an address.
This example demonstrates how to send funds from a contract to an address.
See `endowment_retriever <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/30_endowment_retriever.sol>`_.
@ -175,7 +175,7 @@ datastructure on top of it, for example the `iterable mapping <https://github.co
Can I put arrays inside of a mapping? How do I make a mapping of a mapping?
===========================================================================
Mappings are already syntactically similar to arrays as they are, therefore it doesn't make much sense to store an array in them. Rather what you should do is create a mapping of a mapping.
Mappings are already syntactically similar to arrays as they are, therefore it doesn't make much sense to store an array in them. Rather what you should do is create a mapping of a mapping.
An example of this would be::
@ -278,7 +278,7 @@ Is a constructor required?
No. If there is no constructor, a generic one without arguments and no actions will be used.
Are timestamps (now, block.timestamp) reliable?
Are timestamps (now, block.timestamp) reliable?
===============================================
This depends on what you mean by "reliable".
@ -327,7 +327,7 @@ should implement the fallback function as
`function() { throw; }`
this will cause all transactions to this contract that do not call an
existing function to be reverted, so that all Ether is sent back.
existing function to be reverted, so that all Ether is sent back.
Another use of the fallback function is to e.g. register that your
contract received ether by using an event.
@ -347,7 +347,7 @@ by `msg.data`.
Can state variables be initialized in-line?
===========================================
Yes, this is possible for all types (even for structs). However, for arrays it
Yes, this is possible for all types (even for structs). However, for arrays it
should be noted that you must declare them as static memory arrays.
Examples::
@ -360,7 +360,7 @@ Examples::
S public x = S(1, 2);
string name = "Ada";
string[4] memory AdaArr = ["This", "is", "an", "array"];
string[4] memory AdaArr = ["This", "is", "an", "array"];
}
@ -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;
@ -725,7 +728,7 @@ In this example::
Can a contract function accept a two-dimensional array?
=======================================================
This is not yet implemented for external calls and dynamic arrays -
This is not yet implemented for external calls and dynamic arrays -
you can only use one level of dynamic arrays.
What is the relationship between bytes32 and string? Why is it that bytes32 somevar = "stringliteral"; works and what does the saved 32-byte hex value mean?
@ -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

@ -59,13 +59,13 @@ Set up Homebrew:
brew update
brew upgrade
brew install boost --c++11 # this takes a while
brew install cmake cryptopp miniupnpc leveldb gmp libmicrohttpd libjson-rpc-cpp
brew install cmake cryptopp miniupnpc leveldb gmp libmicrohttpd libjson-rpc-cpp
# For Mix IDE and Alethzero only
brew install xz d-bus
brew install homebrew/versions/v8-315
brew install llvm --HEAD --with-clang
brew install llvm --HEAD --with-clang
brew install qt5 --with-d-bus # add --verbose if long waits with a stale screen drive you crazy as well
Ubuntu
@ -112,7 +112,7 @@ For Ubuntu 15.10 (Wily Werewolf) or newer, use the following command instead:
.. code-block:: bash
sudo apt-get -y install build-essential git cmake libboost-all-dev libgmp-dev libleveldb-dev libminiupnpc-dev libreadline-dev libncurses5-dev libcurl4-openssl-dev libcryptopp-dev libjsonrpccpp-dev libmicrohttpd-dev libjsoncpp-dev libedit-dev libz-dev
The reason for the change is that `libjsonrpccpp-dev` is available in the universe repository for newer versions of Ubuntu.
Building
@ -128,7 +128,7 @@ they relate only to Alethzero and Mix
./webthree-helpers/scripts/ethupdate.sh --no-push --simple-pull --project solidity # update Solidity repo
./webthree-helpers/scripts/ethbuild.sh --no-git --project solidity --all --cores 4 -DEVMJIT=0 # build Solidity and others
#enabling DEVMJIT on OS X will not build
#feel free to enable it on Linux
#feel free to enable it on Linux
If you opted to install Alethzero and Mix:

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

@ -21,7 +21,7 @@ At a global level, you can use import statements of the following form:
import "filename";
...will import all global symbols from "filename" (and symbols imported there) into the
...will import all global symbols from "filename" (and symbols imported there) into the
current global scope (different than in ES6 but backwards-compatible for Solidity).
::
@ -122,18 +122,18 @@ Single-line comments (`//`) and multi-line comments (`/*...*/`) are possible.
::
// This is a single-line comment.
/*
This is a
This is a
multi-line comment.
*/
Additionally, there is another type of comment called a natspec comment,
for which the documentation is not yet written. They are written with a
triple slash (`///`) or a double asterisk block(`/** ... */`) and
they should be used directly above function declarations or statements.
they should be used directly above function declarations or statements.
You can use Doxygen-style tags inside these comments to document
functions, annotate conditions for formal verification, and provide a
functions, annotate conditions for formal verification, and provide a
**confirmation text** which is shown to users when they attempt to invoke a
function.

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

@ -15,7 +15,7 @@ a lot of Solidity's features. It implements a voting
contract. Of course, the main problems of electronic
voting is how to assign voting rights to the correct
persons and how to prevent manipulation. We will not
solve all problems here, but at least we will show
solve all problems here, but at least we will show
how delegated voting can be done so that vote counting
is **automatic and completely transparent** at the
same time.
@ -125,7 +125,7 @@ of votes.
Voter delegate = voters[to];
if (delegate.voted) {
// If the delegate already voted,
// directly add to the number of votes
// directly add to the number of votes
proposals[delegate.vote].voteCount += sender.weight;
}
else {
@ -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,12 +21,12 @@ 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
:ref:`visibility-and-accessors` for possible choices for
:ref:`visibility-and-accessors` for possible choices for
visibility.
.. _structure-functions:
@ -39,14 +39,14 @@ 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
and have different levels of visibility (:ref:`visibility-and-accessors`)
towards other contracts.
towards other contracts.
.. _structure-function-modifiers:
@ -57,18 +57,18 @@ Function modifiers can be used to amend the semantics of functions in a declarat
(see :ref:`modifiers` in contracts section).
::
contract Purchase {
address public seller;
modifier onlySeller() { // Modifier
if (msg.sender != seller) throw;
_
}
function abort() onlySeller { // Modifier usage
// ...
}
address public seller;
modifier onlySeller() { // Modifier
if (msg.sender != seller) throw;
_
}
function abort() onlySeller { // Modifier usage
// ...
}
}
.. _structure-events:
@ -81,15 +81,15 @@ Events are convenience interfaces with the EVM logging facilities.
::
contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() {
// ...
HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
event HighestBidIncreased(address bidder, uint amount); // Event
function bid() {
// ...
HighestBidIncreased(msg.sender, msg.value); // Triggering event
}
}
See :ref:`events` in contracts section for information on how events are declared
See :ref:`events` in contracts section for information on how events are declared
and can be used from within a dapp.
.. _structure-structs-types:
@ -97,18 +97,18 @@ and can be used from within a dapp.
Structs Types
=============
Structs are custom defined types that can group several variables (see
Structs are custom defined types that can group several variables (see
:ref:`structs` in types section).
::
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:
@ -116,11 +116,11 @@ Structs are custom defined types that can group several variables (see
Enum Types
==========
Enums can be used to create custom types with a finite set of values (see
Enums can be used to create custom types with a finite set of values (see
:ref:`enums` in types section).
::
contract Purchase {
enum State { Created, Locked, Inactive } // Enum
enum State { Created, Locked, Inactive } // Enum
}

View File

@ -28,7 +28,7 @@ Booleans
`bool`: The possible values are constants `true` and `false`.
Operators:
Operators:
* `!` (logical negation)
* `&&` (logical conjunction, "and")
@ -45,10 +45,10 @@ Integers
`int` / `uint`: Signed and unsigned integers of various sizes. Keywords `uint8` to `uint256` in steps of `8` (unsigned of 8 up to 256 bits) and `int8` to `int256`. `uint` and `int` are aliases for `uint256` and `int256`, respectively.
Operators:
Operators:
* Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Arithmetic operators: `+`, `-`, unary `-`, unary `+`, `*`, `/`, `%` (remainder), `**` (exponentiation)
Division always truncates (it just maps to the DIV opcode of the EVM), but it does not truncate if both
@ -61,7 +61,7 @@ Address
`address`: Holds a 20 byte value (size of an Ethereum address). Address types also have members and serve as base for all contracts.
Operators:
Operators:
* `<=`, `<`, `==`, `!=`, `>=` and `>`
@ -109,12 +109,12 @@ All three functions `call`, `delegatecall` and `callcode` are very low-level fun
Fixed-size byte arrays
----------------------
`bytes1`, `bytes2`, `bytes3`, ..., `bytes32`. `byte` is an alias for `bytes1`.
`bytes1`, `bytes2`, `bytes3`, ..., `bytes32`. `byte` is an alias for `bytes1`.
Operators:
Operators:
* Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Index access: If `x` is of type `bytesI`, then `x[k]` for `0 <= k < I` returns the `k` th byte (read-only).
Members:
@ -125,7 +125,7 @@ Dynamically-sized byte array
----------------------------
`bytes`:
Dynamically-sized byte array, see :ref:`arrays`. Not a value-type!
Dynamically-sized byte array, see :ref:`arrays`. Not a value-type!
`string`:
Dynamically-sized UTF8-encoded string, see :ref:`arrays`. Not a value-type!
@ -140,7 +140,7 @@ number of bytes, always use one of `bytes1` to `bytes32` because they are much c
Integer Literals
-----------------
Integer Literals are arbitrary precision integers until they are used together with a non-literal. In `var x = 1 - 2;`, for example, the value of `1 - 2` is `-1`, which is assigned to `x` and thus `x` receives the type `int8` -- the smallest type that contains `-1`, although the natural types of `1` and `2` are actually `uint8`.
Integer Literals are arbitrary precision integers until they are used together with a non-literal. In `var x = 1 - 2;`, for example, the value of `1 - 2` is `-1`, which is assigned to `x` and thus `x` receives the type `int8` -- the smallest type that contains `-1`, although the natural types of `1` and `2` are actually `uint8`.
It is even possible to temporarily exceed the maximum of 256 bits as long as only integer literals are used for the computation: `var x = (0xffffffffffffffffffff * 0xffffffffffffffffffff) * 0;` Here, `x` will have the value `0` and thus the type `uint8`.
@ -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
@ -118,7 +118,7 @@ Contract Related
`this` (current contract's type):
the current contract, explicitly convertible to :ref:`address`
`selfdestruct(address)`:
destroy the current contract, sending its funds to the given :ref:`address`