What is function visibility in Solidity?
Written by Adesoye Jeremiah Olayinka
Reviewed by Brady Werkheiser
In Solidity smart contract programming, there is a provision that allows developers to decide who or what other smart contracts can call their functions based on specified restrictions. The ability to define how smart contract functions can be interacted with is known as function visibility.
What is function visibility?
The function visibility feature in Solidity smart contracts is used to ensure that when functions are specified, their level of accessibility, including public, external, internal, and private, are maintained as they were intended by the developers.
If a developer doesn’t use the right function visibility type, or if no visibility model is specified in their code, the contract's default public visibility is exposed to potentially exploitable security vulnerabilities. Apart from the security implications of not having function visibility specified, smart contracts might not work as intended since the functions will be working without proper instructions.
Who can call a smart contract function?
There are three kinds of contracts that can call a function: the main contract itself, a contract inherited from the main contract (DerivedContract), and a third-party contract (OutsideContract).
Calling a smart contract means to access the internal code that is in a smart contract and the data included in it. This is a way of retrieving data from the contract.
1. The Main Contract (MainContract)
This is the syntax of the MainContract calling its function:
contract MainContract {
uint x;
// someone external calls main
function main() external {
// inside main, we call the private store function
store(10);
}
function store(uint _x) public {
x = _x;
}
}
2. A Contract Inherited from the Main Contract (DerivedContract)
This is the syntax of a DerivedContract that is using a derived function from the MainContract:
contract DerivedContract is MainContract {
function newFunction() external {
// call a function derived from the MainContract
store(15);
}
}
3. A 3rd-Party Contract (OutsideContract)
This is the syntax of an OutsideContract that is is calling the main contract from an outside function.
contract OutsideContract {
function functionOutside(address mainContractAddress) external {
// here we send a message call to main contract
MainContract(mainContractAddress).store(15);
}
}
How do function visibility modifiers and inheritance work together?
Inheritance is when the contents of one contract are copied into another contract (a “derived contract”) by using the “is” keyword, and the function modifier visibility works with a derived child contract according to the type of visibility a contract is assigned.
Contract ParentContract {
function performTask1() public {
//performs the first task
}
}
Contract ChildContract is ParentContract {
function performTask2() public {
//performs a second task
}
}
The relationship between function visibility modifiers and inheritance is explained below:
If the modifier of the ParentContract function is public, a ChildContract can access it.
If the modifier of the ParentContract function is internal, the ChildContract can access it.
If the modifier of the ParentContract function is private, the inheriting ChildContract cannot access it.
If the modifier of the ParentContract function is external, the inheriting ChildContract cannot access it.
How can function visibility modifiers help gas optimization?
Because the parameters for external function visibility modifier are not saved to memory, but read directly from calldata, smart contracts consume less gas. In contrast public functions use input parameters are saved to memory, which costs more gas to deploy a smart contract.
What are function visibility modifiers?
There are four different types of function visibility modifiers that range from most accessible to least accessible: public, external, internal, and private. Developers should modify functions with the correct visibility based on who they want to be able to see and call the function.
1. Public
A public function can be accessed by any of the three types of calling contracts: main contract, derived contract, and a third party contract. A function is public by default.
contract RandomContract {
function functionPublic() public {
//performs a task
}
}
As shown in the code sample above, any contract in the codebase can access the “functionPublic
” function because of the “public” visibility.
2. External
An external function is a function that can only be called by a third party. With the external function visibility, a contract that can call the function must be independent of the main contract and can not be a derived contract.
contract RandomContract {
function externalFunction() external {
//performs a task
}
}
Above is a random contract (RandomContract
) that is performing some task. The code snippet below is an external contract that is calling the external function on the RandomContract
.
interface IRandomContract {
function externalFunction() external;
}
contract CallingContract {
function functionIsExternalCall(address addr) external {
IRandomContract(addr).externalFunction();
}
}
3. Internal
An internal function can be called by the main contract and any of its derived contracts. Internal functions are accessible from the main contract in which they were initially declared and by the contracts that extend from this main contract through inheritance.
4. Private
A private function can only be called by the main contract in which it was specified. Private functions are used initially according to common practice, but if the scope is wider than this modifier type, any other plausible modifier should be used.
What is the default function visibility in Solidity?
If the visibility modifier of a function is not explicitly declared in the code, the function is set to public visibility by default. Leaving the function visibility blank and relying on the Solidity compiler to use the default visibility is not a recommended best practice; intentionally setting the function visibility makes code more legible and easier to understand during code reviews.
What is the difference between function and state variable visibility modifiers?
The difference between function visibility modifiers and state variable visibility modifiers is that state variables do not have the external visibility modifier option.
State variables are variables whose values are permanently stored in contract storage, which holds data persistently between function calls. Like function visibility modifiers, state variables also have visibility modifiers which are Public, Private and Internal.
State Variable Visibility Modifiers
State variables are declared in the contract section of the program. The variable data type is specified and after that, the visibility modifier is assigned to the variable.
Contract TestingVariableStorage {
uint public publicData; // Publicly visible variable
string private privateData; // Privately visible variable
string internal internalData; // Internally visible variable
}
1. Public
A state variable with the public modifier can be accessed by any contract in the application. If a variable is declared as public, the data stored in it can be read by the main contract, a derived contract, or an external contract.
2. Internal
State variables declared with the internal modifier can only be accessed within the contract in which they were defined and by a derived contract. A third party or another external contract cannot access the storage of the data defined as an internal variable.
3. Private
If a state variable is private, only the main contract in which they were declared can call them. The private visibility modifier restricts access from other parties apart from the main contract so that the data it holds is protected.
What is the default variable visibility in Solidity?
When the variable visibility is not defined, the default value is internal. It is best practice to declare a variable as private until the scope widens.
Keep Learning About Solidity
This article introduces you to Solidity function visibility and provides you with explanations and resources to use for your next project.
If you’re new to the Solidity language and you’re looking forward to building your first smart contract, secure your spot in Alchemy University's free, online Solidity programming course.
Related overviews
What it is, How it Works, and How to Get Started
Explore the Best Free and Paid Courses for Learning Solidity Development
Your Guide to Getting Started With Solidity Arrays—Functions, Declaring, and Troubleshooting