Functions
Functions are a way to encapsulate logic in a program, but they also serve as entry-points for your Smart Contracts.
Function Declaration
Function declarations in Solidity have a few basic requirements:
- Must start with the
function
keyword - Must have a name
- Must have a parameter list (even if it's empty)
- Must declare a
visibility
- Can have a body
- Can have a return type
- Can have modifiers
- Can be declared as
payable
- Should have a mutability modifier (if applicable)
Let's look at a simple function declaration, and then we'll break it down and get into some more advanced topics.
// function <name>(<parameters>) <visibility> <modifiers?> <returns?> { <body> }
function myFunction(bool _myParam) public {
// Function body
}
Function Parameters
Function parameters are declared as a list of comma-separated types and names, enclosed in parentheses.
function myFunction(bool _myParam, uint256 _myOtherParam) public {}
📘 Parameter naming convention
In Solidity, it is common to prefix function parameters with an underscore (
_
). This is not required, but it is a convention that is widely used. The intention is to differentiate between the parameter and a global variable with the same name.
Function Visibility
Functions in Solidity can have one of four visibilities.
Public
Public functions are the catch-all for visibilities. They can be called from within your contract, from inherited contracts, from other contracts on the blockchain, and from outside the blockchain by users.
function myFunction() public {}
External
External functions can only be called from outside the contract; either by other contracts or by a user outside the blockchain.
function myFunction() external {}
💰 External is cheaper than Public
If you are writing a function that will only be called from outside the contract, you should use
external
instead ofpublic
. This is becauseexternal
functions are cheaper to call thanpublic
functions, as they do not have to copy the parameters to memory.
Internal
Internal functions can only be called from within the contract, or from inherited contracts.
function myFunction() internal {}
Private
Private functions can only be called from within the contract.
function myFunction() private {}
Function Return Types
Functions can return a single value, or multiple values. The return types are declared after the parameter list, and are separated by a comma.
You can also name the return values, which will create a variable in the function body that you can assign a value to.
function myFunction() public returns (uint256) {
return 1;
}
function myOtherFunction() public returns (uint256 myValue) {
myValue = 1;
}
Function modifiers
Modifiers are a way to add functionality to a function which will either run before, or after a function. They are usually used to add additional checks to a function, or to modify the return value of a function.
Modifiers are declared with the modifier
keyword, and can be applied to a function by using the modifier
keyword after the function declaration.
Every modifier must start or end with the _;
statement. This is where the function body will be executed.
// declaration
modifier myModifier() {
// Modifier body
_;
}
// usage
function myFunction() public myModifier {}
You can also chain multiple modifiers together, by separating them with a space.
function myFunction() public myModifier1 myModifier2 {}
Payable functions
Functions can accept the native currency of the blockchain as payment. This is done by declaring the function as payable
.
In the case of the EOS EVM, this is EOS.
function myFunction() public payable {
uint256 amount = msg.value;
}
📘 msg.value
msg.value
is a global variable that is available in every function. It contains the amount of native currency that was sent to the function.
Function mutability
There are three types of mutability that a function can have, and they mean different things.
Default
If a function does not have a mutability modifier, it is considered a "writable" function. This means that the function can modify the state of the contract, and when called from outside the contract, it will cost the user gas.
function myFunction() external {}
View
If a function is declared as view
, it means that the function will not modify the state of the contract, but it will
read state variables from the contract. A user interacting with this function will not be charged gas.
function myFunction() external view returns (uint256) {
return myStateVariable;
}
Pure
If a function is declared as pure
, it means that the function will not modify the state of the contract, and it will not
read state variables from the contract. A user interacting with this function will not be charged gas.
function myFunction(uint256 a, uint256 b) external pure returns (uint256) {
return a + b;
}
📘 Why is Pure useful?
Pure functions are generally used to provide utility functions outwards. For instance, if you wanted to provide a function that would calculate a number based on logic that the contract uses internally in order to replicate the logic in a web application, you could use a
pure
function to do this.
Constructors
Constructors are special functions that are called when a contract is deployed. They are declared with the constructor
keyword,
and are only run once.
constructor() public {
// Constructor body
}