Skip to content

What Is the Difference Between Internal and Private Specifiers in Solidity?

What Is the Difference Between Internal and Private Specifiers in Solidity

Understanding visibility specifiers in Solidity

In Solidity, visibility specifiers are crucial for controlling access to functions and variables within smart contracts. They determine who can access these elements and from where.

1. Public visibility

  • Public functions or variables can be accessed from outside the contract as well as from within.
  • These are commonly used for functions that need to be accessible externally, such as entry points to the contract.

2. Private visibility

  • Private functions or variables are only accessible from within the contract that defines them.
  • They cannot be accessed from outside the contract or from derived contracts.

3. Internal visibility

  • Internal functions or variables are accessible from within the contract as well as from derived contracts.
  • They cannot be accessed externally, i.e., outside the contract hierarchy.

🔥 Check this course out: Build Hogwarts Sorting Hat dApp on Polygon

The difference between internal and private

To understand the difference between internal and private specifiers, let’s consider a metaphor of a house and its rooms:

1. Private: The room locked inside

  • When a function or variable is marked as private, it’s like a room in your house that has a lock on the door.
  • Only you, the owner of the house (or the contract), can access this room. It’s entirely hidden from the outside world.
  • Even if your friends (or derived contracts) are visiting your house, they can’t enter this room because it’s locked and exclusive to you.

2. Internal: The family room

  • Internal functions or variables, on the other hand, are like the family room in your house.
  • This room is accessible to all members of your family (or derived contracts). They can freely enter and use the facilities inside.
  • However, outsiders (external contracts) cannot access this room. It’s limited to the family (or derived contracts) only.

Private visibility specifier example

Here’s the coding example for the private visibility specifier.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract House {
    uint internal myInternalNumber = 20;
    
    function getInternalNumber() public view returns(uint) {
        return myInternalNumber;
    }
}

contract MyDerivedHouse is House {
    function getInternalNumberFromDerived() public view returns(uint) {
        // Can access the internal variable from the parent contract
        return myInternalNumber;
    }
}

Explanation

  • In this example, myInternalNumber is declared as internal in the House contract.
  • The getInternalNumber() function allows external access to retrieve the value of myInternalNumber.
  • MyDerivedHouse is a contract that inherits from House.
  • The getInternalNumberFromDerived() function demonstrates how the internal variable from the parent contract can be accessed within the derived contract.

🔥 Check this course out: Build a One Piece Personality dApp With Solidity

Internal visibility specifier example

Here’s the coding example for the internal visibility specifier.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract House {
    uint private myPrivateNumber = 10;
    
    function getPrivateNumber() public view returns(uint) {
        return myPrivateNumber;
    }
}

contract ExternalContract {
    House private houseInstance;
    
    constructor(address _houseAddress) {
        houseInstance = House(_houseAddress);
    }
    
    function tryAccessPrivate() public view returns(uint) {
        // Cannot access the private variable directly
        // Results in a compilation error
        // return houseInstance.myPrivateNumber;
        
        // Accessing via public getter function
        return houseInstance.getPrivateNumber();
    }
}

Explanation

  • Here, myPrivateNumber is declared as private in the House contract, making it inaccessible from outside the contract.
  • The getPrivateNumber() function provides a way to access the private variable’s value externally.
  • ExternalContract demonstrates an attempt to directly access the private variable, which results in a compilation error.
  • Accessing the private variable indirectly through the public getter function (getPrivateNumber()) is the proper way to retrieve its value.

Combined example

Let’s illustrate these concepts with Solidity code:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract House {
    uint private myPrivateNumber = 10;
    uint internal myInternalNumber = 20;

    function getPrivateNumber() public view returns(uint) {
        return myPrivateNumber;
    }

    function getInternalNumber() public view returns(uint) {
        return myInternalNumber;
    }
}

contract MyDerivedHouse is House {
    function getNumbers() public view returns(uint) {
        // Can access internal variable only from the parent contract
        // as it's derived from it.
        return (myInternalNumber);
    }
}

In this example:

  • myPrivateNumber is private to the House contract. It cannot be accessed directly from MyDerivedHouse.
  • myInternalNumber is accessible within the House contract and its derived contracts, such as MyDerivedHouse.

🔥 Check this course out: Create Your Own Ethereum Token in Just 30 Mins

Conclusion

In summary, while both internal and private specifiers restrict access to variables and functions in Solidity, they differ in their scope of accessibility. Private restricts access solely to the defining contract, akin to a locked room, while internal extends that access to derived contracts, resembling a family room open to all family members. Understanding these nuances is crucial for designing secure and efficient smart contracts.

Try it out, ask us questions, and tell us how it went by tagging Metaschool on Social Media.

Follow us on –

🔮Twitter – https://twitter.com/0xmetaschool

🔗LinkedIn – https://www.linkedin.com/company/0xmetaschool/