Learn Solidity: Variables (Part 1)

Start writing smart contracts on Ethereum

wissal haji
Better Programming

--

neon display of strings of numbers
Photo by Photos Hobby on Unsplash

Welcome to the second article in the Learn Solidity series. If you haven’t read the first one, I highly recommend that you do in order to set up your development environment and write and deploy your first contract.
In this article, we will have a look at variables in Solidity, their types, how they are stored, and how you can use them.

In Solidity we have two types of variables :

State variables

These variables are declared outside of functions (like the attributes of a class) and are stored permanently in the Ethereum blockchain, more specifically in the storage Merkle Patricia tree, which is part of the information that forms the state of an account (that’s why we call it a state variable).

diagram of Merkle Patricia tree
Ethereum Merkle Patricia Trees : source

You can find more information about the way data is stored in Ethereum blockchain in this article.

State variables can be initialized when they are declared and can have the following visibility:

  • private: The state variable is only visible for the contract where it’s defined.
  • public: The state variable can be accessed also from outside the contract where it’s defined since the compiler will automatically create a getter function with the same name as the variable.
  • internal: The state variable is visible for the contract where it’s defined and all other contracts that inherit from it.

The visibility specifier is given after the type of the state variable, and if it’s not specified, the state variable will be considered as internal.

Local variables

These are the variables that are declared inside functions and have a lifetime limited to the scope where they were declared in.

As in any other language, we have primitive types and complex types. Primitive types are always passed by value when used as function arguments or in an assignment, while complex types such as arrays and structs are passed by reference.

Primitive data types

table of Solidity elementary data types and what each may contain
Solidity elementary types

More about the address type:

  • Address Literals: Hexadecimal literals that pass the address checksum test, for example 0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF are of address payable type.
  • Type conversions: address payable can be implicitly converted to a simple address, which means you can assign an address payable to an address without explicitly converting it.

Explicit conversion to address is allowed for integers, integer literals, and bytes20 using the following syntax : address(x). This conversion will result in an address payable type.

  • Members of addresses: The two important members of address type are balance, which allows the querying of the balance of an address, and transfer, which allows the sending of Ether (in units of wei) to a payable address.
  • Contracts and the address type:
    You can explicitly convert contracts to an address type using the previous syntax we have seen: address(x), where x in this case will be an instance of the contract. This will result in an address payable if the contract defines a receive or a payable fallback function (we will talk about functions in more detail later) or an address if it doesn’t, in which case if you want it to be payable, you will have to use payable(address(x)).

Globally Available Variables

There are special variables which always exist in the global namespace and are mainly used to provide information about the blockchain.

We can split these variables in three categories:

  1. Block properties
table of block types and what each main contain

2. Message properties

table of message types and what each may contain

3. Transaction properties

table of transaction types and what each may contain

The two properties that we will heavily use are msg.sender, which can provide us with the address of the sender and thus makes it possible to store the address of the contract’s owner, and msg.value to get the amount sent with the message.

Let’s have an example where we store the address of the contract creator and modify the HelloWorldContract such that if the message is sent by the creator we greet them with “hello Daddy;” otherwise, we greet the sender with “hello world.”

If you deploy the contract as we have seen in the previous post, and then click on sayHell, you will get “hello Daddy” since the address you have used to deploy the contract is the same as that you have used to call that function.

Let’s change the account and call the function again. In order to change your account, you need to click on the dropdown list on the Account section and choose a different address.

If you call sayHello this time, you should get “hello world.”
Great, we have learned something.

Before leaving you with an exercise to apply what you have learned, I would like to mention that the this key word in Solidity references the current contract’s type and is explicitly convertible to an address, as we have seen with contract instances.

I will leave you now with the following tasks as an exercise:

  • Return address of the contract.
  • Return address of the contract’s owner.
  • Return address of the sender.
  • Return balance of the contract.
  • Return balance of the contract’s owner (only if the sender is the owner).
  • Return balance of the sender.

You can find the solution on GitHub.

I hope that you have enjoyed this article. Next time we will talk about the complex types and reveal the mystery behind the memory key word that I have used next to string in previous code. So stick around if you want to learn more, and see you in the next article.

--

--