`external` vs `public` best practices

  • Apart from the public modifier Ethereum introduces the external one. Both may be called outside of the contract and inside (the later one by this.f() pattern). Moreover, according to the docs:

    External functions are sometimes more efficient when they receive large arrays of data.

    but there is no further information what does actually sometimes mean and if this efficiency gain is held also for internal calls.

    What are the best practices of using external vs public keyword? Are there any patterns or recommendations?

  • Tjaden Hess

    Tjaden Hess Correct answer

    4 years ago

    A simple example demonstrating this effect looks like this:

    pragma solidity^0.4.12;
    
    contract Test {
        function test(uint[20] a) public returns (uint){
             return a[10]*2;
        }
    
        function test2(uint[20] a) external returns (uint){
             return a[10]*2;
        }
    }
    

    Calling each function, we can see that the public function uses 496 gas, while the external function uses only 261.

    The difference is because in public functions, Solidity immediately copies array arguments to memory, while external functions can read directly from calldata. Memory allocation is expensive, whereas reading from calldata is cheap.

    The reason that public functions need to write all of the arguments to memory is that public functions may be called internally, which is actually an entirely different process than external calls. Internal calls are executed via jumps in the code, and array arguments are passed internally by pointers to memory. Thus, when the compiler generates the code for an internal function, that function expects its arguments to be located in memory.

    For external functions, the compiler doesn't need to allow internal calls, and so it allows arguments to be read directly from calldata, saving the copying step.

    As for best practices, you should use external if you expect that the function will only ever be called externally, and use public if you need to call the function internally. It almost never makes sense to use the this.f() pattern, as this requires a real CALL to be executed, which is expensive. Also, passing arrays via this method would be far more expensive than passing them internally.

    You will essentially see performance benefits with external any time you are only calling a function externally, and passing in large arrays.

    Examples to differentiate:

    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

    Excellent and a very helpful answer. Thx Tjaden!

    If we are designing a public interface for contracts and other people will rely on the interface (think EIPs), then should we always be using `external`?

    ^ This should be added to the Solidity docs.

    Something wrong with your answer: http://joxi.ru/Drlz51Xc4MDGX2

    Also, external functions cannot be overridden in derived contracts.

    @Anron Pegov I am reporting the execution gas cost, not the total. i.e. only the gas cost incurred by actually running the contract, not sending the transaction to it

    Should in this case `function name() public view returns (string)` of ERC-20 Token Standard be declared as external to save some gas? Because it seems like the function `name()` isn't called internally.

    That function doesn't have arguments, so there's nothing to copy. So the advantage of using `external` over `public` fades away.

    Solidity 0.6.9 now allows `calldata` to be used for any variable or parameter, even in `internal` functions.

    Beginner here, thanks a few Qs popup: 1) Would it be better to have a `external` and `internal` function rather than `public` if you need to call on both then? 2) As the commenter above said is this now irrelevant since `0.6.9`? 3) Does adding `view` further improve perf?

    @TjadenHess Would you please check the latest answer below and help explain if your current explanation still holds. Solidity is changing fast and some of the mechanisms might have been redesigned.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM

Tags used