Functions
The Behavior of Smart Contracts
We saw in the Contract Structure section that methods are what allows for contracts to be decentralized programs that they are. However, we have yet to explore what methods (functions) consist of.
Function Headers
Although one may want to dive right into the logic of a function itself, an equally important task is defining the function header itself. In Solidity, all function headers begin with the function
keyword which tells the compiler that we are defining a function. Afterwards, we declare the name of the function itself, followed by brackets
In the code snippet above, we are defining a function named print
.
What About Function Parameters?
All function parameters live within the brackets next to the function name. As an example, if we wanted print
to take in an unsigned integer, we would modify our function header to the following:
function print(uint num)
If we wanted our function to take in multiple parameters, we would modify our function header as follows:
function print(uint numOne, int numTwo)
After the function
keyword, function name, and optional parameters, the last necessary section of the function header which we must define is the visibility of the function.
All smart contracts live in a distributed system, and one of the challenges this presents is how to make sure only certain actors can call certain functions. For this, Solidity introduces the concept of visibility; listed below are the four types of visibility available to functions:
Public: any actor can call a public function
Private: only the contract itself can call a private function
Internal: only the contract itself and any child contract can call an internal function
External: the contract itself and child contracts cannot call an external function; other actors can call external functions.
Below, we see visibility being used in (syntactically correct) function headers:
Extensions of Function Headers
All function headers are required to have the function
keyword, a function name, and a specified visibility. However, the following questions demonstrate what our current understanding of function headers is missing:
How do we define return values?
What if we can guarantee that our function does not modify or even view the state of the blockchain?
We begin by tackling the idea of defining return values. At the end of the function header, if we want our function to return a value, we append the return
keyword to the function header and in parentheses, declare the return types of the values the function will return. An example of returning values from a function can be seen below:
Like function parameters, we are not limited to just a single return value; functions in Solidity are capable of returning multiple values:
Focusing now on the mutability guarantees of a function, we can add mutability keywords to a function header if a function meets certain criterias:
View: the function at most only views the state of the blockchain
Pure: the function does not view the state of the blockchain at all
As an example, consider the Rectangle contract from contract structure:
Now consider the following two functions we wish to add to Rectangle:
getFive: returns the number 5
getArea: returns the area of the rectangle
Notice that in the case of getFive, we can declare this function as being pure
since this does not require us to view the state of the blockchain in any manner. For getArea, we can mark it as view
since we are viewing the state of the blockchain (via using the fields length
and width
) but we cannot mark it as pure
:
One interesting observation is that all pure
functions can be marked as view
, but not all view
functions can be marked as pure
.
Function Body
The function body is where the logic of a function lives. Like state variables, each line within the function body must end with a semicolon.
Last updated