Open In App

Solidity – State Variables

Last Updated : 26 Apr, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

Any variable created at the contract level is called the state variable (variables that aren’t inside a function) and it is stored permanently on the blockchain i.e., they are persistent and cannot be deleted. So, if you were to create a state variable in your contract and assign it some value, and came back after some time then its value would still be the same.  An important thing to note here is, you’ll have to pay some level of gas for every state variable declared. Hence, you should be careful every time you create a state variable. 

Note: Gas is a fee that is required to execute each transaction. Just like we need fuel to run a vehicle, we also need gas to execute the transactions on the blockchain. And the price of gas is calculated by the supply and the demand of miners in the network.

Important Points:

  • State variables directly store data on the blockchain that is, on the contract storage itself. So, if you were to store data in the state variable and come back after 1-week then your data would still be there.
  • State variables are declared inside a contract and outside the function.
  • Solidity automatically creates a get method with the same name for state variables.
  • The state variable can be assigned one of the access modifiers: public, internal, or private.
  • Since storages are not allocated dynamically, we’ve to re-compile each time we declare a state variable.
  • State variables are expensive as they cost gas.
  • Every instance of a contract will contain only those state variables, which were present in the contract before compilation.

Example:

Solidity




// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract GeeksForGeeks {
    // Created inside the contract 
    // but outside a function
    string public message; 
    
    function setMessage() public {
        message = "Hello Geek !";
    }
}


Explanation: In the above code, we’ve created a state variable – ‘message’ and its value is set to “Hello Geek !” through the set() function. Since we’ve used the access modifier as public, the solidity will automatically create a public get() function to get the value of the message variable which allows everyone to read the value of the message variable even from outside the contract.

Scope of State Variables

We can only control the scope of state variables but we can’t do the same with local and global variables. So every state variable has some level of scope associated with it i.e. to what extent it will be accessible. In solidity, we can define a scope by using the following access modifiers for state variables:

  1. Public.
  2. Internal.
  3. Private.

Note : There are total 4 types of access modifiers but only 3 of them can be applied on variables.

These access modifiers are used to limit the variable’s access throughout various contracts but the data can be accessed & viewed by anyone on the blockchain publicly. 

Syntax:

<data-type> <access-modifier> <var-name>;

1. Public 

The public access modifier makes the variable accessible inside the contract, sub-contracts, and outside of it as well. Meaning, we can access the public variables in other contracts as well, doesn’t matter if they are derived or not. And For every state variable declared as public, there is a get() function created by solidity automatically.  

2. Internal

This access modifier defines the scope which allows the state variables to be accessed only in the contract itself and all the contracts that are derived from it. All the sub-contracts can access the state variables which are declared as ‘internal’. But external contracts can’t access the internal state variables.

3. Private

State variables declared by the use of private access modifiers are limited only to the contract in which they are defined.

Below is the example to show all types of scopes given by each of the access modified with a code example:

Solidity




// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract BaseContract {
    
  // Public state variable
  string public message = "Hello Geek!"
    
  // Internal State variable
  uint internal age = 22; 
    
  // Private state variable
  string private messageTwo = "This is a private variable"
  
  // I haven't defined a get() for message variable as 
  // solidity automatically defines it for 'public' 
  // state variables
  function getAge() public view returns (uint) 
  {
    return age;
  }
    
  function getMessageTwo() public view returns (string memory) 
  {
    return messageTwo;
  }
}
  
contract DerivedContract is BaseContract {
    
  // No Error because, public State Variables 
  // are accessible anywhere.
  function getMessageFromBase() public view returns (string memory) 
  {
    return message;     
  }
    
  // No Error because, internal State Variables are accessible 
  // directly inside derived Contracts.
  function getAgefromBase() public view returns (uint) 
  {
    return age;     
  }
    
  // Compiler Error : Can't access private state variables 
  // in derived contract.
  function getMessageTwo() public view returns (string) 
  {
    return messageTwo;  
  }
}
  
contract ExternalContract {
    
  // We'll need an object to access the public variables.
  BaseContract baseContract = new BaseContract(); 
    
  // public State Variables are accessible by the use 
  // of object in external contracts.
  function getExternalMessageFromBase() public view returns (string memory) 
  {
    return string(abi.encodePacked(baseContract.message));     
  }
  
  // internal State Variables are NOT accessible by the 
  // use of object in external contracts.
  function getNum() public view returns (uint) 
  {
    return baseContract.age;     
  }
    
  // Compiler Error : Can't access private state variables 
  // in External contracts either.
  function getMessageTwo() public view returns (string memory) 
  {
    return baseContract.messageTwo;  
  }
}


Explanation: In the above code, 3 contracts are created: Base Contract, Derived Contract, and External Contract. The Base Contract consists of 3 state variables defined with different access-modifier. Since the message is a public variable, it will be accessible anywhere but in external contracts, you’ll require an object of Base Contract to access it. 

Note: The string data-type is used, due to which there is a need to perform type conversion and its done by the following line: 

