Solidity Fundamentals

Variables

Beginner Level

In Solidity, variables are used to store data that can be accessed and modified during the execution of a smart contract. Solidity supports different types of variables, each serving a unique purpose depending on where and how they are stored or accessed. The three main types are state variables, local variables, and global variables.

1) State variables

State variables are stored permanently on the blockchain. They are declared inside the contract but outside any function. Since they are part of the contract’s storage, they consume gas when modified. State variables are useful for storing persistent information such as account balances, ownership details, or contract settings.

Example 1:


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract StateVariableExample {
    uint public count = 0; // State variable stored on blockchain

    function increment() public {
        count += 1; // Updates blockchain storage
    }
}

Example 2 — State variables (compile with pragma ^0.8.20)


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract StateVariablesExample {
    // State variables (persist on-chain)
    address public owner;          // public -> auto getter: owner()
    uint256 public totalSupply;
    bool internal isActive;        // internal (no external getter)
    string private name;           // private string

    // Constants / immutable
    uint256 public constant MAX_SUPPLY = 1_000_000; // stored in bytecode
    address public immutable deployer;              // set once in constructor

    constructor(string memory _name, uint256 _initialSupply) {
        owner = msg.sender;
        deployer = msg.sender;
        name = _name;
        totalSupply = _initialSupply;
        isActive = true;
    }

    function setName(string memory _newName) public {
        require(msg.sender == owner, "Only owner");
        name = _newName; // writing state -> costs gas
    }

    function getName() public view returns (string memory) {
        return name; // reading state -> no gas when called externally as view
    }
}

2) Local variables

Local variables exist only inside functions and are destroyed once the function execution ends. They are stored temporarily in memory and do not cost gas unless they interact with storage. Local variables are generally used for calculations or temporary storage within a function.

Example 1:


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract LocalVariableExample {
    function addNumbers(uint a, uint b) public pure returns (uint) {
        uint sum = a + b; // Local variable
        return sum;       // Only exists during function execution
    }
}

Example 2 — Local variables (value, memory, storage, calldata)


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract LocalVariablesExample {
    uint[] public numbers; // state array

    // 1) local value type (stack)
    function addNumbers(uint a, uint b) public returns (uint) {
        uint sum = a + b;     // local value-type variable
        numbers.push(sum);    // write to state (costs gas)
        return sum;
    }

    // 2) local reference type in memory (copy)
    function greet(string memory userName) public pure returns (string memory) {
        return string(abi.encodePacked("Hello, ", userName));
    }

    // 3) storage reference — points to state (be careful)
    function modifyFirst() public {
        uint[] storage nums = numbers; // storage pointer to the state array
        if (nums.length > 0) {
            nums[0] = 42; // this modifies the persistent state
        }
    }

    // 4) calldata (cheaper for external read-only inputs)
    function concatExternal(
        string calldata a,
        string calldata b
    ) external pure returns (string memory) {
        return string(abi.encodePacked(a, " ", b));
    }
}

Notes on data locations

  • memory = temporary copy that can be modified and disappears after execution.
  • storage = reference to contract state (modifying it changes on-chain storage).
  • calldata = read-only view into function arguments for external functions (gas-efficient for large inputs).

3) Global variables (environmental / special variables)

Global variables are special built-in variables provided by Solidity that give information about the blockchain and the current transaction. They are always accessible within the contract and are widely used to get data like the sender’s address, block timestamp, or transaction details.

Example 1:


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract GlobalVariableExample {
    address public sender;
    uint public blockNumber;
    uint public timestamp;

    function setDetails() public {
        sender = msg.sender;
        blockNumber = block.number;
        timestamp = block.timestamp;
    }
}

Example 2 — Global variables


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract GlobalVariablesExample {
    address public lastSender;
    uint256 public lastValue;
    uint256 public lastBlock;
    uint256 public lastTimestamp;
    uint256 public lastChainId;
    bytes32 public lastBlockHash;

    function pay() external payable {
        require(msg.value > 0, "Send ETH");
        lastSender = msg.sender;
        lastValue = msg.value;
        lastBlock = block.number;
        lastTimestamp = block.timestamp;
        lastChainId = block.chainid;
        lastBlockHash = blockhash(block.number - 1);
    }

    function getGasLeft() public view returns (uint256) {
        return gasleft();
    }

    function insecureAuth() public view returns (bool) {
        return tx.origin == lastSender;
    }
}

Quick comparison & lifecycle summary

  • State variable: Stored on-chain, persistent, writing costs gas.
  • Local variable: Temporary, exists only during function execution.
  • Global variable: Environmental blockchain and transaction data.

Continue Learning

Explore more topics in Solidity or browse other tutorials.