Back

An Ultimate Guide to Variables in Solidity

An Ultimate Guide to Variables in Solidity

A variable in Solidity is a named storage location that contains data. In a smart contract, data is stored in variables that can later be used or changed by the program. For variables, Solidity supports various data types, including arrays, Booleans, address types, and integers. In this article, we’ll discuss what variables are, what types they may have, what they are used for, etc.

What are Solidity variables used for?

Developers can create more adaptable and dynamic smart contracts that can react to changes in the blockchain environment by using variables. Variables may be explicitly declared with a datatype or may have one inferred from the value that has been assigned to them. Remember that variables declared in smart contract in Solidity are persistent and continue to be stored in the blockchain even after the contract execution is complete. This enables the retrieval of a contract’s state even after it has been put into use, but it also implies that storage space on the blockchain is a finite resource that should be used carefully.

Overview of Data Types in Solidity

A data type in Solidity refers to the type of data that a variable or expression can store or generate. Uint (an unsigned integer), bool (a boolean), and other data types are examples of Solidity datatypes. Before assigning a data type to a variable, you must first understand the data type to work with it. In this section, we’ll go over datatypes in great detail. However, we won’t be writing any code on data types in this section; that will be covered in a different one that explains how to assign data types to variables in Solidity. Let’s begin.

Signed/Unsigned Integers

In the Solidity language, the terms signed and unsigned are utilized to classify integer variables. An integer is a complete number that can be positive, negative, or equal to zero.

Unsigned integers are restricted to holding only positive values or zero. In Solidity, these integers are declared using the uint type, followed by the number of bits designated for storage, for instance, uint256. The number 256 in this example shows that the unsigned integer uses 256 bits for storage, providing a range of values from 0 to 2^256 - 1.

Signed integers, on the other hand, can store both positive and negative values. In Solidity, these integers are declared using the int type, followed by the number of bits designated for storage, for instance, “int256”. The number “256” in this example shows that the signed integer uses 256 bits for storage, providing a range of values from -2^255 to 2^255 - 1.

It’s crucial to select the correct type of integer depending on the intended usage. For example, if the variable is supposed to store only positive values, an unsigned integer should be employed to guarantee that only valid values are stored. On the other hand, if the variable requires the ability to store both positive and negative values, a signed integer should be utilized.

The available types are:

  • Booleans: A boolean data type is used in Solidity to represent truth values, which can be either true or false. The bool data type can be used to declare booleans, and it is frequently employed in conditions to regulate the order of execution in smart contracts.

  • Fixed point numbers: A fixed number, also known as fixed point arithmetic or fixed point decimal, is a type of numerical representation used in computing to represent real numbers with a fixed number of digits after the decimal point. Solidity’s “fixed” type represents fixed point numbers.

  • Addresses: An Ethereum address is represented as a data type called “address” in Solidity. On the Ethereum network, an Ethereum address serves as a distinctive identifier for a contract or external actor, such as a user’s wallet. In smart contracts, addresses can be stored and changed using the “address” data type, a 20-byte value. It comes with a number of built-in features that let you carry out actions on addresses like sending Ether (the Ethereum network’s native cryptocurrency) or calling other contracts.

  • Byte arrays: A dynamic array of bytes is called a byte array, and it is employed in a smart contract to store and manage binary data of variable length. Arrays in other programming languages are similar to byte arrays in that they can store elements of different data types, such as strings or integers, but byte arrays can only store a sequence of bytes. Solidity uses the syntax “bytes name” to declare byte arrays, where “name” is the name of the variable that holds the byte array. The byte array’s length is determined at runtime based on the data contained in the array, not by the declaration, which omits this information.

  • Enums: A custom type in Solidity can be defined using enums, which are lists of named values. They help represent a limited number of options, such as the status of a transaction or contract. The ‘enum’ keyword is used to define enums, followed by the enum’s name and a list of named values, separated by commas.

  • Functions: A function is a named section of code that carries out a particular task. Smart contracts are simpler to create and maintain because functions are used for packaging logic and making it reusable. Solidity functions can be used to communicate with other smart contracts, carry out calculations and update the contract’s state, or simply return information to the caller. A fundamental component of smart contracts, functions allow programmers to create elaborate, reusable logic that can be run on the Ethereum blockchain.

