DEV Community

Cover image for How to understand visibility in Solidity.
Sage
Sage

Posted on

How to understand visibility in Solidity.

In solidity, visibility specifies how a function or state variable in a contract can be accessed by other contracts & external accounts.
There are four(4) levels of visibility in solidity, and they are - private, public, internal, external.

When writing solidity you specify the visibility after the type for state variables(or global variables) and between the function parameters and return types.

address public holder; // type - visibility - varaiableName
function getBalance() private view returns(uint)//parameters - visibillity-returns
Enter fullscreen mode Exit fullscreen mode

PRIVATE

Variables and functions declared as private can only be accessed inside the contract in which they are created. This means that they cannot be accessed from other contracts including sub-contracts.

contract _Account {
    address _holder;

    constructor() payable {
        _holder = msg.sender;
    }

    function getHolder() private view returns (address) {
        return _holder;
    }
}

contract _Checking is _Account {
    function testGetHolder() public view returns (address) {
    return getHolder(); // DeclarationError: Undeclared identifier
}
Enter fullscreen mode Exit fullscreen mode

When we try to access the private function "getHolder" from a child contract we get an error. It can only be accessed in the contract where it was created.

PUBLIC

When a function is declared as public in a contract, this means it can be accessed from within the contract, by contracts that inherit from it and by external accounts.

contract _Account {
    // Function is declared as public
    function checkBalance() public view returns (uint) {
        return address(this).balance;
    }
}

contract _Checking is _Account {
    function testCheckBalance() public view returns (address) {
        return checkBalance(); // We can access it from child contracts.
    }        
}
Enter fullscreen mode Exit fullscreen mode

In this case the function is public so we can call this function from within child contracts, or external accounts.

INTERNAL

Internal visibility means the variable or function declared as internal can be accessed from within the contract and sub contracts only.

contract _Account {
    // Function is declared as internal
    function checkBalance() internal view returns (uint) {
        return address(this).balance;
    }
}

contract _Checking is _Account {
    function testCheckBalance() public view returns (uint) {
        return checkContractBalance(); // We can access it from a child contract!
    }
}

contract TestInternal {
    _Account newAccount = new _Account();
  function testcheckContractBalance() public view returns (uint) {
    return newAccount.checkContractBalance();// TypeError: Member "checkContractBalance" not found or not visible...
  }    
}
Enter fullscreen mode Exit fullscreen mode

It is possible to access functions declared as internal from within the contract they are declared and from sub-contracts but we can't access them from external contracts. Internal visibility is the default visibility for state variables.

EXTERNAL

Functions declared as external are still a part of the contract but they cannot be called from within the contract without using this keyword. They however can be called from external accounts and contracts. State variables cannot be declared as external, it won't compile.

contract _Account {   
    constructor() payable {}

    function checkContractBalance() external view returns (uint) {
        return address(this).balance;
    }
    function testcheckContractBalance() public view returns (uint) {
        uint contractBalance = this.checkContractBalance();// Using this keyword compiles without error!
        return checkContractBalance();// DeclarationError: Undeclared identifier
    }    
}
Enter fullscreen mode Exit fullscreen mode

We are able to access the external function checkContractBalance from within the contract using this keyword, but we get an error when we remove it.

It is important to note that regardless of the visibility, functions and variables are actually visible to everyone who cares to look, so it is meant to visibility from other contracts and external accounts.

Top comments (0)