# Solidity Minimalist Tutorial: 3. Function type
Recently, I have been relearning Solidity, consolidating the finer details, and also writing a "Solidity Minimalist Tutorial" for newbies to learn. Lectures are updated 1~3 times weekly.
Everyone is welcomed to follow my Twitter: @0xAA_Science (opens new window)
WTF Academy Discord: Link (opens new window)
All codebase and tutorial notes are open source and available on GitHub (At 1024 repo stars, course certification is unlocked. At 2048 repo stars, community NFT is unlocked.): github.com/AmazingAng/WTFSolidity (opens new window)
# Function in Solidity
Function is classified into values type by solidity document, but I put it a separate category, since there is a big difference in my opinion. Let's take a look of solidity function:
function (<parameter types>) {internal|external} [pure|view|payable] [returns (<return types>)]
kind of complicated, let's move forward one by one (keyword in square brackets is optional):
function
: Start with the keywordfunction
.(<parameter types>)
: The input variable types and names of the function.{internal|external|public|private}
: Function visibility specifiers. There are 4 kinds, andinternal
is the default visibility level for state variables:public
: Visible to all.private
: Can only be accessed within this contract, derived contracts cannot used it.external
: Can only be called from other contracts. But can be called bythis.f()
inside the contract, wheref
is function name.internal
: Can only be accessed internall and by contracts deriving from it.
Note:
public|private|internal
can be also used on state variables. Public variables will automatically generategetter
functions for querying values.[pure|view|payable]
: Keywords that dictate a Solidity functions behavior.payable
is easy to understand. One can sendETH
to the contract viapayable
functions.pure
andview
are introduced at the next section.[returns ()]
: Return variable types and names.
# WTF is Pure
and View
?
When I started learning solidity
, I didn't understand pure
and view
at all, since there are no similar keywords in other languages. solidity
added these two keywords, because of gas fee
. The contract state variables are stored on block chain, and gas fee
is very expensive. If you don't rewrite the variables on the chain, you don't need to pay gas
. Thus, You don't need to pay gas
for calling pure
and view
functions.
I drew a Mario illustration to help you understand pure
and view
. In the picture, I put state variables (stored on-chain) as Princess Bitch, three different roles represent different keywords.
pure
: Functions containingpure
keyword cannot read nor write state variables on-chain. Just like the little monster, it can't see or touch Princess Bitch.view
: Functions containingview
keyword can read but can not write on-chain state variables. Similar to Mario, able to see Princess but can not get inside.Without
pure
andview
: Functions can both read and write state variables. Like theboss
can do whatever he wants.
# Code
# 1. pure v.s. view
We define a state variable number = 5
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract FunctionTypes{
uint256 public number = 5;
Define an add()
function, add 1 to number
every when called.
// default
function add() external{
number = number + 1;
}
If add()
contains pure
keyword, i.e. function add() pure external
, it will occur error. Because pure
can not read state variable in contract nor write. So what can pure
do ? i.e. you can pass a parameter _number
to function, let function returns _number + 1
.
// pure
function addPure(uint256 _number) external pure returns(uint256 new_number){
new_number = _number+1;
}
Example:
If add()
contains view
, i.e. function add() view external
, it will also occur error. Because view
can read, but can not write state variable. We can modify the function as follows:
// view
function addView() external view returns(uint256 new_number) {
new_number = number + 1;
}
Example:
# 2. internal v.s. external
// internal
function minus() internal {
number = number - 1;
}
// external
function minusCall() external {
minus();
}
Define a internal minus()
function, number
will decrease 1 each time function called. Since internal
function can only be called within the contract itself. Therefore, we need to define a external
minusCall()
function to call minus()
internally.
Example:
# 3. payable
// payable: ensure that money (ETH) is being sent to the contract and out of the contract as well
function minusPayable() external payable returns(uint256 balance) {
minus();
balance = address(this).balance;
}
Define a external payable minusPayable()
function, which calls minus()
and return ETH
balance of the current contract (this
keyword can let us query current contract address). Since the funciton is payable
, we can send 1 ETH
to the contract when calling minusPayable()
.
We can see that contract balance is 1 ETH
in return message.
Example:
# Summary
In this section, we introduced solidity
function type. pure
and view
keywords are difficult to understand, since they have not appeared in other languages. You don't need to pay gas fees for calling pure
or view
functions, since they don't modify the on-chain data.