Solidity variable types and explanations:

There are three types of variables in Solidity: local, state, and global variables. These variables are used in a Solidity smart contract that integrates with the Ethereum network, and let’s get right into the types of variables and discuss them thoroughly.

Local Variables

Local variables in Solidity are temporary variables defined within a function or a code block. These variables are only accessible within the scope of the function or block in which they are declared and destroyed once the function or block has been completed. Local variables are declared like global variables: the data type is specified first, followed by the variable name. As an example:

function sayHelloFunction() {
    uint256 localVariable;
}

Local variables can be used within a function to store intermediate results or temporary values. They enable you to keep your code organized and improve its readability. It’s important to remember that unlike global variables, which are stored in the contract’s storage, local variables are not stored on the blockchain. Local variables do not persist between function calls, and their values are lost after the function is executed.

State Variables

State variables in Solidity are variables that exist within the contract, and that can be accessed or modified by external or internal function calls. These variables are stored in memory instead of on the blockchain, and persist even when the contract is not actively running. State variables are declared within the contract and are accessible to all functions, as well as externally, by other contracts or accounts. An example of a state variable is a counter, which keeps track of the number of times a function has been called.

Code example:

pragma Solidity >=0.5.0 <0.7.0;

contract Example {
    uint public counter = 0;

    function incrementCounter() public {
        counter++;
    }
}

The contract Example has a state variable of type uint in this example. Each time it is called, the function incrementCounter increases the value of counter by one. Because counter is a state variable, its value will be preserved between function calls and transactions.

Global Variables

Global variables in Solidity are variables that are declared outside of a contract and are accessible to any other contract in the network. They are immutable and can only be set by the contract creator. For example, the global variable can be used to store a version number or the address of a contract that other contracts need to interact with.

Here’s a simple code example to illustrate the use of global variables in Solidity:

pragma Solidity >=0.4.22 <0.7.0;    
// Declare a global variable
global uint256 constant GLOBAL_VAR = 100;

// Contract A
contract ContractA {
    function getGlobalVar() public view returns (uint256) {
        // Access the global variable
        return GLOBAL_VAR;
    }
}

// Contract B
contract ContractB {
    function getGlobalVar() public view returns (uint256) {
        // Access the global variable
        return GLOBAL_VAR;
    }
}

Understanding variable scoping and rules for naming variables in Solidity

Variable scoping and naming conventions are important to remember when writing smart contract code in Solidity. Variables are described by a function or contract. Both internal and external scopes are present in Solidity. A variable’s internal scope is used by default when it is declared outside of a function. Other code in the same contract can access variables that are declared in this scope. The use of external scopes occurs when a variable is declared inside a function. A function is the only place where a variable declared in this scope can be accessed. In order to be accessed from outside the function, a variable must be declared as an external variable.

For naming variables, Solidity has a few rules. Only alphanumeric characters, starting with the first letter, may be used in names. Underscores are allowed in names, which are case-sensitive. Additionally, all keywords used in Solidity are reserved and cannot be used as variable or function names.

How to assign data types to a variable in Solidity

In this section, we’ll be working with variables in Solidity. We will learn how to assign a data type to a variable in Solidity, which is very simple to do. We’ll work with Signed/unsigned integers, Booleans, Fixed point numbers, Addresses, Byte arrays, Literals, Enums, and Functions. Let’s get our hands ready to write some codes.

Signed/unsigned integers

You can assign a signed or unsigned integer to a variable in Solidity by using the syntax below:

uint256 x = myInt;

