• Sun. Sep 25th, 2022

Learn Solidity lesson 17. The structure of a smart contract.


Aug 9, 2022 ,

In this chapter we will see the structure of a smart contract, with all its possibilities. Smart contract files have a .sol extension and can have one or more contracts declared within them.

We have already seen that the declaration of a contract is done by the sentence contract, but there are still two unexplored possibilities: libraries and interfaces.

Libraries look like contracts, but do not have state variables. It’s a method-only type of contract, meant to be used by other contracts, not used by itself.

Interfaces are like contract patterns. State variables and methods are defined, but without any implementation. It’s like writing a contract with empty functions, to be implemented in the future.

We will study more about libraries and interfaces in future lessons. For now, we will only work with contracts.

Contracts can (and often do) have the following items defined within them.

  • state variables
  • functions
  • modifiers
  • events
  • errors
  • structures
  • enums

We have already seen some of these items in previous lessons, while others are still unknown in this course. We’ll talk briefly about each item, even the ones we’ve already seen.

State Variables

When we want to store some information on the blockchain, we need to reserve a dedicated space for that data. We do this through state variables. They are variables whose value is stored permanently, as in a database.

Such variables are statically typed, that is, their type must be declared at the time of creation and cannot be modified.

The types available in Solidity are: int (integers), uint (unsigned integers), bool (booleans), bytes, address, strings, arrays and mappings.

Some of these types have sub-divisions, such as integers, ranging from int8 to int256. The largest value is always 32 bytes because storage is a key/value data structure where both the key and the value are 32 bytes long.

Solidity has no undefined or null values. Every variable is initialized at the time of its declaration; when its value is not explicitly declared, it is given a default value. The default value of a number is 0, a string is an empty string and a boolean is false.

It is not possible to create new state variables after deployment. Variables created within functions will either be created in memory or will be pointers to state variables that already exist in storage.


Functions play a fundamental and special role in Ethereum. In many programming languages, functions serve as a block of code for reuse, and the same application could be written without using functions. On Ethereum, functions are not just a block of code.

Functions are the gateway to transactions, and their fundamental role is to manipulate state variables. When an account submits a transaction to the blockchain, it must explicitly indicate which function to invoke. If the function is not specified, a default function (fallback) of the contract will be invoked, if it exists.

All contract logic exists within functions, which can be understood as execution blocks. It is not possible, in a transaction, to directly invoke more than one function; it is possible, however, for a function of a contract to invoke another function, either from the same contract or from others.


It is possible to define function modifiers. Modifiers are blocks of reusable code, which can be included in one or more functions. We’ll see how to set and use modifiers in another lesson.

Modifiers are not essential in the writing of smart contracts. They are used when the same piece of code is continuously repeated in the project, thus avoiding duplication.


Events are a way of recording information on the blockchain as a kind of log. External clients can be programmed to monitor the emission of such events and then be informed of any changes in the state of the blockchain.

Events are emitted within functions, but cannot be read by contracts. Once issued, they can only be consulted from outside the EVM. They are recorded in transaction receipts and not in storage. Once emited, they cannot be deleted either.

In addition to being used to notify external clients of changes in the state of the blockchain, events can also be used to store information for a lower price. Logging (emitting) an event costs less gas than changing a state variable in storage.

I hope it is clear that events are defined and emitted by contracts, but cannot be read by contracts. Their function is to interact with the world outside the blockchain.


We often want a transaction to be declined. This can happen, for example, when we require the origin of the transaction to be an authorized account. We have already seen that we can do such a check using the expression require(msg.sender == owner). If the account that sends the transaction is not the owner, the transaction must revert.

At this point, it is possible to identify the reason why the transaction was declined and send this information to the client. This identification can be done using a string, but there is also the possibility of returning a custom error to the client.

To do this, we first define custom errors, which can then be sent to the client if the transaction reverts.

The biggest advantage of returning custom errors is in gas savings. Instead of using the same string several times, it is possible to define custom errors and send these custom errors when the transaction is reverted.

We’ll see more about custom errors in another lesson.


Structures are custom types, a data structure containing several variables, of different types. Structures can also contain other structures.

Before their use, they need to be defined. Once defined, they cannot be changed. We’ve already used structs in previous lessons and will use it again throughout this course.


Enumerables are also user-defined types, however it is an 8-bit fixed-length type. The enumerable is defined as a set of identifiers, which correspond to a positive integer, starting with the number 0.

Enumerables exist only within the contract where they are defined. State variables of enumerable type are written to the blockchain by their integer number, and are converted to the identifier only within the contract.

We already used enumerables in a previous lesson.

Thanks for reading!

Comments and suggestions about this article are welcome.

Any contribution is welcome. www.buymeacoffee.com/jpmorais

Join Coinmonks Telegram Channel and Youtube Channel learn about crypto trading and investing

Also, Read

Learn Solidity lesson 17. The structure of a smart contract. was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.