diff options
Diffstat (limited to 'docs/contracts.rst')
-rw-r--r-- | docs/contracts.rst | 1765 |
1 files changed, 13 insertions, 1752 deletions
diff --git a/docs/contracts.rst b/docs/contracts.rst index 682cb378..5bab6e78 100644 --- a/docs/contracts.rst +++ b/docs/contracts.rst @@ -10,1764 +10,25 @@ Contracts in Solidity are similar to classes in object-oriented languages. They contain persistent data in state variables and functions that can modify these variables. Calling a function on a different contract (instance) will perform an EVM function call and thus switch the context such that state variables are -inaccessible. +inaccessible. A contract and its functions need to be called for anything to happen. +There is no "cron" concept in Ethereum to call a function at a particular event automatically. -.. index:: ! contract;creation, constructor +.. include:: contracts/creating-contracts.rst -****************** -Creating Contracts -****************** +.. include:: contracts/visibility-and-getters.rst -Contracts can be created "from outside" via Ethereum transactions or from within Solidity contracts. +.. include:: contracts/function-modifiers.rst -IDEs, such as `Remix <https://remix.ethereum.org/>`_, make the creation process seamless using UI elements. +.. include:: contracts/constant-state-variables.rst +.. include:: contracts/functions.rst -Creating contracts programmatically on Ethereum is best done via using the JavaScript API `web3.js <https://github.com/ethereum/web3.js>`_. -It has a function called `web3.eth.Contract <https://web3js.readthedocs.io/en/1.0/web3-eth-contract.html#new-contract>`_ -to facilitate contract creation. +.. include:: contracts/events.rst -When a contract is created, its constructor_ (a function declared with the ``constructor`` keyword) is executed once. +.. include:: contracts/inheritance.rst -A constructor is optional. Only one constructor is allowed, which means -overloading is not supported. +.. include:: contracts/abstract-contracts.rst +.. include:: contracts/interfaces.rst -After the constructor has executed, the final code of the contract is deployed to the -blockchain. This code includes all public and external functions and all functions -that are reachable from there through function calls. The deployed code does not -include the constructor code or internal functions only called from the constructor. +.. include:: contracts/libraries.rst -.. index:: constructor;arguments - -Internally, constructor arguments are passed :ref:`ABI encoded <ABI>` after the code of -the contract itself, but you do not have to care about this 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. -This means that cyclic creation dependencies are impossible. - -:: - - pragma solidity >=0.4.22 <0.6.0; - - contract OwnedToken { - // `TokenCreator` is a contract type that is defined below. - // It is fine to reference it as long as it is not used - // to create a new contract. - TokenCreator creator; - address owner; - bytes32 name; - - // This is the constructor which registers the - // creator and the assigned name. - constructor(bytes32 _name) public { - // State variables are accessed via their name - // and not via e.g. `this.owner`. Functions can - // be accessed directly or through `this.f`, - // but the latter provides an external view - // to the function. Especially in the constructor, - // you should not access functions externally, - // because the function does not exist yet. - // See the next section for details. - owner = msg.sender; - - // We do an explicit type conversion from `address` - // to `TokenCreator` and assume that the type of - // the calling contract is `TokenCreator`, there is - // no real way to check that. - creator = TokenCreator(msg.sender); - name = _name; - } - - function changeName(bytes32 newName) public { - // Only the creator can alter the name -- - // the comparison is possible since contracts - // are explicitly convertible to addresses. - if (msg.sender == address(creator)) - name = newName; - } - - function transfer(address newOwner) public { - // Only the current owner can transfer the token. - if (msg.sender != owner) return; - - // We ask the creator contract if the transfer - // should proceed by using a function of the - // `TokenCreator` contract defined below. If - // the call fails (e.g. due to out-of-gas), - // the execution also fails here. - if (creator.isTokenTransferOK(owner, newOwner)) - owner = newOwner; - } - } - - contract TokenCreator { - function createToken(bytes32 name) - public - returns (OwnedToken tokenAddress) - { - // Create a new `Token` contract and return its address. - // From the JavaScript side, the return type is - // `address`, as this is the closest type available in - // the ABI. - return new OwnedToken(name); - } - - function changeName(OwnedToken tokenAddress, bytes32 name) public { - // Again, the external type of `tokenAddress` is - // simply `address`. - tokenAddress.changeName(name); - } - - // Perform checks to determine if transferring a token to the - // `OwnedToken` contract should proceed - function isTokenTransferOK(address currentOwner, address newOwner) - public - pure - returns (bool ok) - { - // Check an arbitrary condition to see if transfer should proceed - return keccak256(abi.encodePacked(currentOwner, newOwner))[0] == 0x7f; - } - } - -.. index:: ! visibility, external, public, private, internal - -.. _visibility-and-getters: - -********************** -Visibility and Getters -********************** - -Since Solidity knows two kinds of function calls (internal -ones that do not create an actual EVM call (also called -a "message call") and external -ones that do), there are four types of visibilities for -functions and state variables. - -Functions have to be specified as being ``external``, -``public``, ``internal`` or ``private``. -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 - 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 - messages. For public state variables, an automatic getter - function (see below) is generated. - -``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``. - -``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 observers external to the blockchain. Making something ``private`` - only prevents other contracts from accessing and modifying - the information, but it will still be visible to the - whole world outside of the blockchain. - -The visibility specifier is given after the type for -state variables and between parameter list and -return parameter list for functions. - -:: - - pragma solidity >=0.4.16 <0.6.0; - - contract C { - function f(uint a) private pure returns (uint b) { return a + 1; } - function setData(uint a) internal { data = a; } - uint public data; - } - -In the following example, ``D``, can call ``c.getData()`` to retrieve the value of -``data`` in state storage, but is not able to call ``f``. Contract ``E`` is derived from -``C`` and, thus, can call ``compute``. - -:: - - pragma solidity >=0.4.0 <0.6.0; - - contract C { - uint private data; - - function f(uint a) private pure returns(uint b) { return a + 1; } - function setData(uint a) public { data = a; } - function getData() public view returns(uint) { return data; } - 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(); - uint local = c.f(7); // error: member `f` is not visible - c.setData(3); - local = c.getData(); - local = c.compute(3, 5); // error: member `compute` is not visible - } - } - - contract E is C { - function g() public { - C c = new C(); - uint val = compute(3, 5); // access to internal member (from derived to parent contract) - } - } - -.. index:: ! getter;function, ! function;getter -.. _getter-functions: - -Getter Functions -================ - -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``. State variables can be initialized -when they are declared. - -:: - - pragma solidity >=0.4.0 <0.6.0; - - contract C { - uint public data = 42; - } - - contract Caller { - C c = new C(); - function f() public view returns (uint) { - return c.data(); - } - } - -The getter functions have external visibility. If the -symbol is accessed internally (i.e. without ``this.``), -it evaluates to a state variable. If it is accessed externally -(i.e. with ``this.``), it evaluates to a function. - -:: - - pragma solidity >=0.4.0 <0.6.0; - - contract C { - uint public data; - function x() public returns (uint) { - data = 3; // internal access - return this.data(); // external access - } - } - -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 <0.6.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: - -:: - - pragma solidity >=0.4.0 <0.6.0; - - contract Complex { - struct Data { - uint a; - bytes3 b; - mapping (uint => uint) map; - } - mapping (uint => mapping(bool => Data[])) public data; - } - -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; - } - -.. index:: ! function;modifier - -.. _modifiers: - -****************** -Function Modifiers -****************** - -Modifiers can be used to easily change the behaviour of functions. For example, -they can automatically check a condition prior to executing the function. Modifiers are -inheritable properties of contracts and may be overridden by derived contracts. - -:: - - pragma solidity >0.4.99 <0.6.0; - - contract owned { - constructor() public { owner = msg.sender; } - address payable owner; - - // This contract only defines a modifier but does not use - // it: it will be used in derived contracts. - // The function body is inserted where the special symbol - // `_;` in the definition of a modifier appears. - // This means that if the owner calls this function, the - // function is executed and otherwise, an exception is - // thrown. - modifier onlyOwner { - require( - msg.sender == owner, - "Only owner can call this function." - ); - _; - } - } - - contract mortal is owned { - // 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() public onlyOwner { - selfdestruct(owner); - } - } - - contract priced { - // Modifiers can receive arguments: - modifier costs(uint price) { - if (msg.value >= price) { - _; - } - } - } - - contract Register is priced, owned { - mapping (address => bool) registeredAddresses; - uint price; - - constructor(uint initialPrice) public { price = initialPrice; } - - // It is important to also provide the - // `payable` keyword here, otherwise the function will - // automatically reject all Ether sent to it. - function register() public payable costs(price) { - registeredAddresses[msg.sender] = true; - } - - function changePrice(uint _price) public onlyOwner { - price = _price; - } - } - - contract Mutex { - bool locked; - modifier noReentrancy() { - require( - !locked, - "Reentrant call." - ); - locked = true; - _; - locked = false; - } - - /// This function is protected by a mutex, which means that - /// reentrant calls from within `msg.sender.call` cannot call `f` again. - /// The `return 7` statement assigns 7 to the return value but still - /// executes the statement `locked = false` in the modifier. - function f() public noReentrancy returns (uint) { - (bool success,) = msg.sender.call(""); - require(success); - return 7; - } - } - -Multiple modifiers are applied to a function by specifying them in a -whitespace-separated list and are evaluated in the order presented. - -.. warning:: - In an earlier version of Solidity, ``return`` statements in functions - having modifiers behaved differently. - -Explicit returns from a modifier or function body only leave the current -modifier or function body. Return variables are assigned and -control flow continues after the "_" in the preceding modifier. - -Arbitrary expressions are allowed for modifier arguments and in this context, -all symbols visible from the function are visible in the modifier. Symbols -introduced in the modifier are not visible in the function (as they might -change by overriding). - -.. index:: ! constant - -************************ -Constant State Variables -************************ - -State variables can be declared as ``constant``. In this case, they have to be -assigned from an expression which is a constant at compile time. Any expression -that accesses storage, blockchain data (e.g. ``now``, ``address(this).balance`` or -``block.number``) or -execution data (``msg.value`` or ``gasleft()``) or makes calls to external contracts is disallowed. Expressions -that might have a side-effect on memory allocation are allowed, but those that -might have a side-effect on other memory objects are not. The built-in functions -``keccak256``, ``sha256``, ``ripemd160``, ``ecrecover``, ``addmod`` and ``mulmod`` -are allowed (even though, with the exception of ``keccak256``, they do call external contracts). - -The reason behind allowing side-effects on the memory allocator is that it -should be possible to construct complex objects like e.g. lookup-tables. -This feature is not yet fully usable. - -The compiler does not reserve a storage slot for these variables, and every occurrence is -replaced by the respective constant expression (which might be computed to a single value by the optimizer). - -Not all types for constants are implemented at this time. The only supported types are -value types and strings. - -:: - - pragma solidity >=0.4.0 <0.6.0; - - contract C { - uint constant x = 32**22 + 8; - string constant text = "abc"; - bytes32 constant myHash = keccak256("abc"); - } - -.. index:: ! functions - -.. _functions: - -********* -Functions -********* - -.. _function-parameters-return-variables: - -Function Parameters and Return Variables -======================================== - -As in JavaScript, functions may take parameters as input. Unlike in JavaScript -and C, functions may also return an arbitrary number of values as output. - -Function Parameters -------------------- - -Function parameters are declared the same way as variables, and the name of -unused parameters can be omitted. - -For example, if you want your contract to accept one kind of external call -with two integers, you would use something like:: - - pragma solidity >=0.4.16 <0.6.0; - - contract Simple { - uint sum; - function taker(uint _a, uint _b) public { - sum = _a + _b; - } - } - -Function parameters can be used as any other local variable and they can also be assigned to. - -.. note:: - - An :ref:`external function<external-function-calls>` cannot accept a - multi-dimensional array as an input - parameter. This functionality is possible if you enable the new - experimental ``ABIEncoderV2`` feature by adding ``pragma experimental ABIEncoderV2;`` to your source file. - - An :ref:`internal function<external-function-calls>` can accept a - multi-dimensional array without enabling the feature. - -.. index:: return array, return string, array, string, array of strings, dynamic array, variably sized array, return struct, struct - -Return Variables ----------------- - -Function return variables are declared with the same syntax after the -``returns`` keyword. - -For example, suppose you want to return two results: the sum and the product of -two integers passed as function parameters, then you use something like:: - - pragma solidity >=0.4.16 <0.6.0; - - contract Simple { - function arithmetic(uint _a, uint _b) - public - pure - returns (uint o_sum, uint o_product) - { - o_sum = _a + _b; - o_product = _a * _b; - } - } - -The names of return variables can be omitted. -Return variables can be used as any other local variable and they -are initialized with their :ref:`default value <default-value>` and have that value unless explicitly set. - -You can either explicitly assign to return variables and -then leave the function using ``return;``, -or you can provide return values -(either a single or :ref:`multiple ones<multi-return>`) directly with the ``return`` -statement:: - - pragma solidity >=0.4.16 <0.6.0; - - contract Simple { - function arithmetic(uint _a, uint _b) - public - pure - returns (uint o_sum, uint o_product) - { - return (_a + _b, _a * _b); - } - } - -This form is equivalent to first assigning values to the -return variables and then using ``return;`` to leave the function. - -.. note:: - You cannot return some types from non-internal functions, notably - multi-dimensional dynamic arrays and structs. If you enable the - new experimental ``ABIEncoderV2`` feature by adding ``pragma experimental - ABIEncoderV2;`` to your source file then more types are available, but - ``mapping`` types are still limited to inside a single contract and you - cannot transfer them. - -.. _multi-return: - -Returning Multiple Values -------------------------- - -When a function has multiple return types, the statement ``return (v0, v1, ..., vn) can be used to return multiple values. -vn)`` can return multiple values. The number of components must be -the same as the number of return types. - -.. index:: ! view function, function;view - -.. _view-functions: - -View Functions -============== - -Functions can be declared ``view`` in which case they promise not to modify the state. - -.. note:: - If the compiler's EVM target is Byzantium or newer (default) the opcode - ``STATICCALL`` is used for ``view`` functions which enforces the state - to stay unmodified as part of the EVM execution. For library ``view`` functions - ``DELEGATECALL`` is used, because there is no combined ``DELEGATECALL`` and ``STATICCALL``. - This means library ``view`` functions do not have run-time checks that prevent state - modifications. This should not impact security negatively because library code is - usually known at compile-time and the static checker performs compile-time checks. - -The following statements are considered modifying the state: - -#. Writing to state variables. -#. :ref:`Emitting events <events>`. -#. :ref:`Creating other contracts <creating-contracts>`. -#. Using ``selfdestruct``. -#. Sending Ether via calls. -#. Calling any function not marked ``view`` or ``pure``. -#. Using low-level calls. -#. Using inline assembly that contains certain opcodes. - -:: - - pragma solidity >0.4.99 <0.6.0; - - contract C { - function f(uint a, uint b) public view returns (uint) { - return a * (b + 42) + now; - } - } - -.. note:: - ``constant`` on functions used to be an alias to ``view``, but this was dropped in version 0.5.0. - -.. note:: - Getter methods are automatically marked ``view``. - -.. note:: - Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode - for ``view`` functions. - This enabled state modifications in ``view`` functions through the use of - invalid explicit type conversions. - By using ``STATICCALL`` for ``view`` functions, modifications to the - state are prevented on the level of the EVM. - -.. index:: ! pure function, function;pure - -.. _pure-functions: - -Pure Functions -============== - -Functions can be declared ``pure`` in which case they promise not to read from or modify the state. - -.. note:: - If the compiler's EVM target is Byzantium or newer (default) the opcode ``STATICCALL`` is used, - which does not guarantee that the state is not read, but at least that it is not modified. - -In addition to the list of state modifying statements explained above, the following are considered reading from the state: - -#. Reading from state variables. -#. Accessing ``address(this).balance`` or ``<address>.balance``. -#. Accessing any of the members of ``block``, ``tx``, ``msg`` (with the exception of ``msg.sig`` and ``msg.data``). -#. Calling any function not marked ``pure``. -#. Using inline assembly that contains certain opcodes. - -:: - - pragma solidity >0.4.99 <0.6.0; - - contract C { - function f(uint a, uint b) public pure returns (uint) { - return a * (b + 42); - } - } - -Pure functions are able to use the `revert()` and `require()` functions to revert -potential state changes when an :ref:`error occurs <assert-and-require>`. - -Reverting a state change is not considered a "state modification", as only changes to the -state made previously in code that did not have the ``view`` or ``pure`` restriction -are reverted and that code has the option to catch the ``revert`` and not pass it on. - -This behaviour is also in line with the ``STATICCALL`` opcode. - -.. warning:: - It is not possible to prevent functions from reading the state at the level - of the EVM, it is only possible to prevent them from writing to the state - (i.e. only ``view`` can be enforced at the EVM level, ``pure`` can not). - -.. note:: - Prior to version 0.5.0, the compiler did not use the ``STATICCALL`` opcode - for ``pure`` functions. - This enabled state modifications in ``pure`` functions through the use of - invalid explicit type conversions. - By using ``STATICCALL`` for ``pure`` functions, modifications to the - state are prevented on the level of the EVM. - -.. note:: - Prior to version 0.4.17 the compiler did not enforce that ``pure`` is not reading the state. - It is a compile-time type check, which can be circumvented doing invalid explicit conversions - between contract types, because the compiler can verify that the type of the contract does - not do state-changing operations, but it cannot check that the contract that will be called - at runtime is actually of that type. - -.. index:: ! fallback function, function;fallback - -.. _fallback-function: - -Fallback Function -================= - -A contract can have exactly one unnamed function. This function cannot have -arguments, cannot return anything and has to have ``external`` visibility. -It is executed on a call to the contract if none of the other -functions match the given function identifier (or if no data was supplied at -all). - -Furthermore, this function is executed whenever the contract receives plain -Ether (without data). Additionally, in order to receive Ether, the fallback function -must be marked ``payable``. If no such function exists, the contract cannot receive -Ether through regular transactions. - -In the worst case, the fallback function can only rely on 2300 gas being -available (for example when `send` or `transfer` is used), leaving little -room to perform other operations except basic logging. The following operations -will consume more gas than the 2300 gas stipend: - -- Writing to storage -- Creating a contract -- Calling an external function which consumes a large amount of gas -- Sending Ether - -Like any function, the fallback function can execute complex operations as long as there is enough gas passed on to it. - -.. note:: - Even though the fallback function cannot have arguments, one can still use ``msg.data`` to retrieve - any payload supplied with the call. - -.. warning:: - The fallback function is also executed if the caller meant to call - a function that is not available. If you want to implement the fallback - function only to receive ether, you should add a check - like ``require(msg.data.length == 0)`` to prevent invalid calls. - -.. warning:: - Contracts that receive Ether directly (without a function call, i.e. using ``send`` or ``transfer``) - but do not define a fallback function - throw an exception, sending back the Ether (this was different - before Solidity v0.4.0). So if you want your contract to receive Ether, - you have to implement a payable fallback function. - -.. warning:: - A contract without a payable fallback function can receive Ether as a recipient of a `coinbase transaction` (aka `miner block reward`) - or as a destination of a ``selfdestruct``. - - A contract cannot react to such Ether transfers and thus also cannot reject them. This is a design choice of the EVM and Solidity cannot work around it. - - It also means that ``address(this).balance`` can be higher than the sum of some manual accounting implemented in a contract (i.e. having a counter updated in the fallback function). - -:: - - pragma solidity >0.4.99 <0.6.0; - - contract Test { - // This function is called for all messages sent to - // this contract (there is no other function). - // Sending Ether to this contract will cause an exception, - // because the fallback function does not have the `payable` - // modifier. - function() external { x = 1; } - uint x; - } - - - // This contract keeps all Ether sent to it with no way - // to get it back. - contract Sink { - function() external payable { } - } - - contract Caller { - function callTest(Test test) public returns (bool) { - (bool success,) = address(test).call(abi.encodeWithSignature("nonExistingFunction()")); - require(success); - // results in test.x becoming == 1. - - // address(test) will not allow to call ``send`` directly, since ``test`` has no payable - // fallback function. It has to be converted to the ``address payable`` type via an - // intermediate conversion to ``uint160`` to even allow calling ``send`` on it. - address payable testPayable = address(uint160(address(test))); - - // If someone sends ether to that contract, - // the transfer will fail, i.e. this returns false here. - return testPayable.send(2 ether); - } - } - -.. index:: ! overload - -.. _overload-function: - -Function Overloading -==================== - -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``. - -:: - - pragma solidity >=0.4.16 <0.6.0; - - contract A { - function f(uint _in) public pure returns (uint out) { - out = _in; - } - - function f(uint _in, bool _really) public pure returns (uint out) { - if (_really) - out = _in; - } - } - -Overloaded functions are also present in the external interface. It is an error if two -externally visible functions differ by their Solidity types but not by their external types. - -:: - - pragma solidity >=0.4.16 <0.6.0; - - // This will not compile - contract A { - function f(B _in) public pure returns (B out) { - out = _in; - } - - function f(address _in) public pure returns (address out) { - out = _in; - } - } - - contract B { - } - - -Both ``f`` function overloads above end up accepting the address type for the ABI although -they are considered different inside Solidity. - -Overload resolution and Argument matching ------------------------------------------ - -Overloaded functions are selected by matching the function declarations in the current scope -to the arguments supplied in the function call. Functions are selected as overload candidates -if all arguments can be implicitly converted to the expected types. If there is not exactly one -candidate, resolution fails. - -.. note:: - Return parameters are not taken into account for overload resolution. - -:: - - pragma solidity >=0.4.16 <0.6.0; - - contract A { - function f(uint8 _in) public pure returns (uint8 out) { - out = _in; - } - - function f(uint256 _in) public pure returns (uint256 out) { - out = _in; - } - } - -Calling ``f(50)`` would create a type error since ``50`` can be implicitly converted both to ``uint8`` -and ``uint256`` types. On another hand ``f(256)`` would resolve to ``f(uint256)`` overload as ``256`` cannot be implicitly -converted to ``uint8``. - -.. index:: ! event - -.. _events: - -****** -Events -****** - -Solidity events give an abstraction on top of the EVM's logging functionality. -Applications can subscribe and listen to these events through the RPC interface of an Ethereum client. - -Events are inheritable members of contracts. When you call them, they cause the -arguments to be stored in the transaction's log - a special data structure -in the blockchain. These logs are associated with the address of the contract, -are incorporated into the blockchain, and stay there as long as a block is -accessible (forever as of the Frontier and Homestead releases, but this might -change with Serenity). The Log and its event data is not accessible from within -contracts (not even from the contract that created them). - -It is possible to request a simple payment verification (SPV) for logs, so if -an external entity supplies a contract with such a verification, it can check -that the log actually exists inside the blockchain. You have to supply block headers -because the contract can only see the last 256 block hashes. - -You can add the attribute ``indexed`` to up to three parameters which adds them -to a special data structure known as :ref:`"topics" <abi_events>` instead of -the data part of the log. If you use arrays (including ``string`` and ``bytes``) -as indexed arguments, its Keccak-256 hash is stored as a topic instead, this is -because a topic can only hold a single word (32 bytes). - -All parameters without the ``indexed`` attribute are :ref:`ABI-encoded <ABI>` -into the data part of the log. - -Topics allow you to search for events, for example when filtering a sequence of -blocks for certain events. You can also filter events by the address of the -contract that emitted the event. - -For example, the code below uses the web3.js ``subscribe("logs")`` -`method <https://web3js.readthedocs.io/en/1.0/web3-eth-subscribe.html#subscribe-logs>`_ to filter -logs that match a topic with a certain address value: - -.. code-block:: javascript - - var options = { - fromBlock: 0, - address: web3.eth.defaultAccount, - topics: ["0x0000000000000000000000000000000000000000000000000000000000000000", null, null] - }; - web3.eth.subscribe('logs', options, function (error, result) { - if (!error) - console.log(result); - }) - .on("data", function (log) { - console.log(log); - }) - .on("changed", function (log) { - }); - - -The hash of the signature of the event is one of the topics, except if you -declared the event with the ``anonymous`` specifier. This means that it is -not possible to filter for specific anonymous events by name. - -:: - - pragma solidity >=0.4.21 <0.6.0; - - contract ClientReceipt { - event Deposit( - address indexed _from, - bytes32 indexed _id, - uint _value - ); - - function deposit(bytes32 _id) public payable { - // Events are emitted using `emit`, followed by - // the name of the event and the arguments - // (if any) in parentheses. Any such invocation - // (even deeply nested) can be detected from - // the JavaScript API by filtering for `Deposit`. - emit Deposit(msg.sender, _id, msg.value); - } - } - -The use in the JavaScript API is as follows: - -:: - - var abi = /* abi as generated by the compiler */; - var ClientReceipt = web3.eth.contract(abi); - var clientReceipt = ClientReceipt.at("0x1234...ab67" /* address */); - - var event = clientReceipt.Deposit(); - - // watch for changes - event.watch(function(error, result){ - // result contains non-indexed arguments and topics - // given to the `Deposit` call. - if (!error) - console.log(result); - }); - - - // Or pass a callback to start watching immediately - var event = clientReceipt.Deposit(function(error, result) { - if (!error) - console.log(result); - }); - -The output of the above looks like the following (trimmed): - -.. code-block:: json - - { - "returnValues": { - "_from": "0x1111…FFFFCCCC", - "_id": "0x50…sd5adb20", - "_value": "0x420042" - }, - "raw": { - "data": "0x7f…91385", - "topics": ["0xfd4…b4ead7", "0x7f…1a91385"] - } - } - -.. index:: ! log - -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 -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 - -:: - - pragma solidity >=0.4.10 <0.6.0; - - contract C { - function f() public payable { - uint256 _id = 0x420042; - log3( - bytes32(msg.value), - bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), - bytes32(uint256(msg.sender)), - bytes32(_id) - ); - } - } - -where the long hexadecimal number is equal to -``keccak256("Deposit(address,bytes32,uint256)")``, the signature of the event. - -Additional Resources for Understanding Events -============================================== - -- `Javascript documentation <https://github.com/ethereum/wiki/wiki/JavaScript-API#contract-events>`_ -- `Example usage of events <https://github.com/debris/smart-exchange/blob/master/lib/contracts/SmartExchange.sol>`_ -- `How to access them in js <https://github.com/debris/smart-exchange/blob/master/lib/exchange_transactions.js>`_ - -.. index:: ! inheritance, ! base class, ! contract;base, ! deriving - -*********** -Inheritance -*********** - -Solidity supports multiple inheritance including polymorphism. - -All function calls are virtual, which means that the most derived function -is called, except when the contract name is explicitly given or the -``super`` keyword is used. - -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 compiled 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, but there are also -some :ref:`differences <multi-inheritance>`. - -Details are given in the following example. - -:: - - pragma solidity >0.4.99 <0.6.0; - - contract owned { - constructor() public { owner = msg.sender; } - address payable owner; - } - - // Use `is` to derive from another contract. Derived - // contracts can access all non-private members including - // internal functions and state variables. These cannot be - // accessed externally via `this`, though. - contract mortal is owned { - function kill() public { - if (msg.sender == owner) selfdestruct(owner); - } - } - - // These abstract contracts are only provided to make the - // interface known to the compiler. Note the function - // without body. If a contract does not implement all - // functions it can only be used as an interface. - contract Config { - function lookup(uint id) public returns (address adr); - } - - contract NameReg { - function register(bytes32 name) public; - function unregister() public; - } - - // Multiple inheritance is possible. Note that `owned` is - // also a base class of `mortal`, yet there is only a single - // instance of `owned` (as for virtual inheritance in C++). - contract named is owned, mortal { - constructor(bytes32 name) public { - Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); - NameReg(config.lookup(1)).register(name); - } - - // Functions can be overridden by another function with the same name and - // the same number/types of inputs. If the overriding function has different - // types of output parameters, that causes an error. - // Both local and message-based function calls take these overrides - // into account. - function kill() public { - if (msg.sender == owner) { - Config config = Config(0xD5f9D8D94886E70b06E474c3fB14Fd43E2f23970); - NameReg(config.lookup(1)).unregister(); - // It is still possible to call a specific - // overridden function. - mortal.kill(); - } - } - } - - // If a constructor takes an argument, it needs to be - // provided in the header (or modifier-invocation-style at - // the constructor of the derived contract (see below)). - contract PriceFeed is owned, mortal, named("GoldFeed") { - function updateInfo(uint newInfo) public { - if (msg.sender == owner) info = newInfo; - } - - function get() public view returns(uint r) { return info; } - - uint info; - } - -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:: - - pragma solidity >=0.4.22 <0.6.0; - - contract owned { - constructor() public { owner = msg.sender; } - address payable owner; - } - - contract mortal is owned { - function kill() public { - if (msg.sender == owner) selfdestruct(owner); - } - } - - contract Base1 is mortal { - function kill() public { /* do cleanup 1 */ mortal.kill(); } - } - - contract Base2 is mortal { - function kill() public { /* do cleanup 2 */ mortal.kill(); } - } - - contract Final is Base1, Base2 { - } - -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``:: - - pragma solidity >=0.4.22 <0.6.0; - - contract owned { - constructor() public { owner = msg.sender; } - address payable owner; - } - - contract mortal is owned { - function kill() public { - if (msg.sender == owner) selfdestruct(owner); - } - } - - contract Base1 is mortal { - function kill() public { /* do cleanup 1 */ super.kill(); } - } - - - contract Base2 is mortal { - function kill() public { /* do cleanup 2 */ super.kill(); } - } - - contract Final is Base1, Base2 { - } - -If ``Base2`` calls a function of ``super``, it does not simply -call this function on one of its base contracts. Rather, it -calls this function on the next base contract in the final -inheritance graph, so it will call ``Base1.kill()`` (note that -the final inheritance sequence is -- starting with the most -derived contract: Final, Base2, Base1, mortal, owned). -The actual function that is called when using super is -not known in the context of the class where it is used, -although its type is known. This is similar for ordinary -virtual method lookup. - -.. index:: ! constructor - -.. _constructor: - -Constructors -============ - -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 constructor has run, the final code of the contract is deployed -to the blockchain. The deployment of -the code costs additional gas linear to the length of the code. -This code includes all functions that are part of the public interface -and all functions that are reachable from there through function calls. -It does not include the constructor code or internal functions that are -only called from the constructor. - -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: - -:: - - pragma solidity >0.4.99 <0.6.0; - - contract A { - uint public a; - - constructor(uint _a) internal { - a = _a; - } - } - - contract B is A(1) { - constructor() public {} - } - -A constructor set as ``internal`` causes the contract to be marked as :ref:`abstract <abstract-contract>`. - -.. warning :: - Prior to version 0.4.22, constructors were defined as functions with the same name as the contract. - This syntax was deprecated and is not allowed anymore in version 0.5.0. - - -.. index:: ! base;constructor - -Arguments for Base Constructors -=============================== - -The constructors of all the base contracts will be called following the -linearization rules explained below. If the base constructors have arguments, -derived contracts need to specify all of them. This can be done in two ways:: - - pragma solidity >=0.4.22 <0.6.0; - - contract Base { - uint x; - constructor(uint _x) public { x = _x; } - } - - // Either directly specify in the inheritance list... - contract Derived1 is Base(7) { - constructor() public {} - } - - // or through a "modifier" of the derived constructor. - contract Derived2 is Base { - constructor(uint _y) Base(_y * _y) public {} - } - -One way is directly in the inheritance list (``is Base(7)``). The other is in -the way a modifier is invoked as part of -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 -constructor arguments of the base depend on those of the -derived contract. Arguments have to be given either in the -inheritance list or in modifier-style in the derived constructor. -Specifying arguments in both places is an error. - -If a derived contract does not specify the arguments to all of its base -contracts' constructors, it will be abstract. - -.. index:: ! inheritance;multiple, ! linearization, ! C3 linearization - -.. _multi-inheritance: - -Multiple Inheritance and Linearization -====================================== - -Languages that allow multiple inheritance have to deal with -several problems. One is the `Diamond Problem <https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem>`_. -Solidity is similar to Python in that it uses "`C3 Linearization <https://en.wikipedia.org/wiki/C3_linearization>`_" -to force a specific order in the directed acyclic graph (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 -important: You have to list the direct base contracts -in the order from "most base-like" to "most derived". -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". - -:: - - pragma solidity >=0.4.0 <0.6.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`` -(by specifying ``A, X`` in this order), but ``A`` itself -requests to override ``X``, which is a contradiction that -cannot be resolved. - - - -Inheriting Different Kinds of Members of the Same Name -====================================================== - -When the inheritance results in a contract with a function and a modifier of the same name, it is considered as an error. -This error is produced also by an event and a modifier of the same name, and a function and an event of the same name. -As an exception, a state variable getter can override a public function. - -.. index:: ! contract;abstract, ! abstract contract - -.. _abstract-contract: - -****************** -Abstract Contracts -****************** - -Contracts are marked as abstract when at least one of their functions lacks an implementation as in the following example (note that the function declaration header is terminated by ``;``):: - - pragma solidity >=0.4.0 <0.6.0; - - contract Feline { - function utterance() public 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:: - - pragma solidity >=0.4.0 <0.6.0; - - contract Feline { - function utterance() public returns (bytes32); - } - - contract Cat is Feline { - function utterance() public returns (bytes32) { return "miaow"; } - } - -If a contract inherits from an abstract contract and does not implement all non-implemented functions by overriding, it will itself be abstract. - -Note that a function without implementation is different from a :ref:`Function Type <function_types>` even though their syntax looks very similar. - -Example of function without implementation (a function declaration):: - - function foo(address) external returns (address); - -Example of a Function Type (a variable declaration, where the variable is of type ``function``):: - - function(address) external returns (address) foo; - -Abstract contracts decouple the definition of a contract from its implementation providing better extensibility and self-documentation and -facilitating patterns like the `Template method <https://en.wikipedia.org/wiki/Template_method_pattern>`_ and removing code duplication. -Abstract contracts are useful in the same way that defining methods in an interface is useful. It is a way for the designer of the abstract contract to say "any child of mine must implement this method". - - -.. index:: ! contract;interface, ! interface contract - -.. _interfaces: - -********** -Interfaces -********** - -Interfaces are similar to abstract contracts, but they cannot have any functions implemented. There are further restrictions: - -- They cannot inherit other contracts or interfaces. -- All declared functions must be external. -- They cannot declare a constructor. -- They cannot declare state variables. - -Some of these restrictions might be lifted in the future. - -Interfaces are basically limited to what the Contract ABI can represent, and the conversion between the ABI and -an interface should be possible without any information loss. - -Interfaces are denoted by their own keyword: - -:: - - pragma solidity >=0.5.0 <0.6.0; - - interface Token { - enum TokenType { Fungible, NonFungible } - struct Coin { string obverse; string reverse; } - function transfer(address recipient, uint amount) external; - } - -Contracts can inherit interfaces as they would inherit other contracts. - -Types defined inside interfaces and other contract-like structures -can be accessed from other contracts: ``Token.TokenType`` or ``Token.Coin``. - -.. index:: ! library, callcode, delegatecall - -.. _libraries: - -********* -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) -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 -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 no way to name them, otherwise). Library functions can only be -called directly (i.e. without the use of ``DELEGATECALL``) if they do not modify -the state (i.e. if they are ``view`` or ``pure`` functions), -because libraries are assumed to be stateless. In particular, it is -not possible to destroy a library. - -.. note:: - Until version 0.4.20, it was possible to destroy libraries by - circumventing Solidity's type system. Starting from that version, - libraries contain a :ref:`mechanism<call-protection>` that - disallows state-modifying functions - to be called directly (i.e. without ``DELEGATECALL``). - -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 -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 types :ref:`stored in memory <data-location>` will be passed by reference and not copied. -To realize this in the EVM, code of internal library functions -and all functions called from therein will at compile time be pulled into the calling -contract, and a regular ``JUMP`` call will be used instead of a ``DELEGATECALL``. - -.. index:: using for, set - -The following example illustrates how to use libraries (but manual method -be sure to check out :ref:`using for <using-for>` for a -more advanced example to implement a set). - -:: - - pragma solidity >=0.4.22 <0.6.0; - - library Set { - // We define a new struct datatype that will be used to - // hold its data in the calling contract. - struct Data { mapping(uint => bool) flags; } - - // Note that the first parameter is of type "storage - // reference" and thus only its storage address and not - // its contents is passed as part of the call. This is a - // special feature of library functions. It is idiomatic - // to call the first parameter `self`, if the function can - // be seen as a method of that object. - function insert(Data storage self, uint value) - public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) - public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) - public - view - returns (bool) - { - return self.flags[value]; - } - } - - contract C { - Set.Data knownValues; - - function register(uint value) public { - // The library functions can be called without a - // specific instance of the library, since the - // "instance" will be the current contract. - require(Set.insert(knownValues, value)); - } - // In this contract, we can also directly access knownValues.flags, if we want. - } - -Of course, you do not have to follow this way to use -libraries: they can also be used without defining struct -data types. Functions also work without any storage -reference parameters, and they 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``) to an external -contract/library. If you use libraries, be aware 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, because of the use of ``CALLCODE``, ``msg.sender`` and -``msg.value`` changed, though). - -The following example shows how to use :ref:`types stored in memory <data-location>` and -internal functions in libraries in order to implement -custom types without the overhead of external function calls: - -:: - - pragma solidity >=0.4.16 <0.6.0; - - library BigInt { - struct bigint { - uint[] limbs; - } - - function fromUint(uint x) internal pure returns (bigint memory r) { - r.limbs = new uint[](1); - r.limbs[0] = x; - } - - function add(bigint memory _a, bigint memory _b) internal pure returns (bigint memory 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); - uint i; - for (i = 0; i < r.limbs.length; ++i) - newLimbs[i] = r.limbs[i]; - newLimbs[i] = carry; - r.limbs = newLimbs; - } - } - - function limb(bigint memory _a, uint _limb) internal pure returns (uint) { - return _limb < _a.limbs.length ? _a.limbs[_limb] : 0; - } - - function max(uint a, uint b) private pure returns (uint) { - return a > b ? a : b; - } - } - - contract C { - using BigInt for BigInt.bigint; - - function f() public pure { - 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); - } - } - -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 :ref:`commandline-compiler` for 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 -manually by replacing all those 40 symbols by the hex -encoding of the address of the library contract. - -.. note:: - Manually linking libraries on the generated bytecode is discouraged, because - it is restricted to 36 characters. - You should ask the compiler to link the libraries at the time - a contract is compiled by either using - the ``--libraries`` option of ``solc`` or the ``libraries`` key if you use - the standard-JSON interface to the compiler. - -Restrictions for libraries in comparison to contracts: - -- No state variables -- Cannot inherit nor be inherited -- Cannot receive Ether - -(These might be lifted at a later point.) - -.. _call-protection: - -Call Protection For Libraries -============================= - -As mentioned in the introduction, if a library's code is executed -using a ``CALL`` instead of a ``DELEGATECALL`` or ``CALLCODE``, -it will revert unless a ``view`` or ``pure`` function is called. - -The EVM does not provide a direct way for a contract to detect -whether it was called using ``CALL`` or not, but a contract -can use the ``ADDRESS`` opcode to find out "where" it is -currently running. The generated code compares this address -to the address used at construction time to determine the mode -of calling. - -More specifically, the runtime code of a library always starts -with a push instruction, which is a zero of 20 bytes at -compilation time. When the deploy code runs, this constant -is replaced in memory by the current address and this -modified code is stored in the contract. At runtime, -this causes the deploy time address to be the first -constant to be pushed onto the stack and the dispatcher -code compares the current address against this constant -for any non-view and non-pure function. - -.. index:: ! using for, library - -.. _using-for: - -********* -Using For -********* - -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 Python). - -The effect of ``using A for *;`` is that the functions from -the library ``A`` are attached to *any* type. - -In both situations, *all* functions in the library are attached, -even those where the type of the first parameter does not -match the type of the object. 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 only within the current -contract, including within all of its functions, and has no effect -outside of the contract in which it is used. The directive -may only be used inside a contract, not inside any of its functions. - -By including a library, its data types including library functions are -available without having to add further code. - -Let us rewrite the set example from the -:ref:`libraries` in this way:: - - pragma solidity >=0.4.16 <0.6.0; - - // This is the same code as before, just without comments - library Set { - struct Data { mapping(uint => bool) flags; } - - function insert(Data storage self, uint value) - public - returns (bool) - { - if (self.flags[value]) - return false; // already there - self.flags[value] = true; - return true; - } - - function remove(Data storage self, uint value) - public - returns (bool) - { - if (!self.flags[value]) - return false; // not there - self.flags[value] = false; - return true; - } - - function contains(Data storage self, uint value) - public - view - returns (bool) - { - return self.flags[value]; - } - } - - contract C { - using Set for Set.Data; // this is the crucial change - Set.Data knownValues; - - function register(uint value) public { - // Here, all variables of type Set.Data have - // corresponding member functions. - // The following function call is identical to - // `Set.insert(knownValues, value)` - require(knownValues.insert(value)); - } - } - -It is also possible to extend elementary types in that way:: - - pragma solidity >=0.4.16 <0.6.0; - - library Search { - function indexOf(uint[] storage self, uint value) - public - view - returns (uint) - { - for (uint i = 0; i < self.length; i++) - if (self[i] == value) return i; - return uint(-1); - } - } - - contract C { - using Search for uint[]; - uint[] data; - - function append(uint value) public { - data.push(value); - } - - function replace(uint _old, uint _new) public { - // This performs the library function call - uint index = data.indexOf(_old); - if (index == uint(-1)) - data.push(_new); - else - data[index] = _new; - } - } - -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 -is when storage reference variables are used. +.. include:: contracts/using-for.rst
\ No newline at end of file |