Functions
Last updated
Last updated
Type | Description |
---|---|
Function parameters and private function names start with an underscore _
Variables default to internal
if no visibility specifier is given
State variables can be declared as public
, private
, or internal
but not external
A function declaration in Solidity looks like the following:
This is a function named eatHamburgers
that takes 2 parameters: a string and a uint. For now the body of the function is empty. Note that we're specifying the function visibility as public. We're also providing instructions about where the _name
variable should be stored in memory. This is required for all reference types such as arrays
, structs
, mappings
, and strings
.
What is a reference type you ask? Well, there are two ways in which you can pass an argument to a Solidity function:
By value, which means that the Solidity compiler creates a new copy of the parameter's value and passes it to your function. This allows your function to modify the value without worrying that the value of the initial parameter gets changed.
By reference, which means that your function is called with a... reference to the original variable. Thus, if your function changes the value of the variable it receives, the value of the original variable gets changed.
It's convention (but not required) to start function parameter variable names with an underscore (_) in order to differentiate them from global variables.
You would call this function like so:
In Solidity, functions are public
by default. This means anyone (or any other contract) can call your contract's function and execute its code.
Obviously, this isn't always desirable and can make your contract vulnerable to attacks. Thus it's good practice to make all functions private
, and then only make public
the functions you want to expose to the world.
Let's look at how to declare a private function:
This means only other functions within our contract will be able to call this function and add to the numbers
array.
As you can see, we use the keyword private
after the function name.
It's convention to start private function names with an underscore _
.
In addition to public
and private
, Solidity has two more types of visibility for functions:
internal
Similar private
, except that it's also accessible to contracts that inherit from this contract.
external
Similar to public
, except that these functions can ONLY be called outside the contract β they can't be called by other functions inside that contract.
For declaring internal or external functions, the syntax is the same as private and public:
Functions can be defined inside and outside of contracts.
Functions outside of a contract, also called βfree functionsβ, always have implicit internal
visibility. Their code is included in all contracts that call them, similar to internal library functions.
Functions defined outside a contract are still always executed in the context of a contract. They still can call other contracts, send them Ether and destroy the contract that called them, among other things. The main difference to functions defined inside a contract is that free functions do not have direct access to the variable this
, storage variables and functions not in their scope.
If a function requires an input parameter for the function to be valid (e.g. for an override) but you don't actually use the parameter in the function, it can be commented out.
This getKitty
function is the first example we've seen that returns multiple values. Let's look at how to handle them:
Visibility | Description |
---|---|
non-constant
The default function type and doesn't get specified as a modifier.
The function can modify the state of the contract on the blockchain. Non-constant functions can write to the contract's storage, emit events, create other contracts, and use selfdestruct
.
view
Doesn't cost gas when called directly (externally by a user).
Does cost gas when called by another function or contract.
Reads the state of the blockchain but can't modify it.
pure
Doesn't cost gas when called directly.
Does cost gas when called by another function or contract.
Does not read the state of the blockchain, only memory and calldata.
internal
Default visibility specifier when none are specified.
Internal functions can only be called inside the current contract (more specifically, inside the current code unit, which also includes internal library functions and inherited functions) because they cannot be executed outside of the context of the current contract.
Calling an internal function is realized by jumping to its entry label, just like when calling a function of the current contract internally.
Those functions and state variables can only be accessed internally (i.e. from within the current contract or contracts deriving from it), without using this
.
external
External functions consist of an address and a function signature and they can be passed via and returned from external function calls.
Can be called from outside, canβt be called from inside (functions from same contract, functions from inherited contracts).
External functions are part of the contract interface, which means they can be called from other contracts and via transactions.
An external function f
cannot be called internally (i.e. f()
does not work, but this.f()
works).
External functions are sometimes more efficient when they receive large arrays of data.
private
Private functions can only be called from inside the current contract, even the inherited contracts canβt call them.
Private functions and state variables are only visible for the contract they are defined in and not in derived contracts.
public
Public functions can be called from anywhere.
Public functions are part of the contract interface and can be either called internally or via messages.
For public state variables, an automatic getter function is generated.