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

View File

@ -25,27 +25,28 @@ API, this is done as follows::
// The json abi array generated by the compiler // The json abi array generated by the compiler
var abiArray = [ var abiArray = [
{ {
"inputs":[ "inputs":[
{"name":"x","type":"uint256"}, {"name":"x","type":"uint256"},
{"name":"y","type":"uint256"} {"name":"y","type":"uint256"}
], ],
"type":"constructor" "type":"constructor"
}, },
{ {
"constant":true, "constant":true,
"inputs":[], "inputs":[],
"name":"x", "name":"x",
"outputs":[{"name":"","type":"bytes32"}], "outputs":[{"name":"","type":"bytes32"}],
"type":"function" "type":"function"
} }
]; ];
var MyContract = web3.eth.contract(abiArray); var MyContract = web3.eth.contract(abiArray);
// deploy new contract // deploy new contract
var contractInstance = MyContract.new( var contractInstance = MyContract.new(
10, 11, 10,
{from: myAccount, gas: 1000000} 11,
{from: myAccount, gas: 1000000}
); );
.. index:: constructor;arguments .. index:: constructor;arguments
@ -84,7 +85,8 @@ This means that cyclic creation dependencies are impossible.
// Only the creator can alter the name -- // Only the creator can alter the name --
// the comparison is possible since contracts // the comparison is possible since contracts
// are implicitly convertible to addresses. // are implicitly convertible to addresses.
if (msg.sender == creator) name = newName; if (msg.sender == creator)
name = newName;
} }
function transfer(address newOwner) { function transfer(address newOwner) {
@ -221,8 +223,12 @@ The next example is a bit more complex:
:: ::
contract complex { contract complex {
struct Data { uint a; bytes3 b; mapping(uint => uint) map; } struct Data {
mapping(uint => mapping(bool => Data[])) public 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:: 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 // This means that if the owner calls this function, the
// function is executed and otherwise, an exception is // function is executed and otherwise, an exception is
// thrown. // 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 { contract priced {
// Modifiers can receive arguments: // 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 { contract Register is priced, owned {
mapping (address => bool) registeredAddresses; mapping (address => bool) registeredAddresses;
uint price; uint price;
function Register(uint initialPrice) { price = initialPrice; } function Register(uint initialPrice) { price = initialPrice; }
function register() costs(price) { function register() costs(price) {
registeredAddresses[msg.sender] = true; registeredAddresses[msg.sender] = true;
} }
function changePrice(uint _price) onlyowner { function changePrice(uint _price) onlyowner {
price = _price; price = _price;
} }
@ -359,13 +376,13 @@ possible.
contract Caller { contract Caller {
function callTest(address testAddress) { function callTest(address testAddress) {
Test(testAddress).call(0xabcdef01); // hash does not exist Test(testAddress).call(0xabcdef01); // hash does not exist
// results in Test(testAddress).x becoming == 1. // results in Test(testAddress).x becoming == 1.
Rejector r = Rejector(0x123); Rejector r = Rejector(0x123);
r.send(2 ether); r.send(2 ether);
// results in r.balance == 0 // results in r.balance == 0
} }
} }
.. index:: ! event .. index:: ! event
@ -820,56 +837,56 @@ custom types without the overhead of external function calls:
:: ::
library bigint { library bigint {
struct bigint { struct bigint {
uint[] limbs; uint[] limbs;
} }
function fromUint(uint x) internal returns (bigint r) { function fromUint(uint x) internal returns (bigint r) {
r.limbs = new uint[](1); r.limbs = new uint[](1);
r.limbs[0] = x; r.limbs[0] = x;
} }
function add(bigint _a, bigint _b) internal returns (bigint r) { function add(bigint _a, bigint _b) internal returns (bigint r) {
r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length)); r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
uint carry = 0; uint carry = 0;
for (uint i = 0; i < r.limbs.length; ++i) { for (uint i = 0; i < r.limbs.length; ++i) {
uint a = limb(_a, i); uint a = limb(_a, i);
uint b = limb(_b, i); uint b = limb(_b, i);
r.limbs[i] = a + b + carry; r.limbs[i] = a + b + carry;
if (a + b < a || (a + b == uint(-1) && carry > 0)) if (a + b < a || (a + b == uint(-1) && carry > 0))
carry = 1; carry = 1;
else else
carry = 0; carry = 0;
} }
if (carry > 0) { if (carry > 0) {
// too bad, we have to add a limb // too bad, we have to add a limb
uint[] memory newLimbs = new uint[](r.limbs.length + 1); uint[] memory newLimbs = new uint[](r.limbs.length + 1);
for (i = 0; i < r.limbs.length; ++i) for (i = 0; i < r.limbs.length; ++i)
newLimbs[i] = r.limbs[i]; newLimbs[i] = r.limbs[i];
newLimbs[i] = carry; newLimbs[i] = carry;
r.limbs = newLimbs; r.limbs = newLimbs;
} }
} }
function limb(bigint _a, uint _limb) internal returns (uint) { function limb(bigint _a, uint _limb) internal returns (uint) {
return _limb < _a.limbs.length ? _a.limbs[_limb] : 0; return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
} }
function max(uint a, uint b) private returns (uint) { function max(uint a, uint b) private returns (uint) {
return a > b ? a : b; return a > b ? a : b;
} }
} }
contract C { contract C {
using bigint for bigint.bigint; using bigint for bigint.bigint;
function f() { function f() {
var x = bigint.fromUint(7); var x = bigint.fromUint(7);
var y = bigint.fromUint(uint(-1)); var y = bigint.fromUint(uint(-1));
var z = x.add(y); var z = x.add(y);
} }
} }
As the compiler cannot know where the library will be As the compiler cannot know where the library will be
deployed at, these addresses have to be filled into the 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:: this nonsensical example::
contract c { contract c {
function g(uint a) returns (uint ret) { return f(); } function g(uint a) returns (uint ret) { return f(); }
function f() returns (uint ret) { return g(7) + f(); } function f() returns (uint ret) { return g(7) + f(); }
} }
These function calls are translated into simple jumps inside the EVM. This has 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 When calling functions
of other contracts, the amount of Wei sent with the call and the gas can be specified:: of other contracts, the amount of Wei sent with the call and the gas can be specified::
contract InfoFeed { contract InfoFeed {
function info() returns (uint ret) { return 42; } function info() returns (uint ret) { return 42; }
} }
contract Consumer { contract Consumer {
InfoFeed feed; InfoFeed feed;
function setFeed(address addr) { feed = InfoFeed(addr); } function setFeed(address addr) { feed = InfoFeed(addr); }
function callFeed() { feed.info.value(10).gas(800)(); } function callFeed() { feed.info.value(10).gas(800)(); }
} }
Note that the expression `InfoFeed(addr)` performs an explicit type conversion stating 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 { contract c {
function f(uint key, uint value) { ... } function f(uint key, uint value) { ... }
function g() {
// named arguments function g() {
f({value: 2, key: 3}); // named arguments
} f({value: 2, key: 3});
// omitted parameters }
function func(uint k, uint) returns(uint) {
return k; // omitted parameters
} function func(uint k, uint) returns(uint) {
return k;
}
} }
Order of Evaluation of Expressions 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:: 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 { contract C {
uint[] data; uint[] data;
function f() returns (uint, bool, uint) {
return (7, true, 2); 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(); function g() {
// Assigns to a pre-existing variable. // Declares and assigns the variables. Specifying the type explicitly is not possible.
(x, y) = (2, 7); var (x, b, y) = f();
// Common trick to swap values -- does not work for non-value storage types. // Assigns to a pre-existing variable.
(x, y) = (y, x); (x, y) = (2, 7);
// Components can be left out (also for variable declarations). // Common trick to swap values -- does not work for non-value storage types.
// If the tuple ends in an empty component, (x, y) = (y, x);
// the rest of the values are discarded. // Components can be left out (also for variable declarations).
(data.length,) = f(); // Sets the length to 7 // If the tuple ends in an empty component,
// The same can be done on the left side. // the rest of the values are discarded.
(,data[3]) = f(); // Sets data[3] to 2 (data.length,) = f(); // Sets the length to 7
// Components can only be left out at the left-hand-side of assignments, with // The same can be done on the left side.
// one exception: (,data[3]) = f(); // Sets data[3] to 2
(x,) = (1,); // Components can only be left out at the left-hand-side of assignments, with
// (1,) is the only way to specify a 1-component tuple, because (1) is // one exception:
// equivalent to 1. (x,) = (1,);
} // (1,) is the only way to specify a 1-component tuple, because (1) is
// equivalent to 1.
}
} }
Complications for Arrays and Structs 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 { contract Sharer {
function sendHalf(address addr) returns (uint balance) { 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 throw; // also reverts the transfer to Sharer
return this.balance; 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. We now want to describe the inline assembly language in detail.
.. warning:: .. warning::
Inline assembly is still a relatively new feature and might change if it does not prove useful, 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. so please try to keep up to date.
Example Example
------- -------
@ -256,23 +262,23 @@ idea is that assembly libraries will be used to enhance the language in such way
.. code:: .. code::
library GetCode { library GetCode {
function at(address _addr) returns (bytes o_code) { function at(address _addr) returns (bytes o_code) {
assembly { assembly {
// retrieve the size of the code, this needs assembly // retrieve the size of the code, this needs assembly
let size := extcodesize(_addr) let size := extcodesize(_addr)
// allocate output byte array - this could also be done without assembly // allocate output byte array - this could also be done without assembly
// by using o_code = new bytes(size) // by using o_code = new bytes(size)
o_code := mload(0x40) o_code := mload(0x40)
// new "memory end" including padding // new "memory end" including padding
mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f)))) mstore(0x40, add(o_code, and(add(add(size, 0x20), 0x1f), not(0x1f))))
// store length in memory // store length in memory
mstore(o_code, size) mstore(o_code, size)
// actually retrieve the code, this needs assembly // actually retrieve the code, this needs assembly
extcodecopy(_addr, add(o_code, 0x20), 0, size) extcodecopy(_addr, add(o_code, 0x20), 0, size)
} }
} }
} }
Inline assemmbly could also be beneficial in cases where the optimizer fails to produce 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 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:: .. code::
library VectorSum { library VectorSum {
// This function is less efficient because the optimizer currently fails to // This function is less efficient because the optimizer currently fails to
// remove the bounds checks in array access. // remove the bounds checks in array access.
function sumSolidity(uint[] _data) returns (uint o_sum) { function sumSolidity(uint[] _data) returns (uint o_sum) {
for (uint i = 0; i < _data.length; ++i) for (uint i = 0; i < _data.length; ++i)
o_sum += _data[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 // We know that we only access the array in bounds, so we can avoid the check.
// array length. // 0x20 needs to be added to an array because the first slot contains the
function sumAsm(uint[] _data) returns (uint o_sum) { // array length.
for (uint i = 0; i < _data.length; ++i) function sumAsm(uint[] _data) returns (uint o_sum) {
assembly { o_sum := mload(add(add(_data, 0x20), i)) } for (uint i = 0; i < _data.length; ++i) {
} assembly {
} o_sum := mload(add(add(_data, 0x20), i))
}
}
}
}
Syntax 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. The opcodes `pushi` and `jumpdest` cannot be used directly.
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| stop + `-` | stop execution, identical to return(0,0) | | stop + `-` | stop execution, identical to return(0,0) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| add(x, y) | | x + y | | add(x, y) | | x + y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| sub(x, y) | | x - y | | sub(x, y) | | x - y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| mul(x, y) | | x * y | | mul(x, y) | | x * y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| div(x, y) | | x / y | | div(x, y) | | x / y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| sdiv(x, y) | | x / y, for signed numbers in two's complement | | sdiv(x, y) | | x / y, for signed numbers in two's complement |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| mod(x, y) | | x % y | | mod(x, y) | | x % y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| smod(x, y) | | x % y, for signed numbers in two's complement | | smod(x, y) | | x % y, for signed numbers in two's complement |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| exp(x, y) | | x to the power of y | | exp(x, y) | | x to the power of y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| not(x) | | ~x, every bit of x is negated | | not(x) | | ~x, every bit of x is negated |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| lt(x, y) | | 1 if x < y, 0 otherwise | | lt(x, y) | | 1 if x < y, 0 otherwise |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| gt(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| | 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| | 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 | | eq(x, y) | | 1 if x == y, 0 otherwise |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| iszero(x) | | 1 if x == 0, 0 otherwise | | iszero(x) | | 1 if x == 0, 0 otherwise |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| and(x, y) | | bitwise and of x and y | | and(x, y) | | bitwise and of x and y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| or(x, y) | | bitwise or of x and y | | or(x, y) | | bitwise or of x and y |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| xor(x, y) | | bitwise xor 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| | 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 | | addmod(x, y, m) | | (x + y) % m with arbitrary precision arithmetics |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| mulmod(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| | signextend(i, x) | | sign extend from (i*8+7)th bit counting from least significant |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| sha3(p, n) | | keccak(mem[p...(p+n))) | | sha3(p, n) | | keccak(mem[p...(p+n))) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| jump(label) | `-` | jump to label / code position | | jump(label) | `-` | jump to label / code position |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| jumpi(label, cond) | `-` | jump to label if cond is nonzero | | jumpi(label, cond) | `-` | jump to label if cond is nonzero |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| pc | | current position in code | | pc | | current position in code |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| pop | `*` | remove topmost stack slot | | pop | `*` | remove topmost stack slot |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| dup1 ... dup16 | | copy ith stack slot to the top (counting from top) | | dup1 ... dup16 | | copy ith stack slot to the top (counting from top) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| swap1 ... swap1 | `*` | swap topmost and ith stack slot below it | | swap1 ... swap1 | `*` | swap topmost and ith stack slot below it |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| mload(p) | | mem[p..(p+32)) | | mload(p) | | mem[p..(p+32)) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| mstore(p, v) | `-` | mem[p..(p+32)) := v | | mstore(p, v) | `-` | mem[p..(p+32)) := v |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| mstore8(p, v) | `-` | mem[p] := v & 0xff - only modifies a single byte | | mstore8(p, v) | `-` | mem[p] := v & 0xff - only modifies a single byte |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| sload(p) | | storage[p] | | sload(p) | | storage[p] |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| sstore(p, v) | `-` | storage[p] := v | | sstore(p, v) | `-` | storage[p] := v |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| msize | | size of memory, i.e. largest accessed memory index | | msize | | size of memory, i.e. largest accessed memory index |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| gas | | gas still available to execution | | gas | | gas still available to execution |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| address | | address of the current contract / execution context | | address | | address of the current contract / execution context |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| balance(a) | | wei balance at address a | | balance(a) | | wei balance at address a |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| caller | | call sender (excluding delegatecall) | | caller | | call sender (excluding delegatecall) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| callvalue | | wei sent together with the current call | | callvalue | | wei sent together with the current call |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| calldataload(p) | | call data starting from position p (32 bytes) | | calldataload(p) | | call data starting from position p (32 bytes) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| calldatasize | | size of call data in 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 | | 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 | | 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 | | 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 | | 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 | | 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 | | create(v, p, s) | | create new contract with code mem[p..(p+s)) and send v wei |
| | | and return the new address | | | | and return the new address |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| call(g, a, v, in, | | call contract at address a with input mem[in..(in+insize)] | | 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 | | insize, out, outsize) | | providing g gas and v wei and output area |
| | | mem[out..(out+outsize)] returting 1 on error (out of gas) | | | | 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 | | 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 | | insize, out, outsize) | | in the context of the current contract otherwise |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| delegatecall(g, a, in,| | identical to callcode but also keep `caller` and `callvalue` | | delegatecall(g, a, in, | | identical to callcode but also keep `caller` and `callvalue` |
| insize, out, outsize) | | | | insize, out, outsize) | | |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| return(p, s) | `*` | end execution, return data mem[p..(p+s)) | | return(p, s) | `*` | end execution, return data mem[p..(p+s)) |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| selfdestruct(a) | `*` | end execution, destroy current contract and send funds to a | | selfdestruct(a) | `*` | end execution, destroy current contract and send funds to a |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| log0(p, s) | `-` | log without topics and data mem[p..(p+s)) | | 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)) | | 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)) | | 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)) | | 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)) | | log4(p, s, t1, t2, t3, | `-` | log with topics t1, t2, t3, t4 and data mem[p..(p+s)) |
| t4) | | | | t4) | | |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| origin | | transaction sender | | origin | | transaction sender |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| gasprice | | gas price of the transaction | | gasprice | | gas price of the transaction |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| blockhash(b) | |hash of block nr b - only for last 256 blocks excluding current| | blockhash(b) | | hash of block nr b - only for last 256 blocks excluding current |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| coinbase | | current mining beneficiary | | coinbase | | current mining beneficiary |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| timestamp | | timestamp of the current block in seconds since the epoch | | timestamp | | timestamp of the current block in seconds since the epoch |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| number | | current block number | | number | | current block number |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| difficulty | | difficulty of the current block | | difficulty | | difficulty of the current block |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
| gaslimit | | block gas limit of the current block | | gaslimit | | block gas limit of the current block |
+-----------------------+------+---------------------------------------------------------------+ +-------------------------+------+-----------------------------------------------------------------+
Literals Literals
-------- --------
@ -482,7 +492,7 @@ Strings are stored left-aligned and cannot be longer than 32 bytes.
.. code:: .. code::
assembly { 2 3 add "abc" and } assembly { 2 3 add "abc" and }
Functional Style Functional Style
----------------- -----------------
@ -492,7 +502,7 @@ adding `3` to the contents in memory at position `0x80` would be
.. code:: .. 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, 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 Solidity inline assembly also provides a "functional style" notation where the same code
@ -500,7 +510,7 @@ would be written as follows
.. code:: .. 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 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). 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:: .. code::
contract c { contract c {
uint b; uint b;
function f(uint x) returns (uint r) { function f(uint x) returns (uint r) {
assembly { assembly {
b pop // remove the offset, we know it is zero b pop // remove the offset, we know it is zero
sload sload
x x
mul mul
=: r // assign to return variable r =: r // assign to return variable r
} }
} }
} }
Labels Labels
------ ------
@ -553,19 +563,19 @@ jumps easier. The following code computes an element in the Fibonacci series.
.. code:: .. code::
{ {
let n := calldataload(4) let n := calldataload(4)
let a := 1 let a := 1
let b := a let b := a
loop: loop:
jumpi(loopend, eq(n, 0)) jumpi(loopend, eq(n, 0))
a add swap1 a add swap1
n := sub(n, 1) n := sub(n, 1)
jump(loop) jump(loop)
loopend: loopend:
mstore(0, a) mstore(0, a)
return(0, 0x20) return(0, 0x20)
} }
Please note that automatically accessing stack variables can only work if the 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 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:: .. code::
{ {
jump(two) jump(two)
one: one:
// Here the stack height is 1 (because we pushed 7), // Here the stack height is 1 (because we pushed 7),
// but the assembler thinks it is 0 because it reads // but the assembler thinks it is 0 because it reads
// from top to bottom. // from top to bottom.
// Accessing stack variables here will lead to errors. // Accessing stack variables here will lead to errors.
jump(three) jump(three)
two: two:
7 // push something onto the stack 7 // push something onto the stack
jump(one) jump(one)
three: three:
} }
Declaring Assembly-Local Variables Declaring Assembly-Local Variables
@ -605,19 +615,19 @@ be just `0`, but it can also be a complex functional-style expression.
.. code:: .. code::
contract c { contract c {
function f(uint x) returns (uint b) { function f(uint x) returns (uint b) {
assembly { assembly {
let v := add(x, 1) let v := add(x, 1)
mstore(0x80, v) mstore(0x80, v)
{ {
let y := add(sload(v), 1) let y := add(sload(v), 1)
b := y b := y
} // y is "deallocated" here } // y is "deallocated" here
b := add(b, v) b := add(b, v)
} // v is "deallocated" here } // v is "deallocated" here
} }
} }
Assignments Assignments
@ -635,12 +645,12 @@ For both ways, the colon points to the name of the variable.
.. code:: .. code::
assembly { assembly {
let v := 0 // functional-style assignment as part of variable declaration let v := 0 // functional-style assignment as part of variable declaration
let g := add(v, 2) let g := add(v, 2)
sload(10) sload(10)
=: v // instruction style assignment, puts the result of sload(10) into v =: v // instruction style assignment, puts the result of sload(10) into v
} }
Things to Avoid 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. first slot of the array and then only the array elements follow.
.. warning:: .. warning::
Statically-sized memory arrays do not have a length field, but it will be added soon 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 to allow better convertibility between statically- and dynamically-sized arrays, so
please do not rely on that. 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 That is, because they can change state, they have to have a gas
payment sent along to get the work done. 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>`_. 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? 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:: 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. 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". This depends on what you mean by "reliable".
@ -327,7 +327,7 @@ should implement the fallback function as
`function() { throw; }` `function() { throw; }`
this will cause all transactions to this contract that do not call an 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 Another use of the fallback function is to e.g. register that your
contract received ether by using an event. contract received ether by using an event.
@ -347,7 +347,7 @@ by `msg.data`.
Can state variables be initialized in-line? 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. should be noted that you must declare them as static memory arrays.
Examples:: Examples::
@ -360,7 +360,7 @@ Examples::
S public x = S(1, 2); S public x = S(1, 2);
string name = "Ada"; 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:: 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; mapping(string => address) usedContracts;
} }
function somefunction{ function somefunction {
user user1; user user1;
user1.usedContracts["Hello"] = "World"; user1.usedContracts["Hello"] = "World";
user user2 = user1; 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`. `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. You will need to make sure that you have both contracts aware of each other's presence.
In this example:: In this example::
contract B {} contract B {}
contract A { contract A {
address child; address child;
@ -725,7 +728,7 @@ In this example::
Can a contract function accept a two-dimensional array? 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. 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? 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:: independent copies will be created::
contract C { contract C {
uint[20] x; uint[20] x;
function f() { function f() {
g(x); g(x);
h(x); h(x);
} }
function g(uint[20] y) { function g(uint[20] y) {
y[2] = 3; y[2] = 3;
} }
function h(uint[20] storage y) { function h(uint[20] storage y) {
y[3] = 4; y[3] = 4;
} }
} }
The call to `g(x)` will not have an effect on `x` because it needs 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 to create an independent copy of the storage value in memory

View File

@ -59,13 +59,13 @@ Set up Homebrew:
brew update brew update
brew upgrade brew upgrade
brew install boost --c++11 # this takes a while 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 # For Mix IDE and Alethzero only
brew install xz d-bus brew install xz d-bus
brew install homebrew/versions/v8-315 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 brew install qt5 --with-d-bus # add --verbose if long waits with a stale screen drive you crazy as well
Ubuntu Ubuntu
@ -112,7 +112,7 @@ For Ubuntu 15.10 (Wily Werewolf) or newer, use the following command instead:
.. code-block:: bash .. 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 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. The reason for the change is that `libjsonrpccpp-dev` is available in the universe repository for newer versions of Ubuntu.
Building 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/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 ./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 #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: If you opted to install Alethzero and Mix:

View File

@ -20,9 +20,11 @@ Storage
contract SimpleStorage { contract SimpleStorage {
uint storedData; uint storedData;
function set(uint x) { function set(uint x) {
storedData = x; storedData = x;
} }
function get() constant returns (uint retVal) { function get() constant returns (uint retVal) {
return storedData; return storedData;
} }
@ -88,10 +90,12 @@ registering with username and password - all you need is an Ethereum keypair.
function Coin() { function Coin() {
minter = msg.sender; minter = msg.sender;
} }
function mint(address receiver, uint amount) { function mint(address receiver, uint amount) {
if (msg.sender != minter) return; if (msg.sender != minter) return;
balances[receiver] += amount; balances[receiver] += amount;
} }
function send(address receiver, uint amount) { function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return; if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount; 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"; 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). 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 single-line comment.
/* /*
This is a This is a
multi-line comment. multi-line comment.
*/ */
Additionally, there is another type of comment called a natspec 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 for which the documentation is not yet written. They are written with a
triple slash (`///`) or a double asterisk block(`/** ... */`) and 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 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 **confirmation text** which is shown to users when they attempt to invoke a
function. 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; if (useB) f = b;
return f(x); return f(x);
} }
function a(uint x) returns (uint z) { function a(uint x) returns (uint z) {
return x * x; return x * x;
} }
function b(uint x) returns (uint z) { function b(uint x) returns (uint z) {
return 2 * x; 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 contract. Of course, the main problems of electronic
voting is how to assign voting rights to the correct voting is how to assign voting rights to the correct
persons and how to prevent manipulation. We will not 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 how delegated voting can be done so that vote counting
is **automatic and completely transparent** at the is **automatic and completely transparent** at the
same time. same time.
@ -125,7 +125,7 @@ of votes.
Voter delegate = voters[to]; Voter delegate = voters[to];
if (delegate.voted) { if (delegate.voted) {
// If the delegate already 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; proposals[delegate.vote].voteCount += sender.weight;
} }
else { else {
@ -292,7 +292,7 @@ activate themselves.
} }
Blind Auction Blind Auction
================ =============
The previous open auction is extended to a blind auction The previous open auction is extended to a blind auction
in the following. The advantage of a blind auction is 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 { contract SimpleStorage {
uint storedData; // State variable uint storedData; // State variable
// ... // ...
} }
See the :ref:`types` section for valid state variable types and 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. visibility.
.. _structure-functions: .. _structure-functions:
@ -39,14 +39,14 @@ Functions are the executable units of code within a contract.
:: ::
contract SimpleAuction { contract SimpleAuction {
function bid() { // Function function bid() { // Function
// ... // ...
} }
} }
:ref:`function-calls` can happen internally or externally :ref:`function-calls` can happen internally or externally
and have different levels of visibility (:ref:`visibility-and-accessors`) and have different levels of visibility (:ref:`visibility-and-accessors`)
towards other contracts. towards other contracts.
.. _structure-function-modifiers: .. _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). (see :ref:`modifiers` in contracts section).
:: ::
contract Purchase { contract Purchase {
address public seller; address public seller;
modifier onlySeller() { // Modifier modifier onlySeller() { // Modifier
if (msg.sender != seller) throw; if (msg.sender != seller) throw;
_ _
} }
function abort() onlySeller { // Modifier usage function abort() onlySeller { // Modifier usage
// ... // ...
} }
} }
.. _structure-events: .. _structure-events:
@ -81,15 +81,15 @@ Events are convenience interfaces with the EVM logging facilities.
:: ::
contract SimpleAuction { contract SimpleAuction {
event HighestBidIncreased(address bidder, uint amount); // Event event HighestBidIncreased(address bidder, uint amount); // Event
function bid() { function bid() {
// ... // ...
HighestBidIncreased(msg.sender, msg.value); // Triggering event 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. and can be used from within a dapp.
.. _structure-structs-types: .. _structure-structs-types:
@ -97,18 +97,18 @@ and can be used from within a dapp.
Structs Types 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). :ref:`structs` in types section).
:: ::
contract Ballot { contract Ballot {
struct Voter { // Struct struct Voter { // Struct
uint weight; uint weight;
bool voted; bool voted;
address delegate; address delegate;
uint vote; uint vote;
} }
} }
.. _structure-enum-types: .. _structure-enum-types:
@ -116,11 +116,11 @@ Structs are custom defined types that can group several variables (see
Enum Types 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). :ref:`enums` in types section).
:: ::
contract Purchase { 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`. `bool`: The possible values are constants `true` and `false`.
Operators: Operators:
* `!` (logical negation) * `!` (logical negation)
* `&&` (logical conjunction, "and") * `&&` (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. `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`) * Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation) * Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation)
* Arithmetic operators: `+`, `-`, unary `-`, unary `+`, `*`, `/`, `%` (remainder), `**` (exponentiation) * 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 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. `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 `>` * `<=`, `<`, `==`, `!=`, `>=` and `>`
@ -109,12 +109,12 @@ All three functions `call`, `delegatecall` and `callcode` are very low-level fun
Fixed-size byte arrays 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`) * Comparisons: `<=`, `<`, `==`, `!=`, `>=`, `>` (evaluate to `bool`)
* Bit operators: `&`, `|`, `^` (bitwise exclusive or), `~` (bitwise negation) * 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). * Index access: If `x` is of type `bytesI`, then `x[k]` for `0 <= k < I` returns the `k` th byte (read-only).
Members: Members:
@ -125,7 +125,7 @@ Dynamically-sized byte array
---------------------------- ----------------------------
`bytes`: `bytes`:
Dynamically-sized byte array, see :ref:`arrays`. Not a value-type! Dynamically-sized byte array, see :ref:`arrays`. Not a value-type!
`string`: `string`:
Dynamically-sized UTF8-encoded string, see :ref:`arrays`. Not a value-type! 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
----------------- -----------------
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`. 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 } enum ActionChoices { GoLeft, GoRight, GoStraight, SitStill }
ActionChoices choice; ActionChoices choice;
ActionChoices constant defaultChoice = ActionChoices.GoStraight; ActionChoices constant defaultChoice = ActionChoices.GoStraight;
function setGoStraight()
{ function setGoStraight() {
choice = ActionChoices.GoStraight; choice = ActionChoices.GoStraight;
} }
// Since enum types are not part of the ABI, the signature of "getChoice" // Since enum types are not part of the ABI, the signature of "getChoice"
// will automatically be changed to "getChoice() returns (uint8)" // will automatically be changed to "getChoice() returns (uint8)"
// for all matters external to Solidity. The integer type used is just // 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, // large enough to hold all enum values, i.e. if you have more values,
// `uint16` will be used and so on. // `uint16` will be used and so on.
function getChoice() returns (ActionChoices) function getChoice() returns (ActionChoices) {
{
return choice; return choice;
} }
function getDefaultChoice() returns (uint)
{ function getDefaultChoice() returns (uint) {
return uint(defaultChoice); return uint(defaultChoice);
} }
} }
@ -226,26 +226,28 @@ memory-stored reference type does not create a copy.
:: ::
contract c { contract C {
uint[] x; // the data location of x is storage uint[] x; // the data location of x is storage
// the data location of memoryArray is memory
function f(uint[] memoryArray) { // the data location of memoryArray is memory
x = memoryArray; // works, copies the whole array to storage function f(uint[] memoryArray) {
var y = x; // works, assigns a pointer, data location of y is storage x = memoryArray; // works, copies the whole array to storage
y[7]; // fine, returns the 8th element var y = x; // works, assigns a pointer, data location of y is storage
y.length = 2; // fine, modifies x through y y[7]; // fine, returns the 8th element
delete x; // fine, clears the array, also modifies y y.length = 2; // fine, modifies x through y
// The following does not work; it would need to create a new temporary / delete x; // fine, clears the array, also modifies y
// unnamed array in storage, but storage is "statically" allocated: // The following does not work; it would need to create a new temporary /
// y = memoryArray; // unnamed array in storage, but storage is "statically" allocated:
// This does not work either, since it would "reset" the pointer, but there // y = memoryArray;
// is no sensible location it could point to. // This does not work either, since it would "reset" the pointer, but there
// delete y; // is no sensible location it could point to.
g(x); // calls g, handing over a reference to x // delete y;
h(x); // calls h and creates an independent, temporary copy in memory 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) {}
function g(uint[] storage storageArray) internal {}
function h(uint[] memoryArray) {}
} }
Summary Summary
@ -303,12 +305,12 @@ the `.length` member.
:: ::
contract C { contract C {
function f(uint len) { function f(uint len) {
uint[] memory a = new uint[](7); uint[] memory a = new uint[](7);
bytes memory b = new bytes(len); bytes memory b = new bytes(len);
// Here we have a.length == 7 and b.length == len // Here we have a.length == 7 and b.length == len
a[6] = 8; a[6] = 8;
} }
} }
@ -339,51 +341,59 @@ Members
:: ::
contract ArrayContract { contract ArrayContract {
uint[2**20] m_aLotOfIntegers; uint[2**20] m_aLotOfIntegers;
// Note that the following is not a pair of arrays but an array of pairs. // Note that the following is not a pair of arrays but an array of pairs.
bool[2][] m_pairsOfFlags; bool[2][] m_pairsOfFlags;
// newPairs is stored in memory - the default for function arguments // newPairs is stored in memory - the default for function arguments
function setAllFlagPairs(bool[2][] newPairs) {
// assignment to a storage array replaces the complete array function setAllFlagPairs(bool[2][] newPairs) {
m_pairsOfFlags = 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; function setFlagPair(uint index, bool flagA, bool flagB) {
m_pairsOfFlags[index][1] = flagB; // access to a non-existing index will throw an exception
} m_pairsOfFlags[index][0] = flagA;
function changeFlagArraySize(uint newSize) { m_pairsOfFlags[index][1] = flagB;
// if the new size is smaller, removed array elements will be cleared }
m_pairsOfFlags.length = newSize;
} function changeFlagArraySize(uint newSize) {
function clear() { // if the new size is smaller, removed array elements will be cleared
// these clear the arrays completely m_pairsOfFlags.length = newSize;
delete m_pairsOfFlags; }
delete m_aLotOfIntegers;
// identical effect here function clear() {
m_pairsOfFlags.length = 0; // these clear the arrays completely
} delete m_pairsOfFlags;
bytes m_byteData; delete m_aLotOfIntegers;
function byteArrays(bytes data) { // identical effect here
// byte arrays ("bytes") are different as they are stored without padding, m_pairsOfFlags.length = 0;
// but can be treated identical to "uint8[]" }
m_byteData = data;
m_byteData.length += 7; bytes m_byteData;
m_byteData[3] = 8;
delete m_byteData[2]; function byteArrays(bytes data) {
} // byte arrays ("bytes") are different as they are stored without padding,
function addFlag(bool[2] flag) returns (uint) { // but can be treated identical to "uint8[]"
return m_pairsOfFlags.push(flag); m_byteData = data;
} m_byteData.length += 7;
function createMemoryArray(uint size) returns (bytes) { m_byteData[3] = 8;
// Dynamic memory arrays are created using `new`: delete m_byteData[2];
uint[2][] memory arrayOfPairs = new uint[2][](size); }
// Create a dynamic byte array:
bytes memory b = new bytes(200); function addFlag(bool[2] flag) returns (uint) {
for (uint i = 0; i < b.length; i++) return m_pairsOfFlags.push(flag);
b[i] = byte(i); }
return b;
} 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 { contract CrowdFunding {
// Defines a new type with two fields. // Defines a new type with two fields.
struct Funder { struct Funder {
address addr; address addr;
uint amount; uint amount;
} }
struct Campaign {
address beneficiary; struct Campaign {
uint fundingGoal; address beneficiary;
uint numFunders; uint fundingGoal;
uint amount; uint numFunders;
mapping (uint => Funder) funders; uint amount;
} mapping (uint => Funder) funders;
uint numCampaigns; }
mapping (uint => Campaign) campaigns;
function newCampaign(address beneficiary, uint goal) returns (uint campaignID) { uint numCampaigns;
campaignID = numCampaigns++; // campaignID is return variable mapping (uint => Campaign) campaigns;
// Creates new struct and saves in storage. We leave out the mapping type.
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0); function newCampaign(address beneficiary, uint goal) returns (uint campaignID) {
} campaignID = numCampaigns++; // campaignID is return variable
function contribute(uint campaignID) { // Creates new struct and saves in storage. We leave out the mapping type.
Campaign c = campaigns[campaignID]; 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 // Creates a new temporary memory struct, initialised with the given values
// and copies it over to storage. // and copies it over to storage.
// Note that you can also use Funder(msg.sender, msg.value) to initialise. // 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.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
c.amount += msg.value; c.amount += msg.value;
} }
function checkGoalReached(uint campaignID) returns (bool reached) {
Campaign c = campaigns[campaignID]; function checkGoalReached(uint campaignID) returns (bool reached) {
if (c.amount < c.fundingGoal) Campaign c = campaigns[campaignID];
return false; if (c.amount < c.fundingGoal)
c.beneficiary.send(c.amount); return false;
c.amount = 0; c.beneficiary.send(c.amount);
return true; c.amount = 0;
} return true;
}
} }
The contract does not provide the full functionality of a crowdfunding 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 { contract DeleteExample {
uint data; uint data;
uint[] dataArray; uint[] dataArray;
function f() {
uint x = data; function f() {
delete x; // sets x to 0, does not affect data uint x = data;
delete data; // sets data to 0, does not affect x which still holds a copy delete x; // sets x to 0, does not affect data
uint[] y = dataArray; delete data; // sets data to 0, does not affect x which still holds a copy
delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also uint[] y = dataArray;
// y is affected which is an alias to the storage object delete dataArray; // this sets dataArray.length to zero, but as uint[] is a complex object, also
// On the other hand: "delete y" is not valid, as assignments to local variables // y is affected which is an alias to the storage object
// referencing storage objects can only be made from existing storage objects. // 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 .. 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:: interpret some input variable in e.g. days, you can do it in the following way::
function f(uint start, uint daysAfter) { function f(uint start, uint daysAfter) {
if (now >= start + daysAfter * 1 days) { ... } if (now >= start + daysAfter * 1 days) { ... }
} }
Special Variables and Functions Special Variables and Functions
@ -118,7 +118,7 @@ Contract Related
`this` (current contract's type): `this` (current contract's type):
the current contract, explicitly convertible to :ref:`address` the current contract, explicitly convertible to :ref:`address`
`selfdestruct(address)`: `selfdestruct(address)`:
destroy the current contract, sending its funds to the given :ref:`address` destroy the current contract, sending its funds to the given :ref:`address`