Collaboration between Neptune Mutual and SushiSwap
Explore Neptune Mutual's ongoing collaboration with SushiSwap offering several benefits.
Youtube Video
Playing the video that you've selected below in an iframe
Understanding how to manage the visibility of functions, and variables in Solidity.
The objective of this blog post is to provide a detailed understanding of visibility specifiers in solidity, their hidden dangers, and a set of best practices to prevent them. This is an addition to the series from our earlier blog, where we shared the details of Integer Overflow and Underflow, Front Running Attack, Understanding Block Timestamp Manipulation, Issues with Authorization Using tx.origin, and Precision Loss in Solidity Operations.
There are four levels of visibility for functions and state variables in Solidity: public, private, internal, and external. Each visibility level governs how a function or state variable can be accessed. The visibility level for functions is set to public by default, which means that anyone can access them. Variable has a private visibility level by default, which means it can only be accessed within the same contract.
These specifiers are classified as follows:
It is critical to select the appropriate level of visibility to ensure the security and integrity of a smart contract. The vulnerability occurs when smart contract developers unintentionally extend the visibility level of a function or data beyond what is required. For example, if a function is set to public when it should be private, anyone, including malicious actors, can access it. This can result in unauthorized data access, manipulation, or deletion, as well as unintended function execution. Making a function or state variable too restrictive, on the other hand, can limit the contract's functionality and usefulness.
Consider the below smart contract Visibility.sol.
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.17;
contract Visibility{
address public owner;
constructor() {
owner = msg.sender;
}
function changeOwner(address newOwner) public {
require(newOwner != address(0));
owner = newOwner;
}
}
Line 5:
In line 5 of the contract, we have defined a public state variable `owner` of type address. This means that the variable can be accessed by any other contract or external account.
Line 7-9:
In line 7 of the contract, we have declared a constructor that sets the `owner` variable to the address of the account that deployed the contract, which is accessed using msg.sender.
Line 11-14:
In line 11 of the contract, we have declared a public function `changeOwner` that takes an address parameter `newOwner`. It first checks that `newOwner` is not the zero address. If `newOwner` is not the zero address, it sets the owner variable to newOwner.
The above contract can be easily exploited by anyone who has access to call it. This is because the `owner` variable is declared as public, which means it can be accessed and modified by anyone, even from outside the contract.
Suppose an attacker calls the `changeOwner` function with an address of their choice, they will be able to change the `owner` of the contract to their address. Following the course of actions, the malicious actor will be able to perform actions on behalf of the owner and potentially steal funds or perform other unintended behavior.
Additionally, the require statement in the `changeOwner` function only checks that the new owner is not the zero address, but it does not check if the caller is authorized to change the owner. This means that any address can call the function and change the owner, even if they are not authorized to do so.
Following are the preventive measures that can be undertaken to ensure that the state variables and functions are set with appropriate visibility specifiers.
Solidity provides many features for developing smart contracts, but it also has significant attack vectors that can be exploited by attackers. Visibility-related issues are among the most common vulnerabilities in Solidity, but they can be prevented by following best practices as shared in this blog. Developers are likely to reduce the likelihood of visibility-related vulnerabilities and make their smart contracts more secure by implementing these standard prevention measures.