string(abi.encodePacked(var-name). 

The data type like – byte32 can also be used , then there is no need to perform this type conversion.

The internal variables will only be accessed in the contract in which they are defined and the inherited ones and the private ones will only be accessible in the contract in which they are defined.

Initialization of State Variable

Now let’s see how many ways we can initialize a state variable. There are three ways in which one can initialize a state variable:

1. Initialization at the Time of the Declaration

Below is the Solidity program to initialize the state variable at the time of declaration:

Solidity




// Solidity program to initialize 
// state variable at the time of declaration
// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract GeeksForGeeksStateDemo {
    
  string public name = "Geek Adwitiya";
  uint public age = 23;
}


Output: 

Initialization at the time of declaration

 

Explanation: A simple contract is created, to demonstrate 1st way in which one can initialize state variables ‘name’ and ‘age’.

Note: Adding public as access modifier between the variable name and the data type, allows solidity to create a get() method automatically.

2. Initialization Using Constructors

Below is the Solidity program to initialize state variables using constructors:

Solidity




// Solidity program to initialize 
// state variables using constructors
// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract GeeksForGeeksStateDemo {
    string public name;
    uint public age;
    
      Constructor() public
    {
      name = "Geek Adwitiya";
      age = 23;
    }
}


Output:

Initialization using Constructors

 

Explanation: In the above code, we’ve created a contract and declared two state variables as – ‘name’ and ‘age’. And initialize them by making use of a ‘Constructor’. This is another way to initialize a state variable.

3. Initialization Using Setter Method

Below is the Solidity program to initialize state variables using the setter method:

Solidity




// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract GeeksForGeeksStateDemo {
    string public name;
    uint public age;
        
      function setName() public
    {
      name = "Geek Adwitiya";
    }
    
      function setAge() public
    {
      age = 22;
    }
}


Output:

State Variables

 

Explanation: This is the 3rd way of initializing a state variable by making use of the setter function, set(). We’ve created two separate functions to initialize each of the state variables.

Above mentioned 3 ways are the only way to initialize a state variable, we cannot initialize state variables after declaration. Either do it while declaring or make use of a constructor or set() function. 

Reading and Writing to a State Variable

1. Reading From a State Variable 

The values in a state variable can be read easily by the use of functions, just add a ‘view’ keyword to the signature of the function. Below is the Solidity program to read from a state variable:

Solidity




// Solidity program to read from 
// a state variable:
// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract ReadStateVariable {
    
  string public message = "Hello Adwitiya Mourya!"
  uint private num = 10;
      
  //* Function to read the value of a state variable  
  function get() public view returns (uint) 
  {
    return num;
  }
}


Explanation: In solidity for every public state variable, a get() is automatically created to read its value, hence I’ve created a get() only for num because it’s declared as private. 

You can execute the code on the online Remix IDE or the one you’ve installed on your local computer. Just open it and type the above code, click Deploy > then your output should be something like this when you call the get() and message():

Output:

Reading from a state variable

 

2. Writing to a State Variable 

When writing a value to a state variable, we need to send a transaction to do so. Below is the Solidity program to write to a state variable:

Solidity




// Solidity program to write to 
// a state variable
// SPDX-License-Identifier: MIT
pragma solidity >= 0.5.0 < 0.9.0;
  
contract GeeksForGeeksStateDemo {
    
  string public name;
  uint256 public num;
  
  //* Forces us to Set(Write) the values before 
  // deploying the contract
  constructor(string memory _name, uint _no) 
  {
    name = _name;
    num = _no;
  }
    
  //* A function to update(Write) the values stored 
  // in the state variables
  function update(string memory _name, uint _no)  public 
  {
    name = _name;
    num = _no;
  }
}


Output:

Writing to State Variable

 

In the above output, we can see every time we need to write(update) the value of the state variable, we’ll have to send a transaction. 

State Variables vs Local Variables  

Below are the differences between state variables and local variables:

Parameter

State Variables

Local Variables

 Scope State Variables are defined at the contract level, i.e. outside the function but inside the contract. And their scope depends upon the type of access modifier we’re assigning to it The scope of local variables is limited to the function or a code block that they are defined in.
Lifetime State variables have a persistent lifespan as they are stored on the contract storage and they can exist as long as the contract is deployed on the blockchain. Whereas the Local variable’s lifespan is limited and they are destroyed from the memory once the code block or the function they are defined in returns or completes its execution 
Visibility State variables are visible to all the functions within the contract and their visibility can be controlled by the use of access modifiers Local Variables are visible only to the code block or the function they are defined in
Storage State variables are stored on the blockchain which means they are allocated some space and that can contribute to the overall cost of deploying the contract Local Variables are stored in the memory and don’t cost anything which means using local variables could be cost-efficient.
Security State variables are vulnerable as they are stored on the blockchain and can be accessed by any function. Hence it’s very important to ensure that state variables are allowed access only to the appropriate components. Since the local variable’s scope is limited to the function or the code block they are defined in, they are pretty much secure compared to the state variables


Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads