The focus of today’s newsletter is on a major component of smart contracts, functions. Functions are at the soul of contracts and help us to create modularized pieces of code that handle individual operations within the smart contract. In very basic terms, functions group together pieces of code that execute like a set of instructions to return a defined outcome. They represent the basic intent of coding and are used in the most common programming languages. Structurally and somewhat syntactically, solidity functions match how functions are represented in other languages, but there are some nuances that I will go deep in for the remainder of this newsletter.
The basic structure of Solidity functions looks like:
function (<parameter types>) {internal|external|public|private} [pure|view] [returns (<return types>)]{}
Function Declaration
<parameter types>
Parameter types take the value type and parameter name that (e.g. unit paramName) the function can be used within the scope of the function.
{internal|external|public|private} (visibility)
Function visibility is a topic covered in a previous newsletter, but can be summarized as the permissions applied to the function that dictates how it can be used in or outside of the contract and the blockchain.
[pure|view]
These two values represent the different types of state mutability. State mobility behaves similarly to function visibility in that it acts as sets of permissions to control how the function can be used. A function is not required to have either state mutability value and if left without, is considered to be a normal function.
pure
Pure functions do not view or modify the state of the blockchain. It will not access state variables and can call other pure functions. It takes what is passed to the function and will always return the same output. When a pure function is called externally it does not incur a gas fee.
view
View functions view the state of the blockchain, but do not change the state of the blockchain. When applied, getter methods are automatically applied to the function. View can be used expose internal components in a safe manner, as well as eliminate the possibility of someone adding code to change the state in unexpected ways. When a view function is called externally it does not incur a gas fee.
[returns (<return types>)]
The returns statement is an optional part of function creation, but if you want a value returned it is necessary. The use of returns indicates that a value should be returned by the function with the value type and parameter name passed with the parentheses. A variable name does not have to be passed as a parameter value. If you would like to return multiple values, then you will pass a return statement within the function with each value comma separated returns (e.g. returns (value1, value2)).
Within the Function
Shifting the focus from the function declaration to the within the function, it is common to see a function pattern using conditional statements and loops.
Conditional statements (If...else)
Conditional statements create code control within the function (globally as well) and tell the contract to make a decision on whether the statement or block of code should be executed based on if an expression evaluates to true.
Conditional statements follow the structure of
if (condition) {
// Statement to be executed if condition is true
} else if (condition) {
// Optional statement if an additional condition should be evaluated. Same output as the first statement
} else {
// Statement to be executed if previous conditions are false
}
Loops (for | do...while | while)
for loop
For loops are a repetitive command that executes for a pre-known amount of times and is initialized only once. It will iterate as long as the condition is true and for the length of the predefined number of iterations.
while loop
A basic loop that executes a statement as long as the condition is true. Once a condition is false, the loop stops.
do...while
Similar to the while loop with the main difference being it executes the condition at the end of the loop. This means that the loop runs at least once regardless of if the condition is true or false.
Fallback Functions
function() public payable {}
A fallback or default function is called if the transaction that triggered the contract didn’t
Call a function
Call any declared functions in the contract
Didn’t contain data
Smart contracts can only have one default function and are typically used to receive ether. This is the reason why it is declared public payable and does nothing other than accept ether.
Wrapping it up
There are a lot of considerations to be made when architecting a function and while it might seem overwhelming at first, it will start to make sense when translating business logic to code architecture. If there is one element of programming in solidity that you will spend a good amount of time on, it is on function architecture. They make your code reusable and organized which given the current state of the Ethereum blockchain is important in order to prevent hacks, wasted gas and error-prone ether transactions.