Solidity Basics: State & State Variables

Solidity Basics: State & State Variables

An Introduction To State In Solidity And How To Change It

Featured on Hashnode

One of the great things about blockchains are their ability to store data in their distributed ledger systems. This is typically done through transactions, and once accepted, they form part of a block and then permanently become part of the blockchain. When the information is part of the blockchain it is immutable, meaning there is a permanent record of that transaction that can never be deleted or modified.

The Ethereum Blockchain however is more advanced than this. It can store blocks of code called smart contracts and through the Ethereum Virtual Machine (EVM) can execute the code stored in these contracts. This effectively allows for the modification of the EVM's state from block to block. Due to the immutability aspect, the previous state is still in the records of the blockchain, albeit in the form of hexadecimal hashes instead of human-readable text.

In this article we will write a simple smart contract with a function we can use to change its state. Before we get into coding though, it is important to understand a few concepts around contract state and transactions.


What You Will Learn

  • What state and state variables are in Solidity
  • Transactions and changing the state of a state variable
  • General information about variables in Solidity

What You Will Need

Resources


Why Does State Matter?

The internet as we know it today is stateless. State refers to information. Since there isn't a native mechanism for keeping track of or changing state built into the current internet, We rely on centralized authorities to act as intermediaries for the transfer of value and maintaining state.

Workarounds such as cookies have been implemented, but they are created by companies who may not have the best intentions when it comes to your data. It often leads to the mishandling of user data and can also be an enticing target for hackers looking for credit card information.

The ability to track and maintain state on Ethereum takes the power out of these institution's hands and gives it back to the people. State of the network is then collectively maintained. We no longer need to rely on these companies to settle payments or keep track of our sessions online.

So What Is State in Solidity?

This just refers to the data being stored on the blockchain at a particular block. There are two types of data that can be stored on the Ethereum Blockchain: permanent data and ephemeral data.

Once permanent data is stored, you guessed it, it's permanent. It can't be modified or deleted. An example of this would be a transaction hash. The simplest transaction would be sending ETH from one account to another and would include information such as the recipient, the amount of ETH sent, and a signature to identify the sender. This data is then hashed and stored on the blockchain.

Ephemeral data refers to information that could change from block to block, such as the balance of a particular account or the value of a variable stored inside a smart contract.

State Variables

There are three types of variables in the Solidity coding language:

  • Local Variables - A temporary value that is declared inside of a function, cannot be accessed outside and is only present until that function is finished executing.
  • Global Variables - Special variables that hold information about transactions and blockchain properties (eg: msg.sender, tx.origin).
  • State Variables - Values that are permanently stored in contract storage and hold data related to the contract state.

Through the manipulation of state variables, we can effectively change the data being stored in a smart contract. State variables are declared inside contract scope and outside of function scope, meaning they would be one of your first declarations in a contract before declaring functions.

variables(resized).jpg

Transactions

In order to change the value of a state variable, you need to send a transaction. Although reading the value of this variable is free, it will cost a gas fee to send the transaction to change it. I won't go into what gas fees are in this post, but it is important to note that any transaction that changes the state of the Ethereum Virtual Machine will cost some amount of ETH.

There are also many factors that go into the calculation of gas fees such as the variable type, its size and even the order it is declared in relation to other variables. If you are deploying smart contracts onto Ethereum mainnet, gas fee optimization will play an important role. To learn more about gas fees check out the Ethereum Docs.

Now that you've got a basic understanding of what state is in Solidity and what it takes to change it, let's write our own smart contract to see it in action!


The Code

