Overview of Functions

How are functions used?

Functions in Solidity are the building blocks of smart contracts. They define how the contract should run and its available features. Depending on the visibility of the function, it can be called externally by user accounts or internally by other functions within the contract. A function is essentially a set of code that can be reused and invoked from any part of our program.

Declaring a function

To declare a function:

  1. Begin by using the keyword function.

  2. Next, specify the function name.

  3. Enclose a list of parameters in brackets that the function may or may not take (the list can be empty).

  4. State the scope of the function using a modifier.

  5. If the function returns a value, use the return keyword followed by the returned value type.

  6. Write the body of the function, which contains the code that will be executed when the function is called.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract TestContract {
function testFunction(int num1, int num2) public pure returns (int num3) {
num3 = num1 + num2;
}
}
How to declare a function in Solidity

In the code above, we define a function called testFunction that accepts two parameters of type int called num1 and num2.

Function modifiers

The public and pure keywords are called function modifiers. The public keyword is an example of a visibility modifier, and it means the function can be accessed and called externally, while pure is a state mutability modifier, which means the function will not access or modify any state variables or data stored within the contract.

Return value

The function returns a single variable, an integer named num3. This is one way of specifying return values. We can name each return variable and assign the values to these variables in the body of the function. Another way is to simply list the types, and then explicitly return variables with these types at the end of the code. For example, the code below is the same as the one above.

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract TestContract {
function testFunction(int num1, int num2) external pure returns (int) {
int num3 = num1 + num2;
return num3;
}
}
Another way to declare a function in Solidity

Function visibility

The keyword public is an example of function visibility in Solidity. There are four important types:

  • Public: Every account can access this function, both internal and external.

  • External: It can be accessed externally only. It cannot be called by other functions in the smart contract. When we try to do this, we get a compile error: DeclarationError: Undeclared identifier. "testFunction" is not (or not yet) visible at this point.

  • Internal: It can only be called by other functions within this contract and other contracts derived from it.

  • Private: It can only be called by other functions within this contract.

When we define functions, we must set the visibility type. When we define publicly visible functions (i.e., with public or external), we get a function helper button on Remix. We won’t see this with a private or internal function.

Function state mutability

The keyword pure is an example of state mutability. This is used to specify the behavior of this function with regard to the contract state data. All possible types include:

  • pure: This function will never attempt to access or modify the current state of the contract. Most times, these are just utility or helper functions that will only work with data provided to them as arguments during the function’s call. They usually return a value used in other areas of the smart contract. The code sample above is an example of a pure function.

  • view: The smart contract will access contract data but never modify it. Below is an example:

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract TestContract {
int public testNumber = 20;
function testFunction(int num1, int num2) external view returns (int) {
int num3 = num1 + num2 + testNumber;
return num3;
}
}
Sample code demonstrating view functions

The function only uses the value of the state contract, testNumber. It doesn’t modify its value in any way.

  • payable: We expect some value in the form of ETH to be sent alongside the function call. This is different from the regular gas fee. When we mark a function as payable, it can also accept payment of zero ETH, meaning a payable function can also be non-payable. However, a non-payable function will reject any ETH sent to it.

Returning value

The next part of a function statement is the returns block. This is used to specify the data types that the function will return in the form of a list. This list can’t be empty. If a function is not supposed to return anything, we can omit the returns (<return types>) block.

You can test all these code samples using the widget below: