diff options
Diffstat (limited to 'docs/contracts.rst')
-rw-r--r-- | docs/contracts.rst | 318 |
1 files changed, 168 insertions, 150 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst index 68905fa4..fbcc858d 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -20,39 +20,40 @@ Contracts can be created "from outside" or from Solidity contracts. When a contract is created, its constructor (a function with the same name as the contract) is executed once. -From `web3.js`, i.e. the JavaScript +From ``web3.js``, i.e. the JavaScript 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, - {from: myAccount, gas: 1000000} + 10, + 11, + {from: myAccount, gas: 1000000} ); .. index:: constructor;arguments Internally, constructor arguments are passed after the code of the contract itself, but you do not have to care about this -if you use `web3.js`. +if you use ``web3.js``. If a contract wants to create another contract, the source code (and the binary) of the created contract has to be known to the creator. @@ -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) { @@ -141,38 +143,38 @@ a "message call") and external ones that do), there are four types of visibilities for functions and state variables. -Functions can be specified as being `external`, -`public`, `internal` or `private`, where the default is -`public`. For state variables, `external` is not possible -and the default is `internal`. +Functions can be specified as being ``external``, +``public``, ``internal`` or ``private``, where the default is +``public``. For state variables, ``external`` is not possible +and the default is ``internal``. -`external`: +``external``: External functions are part of the contract interface, which means they can be called from other contracts and - via transactions. An external function `f` cannot be called - internally (i.e. `f()` does not work, but `this.f()` works). + via transactions. An external function ``f`` cannot be called + internally (i.e. ``f()`` does not work, but ``this.f()`` works). External functions are sometimes more efficient when they receive large arrays of data. -`public`: +``public``: Public functions are part of the contract interface and can be either called internally or via messages. For public state variables, an automatic accessor function (see below) is generated. -`internal`: +``internal``: Those functions and state variables can only be accessed internally (i.e. from within the current contract - or contracts deriving from it), without using `this`. + or contracts deriving from it), without using ``this``. -`private`: +``private``: Private functions and state variables are only visible for the contract they are defined in and not in derived contracts. .. note:: Everything that is inside a contract is visible to - all external observers. Making something `private` + all external observers. Making something ``private`` only prevents other contract from accessing and modifying the information, but it will still be visible to the whole world outside of the blockchain. @@ -183,15 +185,15 @@ return parameter list for functions. :: - contract c { + contract C { function f(uint a) private returns (uint b) { return a + 1; } function setData(uint a) internal { data = a; } uint public data; } -Other contracts can call `c.data()` to retrieve the value of data in state -storage, but are not able to call `f`. Contracts derived from `c` can call -`setData` to alter the value of `data` (but only in their own state). +Other contracts can call ``c.data()`` to retrieve the value of data in state +storage, but are not able to call ``f``. Contracts derived from ``c`` can call +``setData`` to alter the value of ``data`` (but only in their own state). .. index:: ! accessor;function, ! function;accessor @@ -200,19 +202,19 @@ Accessor Functions The compiler automatically creates accessor functions for all public state variables. The contract given below will -have a function called `data` that does not take any +have a function called ``data`` that does not take any arguments and returns a uint, the value of the state -variable `data`. The initialization of state variables can +variable ``data``. The initialization of state variables can be done at declaration. The accessor functions have external visibility. If the -symbol is accessed internally (i.e. without `this.`), +symbol is accessed internally (i.e. without ``this.``), it is a state variable and if it is accessed externally -(i.e. with `this.`), it is a function. +(i.e. with ``this.``), it is a function. :: - contract test { + contract Test { uint public data = 42; } @@ -220,9 +222,13 @@ 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; + contract Complex { + 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,16 +266,20 @@ 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; + _ + } } contract mortal is owned { - // This contract inherits the "onlyowner"-modifier from + // This contract inherits the "onlyOwner"-modifier from // "owned" and applies it to the "close"-function, which // causes that calls to "close" only have an effect if // they are made by the stored owner. - function close() onlyowner { + function close() onlyOwner { selfdestruct(owner); } } @@ -277,18 +287,25 @@ 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 { + + function changePrice(uint _price) onlyOwner { price = _price; } } @@ -338,7 +355,7 @@ functions matches the given function identifier (or if no data was supplied at all). Furthermore, this function is executed whenever the contract receives plain -Ether (witout data). In such a context, there is very little gas available to +Ether (without data). In such a context, there is very little gas available to the function call, so it is important to make fallback functions as cheap as possible. @@ -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 @@ -397,15 +414,15 @@ ultimately, also the block headers have to be supplied because the contract can only see the last 256 block hashes). Up to three parameters can -receive the attribute `indexed` which will cause the respective arguments +receive the attribute ``indexed`` which will cause the respective arguments to be searched for: It is possible to filter for specific values of indexed arguments in the user interface. -If arrays (including `string` and `bytes`) are used as indexed arguments, the +If arrays (including ``string`` and ``bytes``) are used as indexed arguments, the sha3-hash of it is stored as topic instead. The hash of the signature of the event is one of the topics except if you -declared the event with `anonymous` specifier. This means that it is +declared the event with ``anonymous`` specifier. This means that it is not possible to filter for specific anonymous events by name. All non-indexed arguments will be stored in the data part of the log. @@ -458,8 +475,8 @@ Low-Level Interface to Logs =========================== It is also possible to access the low-level interface to the logging -mechanism via the functions `log0`, `log1`, `log2`, `log3` and `log4`. -`logi` takes `i + 1` parameter of type `bytes32`, where the first +mechanism via the functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``. +``logi`` takes ``i + 1`` parameter of type ``bytes32``, where the first argument will be used for the data part of the log and the others as topics. The event call above can be performed in the same way as @@ -473,7 +490,7 @@ as topics. The event call above can be performed in the same way as ); where the long hexadecimal number is equal to -`sha3("Deposit(address,hash256,uint256)")`, the signature of the event. +``sha3("Deposit(address,hash256,uint256)")``, the signature of the event. Additional Resources for Understanding Events ============================================== @@ -574,7 +591,7 @@ Details are given in the following example. uint info; } -Note that above, we call `mortal.kill()` to "forward" the +Note that above, we call ``mortal.kill()`` to "forward" the destruction request. The way this is done is problematic, as seen in the following example:: @@ -598,10 +615,10 @@ seen in the following example:: contract Final is Base1, Base2 { } -A call to `Final.kill()` will call `Base2.kill` as the most +A call to ``Final.kill()`` will call ``Base2.kill`` as the most derived override, but this function will bypass -`Base1.kill`, basically because it does not even know about -`Base1`. The way around this is to use `super`:: +``Base1.kill``, basically because it does not even know about +``Base1``. The way around this is to use ``super``:: contract mortal is owned { function kill() { @@ -623,10 +640,10 @@ derived override, but this function will bypass contract Final is Base2, Base1 { } -If `Base1` calls a function of `super`, it does not simply +If ``Base1`` calls a function of ``super``, it does not simply call this function on one of its base contracts, it rather calls this function on the next base contract in the final -inheritance graph, so it will call `Base2.kill()` (note that +inheritance graph, so it will call ``Base2.kill()`` (note that the final inheritance sequence is -- starting with the most derived contract: Final, Base1, Base2, mortal, owned). The actual function that is called when using super is @@ -653,9 +670,9 @@ the base constructors. This can be done at two places:: } } -Either directly in the inheritance list (`is Base(7)`) or in +Either directly in the inheritance list (``is Base(7)``) or in the way a modifier would be invoked as part of the header of -the derived constructor (`Base(_y * _y)`). The first way to +the derived constructor (``Base(_y * _y)``). The first way to do it is more convenient if the constructor argument is a constant and defines the behaviour of the contract or describes it. The second way has to be used if the @@ -674,7 +691,7 @@ Solidity follows the path of Python and uses "`C3 Linearization <https://en.wiki to force a specific order in the DAG of base classes. This results in the desirable property of monotonicity but disallows some inheritance graphs. Especially, the order in -which the base classes are given in the `is` directive is +which the base classes are given in the ``is`` directive is important. In the following code, Solidity will give the error "Linearization of inheritance graph impossible". @@ -684,9 +701,9 @@ error "Linearization of inheritance graph impossible". contract A is X {} contract C is A, X {} -The reason for this is that `C` requests `X` to override `A` -(by specifying `A, X` in this order), but `A` itself -requests to override `X`, which is a contradiction that +The reason for this is that ``C`` requests ``X`` to override ``A`` +(by specifying ``A, X`` in this order), but ``A`` itself +requests to override ``X``, which is a contradiction that cannot be resolved. A simple rule to remember is to specify the base classes in @@ -698,15 +715,15 @@ the order from "most base-like" to "most derived". Abstract Contracts ****************** -Contract functions can lack an implementation as in the following example (note that the function declaration header is terminated by `;`):: +Contract functions can lack an implementation as in the following example (note that the function declaration header is terminated by ``;``):: - contract feline { + contract Feline { function utterance() returns (bytes32); } Such contracts cannot be compiled (even if they contain implemented functions alongside non-implemented functions), but they can be used as base contracts:: - contract Cat is feline { + contract Cat is Feline { function utterance() returns (bytes32) { return "miaow"; } } @@ -721,26 +738,26 @@ Libraries ************ Libraries are similar to contracts, but their purpose is that they are deployed -only once at a specific address and their code is reused using the `DELEGATECALL` -(`CALLCODE` until homestead) +only once at a specific address and their code is reused using the ``DELEGATECALL`` +(``CALLCODE`` until Homestead) feature of the EVM. This means that if library functions are called, their code -is executed in the context of the calling contract, i.e. `this` points to the +is executed in the context of the calling contract, i.e. ``this`` points to the calling contract and especially the storage from the calling contract can be accessed. As a library is an isolated piece of source code, it can only access state variables of the calling contract if they are explicitly supplied (it -would have to way to name them, otherwise). +would have no way to name them, otherwise). Libraries can be seen as implicit base contracts of the contracts that use them. They will not be explicitly visible in the inheritance hierarchy, but calls to library functions look just like calls to functions of explicit base -contracts (`L.f()` if `L` is the name of the library). Furthermore, -`internal` functions of libraries are visible in all contracts, just as +contracts (``L.f()`` if ``L`` is the name of the library). Furthermore, +``internal`` functions of libraries are visible in all contracts, just as if the library were a base contract. Of course, calls to internal functions use the internal calling convention, which means that all internal types can be passed and memory types will be passed by reference and not copied. In order to realise this in the EVM, code of internal library functions (and all functions called from therein) will be pulled into the calling -contract and a regular `JUMP` call will be used instead of a `DELEGATECALL`. +contract and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. .. index:: using for, set @@ -806,13 +823,13 @@ data types, functions also work without any storage reference parameters, can have multiple storage reference parameters and in any position. -The calls to `Set.contains`, `Set.insert` and `Set.remove` -are all compiled as calls (`DELEGATECALL`s) to an external +The calls to ``Set.contains``, ``Set.insert`` and ``Set.remove`` +are all compiled as calls (``DELEGATECALL``) to an external contract/library. If you use libraries, take care that an actual external function call is performed. -`msg.sender`, `msg.value` and `this` will retain their values -in this call, though (prior to Homestead, `msg.sender` and -`msg.value` changed, though). +``msg.sender``, ``msg.value`` and ``this`` will retain their values +in this call, though (prior to Homestead, ``msg.sender`` and +``msg.value`` changed, though). The following example shows how to use memory types and internal functions in libraries in order to implement @@ -820,65 +837,66 @@ custom types without the overhead of external function calls: :: - library bigint { - struct bigint { - uint[] limbs; - } - - 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 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; - } - } - - - 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); - } - } + library BigInt { + struct bigint { + uint[] limbs; + } + + 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 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; + } + } + + + 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 -final bytecode by a linker (see [Using the Commandline -Compiler](#using-the-commandline-compiler) on how to use the +final bytecode by a linker +(see :ref:`commandline-compiler`) on how to use the commandline compiler for linking). If the addresses are not given as arguments to the compiler, the compiled hex code -will contain placeholders of the form `__Set______` (where -`Set` is the name of the library). The address can be filled +will contain placeholders of the form ``__Set______`` (where +``Set`` is the name of the library). The address can be filled manually by replacing all those 40 symbols by the hex encoding of the address of the library contract. @@ -897,14 +915,14 @@ Restrictions for libraries in comparison to contracts: Using For ********* -The directive `using A for B;` can be used to attach library -functions (from the library `A`) to any type (`B`). +The directive ``using A for B;`` can be used to attach library +functions (from the library ``A``) to any type (``B``). These functions will receive the object they are called on -as their first parameter (like the `self` variable in +as their first parameter (like the ``self`` variable in Python). -The effect of `using A for *;` is that the functions from -the library `A` are attached to any type. +The effect of ``using A for *;`` is that the functions from +the library ``A`` are attached to any type. In both situations, all functions, even those where the type of the first parameter does not match the type of @@ -912,7 +930,7 @@ the object, are attached. The type is checked at the point the function is called and function overload resolution is performed. -The `using A for B;` directive is active for the current +The ``using A for B;`` directive is active for the current scope, which is limited to a contract for now but will be lifted to the global scope later, so that by including a module, its data types including library functions are @@ -996,5 +1014,5 @@ It is also possible to extend elementary types in that way:: Note that all library calls are actual EVM function calls. This means that if you pass memory or value types, a copy will be performed, even of the -`self` variable. The only situation where no copy will be performed +``self`` variable. The only situation where no copy will be performed is when storage reference variables are used. |