Whether the integer is signed or unsigned, this will set the variable ‘x’ to the value of the integer myInt. You can also use the form: uint8 x = myInt; or int8 x = myInt; to assign a specific size integer to a variable, where the number after uint or int indicates the size of the integer.

The following code snippet illustrates how to use signed/unsigned integers in Solidity;

pragma Solidity ^0.6.0;

contract Sample {
    // signed integer
    int256 sampleInt;

    // unsigned integer
    uint256 sampleUint;

    // assigning a signed integer
    function assignSigned() public {
        sampleInt = -10;
    }

    // assigning an unsigned integer
    function assignUnsigned() public {
        sampleUint = 15;
    }
}

Booleans

You can assign a boolean value to a variable using the following syntax:

bool myBooleanVariable = false;

You can also declare a boolean variable without initializing it, and then assign a value to it later:

 bool myBooleanVariable;
 myBooleanVariable = true;

Note that the value of a boolean variable can be either true or false.

bool myBoolean = false;

Please remember that in the code above, you assigned the boolean value false to the variable myBoolean. When working with any programming language, make sure to use the proper syntax. Boolean types are a powerful tool for controlling the flow of your program.

Here’s an example of declaring a boolean variable:

 bool public myBool;

More example:

pragma Solidity ^0.8.1;

contract BooleanExample {
    bool public myBool;

    function setMyBool(bool _myBool) public {
        myBool = _myBool;
    }
}

We can simply run the above code in Remix and deploy it locally. Kindly refer to the video below:

1

Fixed point numbers

The fixed() function assigns a fixed-point number to a variable. The first argument to this function is the number to be assigned to the variable, and the second argument is a decimal place modifier. For example, if you wanted to assign a number to a variable with two decimal places, you would use the following syntax:

uint fixedNumber = fixed(123.23, 2);

In this code, the variable fixedNumber will be assigned the value of 123.23 with two decimal places. This is useful for making calculations with fixed precision.

Addresses

To assign an Ethereum address to a variable in Solidity, use the address keyword. The syntax is as follows:

pragma Solidity >=0.3.0 <0.8.0;

contract ContractFunction {
    address AnyAddress = 0x742d35Cc6634C0532925a3b844Bc454e4438f44e;
}

The variable AnyAddress is given an Ethereum address represented as a hexadecimal string in this case. Please remember that the address keyword in Solidity is a special type with a 20-byte Ethereum address. The address type can be used to interact with other contracts, send Ether, and perform other operations. Below is another example of assigning an Address to a variable in Solidity:

contract MyContract {
    address public myAddress;

    function MyContract() public {
        myAddress = msg.sender;
    }
}

In the code above, a variable is given to the sender of the transaction’s address (myAddress). The sender’s address can then be saved or referred to using this variable.

The balance of an address can be obtained using the code below.

pragma Solidity 0.8.1;

contract AddressExample {
    address public myAddress;

    function setAddressFunction(address _address) public {
        myAddress = _address;
    }

    function getBalanceOfAccount() public view returns (uint) {
        return myAddress.balance;
    }
}

To run the code, we’ll first set our address to the setAddressFunction. After we deploy the contract and set the address, we’ll get a balance.

The following video demonstrates how to deploy the contract and obtain the balance of a specific address:

2

Byte arrays

To assign a byte array to a variable in Solidity, you first need to create a storage variable of type bytes, for example:

 bytes32 myBytes;

Then, you can assign a byte array of any size to this storage variable. Use the built-in function abi.encodePacked to accomplish this:

myBytes = abi.encodePacked("myByteArray");

Finally, you can access the data stored in the variable using the abi.decode function:

 bytes memory myByteArray = abi.decode(myBytes, (string));

Enums

Enums can be assigned to variables in the same manner as any other kind of value. This is the fundamental syntax:

enum EnumName {
    EnumValue1,
    EnumValue2,
    EnumValue3
}
    
EnumName variableName = EnumName.EnumValue1;

