Introduction to Function Visibility in Solidity

Here's a detailed thread on Function Visibility in Solidity.

Understanding visibility is key to writing secure and efficient smart contracts.

Let's dive in!

In Solidity, function visibility determines who can access and call the function. Solidity offers four types of visibility specifiers: public, external, internal, and private. Each serves a specific purpose, and choosing the right one can enhance both security and functionality. Let's break down each one!


2/ public Visibility

  • What it is: Functions marked as public can be accessed both externally (outside the contract) and internally (within the contract and derived contracts).

  • Use Cases: Use public for functions that need to be accessible to other contracts, users, or off-chain interactions (like reading data).

  • Gas Cost Note: Public functions create a "getter" function when used with a state variable.

Example:

uint public data; // This variable is accessible from outside as a getter function is created.
function setData(uint _data) public {
    data = _data;
}

3/ external Visibility

  • What it is: external functions can be called from outside the contract but not from within. If accessed internally, this.functionName() must be used, which can be less gas-efficient.

  • Use Cases: Use external for functions primarily meant for external contract or user calls, especially if they don’t need to interact with internal functions.

  • Gas Efficiency: external is often cheaper than public for large calldata arrays since it saves gas on internal calls.

Example:

function updateData(uint _data) external {
    data = _data;
}

4/ internal Visibility

  • What it is: internal functions are accessible only within the contract and by derived contracts. They’re not accessible from external calls.

  • Use Cases: Use internal for helper functions that are only meant for the contract itself or inherited contracts. They are ideal for reusable logic within a contract family.

Example:

function _calculate(uint a, uint b) internal pure returns (uint) {
    return a + b;
}

5/ private Visibility

  • What it is: private functions are the most restrictive—they’re only accessible within the contract in which they are defined, not even in derived contracts.

  • Use Cases: Use private for functions that should only be available within the contract and contain sensitive or confidential logic.

Example:

function _generateSecret() private view returns (uint) {
    return uint(keccak256(abi.encodePacked(block.timestamp, msg.sender)));
}

6/ Choosing the Right Visibility

  • Security: Use the least permissive visibility whenever possible. If a function doesn’t need to be accessed externally, avoid public or external.

  • Gas Optimization: external functions are often cheaper for larger calldata arrays, while internal functions save gas on internal calls compared to public.


7/ State Variable Visibility

  • Public Variables: Solidity automatically generates a getter function for public state variables. This can save effort in writing accessor functions but should be used cautiously to avoid unnecessary exposure.

  • Private/Internal Variables: Both private and internal restrict external access. Use private if a variable should be accessible only within the same contract.


8/ Practical Example

Here’s a contract demonstrating each type of visibility:

pragma solidity ^0.8.0;

contract VisibilityExample {
    uint public publicData = 1; // Public variable with automatic getter
    uint private privateData = 2; // Private variable, no automatic getter

    // Public function
    function updatePublicData(uint _data) public {
        publicData = _data;
    }

    // External function
    function updateExternalData(uint _data) external {
        publicData = _data;
    }

    // Internal function
    function _internalFunction() internal pure returns (string memory) {
        return "Internal";
    }

    // Private function
    function _privateFunction() private pure returns (string memory) {
        return "Private";
    }
}

9/ Key Takeaways

  • Use public and external cautiously to avoid exposing unnecessary data or functionality.

  • Prefer internal and private when possible to improve security and limit access.

  • Select visibility based on who needs access to the function or data—only open access if required.


10/ Wrapping Up

Mastering function visibility in Solidity is fundamental to writing secure, efficient contracts. Carefully consider access requirements for each function, and use the most restrictive visibility that meets your needs.


Happy coding, and remember: Security starts with visibility!

0
Subscribe to my newsletter

Read articles from Abraham Dominic Newton directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Abraham Dominic Newton
Abraham Dominic Newton

Hi, I’m Abraham Dominic Newton an ardent Front-End Developer with the brand name; Abraham Cyber Tech. I'm passionate about using codes to solve real life problems; thereby creating a sustainable world for all. 💻 I’m currently an Ingressive for Good Student Ambassador for Federal University Wukari, Taraba State, Nigeria. 👀 I’m interested in Cyber Security & Python Language 💻 ... 🌱 I’m currently learning Front-end & Python ... 💞️I’m looking to collaborate on different projects on Website Development, Python project particularly Front-End & Backend. 💬 Ask me anything about Ingressive for Good ⚡ Fun fact: I love participating in changemaking activities