mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #580 from Denton-L/docs-whitespace
Corrections to Documentation Spacing
This commit is contained in:
commit
ec061b09a3
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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.
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
280
docs/types.rst
280
docs/types.rst
@ -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
|
||||||
|
@ -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`
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user