solidity logo

Question: What are the types of Visibility Modifiers in Solidity? Please explain each with use cases.

In Solidity, visibility modifiers are used to control the accessibility of functions and variables. There are four types of visibility modifiers: public, external, internal, and private. Below is a detailed explanation of each modifier, along with examples and typical use cases.


1. public

Definition:
A function or variable declared as public can be accessed both inside and outside of the contract. This means that internal contract functions, external contracts, and even transactions from outside the blockchain can all call public functions or access public variables.

Use Cases:

  • When you want to expose certain functionality or state to the outside world.
  • Commonly used for public query functions or for setting contract state variables.

Example:

pragma solidity ^0.8.0;

contract BalanceReader {
    mapping(address => uint) public balances;

    function setBalance(address _address, uint _balance) public {
        balances[_address] = _balance;
    }
}

Here, the balances mapping is declared as public, meaning anyone can directly query a user’s balance by calling:

BalanceReaderInstance.balances(userAddress);

2. external

Definition:
A function declared as external can only be called from outside the contract, via an external transaction or call. It cannot be invoked internally (from within the same contract) without using the special keyword this. Note that variables cannot be declared as external.

Use Cases:

  • Used for functions intended to serve as external APIs.
  • Commonly used for functions that receive tokens or process external interactions.

Example:

pragma solidity ^0.8.0;

contract TokenReceiver {
    function receiveTokens(address _token, uint _amount) external {
        // Logic for receiving tokens
    }
}

Here, receiveTokens is marked as external, ensuring that it can only be called from outside the contract.


3. internal

Definition:
A function or variable declared as internal can be accessed only within the contract itself and by derived (inherited) contracts. It cannot be accessed from outside.

Use Cases:

  • Ideal for hiding implementation details.
  • Suitable for logic or variables that child contracts need to use, but should not be exposed publicly.

Example:

pragma solidity ^0.8.0;

contract UserManagement {
    mapping(address => uint) internal userLevels;

    function updateUserLevel(address _user, uint _level) internal {
        userLevels[_user] = _level;
    }
}

Here, both userLevels and updateUserLevel are internal, meaning only UserManagement or its derived contracts can access them.


4. private

Definition:
A function or variable declared as private can only be accessed within the contract in which it is defined. Even derived (inherited) contracts cannot access private members.

Use Cases:

  • Suitable for hiding sensitive data or critical logic.
  • Used when you want complete encapsulation with no exposure to derived contracts.

Example:

pragma solidity ^0.8.0;

contract InternalState {
    uint private internalCounter;

    function incrementInternalCounter() private {
        internalCounter++;
    }
}

Here, both internalCounter and incrementInternalCounter are private, meaning they can only be used within InternalState itself.


Summary Table

ModifierAccessible Inside ContractAccessible by Derived ContractsAccessible Externally
public✅ Yes✅ Yes✅ Yes
external❌ No (except via this)❌ No✅ Yes
internal✅ Yes✅ Yes❌ No
private✅ Yes❌ No❌ No

Subscribe for New Articles!

Leave a Comment

Your email address will not be published. Required fields are marked *