Solidity functions use function keyword, can be view or pure, and have visibility levels: public, external, internal, private.
Intro to Solidity Functions
Previous Section Recap
In the previous section, we learned the basics of the Solidity smart contract programming language. Here are some of the important takeaways we looked at:
- In Solidity, a
contractis very similar to a JavaScriptclass- The syntax to declare state variables is:
// data_type + visibility + variable_name = some_value;
bool public isHappy = true;msg.sender: who is thefromin the current calling tx?msg.value: what is thevaluein the current calling tx?
In Solidity, a function is generally defined by using the function keyword. Functions are where actual logic is contained on a smart contract. Let's dive in...
The most common way to define a function in Solidity is by using the function keyword:
// function_keyword + function_name(paramter_list) + visibility {}
function helloWorld(bool _saysHello) public {
// statements
}If the function returns a value, the syntax of a function header includes a returns statement, as shown below:

Let's get some Solidity up in this place! Here's a quick function in a sample MyContract:
contract MyContract {
function myFunction() external pure {
uint x = 5;
}
}The
myFunctionabove doesn't really do much! Once called, the function will just declare a new variablexwith a value of5in local memory, then execution will end which means local memory is wiped. Nothing happens! 🤷
This is what a script call to this function would look like in JavaScript:
const myTx = await contract.myFunction();The above script call will send a transaction to the MyContract address with a specific call to the myFunction() endpoint. The EVM will execute the statements inside until it reaches the closing bracket. Once the logic in a function completes, the transaction is mined and any effects are indexed in the tx's own receipt.
What about a function that actually does something? Here is one example:
function changeOwner(address _newOwner) public {
owner = _newOwner;
} The above function lives in a smart contract containing an owner state variable. By calling the changeOwner() function and passing a new address to it, the contract will overwrite the current contract owner with the passed-in _newOwner value.
You will sometimes see functions in Solidity contain one of the following keywords: view and pure.
view: this function promises that NO state will be changed, only read
This is basically a keyword that can be seen as the function itself saying: "I promise to just "view", not change state!" 🙋♂️
pure: this function promises that NO state will be changed nor read
This is basically a keyword that can be seen as the function itself saying: "I promise to act completely independent of the smart contract I am in!" 🙋♂️
View Function Example
Let's set up a simple contract with two state variables...
pragma solidity 0.8.4;
contract MyContract {
uint x = 5;
uint y = 10;
}Let's then add a new function called sum() and declare it as view:
pragma solidity 0.8.4;
contract MyContract {
uint x = 5;
uint y = 10;
function sum() external view returns(uint) {
return x + y;
}
}Notice how the sum() function, declared as view, keeps it promise? It is only reading from state because it uses the x and y state variable values in order to return their sum. It is reading from state to produce a new value but it is not changing any state.
A
viewcannot write to storage. 🔏
Pure Function Example
If you noticed in the first contract example, there is already a pure function used:
contract MyContract {
function myFunction() external pure {
uint x = 5;
}
}The keyword pure means this function does not read or write storage. It is function completely independent from contract state. But again, the function above is not really useful at all...
A more useful pure function would be one that returns something:
contract MyContract {
function add(uint x, uint y) external pure returns(uint) {
return x + y;
}
}pure functions like the one shown above are typically used in libraries or for functionality that is not specific to a smart contract's state but is still needed for independent contract operations.
Notice the syntax required for functions that actually return a value? You must indicate the return type in the returns(data_type) block.
Implicit Return
The returns syntax in Solidity can also look like this:
contract MyContract {
function add(uint x, uint y) external pure returns(uint z) {
z = x + y;
}
}Believe it or not,
zis implicitly returned here! 🤯
Return Multiple Values
contract MyContract {
function mathTime(uint sum, uint product) external pure returns(uint sum, uint product) {
sum = x + y;
product = x * y;
}
}In this case, both the sum and product are returned.
Return Multiple Values Using return
contract MyContract {
function mathTime(uint sum, uint product) external pure returns(uint, uint) {
uint sum = x + y;
uint product = x * y;
return (sum, product);
}
}The returned value is referred to as a tuple.
A function can write (fancy term for changing some state) if it is NOT pure or view:
contract MyContract {
uint x = 5;
uint y = 10;
uint z;
function storeSum() external {
z = x + y;
}
}Since this function is writing to storage via directly assigning a value to the z state variable, it will always cost gas to execute on the Ethereum network.
Storage is expensive on the Ethereum network! 💸 As a developer, you must always be optimizing for the least friction possible when changing state so that you do not incur large gas costs to you or your users!
We've only seen the public visibility so far. Function signatures always contain a visibility identifier... basically, how accessible to do you want this function to be?
Functions can be declared, from most-public to least-public, as:
public- any contract or EOA can call into this functionexternal- only other contracts (external to the current contract) and EOAs can call, no internal callinginternal- only this contract along with its inheritance chain can callprivate- only this contract can call
🚨 State variables work off the same exact criteria for visibility. State variables can be declared as public, private, or internal but not external.
- Solidity function visibility explained
- Solidity by Example - Visibility
- Solidity by Example - Pure and View
- Modifying the Merkle Patricia Trie
We've looked main pillars of Solidity logic: functions. It is important to distinguish the appropriate visbility and declaration. These keywords are extremely important to know, as they are typically included in most Solidity function signatures and have important security ramifications (ie. who can access this function?).
In the next section, we'll look at how contracts communicate. Let's gooooooooooooooo! 🏃♂️
Alchemy University offers free web3 development bootcamps that explain Solidity functions in-depth and help developers master the fundamentals of web3 technology. Sign up for free, and start building today!