The next morning Alex woke up with an unusual feeling. His first contract was already deployed in the blockchain — even if simple, it was alive. And this fact wouldn't let him rest:
— "Yesterday I just said hello to the blockchain..." — he muses thoughtfully, looking at the ceiling. — "But today I want more. Just saying hello is too simple. I want my contract to be interactive!"
He starts studying the Solidity documentation. And suddenly discovers: there are tools for all this. Variables. Functions. Everything like in regular programming — only inside the blockchain.
Alex woke up
Terms
Contract deployment — the process of publishing a smart contract to the blockchain. During deployment, the contract code is written to the blockchain forever, gets a unique address and becomes available for interaction. After deployment, the contract cannot be changed, but its functions can be called.
License — indication of the terms of use for smart contract code. Defines how the code can be used, modified and distributed. Usually specified at the beginning of the file in SPDX format.
Solidity version — specification of which version of the Solidity compiler should be used to compile the contract. Different versions may have different syntax and capabilities.
Import — connecting external libraries or contracts to the current contract. Allows using ready-made tested solutions and not writing code from scratch.
Structure (struct) — a custom data type that groups several related variables under one name. For example, a User structure can contain a user's name, age and address.
Enumeration (enum) — a custom data type with a limited set of named values. For example, order status can only be "new", "processed" or "shipped".
Event — a way to notify external applications that something important has happened in the contract. Events are recorded in blockchain logs and can be tracked.
Modifier — a special construct that allows adding checks or restrictions to functions. Used for access control and condition validation.
Constructor — a special function that executes only once when creating a contract. Used to initialize state variables and set initial parameters.
Smart contract structure
A smart contract is similar to a class in an object-oriented programming language. It represents a set of data and functions — actions capable of working with data. Usually functions and data in one smart contract are logically related. For example, a smart contract can track user balance or manage a counter. One task — one smart contract.
A smart contract has the following structure:
License
Solidity version
Imports
Contract declaration
Declaration of structures, enumerations, events, modifiers
Variables
Constructor
Functions
Complex smart contract
Next, we'll examine each element of the smart contract structure.
License
The license defines how the smart contract can be used. For example, the MIT license allows using code without restrictions, while the GPL license requires that code created based on this code also be open. Smart contracts usually have an MIT license.
Solidity
// SPDX-License-Identifier: MIT
Solidity version
The Solidity version defines what capabilities and syntax will be available in the code.
Solidity
pragmasolidity ^0.8.0;
Imports
Connecting libraries allows using ready-made functions and structures that have already been tested and verified.
Contract declaration sets the name of the smart contract.
Solidity
contractMyContract{
// Contract code
}
Declaration of structures, enumerations, events, modifiers
Structures, enumerations and events define data types that can be used in the contract.
Structures group logically related data into one type.
Enumerations allow creating a custom data type with a limited set of named options. For example, user status can only be "active", "blocked" or "deleted" — no other values are possible.
Events are used to notify the external world about events that have occurred.
Solidity
// SPDX-License-Identifier: MIT
pragmasolidity ^0.8.0;
contractSimpleStorage{
// Structure storing user ID, name and status
structUser {
uint256 id;
string name;
UserStatus status;
}
// Enumeration of user statuses
enumUserStatus {
ACTIVE,
INACTIVE,
BANNED
}
// Event notifying that a user changed their name
eventNameChanged(uint256 id, string name);
...
}
Custom modifiers are used to restrict access to smart contract functions. We can define who can call a function and what actions can be performed with it.
Solidity
// SPDX-License-Identifier: MIT
pragmasolidity ^0.8.0;
contractSimpleStorage{
...
// Modifier restricting access to function only for contract owner
modifieronlyOwner() {
require(msg.sender== owner, "Only owner can call this function");
_;
}
// Modifier restricting access to function only for active users
modifieronlyActive() {
require(user.status == UserStatus.ACTIVE, "User is not active");
_;
}
...
}
Custom modifiers can be specified in function declaration to control who can call it.
Variables
Variables are needed to store data in the smart contract. They can be public, private or internal.
Depending on the visibility type, variables may be accessible for reading from outside, inside the contract or only inside its functions.
Important:public variable doesn't mean it can be changed from outside! This declaration only creates a getter — a function for reading the variable from outside. To change it, you need to assign a new value to the variable in a function.
Functions
Functions are actions that a smart contract can perform. They can be public, private or internal.
Depending on the visibility type, functions may be accessible or inaccessible for calling from outside. For example, private functions are accessible for calling only inside another function of the current smart contract, they cannot be called from outside. public functions can be called by other smart contracts or users in a transaction.
Constructor
A constructor is a special function that is called when creating a smart contract. It's used to initialize variables.
Solidity
// SPDX-License-Identifier: MIT
pragmasolidity ^0.8.0;
contractSimpleStorage{
addresspublic owner;
...
constructor() {
// Put the address of the user who created the contract into the owner variable
owner =msg.sender;
}
...
}
Practical assignment
Alex studied the smart contract structure and decided to create his own contract for user management. But when he was writing code, his younger brother decided to "help" and mixed up all parts of the contract! Now the license is in the middle, functions are at the beginning, and variables are scattered throughout the file.
— "The compiler doesn't understand my code! Need to arrange all parts in the correct order!" — Alex exclaimed in panic.
Help Alex restore the correct smart contract structure.