In this illustration, EnumName denotes your enum, EnumValues1, 2, and 3 are the enum values, and variableName denotes the name of the variable to which you are assigning an enum value. You can also assign an enum to a variable without specifically stating its name. By adding the enum keyword after the variable name, as shown below, it is used in this way:

Finally, by using the ”|” operator to divide up multiple enums into separate variables, as shown in the example below:

enum EnumName {
    EnumValue1,
    EnumValue2,
    EnumValue3
}
    
enum variableName = EnumName.EnumValue1;

After reading this, you ought to have a basic knowledge of how to assign enums to variables in Solidity.

Functions

By defining a new variable and changing its type to a function type, you can associate a function with a variable in Solidity. For instance, you can carry out the following if you want to assign the function foo() to the variable bar:

function foo() public view returns (uint) {
    return 1;
}

function bar() public view returns (uint) {
    uint result = foo();
    return result;
}

The function foo() is defined in the first section of the code, and its type is set to public view, which allows outside calls and limits its capabilities to data reading. The second section declares a new variable called bar and gives it the type of a function, calling the function foo() and returning the result of foo().

Variable clean-up in Solidity

To clear out the storage of a variable, use Solidity’s delete keyword. This changes the variable’s value to zero (e.g., 0 for numeric types, false for booleans, "" for strings, and the address 0x0 for addresses).

Example using the delete keyword

pragma Solidity >=0.5.0 <0.8.0;

contract MyContract {
    uint256 myVariable = 42;

    function cleanUp() public {
        delete myVariable;
    }
}

In this illustration, the cleanUp function purges the storage of the myVariable variable using the delete operator. The value of myVariable will be set to 0 after the cleanUp function is called. Be aware that while cleaning up a variable’s storage can free up space, it is typically more effective to reuse storage slots by overwriting their values rather than deleting them and allotting new storage slots. Furthermore, clearing out a storage space that is still used as a reference in another contract may have unintended results.

Session Replay for Developers

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — an open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

Benefits of optimizing variables in Solidity

The advantages of variable optimization in Solidity include increased security, quicker execution, and cheaper gas usage. It is possible to improve the performance and security of code by optimizing the types of variables used in Solidity. For instance, one can use uint8 variables, which use 8 bits instead of the 256 bits used by default uint256 variables, as long as this is sufficient for the intended use. As the Solidity compiler won’t need to calculate the 256 bits of data, this will lower gas costs and speed up code execution. Using the most optimized variable types has the added benefit of reducing the likelihood of common security flaws. The potential for integer overflow and underflow, which can expose a contract’s code to malicious exploits, can be reduced by restricting variable data types to only the necessary size. Additionally, using the most optimized variable types can make code easier to read and comprehend, which facilitates the discovery of potential security flaws. In conclusion, optimizing Solidity variables can have a variety of advantages, including increased security, quicker execution, and lower gas costs. Solidity contracts should only employ variable types that are the most optimized, as this can help to prevent security flaws and improve the performance of the code.

How do variables affect Gas in Smart Contracts

Variables are a crucial part of creating and executing smart contracts because they are written in code and supported by the blockchain. The quantity of gas needed to deploy and run the code is one example of how variables are used to define conditions and determine specific outcomes. The complexity of the contract and the number of variables in the code determine how much gas is required to process a smart contract, so variables play a significant role in this. The kind of variables used in the code can also impact how much gas is required because some kinds of variables need more gas to process than others. You should pick variables that use the least amount of gas to make sure your smart contract is as effective as possible.

Conclusion

I hope you enjoyed reading this article. We covered everything you needed to know about using variables in Solidity in this article, Before assigning a datatype to a variable in solidity, we also discussed datatypes in general. We then discussed the advantages of optimizing a Solidity variable, which is an important concept to understand while using Solidity variables. You can visit the official documentation by clicking here to learn more about solidity.

Gain Debugging Superpowers

Unleash the power of session replay to reproduce bugs and track user frustrations. Get complete visibility into your frontend with OpenReplay, the most advanced open-source session replay tool for developers.

OpenReplay