Welcome to lesson 7!
Ever heard of visibility in regards to cryptocurrency? If the answer is no, then you have come to the right place, but if the answer is yes, then you should still stay and check out our video because we take you through everything that you need to know about visibility! To find out more check out our video below and read the article:
In this lesson, we will have a look at Visibility of Variables and Functions. There are four types of visibilities for functions and state variables. If you’re not familiar with the term visibility, it simply declares what level of visibility a variable of function has within and outside the contract. We will have a look of how it works in the example later, but now let’s explore what visibilities functions and state variables have.
So functions can be specified as being:
- private- where the default is public
For state variables external is not possible and the default is internal.
Now let’s have a look at external visibility type. External functions are part of a contract interface, which means they can be called from other contracts and via transactions. An external function ’f’ cannot be called by simply typing ‘f() ’ you have to use ‘this.f()’ which works since Solidity makes an actual call by sending a message to a contract which makes it look like an external call.
External functions are sometimes more efficient when we receive large arrays of data. In this example, we have two identical functions which return a ‘unit’ array. In this case, a public function uses 496 gas to execute in comparison to only 261 gas for external function.
So if your function is expected to receive large arrays of data and is only expected to be used by external contracts, I would recommend using external visibility.
Public functions are part of the contract interface and can be either called internally via messages or by any other contract. It’s the simplest type of all and it’s visible within and outside the contract for everybody.
Internal functions and state variables can only be accessed internally which means that it can only be accessed from within the current contract or contracts deriving from it, without using ‘this’ like in external functions.
Internal can be compared to protected visibility in object-oriented languages such as Java if you are familiar with it.
Private functions and state variables are only visible for the contract that they are defined in and not in any derived contracts.
Now all of this can be quite confusing so let’s have a look at this example.
Now let’s have a look at what this does. So we have a contract chatty with several state variables and functions. State variables are simple strings which have different visibility types so public, private, and internal. Then we have several functions which all do the same thing, they simply return a string or to be more exact a bytes array but they all have different visibility types. So public, internal, private, and external.
Now here below we have this function chat which accepts a contract instance of the same Chatty contract. So let’s see how this behaves and we will explore it by seeing which messages complier throws at us. So in this case the complier is not complaining about anything, except that the function state mutability can be restricted to pure so we can do that and we call the helloPublic() function from within the chat function and the compiler does not complain. So this works just fine because public functions are visible internally so no problems here, and also public functions are visible by other contract instances so buddy.helloPublic() also works just fine.
Now let’s have a look at helloInternal(). This also will work, and buddy.helloInternal() will not work since buddy is another contract instance. We can see what the compiler is saying and it’s saying that helloInternal is not found or not visible after argument-dependent lookup in contract Chatty.
Now let’s have a look at private visibility for functions, so let’s uncomment this code, and helloPrivate() will work but buddy.helloPrivate() will not work again since buddy once again is another contract instance.
What about helloExternal()? This is a more interesting example, as you can see there are three calls.
So the first one helloExternal() surprisingly does not work so as I said here previously external cannot be called internally. So simply calling f() does not work and we have to use this.f().
As you can see, helloExternal() does not work since this is an internal call but buddy.helloExternal() works because it’s another contract instance and also this.helloExternal() also works because we retrieve instance of current via a message.
So this is quite surprising but remember that the purpose of external visibility is to be used by other contracts.
Now let’s have a look at the strings we declared, so buddy.publicStr will work but buddy.privateStr will not work since buddy is another instance and if we comment this out the complier will also complain about internal string and will also throw a message that internal string is not visible once again this is because buddy is another contract instance and internal strings are only visible to the same contract instance in which they were declared.
So this could be some new syntax for you but basically, here we have a new contract which inherits from contract Chatty, this is the same as in Java for example where we inherit a class from another class.
So let’s see how this behaves:
Here we use helloPublic() function from Chatty contract and it works just fine, as you can see helloInternal() will also work because internal visibility is visible for derived contracts too.
Chatty.helloPrivate() will not work because private is only visible for the contract that they are defined in, and hello external will also not work because it can only be called from external contracts instances. Now public strings will be visible obviously, an internal string will be visible but sorry this is a wrong example, it should be like this Chatty.internalStr and this will work.
Also, we have to remove this, so this works, and then let’s see whether a private works and it will not so let’s type Chatty.privateStr and this will not work because private is only visible for the contract they are defined in.
So this is it for this lesson, in the next lesson we will have a look at ERC20 tokens what they are, how they work and that will prepare us to make an actual ERC20 token by ourselves.