functions.rst 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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. .. code-block:: solidity
  7. /// get_initial_bound is called from the constructor
  8. function get_initial_bound() returns (uint value) {
  9. value = 102;
  10. }
  11. contact foo {
  12. uint bound = get_initial_bound();
  13. /** set bound for get with bound */
  14. function set_bound(uint _bound) public {
  15. bound = _bound;
  16. }
  17. /// Clamp a value within a bound.
  18. /// The bound can be set with set_bound().
  19. function get_with_bound(uint value) view public return (uint) {
  20. if (value < bound) {
  21. return value;
  22. } else {
  23. return bound;
  24. }
  25. }
  26. }
  27. Function can have any number of arguments. Function arguments may have names;
  28. if they do not have names then they cannot be used in the function body, but they will
  29. be present in the public interface.
  30. The return values may have names as demonstrated in the get_initial_bound() function.
  31. When at all of the return values have a name, then the return statement is no
  32. longer required at the end of a function body. In stead of returning the values
  33. which are provided in the return statement, the values of the return variables at the end
  34. of the function is returned. It is still possible to explicitly return some values
  35. with a return statement.
  36. Functions which are declared ``public`` will be present in the ABI and are callable
  37. externally. If a function is declared ``private`` then it is not callable externally,
  38. but it can be called from within the contract. If a function is defined outside a
  39. contract, then it cannot have a visibility specifier (e.g. ``public``).
  40. Any DocComment before a function will be include in the ABI. Currently only Substrate
  41. supports documentation in the ABI.
  42. Arguments passing and return values
  43. ___________________________________
  44. Function arguments can be passed either by position or by name. When they are called
  45. by name, arguments can be in any order. However, functions with anonymous arguments
  46. (arguments without name) cannot be called this way.
  47. .. code-block:: solidity
  48. contract foo {
  49. function bar(uint32 x, bool y) public returns (uint32) {
  50. if (y) {
  51. return 2;
  52. }
  53. return 3;
  54. }
  55. function test() public {
  56. uint32 a = bar(102, false);
  57. a = bar({ y: true, x: 302 });
  58. }
  59. }
  60. If the function has a single return value, this can be assigned to a variable. If
  61. the function has multiple return values, these can be assigned using the :ref:`destructuring`
  62. assignment statement:
  63. .. code-block:: solidity
  64. contract foo {
  65. function bar1(uint32 x, bool y) public returns (address, byte32) {
  66. return (address(3), hex"01020304");
  67. }
  68. function bar2(uint32 x, bool y) public returns (bool) {
  69. return !y;
  70. }
  71. function test() public {
  72. (address f1, bytes32 f2) = bar1(102, false);
  73. bool f3 = bar2({x: 255, y: true})
  74. }
  75. }
  76. It is also possible to call functions on other contracts, which is also known as calling
  77. external functions. The called function must be declared public.
  78. Calling external functions requires ABI encoding the arguments, and ABI decoding the
  79. return values. This much more costly than an internal function call.
  80. .. code-block:: solidity
  81. contract foo {
  82. function bar1(uint32 x, bool y) public returns (address, byte32) {
  83. return (address(3), hex"01020304");
  84. }
  85. function bar2(uint32 x, bool y) public returns (bool) {
  86. return !y;
  87. }
  88. }
  89. contract bar {
  90. function test(foo f) public {
  91. (address f1, bytes32 f2) = f.bar1(102, false);
  92. bool f3 = f.bar2({x: 255, y: true})
  93. }
  94. }
  95. The syntax for calling external call is the same as the external call, except for
  96. that it must be done on a contract type variable. Any error in an external call can
  97. be handled with :ref:`try-catch`.
  98. Internal calls and externals calls
  99. ___________________________________
  100. An internal function call is executed by the current contract. This
  101. is much more efficient than an external call, which requires the
  102. address of the contract to call, whose arguments must be *abi encoded* (also known
  103. as serialization). Then, the runtime must set up the VM for the called contract
  104. (the callee), decode the arguments, and encode return values. Lastly,
  105. the first contract (the caller) must decode return values.
  106. A method call done on a contract type will always be an external call.
  107. Note that ``this`` returns the current contract, so ``this.foo()`` will do an
  108. external call, which is much more expensive than ``foo()``.
  109. Passing accounts with external calls on Solana
  110. ______________________________________________
  111. The Solana runtime allows you the specify the accounts to be passed for an
  112. external call. This is specified in an array of the struct ``AccountMeta``,
  113. see the section on :ref:`account_meta`.
  114. .. code-block:: solidity
  115. import {AccountMeta} from 'solana';
  116. contract SplToken {
  117. address constant tokenProgramId = address"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
  118. address constant SYSVAR_RENT_PUBKEY = address"SysvarRent111111111111111111111111111111111";
  119. struct InitializeMintInstruction {
  120. uint8 instruction;
  121. uint8 decimals;
  122. address mintAuthority;
  123. uint8 freezeAuthorityOption;
  124. address freezeAuthority;
  125. }
  126. function create_mint_with_freezeauthority(uint8 decimals, address mintAuthority, address freezeAuthority) public {
  127. InitializeMintInstruction instr = InitializeMintInstruction({
  128. instruction: 0,
  129. decimals: decimals,
  130. mintAuthority: mintAuthority,
  131. freezeAuthorityOption: 1,
  132. freezeAuthority: freezeAuthority
  133. });
  134. AccountMeta[2] metas = [
  135. AccountMeta({pubkey: instr.mintAuthority, is_writable: true, is_signer: false}),
  136. AccountMeta({pubkey: SYSVAR_RENT_PUBKEY, is_writable: false, is_signer: false})
  137. ];
  138. tokenProgramId.call{accounts: metas}(instr);
  139. }
  140. }
  141. If ``{accounts}`` is not specified, then all account are passed.
  142. .. _passing_value_gas:
  143. Passing value and gas with external calls
  144. _________________________________________
  145. For external calls, value can be sent along with the call. The callee must be
  146. ``payable``. Likewise, a gas limit can be set.
  147. .. code-block:: solidity
  148. contract foo {
  149. function bar() public {
  150. other o = new other();
  151. o.feh{value: 102, gas: 5000}(102);
  152. }
  153. }
  154. contract other {
  155. function feh(uint32 x) public payable {
  156. // ...
  157. }
  158. }
  159. .. note::
  160. The gas cannot be set on Solana for external calls.
  161. State mutability
  162. ________________
  163. Some functions only read contract storage (also known as *state*), and others may write
  164. contract storage. Functions that do not write state can be executed off-chain. Off-chain
  165. execution is faster, does not require write access, and does not need any balance.
  166. Functions that do not write state come in two flavours: ``view`` and ``pure``. ``pure``
  167. functions may not read state, and ``view`` functions that do read state.
  168. Functions that do write state come in two flavours: ``payable`` and non-payable, the
  169. default. Functions that are not intended to receive any value, should not be marked
  170. ``payable``. The compiler will check that every call does not included any value, and
  171. there are runtime checks as well, which cause the function to be reverted if value is
  172. sent.
  173. A constructor can be marked ``payable``, in which case value can be passed with the
  174. constructor.
  175. .. note::
  176. If value is sent to a non-payable function on Parity Substrate, the call will be
  177. reverted. However there is no refund performed, so value will remain with the callee.
  178. ``payable`` on constructors is not enforced on Parity Substrate. Funds are needed
  179. for storage rent and there is a minimum deposit needed for the contract. As a result,
  180. constructors always receive value on Parity Substrate.
  181. Function overloading
  182. ____________________
  183. Multiple functions with the same name can be declared, as long as the arguments are
  184. different in at least one of two ways:
  185. - The number of arguments must be different
  186. - The type of at least one of the arguments is different
  187. A function cannot be overloaded by changing the return types or number of returned
  188. values. Here is an example of an overloaded function:
  189. .. code-block:: solidity
  190. contract shape {
  191. int64 bar;
  192. function abs(int val) public returns (int) {
  193. if (val >= 0) {
  194. return val;
  195. } else {
  196. return -val;
  197. }
  198. }
  199. function abs(int64 val) public returns (int64) {
  200. if (val >= 0) {
  201. return val;
  202. } else {
  203. return -val;
  204. }
  205. }
  206. function foo(int64 x) public {
  207. bar = abs(x);
  208. }
  209. }
  210. In the function foo, abs() is called with an ``int64`` so the second implementation
  211. of the function abs() is called.
  212. Function Modifiers
  213. __________________
  214. Function modifiers are used to check pre-conditions or post-conditions for a function call. First a
  215. new modifier must be declared which looks much like a function, but uses the ``modifier``
  216. keyword rather than ``function``.
  217. .. code-block:: solidity
  218. contract example {
  219. address owner;
  220. modifier only_owner() {
  221. require(msg.sender == owner);
  222. _;
  223. // insert post conditions here
  224. }
  225. function foo() only_owner public {
  226. // ...
  227. }
  228. }
  229. The function `foo` can only be run by the owner of the contract, else the ``require()`` in its
  230. modifier will fail. The special symbol ``_;`` will be replaced by body of the function. In fact,
  231. if you specify ``_;`` twice, the function will execute twice, which might not be a good idea.
  232. A modifier cannot have visibility (e.g. ``public``) or mutability (e.g. ``view``) specified,
  233. since a modifier is never externally callable. Modifiers can only be used by attaching them
  234. to functions.
  235. A modifier can have arguments, just like regular functions. Here if the price is less
  236. than 50, `foo()` itself will never be executed, and execution will return to the caller with
  237. nothing done since ``_;`` is not reached in the modifier and as result foo() is never
  238. executed.
  239. .. code-block:: solidity
  240. contract example {
  241. modifier check_price(int64 price) {
  242. if (price >= 50) {
  243. _;
  244. }
  245. }
  246. function foo(int64 price) check_price(price) public {
  247. // ...
  248. }
  249. }
  250. Multiple modifiers can be applied to single function. The modifiers are executed in the
  251. order of the modifiers specified on the function declaration. Execution will continue to the next modifier
  252. when the ``_;`` is reached. In
  253. this example, the `only_owner` modifier is run first, and if that reaches ``_;``, then
  254. `check_price` is executed. The body of function `foo()` is only reached once `check_price()`
  255. reaches ``_;``.
  256. .. code-block:: solidity
  257. contract example {
  258. address owner;
  259. // a modifier with no arguments does not need "()" in its declaration
  260. modifier only_owner {
  261. require(msg.sender == owner);
  262. _;
  263. }
  264. modifier check_price(int64 price) {
  265. if (price >= 50) {
  266. _;
  267. }
  268. }
  269. function foo(int64 price) only_owner check_price(price) public {
  270. // ...
  271. }
  272. }
  273. Modifiers can be inherited or declared ``virtual`` in a base contract and then overriden, exactly like
  274. functions can be.
  275. .. code-block:: solidity
  276. contract base {
  277. address owner;
  278. modifier only_owner {
  279. require(msg.sender == owner);
  280. _;
  281. }
  282. modifier check_price(int64 price) virtual {
  283. if (price >= 10) {
  284. _;
  285. }
  286. }
  287. }
  288. contract example is base {
  289. modifier check_price(int64 price) override {
  290. if (price >= 50) {
  291. _;
  292. }
  293. }
  294. function foo(int64 price) only_owner check_price(price) public {
  295. // ...
  296. }
  297. }
  298. Calling an external function using ``call()``
  299. _____________________________________________
  300. If you call a function on a contract, then the function selector and any arguments
  301. are ABI encoded for you, and any return values are decoded. Sometimes it is useful
  302. to call a function without abi encoding the arguments.
  303. You can call a contract directly by using the ``call()`` method on the address type.
  304. This takes a single argument, which should be the ABI encoded arguments. The return
  305. values are a ``boolean`` which indicates success if true, and the ABI encoded
  306. return value in ``bytes``.
  307. .. code-block:: solidity
  308. contract a {
  309. function test() public {
  310. b v = new b();
  311. // the following four lines are equivalent to "uint32 res = v.foo(3,5);"
  312. // Note that the signature is only hashed and not parsed. So, ensure that the
  313. // arguments are of the correct type.
  314. bytes data = abi.encodeWithSignature("foo(uint32,uint32)", uint32(3), uint32(5));
  315. (bool success, bytes rawresult) = address(v).call(data);
  316. assert(success == true);
  317. uint32 res = abi.decode(rawresult, (uint32));
  318. assert(res == 8);
  319. }
  320. }
  321. contract b {
  322. function foo(uint32 a, uint32 b) public returns (uint32) {
  323. return a + b;
  324. }
  325. }
  326. Any value or gas limit can be specified for the external call. Note that no check is done to see
  327. if the called function is ``payable``, since the compiler does not know what function you are
  328. calling.
  329. .. code-block:: solidity
  330. function test(address foo, bytes rawcalldata) public {
  331. (bool success, bytes rawresult) = foo.call{value: 102, gas: 1000}(rawcalldata);
  332. }
  333. .. note::
  334. ewasm also supports ``staticcall()`` and ``delegatecall()`` on the address type. These
  335. call types are not supported on Parity Substrate.
  336. .. _fallback_receive:
  337. fallback() and receive() function
  338. _________________________________
  339. When a function is called externally, either via an transaction or when one contract
  340. call a function on another contract, the correct function is dispatched based on the
  341. function selector in the raw encoded ABI call data. If there is no match, the call
  342. reverts, unless there is a ``fallback()`` or ``receive()`` function defined.
  343. If the call comes with value, then ``receive()`` is executed, otherwise ``fallback()``
  344. is executed. This made clear in the declarations; ``receive()`` must be declared
  345. ``payable``, and ``fallback()`` must not be declared ``payable``. If a call is made
  346. with value and no ``receive()`` function is defined, then the call reverts, likewise if
  347. call is made without value and no ``fallback()`` is defined, then the call also reverts.
  348. Both functions must be declared ``external``.
  349. .. code-block:: solidity
  350. contract test {
  351. int32 bar;
  352. function foo(uint32 x) public {
  353. bar = x;
  354. }
  355. fallback() external {
  356. // execute if function selector does not match "foo(uint32)" and no value sent
  357. }
  358. receive() payable external {
  359. // execute if function selector does not match "foo(uint32)" and value sent
  360. }
  361. }