aboutsummaryrefslogtreecommitdiffstats
path: root/docs/contracts.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/contracts.rst')
-rw-r--r--docs/contracts.rst147
1 files changed, 102 insertions, 45 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst
index 561d2f97..669a374f 100644
--- a/docs/contracts.rst
+++ b/docs/contracts.rst
@@ -26,8 +26,8 @@ Creating contracts programmatically on Ethereum is best done via using the JavaS
As of today it has a method called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_
to facilitate contract creation.
-When a contract is created, its constructor (a function declared with the
-``constructor`` keyword) is executed once.
+When a contract is created, its constructor_ (a function declared with the ``constructor`` keyword) is executed once.
+
A constructor is optional. Only one constructor is allowed, and this means
overloading is not supported.
@@ -110,12 +110,11 @@ This means that cyclic creation dependencies are impossible.
function isTokenTransferOK(address currentOwner, address newOwner)
public
- view
+ pure
returns (bool ok)
{
// Check some arbitrary condition.
- address tokenAddress = msg.sender;
- return (keccak256(abi.encodePacked(newOwner)) & 0xff) == (bytes20(tokenAddress) & 0xff);
+ return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f;
}
}
@@ -138,16 +137,16 @@ Functions have to be specified as being ``external``,
For state variables, ``external`` is not possible.
``external``:
- External functions are part of the contract
- interface, which means they can be called from other contracts and
+ 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).
External functions are sometimes more efficient when
they receive large arrays of data.
``public``:
- Public functions are part of the contract
- interface and can be either called internally or via
+ Public functions are part of the contract interface
+ and can be either called internally or via
messages. For public state variables, an automatic getter
function (see below) is generated.
@@ -188,8 +187,6 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
::
- // This will not compile
-
pragma solidity ^0.4.0;
contract C {
@@ -201,6 +198,7 @@ In the following example, ``D``, can call ``c.getData()`` to retrieve the value
function compute(uint a, uint b) internal pure returns (uint) { return a + b; }
}
+ // This will not compile
contract D {
function readData() public {
C c = new C();
@@ -228,8 +226,8 @@ The compiler automatically creates getter functions for
all **public** state variables. For the contract given below, the compiler will
generate 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
-be done at declaration.
+variable ``data``. State variables can be initialized
+when they are declared.
::
@@ -241,8 +239,8 @@ be done at declaration.
contract Caller {
C c = new C();
- function f() public {
- uint local = c.data();
+ function f() public view returns (uint) {
+ return c.data();
}
}
@@ -257,13 +255,43 @@ it is evaluated as a state variable. If it is accessed externally
contract C {
uint public data;
- function x() public {
+ function x() public returns (uint) {
data = 3; // internal access
- uint val = this.data(); // external access
+ return this.data(); // external access
}
}
-The next example is a bit more complex:
+If you have a `public` state variable of array type, then you can only retrieve
+single elements of the array via the generated getter function. This mechanism
+exists to avoid high gas costs when returning an entire array. You can use
+arguments to specify which individual element to return, for example
+``data(0)``. If you want to return an entire array in one call, then you need
+to write a function, for example:
+
+::
+
+ pragma solidity ^0.4.0;
+ contract arrayExample {
+ // public state variable
+ uint[] public myArray;
+
+ // Getter function generated by the compiler
+ /*
+ function myArray(uint i) returns (uint) {
+ return myArray[i];
+ }
+ */
+
+ // function that returns entire array
+ function getArray() returns (uint[] memory) {
+ return myArray;
+ }
+ }
+
+Now you can use ``getArray()`` to retrieve the entire array, instead of
+``myArray(i)``, which returns a single element per call.
+
+The next example is more complex:
::
@@ -278,16 +306,16 @@ The next example is a bit more complex:
mapping (uint => mapping(bool => Data[])) public data;
}
-It will generate a function of the following form::
+It generates a function of the following form. The mapping in the struct is omitted
+because there is no good way to provide the key for the mapping:
+
+::
function data(uint arg1, bool arg2, uint arg3) public returns (uint a, bytes3 b) {
a = data[arg1][arg2][arg3].a;
b = data[arg1][arg2][arg3].b;
}
-Note that the mapping in the struct is omitted because there
-is no good way to provide the key for the mapping.
-
.. index:: ! function;modifier
.. _modifiers:
@@ -616,14 +644,13 @@ Like any function, the fallback function can execute complex operations as long
}
contract Caller {
- function callTest(Test test) public {
- address(test).call(abi.encodeWithSignature("nonExistingFunction()"));
+ function callTest(Test test) public returns (bool) {
+ require(address(test).call(abi.encodeWithSignature("nonExistingFunction()")));
// results in test.x becoming == 1.
// If someone sends ether to that contract,
- // the transaction will fail and reject the
- // Ether.
- address(test).send(2 ether);
+ // the transfer will fail, i.e. this returns false here.
+ return address(test).send(2 ether);
}
}
@@ -634,9 +661,11 @@ Like any function, the fallback function can execute complex operations as long
Function Overloading
====================
-A Contract can have multiple functions of the same name but with different arguments.
-This also applies to inherited functions. The following example shows overloading of the
-``f`` function in the scope of contract ``A``.
+A contract can have multiple functions of the same name but with different parameter
+types.
+This process is called "overloading" and also applies to inherited functions.
+The following example shows overloading of the function
+``f`` in the scope of contract ``A``.
::
@@ -644,11 +673,12 @@ This also applies to inherited functions. The following example shows overloadin
contract A {
function f(uint _in) public pure returns (uint out) {
- out = 1;
+ out = _in;
}
- function f(uint _in, bytes32 _key) public pure returns (uint out) {
- out = 2;
+ function f(uint _in, bool _really) public pure returns (uint out) {
+ if (_really)
+ out = _in;
}
}
@@ -657,9 +687,9 @@ externally visible functions differ by their Solidity types but not by their ext
::
- // This will not compile
pragma solidity ^0.4.16;
+ // This will not compile
contract A {
function f(B _in) public pure returns (B out) {
out = _in;
@@ -811,12 +841,12 @@ as topics. The event call above can be performed in the same way as
contract C {
function f() public payable {
- bytes32 _id = 0x420042;
+ uint256 _id = 0x420042;
log3(
bytes32(msg.value),
bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20),
bytes32(uint256(msg.sender)),
- _id
+ bytes32(_id)
);
}
}
@@ -842,13 +872,14 @@ Solidity supports multiple inheritance by copying code including polymorphism.
All function calls are virtual, which means that the most derived function
is called, except when the contract name is explicitly given.
-When a contract inherits from multiple contracts, only a single
+When a contract inherits from other contracts, only a single
contract is created on the blockchain, and the code from all the base contracts
is copied into the created contract.
The general inheritance system is very similar to
`Python's <https://docs.python.org/3/tutorial/classes.html#inheritance>`_,
-especially concerning multiple inheritance.
+especially concerning multiple inheritance, but there are also
+some :ref:`differences <multi-inheritance>`.
Details are given in the following example.
@@ -993,12 +1024,26 @@ virtual method lookup.
.. index:: ! constructor
+.. _constructor:
+
Constructors
============
-A constructor is an optional function declared with the ``constructor`` keyword which is executed upon contract creation.
-Constructor functions can be either ``public`` or ``internal``. If there is no constructor, the contract will assume the
-default constructor: ``contructor() public {}``.
+A constructor is an optional function declared with the ``constructor`` keyword
+which is executed upon contract creation, and where you can run contract
+initialisation code.
+
+Before the constructor code is executed, state variables are initialised to
+their specified value if you initialise them inline, or zero if you do not.
+
+After the final code of the contract is returned. The final deployment of
+the code costs additional gas linear to the length of the code. If you did not
+supply enough gas to initiate the state variables declared in the constructor,
+then an "out of gas" exception is generated.
+
+Constructor functions can be either ``public`` or ``internal``. If there is no
+constructor, the contract will assume the default constructor, which is
+equivalent to ``constructor() public {}``. For example:
::
@@ -1038,10 +1083,12 @@ derived contracts need to specify all of them. This can be done in two ways::
constructor(uint _x) public { x = _x; }
}
+ // Either directly specify in the inheritance list...
contract Derived1 is Base(7) {
- constructor(uint _y) public {}
+ constructor() public {}
}
+ // or through a "modifier" of the derived constructor.
contract Derived2 is Base {
constructor(uint _y) Base(_y * _y) public {}
}
@@ -1062,6 +1109,8 @@ contracts' constructors, it will be abstract.
.. index:: ! inheritance;multiple, ! linearization, ! C3 linearization
+.. _multi-inheritance:
+
Multiple Inheritance and Linearization
======================================
@@ -1074,18 +1123,23 @@ disallows some inheritance graphs. Especially, the order in
which the base classes are given in the ``is`` directive is
important: You have to list the direct base contracts
in the order from "most base-like" to "most derived".
-Note that this order is different from the one used in Python.
+Note that this order is the reverse of the one used in Python.
+
+Another simplifying way to explain this is that when a function is called that
+is defined multiple times in different contracts, the given bases
+are searched from right to left (left to right in Python) in a depth-first manner,
+stopping at the first match. If a base contract has already been searched, it is skipped.
+
In the following code, Solidity will give the
error "Linearization of inheritance graph impossible".
::
- // This will not compile
-
pragma solidity ^0.4.0;
contract X {}
contract A is X {}
+ // This will not compile
contract C is A, X {}
The reason for this is that ``C`` requests ``X`` to override ``A``
@@ -1093,6 +1147,8 @@ The reason for this is that ``C`` requests ``X`` to override ``A``
requests to override ``X``, which is a contradiction that
cannot be resolved.
+
+
Inheriting Different Kinds of Members of the Same Name
======================================================
@@ -1343,6 +1399,7 @@ custom types without the overhead of external function calls:
BigInt.bigint memory x = BigInt.fromUint(7);
BigInt.bigint memory y = BigInt.fromUint(uint(-1));
BigInt.bigint memory z = x.add(y);
+ assert(z.limb(1) > 0);
}
}