60

Currently reading solidity documentation: https://solidity.readthedocs.io/en/develop/types.html#function-types

By default, function types are internal, so the internal keyword can be omitted. In contrast, contract functions themselves are public by default, only when used as the name of a type, the default is internal.

This does not make sense to me. How can a function be internal and public at the same time?

What does this part mean?

only when used as the name of a type

I know internal means functions can only be called within the contract and external can be called outside of the contract. So to me, internal is private and external is public but the documentation makes it sound like it can be public and internal at the same time?

So what is the difference, if any, between internal/external and public/private in regards to functions and how can the default be both internal and public at the same time?

2
  • For an explanation of contract functions, not function types, you probably want to check out this part of the doc: solidity.readthedocs.io/en/develop/…
    – willjgriff
    Jan 15, 2018 at 10:02
  • 1
    +1 very good question. Upon reading that exact same text in the docs I was puzzled too :) (You should mark @dragosb his answer as the one that answered your question.) Feb 24, 2018 at 16:32

5 Answers 5

74

The paragraph specifically mentions that only function types are by default internal, and contract functions are by default public, even though I agree the wording is a little bit confusing. It says nowhere that they are at the same time both public and internal.

I think that there is some confusion to what a function type is. The same way you specify the type for a 256 int variable with the keyword uint256, you can also specify the type of a variable that will hold a function. The only difference is that this type declaration is a little more complex since functions are more complex and it looks like this:

function (param types) {internal|external} [pure|constant|view|payable] [returns (return types)] varName;

You can then assign to the variable varName a function that has the same type that you defined. This is only possible inside another function.

As a very simple example:

contract Example{
    function(uint256) returns (uint256) varName;

    function simpleFunction(uint256 parameter) returns (uint256){
        return parameter;
    }

    function test(){
        varName = simpleFunction;
    }
}

Where varName is the variable of function type, while simpleFunction and test are normal contract functions

Just so you have a simple definition for all those access classifiers:

  • public - all can access
  • external - Cannot be accessed internally, only externally
  • internal - only this contract and contracts deriving from it can access
  • private - can be accessed only from this contract

As you can notice private is a subset of internal and external is a subset of public.

1
  • this can be great if you can add details about the dual visibility of the same function
    – Aniket
    Nov 21, 2018 at 5:55
8

How can a function be internal and public at the same time?

Imagine you have

function F(function (uint) G) { ... }

F and G are the different things:

  • F is a function.
  • G is a function type.

By default functions are public. That means everyone can call F.
Function types are internal if no keyword specified. In code above, it means that F can be called with functions from your contract or library only. No one can pass function from some other contract. Official documentation has some great examples.

What does this part mean?

function G() {  }
function F(function (uint) G) { ... }

In first line G is public, in second it's internal.

2
  • Note that though this is a good example of the contextual distinction between the two defaults, function F would be a completely useless public function as an externally owned account would never be able to pass an internal function "G" into the call, as it cannot be defined outside of the context of the current contract and therefore never executed. Apr 15, 2022 at 1:05
  • And in fact will not compile with the error "TypeError: Internal type is not allowed for public or external functions. --> contracts/Test.sol..." Apr 15, 2022 at 1:48
3

Internal- this contract and derived contracts

external- can be accessed by this contract using this keyword and can be accessed externally

public - functions all public by default

private- only this contract

1

Access types:

public : can be used when contract was deployed, can be used in inherited contract

external : can be used when contract was deployed , can NOT be used in inherited contract

internal : can NOT be used when contract was deployed , can be used in inherited contract

private : can NOT be used when contract was deployed, can NOT be used in inherited contract

0

The access specifiers in Solidity control the visibility and accessibility of functions and state variables

  1. public

    Functions declared as public can be called from within the contract, derived contracts, and other contracts which have an instance of this contract. Public functions are part of the contract's interface and can also be called externally by users, other contracts, or through web3 platforms.

    State variables declared as public are automatically provided with getter functions that are accessible from within the contract, derived contracts, and externally.

    Example:

    function doSomething() public {
        // Implementation
    }
    
    uint256 public value;
    
  2. private

    Functions declared as private can only be called from within the contract they are defined in. They are not accessible from derived contracts or other contracts.

    State variables declared as private can only be accessed from within the contract they are defined in, and no getter function is created.

    Example:

    function _doSomethingPrivate() private {
        // Implementation
    }
    
    uint256 private secretValue;
    
  3. internal

    Functions declared as internal can be called from within the contract and derived contracts (through inheritance). They are not accessible from other contracts.

    State variables declared as internal can be accessed from within the contract and derived contracts, and no getter function is created.

    Example:

    function _doSomethingInternal() internal {
        // Implementation
    }
    
    uint256 internal internalValue;
    
  4. external

    Functions declared as external can only be called from other contracts and cannot be called from within the contract they are defined in (unless using this.functionName() syntax). They are part of the contract's interface and can be called externally by users, other contracts, or through web3 platforms.

    State variables cannot be declared as external.

    Example:

    function doSomethingExternal() external {
        // Implementation
    }
    

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.