I'm going to assume you know the basic structure of a Solidity smart contract, so I won't be explaining anything pertaining to that. If you need to get caught up, you can do so here → https://blog.paulmcaviney.ca/hello-world

  1. Head over to https://remix.ethereum.org/
  2. Click on the Create New File button and let's name our new file ChangeState.sol
  3. Enter the following code:

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.7;
    
    contract ChangeState {
    
      string message;
    
      function setMessage(string memory newMessage) public {
          message = newMessage;
      }
    
      function getMessage() public view returns (string memory) {
          return message;
      }
    
    }
    
    • The line string message; is declaring the state variable that will be saved in contract storage.

    • The function setMessage() allows us to change the value of message and is set to public so any one can access it.

    • The function getMessage() is a getter function that returns whatever the value of message is at the time it is called. You should be aware that if you were to declare the state variable message as public, Solidity automatically creates a getter function with the same name. I just wrote it out like this for the sake of clarity. It would look like string public message; otherwise.

    Alright, so now we have this fancy bit of code and understand what it's supposed to do, let's test it out and see if it actually works!


    Testing The Code

  4. Hit ctrl+s to save and compile the code. If all goes well, you should have a little green checkmark next to the Solidity compiler icon on the left side navigation bar. If there was an issue, the line number with the issue will be highlighted red and hovering over it will give you an idea of what the error might be.

  5. Click on the Deploy & run transactions icon. You should then see the name of our contract ChangeState - ChangeState.sol underneath the Contract heading and directly underneath that there will be an orange Deploy button.

  6. Click on the orange Deploy button and our contract should appear under the Deployed Contracts heading at the bottom. If you click on the little arrow beside CHANGESTATE it will reveal buttons for the two functions in our smart contract - setMessage and getMessage. These are the buttons that will allow us to test if everything is working properly.

    deployed-contract(resized).jpg

    Remix does something cool here. Notice how the two function buttons are different colors? The orange setMessage button represents a transaction that is not payable. This means the function does not transfer ETH from one account to another, just the gas fees associated with the transaction. Transactions that are payable will appear as red. They will transfer ETH and also cost gas fees. The blue getMessage button represents a call function, meaning it is just trying to read some data from a contract.

    So just remember, orange and red buttons mean it costs gas, blue means it does not. Hovering over the buttons will display this as well.

    Now let's actually test these functions and see what's going on.

  7. First, click on the getMessage button and it will reveal the default value for our message state variable. This will display 0: string: underneath the button, meaning it just returned an empty string.

    • Side Note - Each declared variable will have a default value based on its type - there is no concept of undefined or null in Solidity.
  8. Next let's test the setMessage button. Enter in a new message in the text input that you'd like to assign to our message state variable. After clicking the button, you will notice that some new information was added in the console, which is located right underneath where we wrote our smart contract code. Click on the arrow beside the Debug button and let's check out what it says.

    setmessage-transaction.png

    Remember how in order to change the value of our state variable we need to send a transaction? This new message in the console is what's called a transaction receipt. It contains information about where the transaction came from, where it was going to and the amount of gas it cost. Interacting with any function that costs gas will produce a transaction receipt.

    More on transaction receipts → https://medium.com/remix-ide/the-anatomy-of-a-transaction-receipt-d935aacc9fcd

  9. The last step in testing our contract is clicking on the getMessage button one more time. This time, you will see that the message was updated to whatever you set the message as! It read the value of the message variable from its location in contract storage on the blockchain and displayed it for you to see in all its glory!

    final-message(resized).jpg

    Since we are accessing the value of our state variable through a function in our own smart contract, you might not see the significance here. To really get an idea of how awesome this is we should deploy our contract to a testnet and interact with it there through another contract! This will be the subject of my next article.

More On Variables

Before I conclude this article, I want to leave you with some of the basic rules associated with variables:

  • Variable scope can be defined to control who can use them
    • Public - anyone can get the value of this variable
    • External - only external functions can get the value - not used on state variables
    • Internal - only functions in this contract and related contracts can get the values of these variables
    • Private - can only be accessed by functions from the current contract
  • Variable names are case sensitive.
  • There are reserved keywords you should not use as variable names
  • Solidity variables can't start with a number, they should start with a letter or an underscore.
  • Solidity is a statically typed language, meaning the variable types need to be specified when declaring them

Conclusion

One of the greatest aspects of the Ethereum Blockchain is its ability to manage state through the EVM. You were able to successfully create a state variable, update its value which is placed in contract storage on the blockchain and retrieve that value. You should now have a basic understanding of how this is accomplished through the use of state variables and transactions. Congratulations! You are one step closer to mastering the fundamentals of Solidity!

Thanks for taking the time to read this article! I hope it helped you learn a little more about how Solidity works. If you would like me to write an article about a specific topic related to Solidity or Web3 in general, drop a comment or hit me up on Twitter!