functions.rst 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. Functions
  2. =========
  3. A function can be declared inside a contract, in which case it has access to the contracts
  4. contract storage variables, other contract functions etc. Functions can be also be declared outside
  5. a contract.
  6. .. include:: ../examples/functions.sol
  7. :code: solidity
  8. Function can have any number of arguments. Function arguments may have names;
  9. if they do not have names then they cannot be used in the function body, but they will
  10. be present in the public interface.
  11. The return values may have names as demonstrated in the get_initial_bound() function.
  12. When at all of the return values have a name, then the return statement is no
  13. longer required at the end of a function body. In stead of returning the values
  14. which are provided in the return statement, the values of the return variables at the end
  15. of the function is returned. It is still possible to explicitly return some values
  16. with a return statement.
  17. Functions which are declared ``public`` will be present in the ABI and are callable
  18. externally. If a function is declared ``private`` then it is not callable externally,
  19. but it can be called from within the contract. If a function is defined outside a
  20. contract, then it cannot have a visibility specifier (e.g. ``public``).
  21. Any DocComment before a function will be include in the ABI. Currently only Substrate
  22. supports documentation in the ABI.
  23. Arguments passing and return values
  24. ___________________________________
  25. Function arguments can be passed either by position or by name. When they are called
  26. by name, arguments can be in any order. However, functions with anonymous arguments
  27. (arguments without name) cannot be called this way.
  28. .. include:: ../examples/function_arguments.sol
  29. :code: solidity
  30. If the function has a single return value, this can be assigned to a variable. If
  31. the function has multiple return values, these can be assigned using the :ref:`destructuring`
  32. assignment statement:
  33. .. include:: ../examples/function_destructing_arguments.sol
  34. :code: solidity
  35. It is also possible to call functions on other contracts, which is also known as calling
  36. external functions. The called function must be declared public.
  37. Calling external functions requires ABI encoding the arguments, and ABI decoding the
  38. return values. This much more costly than an internal function call.
  39. .. include:: ../examples/function_call_external.sol
  40. :code: solidity
  41. The syntax for calling external call is the same as the external call, except for
  42. that it must be done on a contract type variable. Any error in an external call can
  43. be handled with :ref:`try-catch`.
  44. Internal calls and externals calls
  45. ___________________________________
  46. An internal function call is executed by the current contract. This
  47. is much more efficient than an external call, which requires the
  48. address of the contract to call, whose arguments must be *abi encoded* (also known
  49. as serialization). Then, the runtime must set up the VM for the called contract
  50. (the callee), decode the arguments, and encode return values. Lastly,
  51. the first contract (the caller) must decode return values.
  52. A method call done on a contract type will always be an external call.
  53. Note that ``this`` returns the current contract, so ``this.foo()`` will do an
  54. external call, which is much more expensive than ``foo()``.
  55. Passing accounts with external calls on Solana
  56. ______________________________________________
  57. The Solana runtime allows you the specify the accounts to be passed for an
  58. external call. This is specified in an array of the struct ``AccountMeta``,
  59. see the section on :ref:`account_meta`.
  60. .. include:: ../examples/solana/function_call_external_accounts.sol
  61. :code: solidity
  62. If ``{accounts}`` is not specified, then all account are passed.
  63. Passing seeds with external calls on Solana
  64. ___________________________________________
  65. The Solana runtime allows you to specify the seeds to be passed for an
  66. external call. This is used for program derived addresses: the seeds are
  67. hashed with the calling program id to create program derived addresses.
  68. They will automatically have the signer bit set, which allows a contract to
  69. sign without using any private keys.
  70. .. include:: ../examples/solana/function_call_external_seeds.sol
  71. :code: solidity
  72. Now if the program derived address for the running program id and the seeds match the address
  73. ``addr`` and ``addr2``, then then the called program will run with signer and writable bits
  74. set for ``addr`` and ``addr2``. If they do not match, the Solana runtime will detect that
  75. the ``is_signer`` is set without the correct signature being provided.
  76. The seeds can provided in any other, which will be used to sign for multiple accounts. In the example
  77. above, the seed ``"test"`` is concatenated with the value of ``seed``, and that produces
  78. one account signature. In adition, ``"foo"`` is concatenated with ``"bar"`` to produce ``"foobar"``
  79. and then used to sign for another account.
  80. The ``seeds:`` call parameter is a slice of bytes slices; this means the literal can contain any
  81. number of elements, including 0 elements. The values can be ``bytes`` or anything that can be
  82. cast to ``bytes``.
  83. .. _passing_value_gas:
  84. Passing value and gas with external calls
  85. _________________________________________
  86. For external calls, value can be sent along with the call. The callee must be
  87. ``payable``. Likewise, a gas limit can be set.
  88. .. include:: ../examples/substrate/function_call_external_gas.sol
  89. :code: solidity
  90. .. note::
  91. The gas cannot be set on Solana for external calls.
  92. State mutability
  93. ________________
  94. Some functions only read contract storage (also known as *state*), and others may write
  95. contract storage. Functions that do not write state can be executed off-chain. Off-chain
  96. execution is faster, does not require write access, and does not need any balance.
  97. Functions that do not write state come in two flavours: ``view`` and ``pure``. ``pure``
  98. functions may not read state, and ``view`` functions that do read state.
  99. Functions that do write state come in two flavours: ``payable`` and non-payable, the
  100. default. Functions that are not intended to receive any value, should not be marked
  101. ``payable``. The compiler will check that every call does not included any value, and
  102. there are runtime checks as well, which cause the function to be reverted if value is
  103. sent.
  104. A constructor can be marked ``payable``, in which case value can be passed with the
  105. constructor.
  106. .. note::
  107. If value is sent to a non-payable function on Parity Substrate, the call will be
  108. reverted. However there is no refund performed, so value will remain with the callee.
  109. ``payable`` on constructors is not enforced on Parity Substrate. Funds are needed
  110. for storage rent and there is a minimum deposit needed for the contract. As a result,
  111. constructors always receive value on Parity Substrate.
  112. Overriding function selector
  113. ____________________________
  114. When a function is called, the function selector and the arguments are serialized
  115. (also known as abi encoded) and passed to the program. The function selector is
  116. what the runtime program uses to determine what function was called. On Substrate, the
  117. function selector is generated using a deterministic hash value of the function
  118. name and the arguments types. On Solana, the selector is known as discriminator.
  119. The selector value can be overriden with the annotation
  120. ``@selector([0xde, 0xad, 0xbe, 0xa1])``.
  121. .. include:: ../examples/substrate/function_selector_override.sol
  122. :code: solidity
  123. The given example only works for Substrate, whose selectors are four bytes wide. On Solana, they are eight bytes wide.
  124. Only ``public`` and ``external`` functions have a selector, and can have their
  125. selector overriden. On Substrate, constructors have selectors too, so they
  126. can also have their selector overriden. If a function overrides another one in a
  127. base contract, then the selector of both must match.
  128. .. warning::
  129. On Solana, changing the selector may result in a mismatch between
  130. the contract metadata and the actual contract code, because the metadata does
  131. not explicitly store the selector.
  132. Use this feature carefully, as it may either break a contract or cause
  133. undefined behavior.
  134. Function overloading
  135. ____________________
  136. Multiple functions with the same name can be declared, as long as the arguments are
  137. different in at least one of two ways:
  138. - The number of arguments must be different
  139. - The type of at least one of the arguments is different
  140. A function cannot be overloaded by changing the return types or number of returned
  141. values. Here is an example of an overloaded function:
  142. .. include:: ../examples/function_overloading.sol
  143. :code: solidity
  144. In the function foo, abs() is called with an ``int64`` so the second implementation
  145. of the function abs() is called.
  146. Both Substrate and Solana runtime require unique function names, so
  147. overloaded function names will be mangled in the ABI or the IDL.
  148. The function name will be concatenated with all of its argument types, separated by underscores, using the
  149. following rules:
  150. - Struct types are represented by their field types (preceded by an extra underscore).
  151. - Enum types are represented as their underlying ``uint8`` type.
  152. - Array types are recognizable by having ``Array`` appended.
  153. - Fixed size arrays will additionally have their length appended as well.
  154. The following example illustrates some overloaded functions and their mangled name:
  155. .. include:: ../examples/function_name_mangling.sol
  156. :code: solidity
  157. Function Modifiers
  158. __________________
  159. Function modifiers are used to check pre-conditions or post-conditions for a function call. First a
  160. new modifier must be declared which looks much like a function, but uses the ``modifier``
  161. keyword rather than ``function``.
  162. .. include:: ../examples/substrate/function_modifier.sol
  163. :code: solidity
  164. The function `foo` can only be run by the owner of the contract, else the ``require()`` in its
  165. modifier will fail. The special symbol ``_;`` will be replaced by body of the function. In fact,
  166. if you specify ``_;`` twice, the function will execute twice, which might not be a good idea.
  167. On Solana, ``msg.sender`` does not exist, so the usual way to implement a similar test is using
  168. an `authority` accounts rather than an owner account.
  169. .. include:: ../examples/solana/use_authority.sol
  170. :code: solidity
  171. A modifier cannot have visibility (e.g. ``public``) or mutability (e.g. ``view``) specified,
  172. since a modifier is never externally callable. Modifiers can only be used by attaching them
  173. to functions.
  174. A modifier can have arguments, just like regular functions. Here if the price is less
  175. than 50, `foo()` itself will never be executed, and execution will return to the caller with
  176. nothing done since ``_;`` is not reached in the modifier and as result foo() is never
  177. executed.
  178. .. include:: ../examples/function_modifier_arguments.sol
  179. :code: solidity
  180. Multiple modifiers can be applied to single function. The modifiers are executed in the
  181. order of the modifiers specified on the function declaration. Execution will continue to the next modifier
  182. when the ``_;`` is reached. In
  183. this example, the `only_owner` modifier is run first, and if that reaches ``_;``, then
  184. `check_price` is executed. The body of function `foo()` is only reached once `check_price()`
  185. reaches ``_;``.
  186. .. include:: ../examples/substrate/function_multiple_modifiers.sol
  187. :code: solidity
  188. Modifiers can be inherited or declared ``virtual`` in a base contract and then overriden, exactly like
  189. functions can be.
  190. .. include:: ../examples/substrate/function_override_modifiers.sol
  191. :code: solidity
  192. Calling an external function using ``call()``
  193. _____________________________________________
  194. If you call a function on a contract, then the function selector and any arguments
  195. are ABI encoded for you, and any return values are decoded. Sometimes it is useful
  196. to call a function without abi encoding the arguments.
  197. You can call a contract directly by using the ``call()`` method on the address type.
  198. This takes a single argument, which should be the ABI encoded arguments. The return
  199. values are a ``boolean`` which indicates success if true, and the ABI encoded
  200. return value in ``bytes``.
  201. .. include:: ../examples/function_call.sol
  202. :code: solidity
  203. Any value or gas limit can be specified for the external call. Note that no check is done to see
  204. if the called function is ``payable``, since the compiler does not know what function you are
  205. calling.
  206. .. code-block:: solidity
  207. function test(address foo, bytes rawcalldata) public {
  208. (bool success, bytes rawresult) = foo.call{value: 102, gas: 1000}(rawcalldata);
  209. }
  210. .. _fallback_receive:
  211. fallback() and receive() function
  212. _________________________________
  213. When a function is called externally, either via an transaction or when one contract
  214. call a function on another contract, the correct function is dispatched based on the
  215. function selector in the raw encoded ABI call data. If there is no match, the call
  216. reverts, unless there is a ``fallback()`` or ``receive()`` function defined.
  217. If the call comes with value, then ``receive()`` is executed, otherwise ``fallback()``
  218. is executed. This made clear in the declarations; ``receive()`` must be declared
  219. ``payable``, and ``fallback()`` must not be declared ``payable``. If a call is made
  220. with value and no ``receive()`` function is defined, then the call reverts, likewise if
  221. call is made without value and no ``fallback()`` is defined, then the call also reverts.
  222. Both functions must be declared ``external``.
  223. .. include:: ../examples/substrate/function_fallback_and_receive.sol
  224. :code: solidity
  225. .. note::
  226. On Solana, there is no mechanism to have some code executed if an account
  227. gets credited. So, `receive()` functions are not supported.