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