To make the magic happen in Solidity you will need to create functions. In this post we will be going through what is needed to create a function and what the keywords mean.
Function
The first thing we will need to do is to use the keyword function
function deposit()
The function
keyword is used to define what functions are available on the contract. After specifying the function
keyword you will want to name the function, using it to describe what the function is doing.
This will allow others looking at, or using the contract, to understand what the function is intended to do.
Lastly, ()
are used to indicate if this function has any parameters. Parameters are explained in just a little bit.
Visibility Keywords
Next we will want to identify if this function is public, external, internal, or private. This will determine who or what can call this function.
Public
This will allow anyone to call this function. This will copy any array data passed in as parameters to be copied to memory, which can increase the cost of gas of a function.
It is recommend to use public if you want external callers and functions on the contract itself to call this function.
function deposit() public { }
External
This allows anyone to call this function as well but any array parameters are read directly from the calldata instead of being copied to memory.
This will allow the call to save gas but this function should not be used by functions inside the same contract. It is possible by using this.[functionName]
but this will execute as if it was an external call coming into the contract.
function deposit() external { }
Internal
This will allow the function to be called by functions within the contract and any contracts which inherit from this contract.
function deposit() internal { }
Private
Only functions on the contract itself can call this function.
Note: Just because this is called private it does NOT mean no one can see it. Everything on the blockchain is visible, so this simply means external contracts cannot call it.
function deposit() private { }
Parameters
Parameters are used to pass in additional information to a function. This allows for functions to have flexibility in what they are acting on.
function setActive(uint256 _id, bool _isActive) pubic { // Now we are able to set an item with and id == _id // active value equal to _isActive }
Here the function is taking an _id
and a _isActive
parameter which will allow us to now use those parameters as we need in function.
Returns
returns
is used when a function returns any type of value, whether from a calculation or storage values.
function isAccountActive() public returns (bool) { return true; }
Pure Vs View
The next thing we can do is specify if a function is a pure
function or a view
function. We only want to add one of these keywords if we are not modifying the state of a contract.
Pure
is used if this function does not modify or use any storage values of the contract.
function getTotal() public pure returns (uint256) { return 1 + 2; }
View
is used when the function doesn’t modify any state but it does use values from the contract
uint256 total; function getTotal() public view returns (uint256) { return total; }
As a side note. You may see the word constant
in older versions of Solidity code. Just know pure
and view
were created to replace constant
and allow us to write more expressive contract functions.
Modifiers
Another thing we should touch on are modifiers. They are not a keyword, however, they are used very often in the creation of contract functions.
Modifiers are used most often for writing re-usable validation code but it can do anything. With that said, a motto when writing Solidity contracts is to make them as simple as possible. I would personally avoid making modifiers do more than one thing.
After saying that, here is an example showing you can have logic before and/or after the modifier calls the function.
modifier onlyOwner() { require(msg.sender == owner, "Only the owner can do this"); _; require(wasSuccessful, "It must have been successful"); } function closeAccount(address account) public onlyOwner { // Close an account }
The example will first require the owner is the msg.sender. Next, the _;
is used to tell Solidity to run the function this modifier is on.
Once the function has finished running we will check to see that it has set a contract value called wasSuccessful
and revert the whole transaction if it did not set the value to true.
Payable
payable
is a big one. This allows a function to accept ETH as part of the call. If the function is called with ETH but does not have the payable modifier the call will be rejected.
function deposit() public payable { }
Putting the Fun in Functions
Functions are a core part of how smart contracts are used to manage state and run the business logic needed to provide value to the users of the contract.
A key to growing Solidity knowledge is to learn how the basic function keywords work, which ones are required, and how to use them to identify how a function should be used.