Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Mastering Immutability: View and Pure Functions

Hello! Welcome back to your Solidity development course.

In our last lesson, we explored the four function visibility modifiers (public, private, external, internal), which control who can call your functions. This is a critical pillar of smart contract security.

Today, we're building on that foundation to address the next logical question: what is a function allowed to do with the contract's data? The goal of this lesson is to learn how to control function behavior and gas costs with the state mutability keywords view and pure.

As a backend developer, you're used to thinking about read/write operations on a database. view and pure are Solidity's way of explicitly declaring whether a function is a "read" operation or a pure computation, with significant consequences for gas costs and security. This is one of the most important gas optimization techniques in Solidity, and mastering it is essential for building an efficient token.

The State Mutability Spectrum

In Solidity, functions interact with the contract's state in three primary ways:

  1. They read and write to state. (e.g., updating a user's token balance)
  2. They only read from state. (e.g., checking a user's token balance)
  3. They neither read from nor write to state. (e.g., performing a mathematical calculation on its inputs)

Solidity gives us keywords to explicitly declare this behavior.

State-Modifying Functions (No Keyword)

If a function doesn't have a state mutability keyword, the EVM assumes it can modify the state (i.e., write data to the blockchain). These are the most common types of functions you'll write, like transfer or mint.

Crucially, any operation that changes the state of the blockchain requires a transaction and costs gas.

How do Solidity functions work?

Let's first establish the connection between writing to state and gas costs. This section from the Alchemy documentation explains it well.

Read the section titled 'Functions - Writing to Storage'. The key takeaway is that functions that change state variables, like assigning a value to z, always cost gas.

view: Read-Only Functions

A view function promises that it will not modify the state. It can read state variables, but it cannot change them.

View and Pure Functions

The Solidity by Example resource offers a very direct definition and a clear code example for view functions.

Read the definition for view and look at the addToX function in the code sample. Notice how it reads the state variable x but doesn't change its value.

pure: Computation-Only Functions

A pure function makes an even stronger promise: it will neither modify nor read from the state. These functions are self-contained and behave like utility functions; their output depends only on their input parameters.

View and Pure Functions

Now, look at the pure function in the same Solidity by Example resource.

Read the definition for pure and look at the add function. See how it only uses its inputs (i and j) and has no interaction with the contract's state variable x.

This flowchart provides a great visual summary of the distinction:

Solidity State Mutability Flowchart
This flowchart shows that `pure` functions cannot read or write state, `view` functions can only read state, and functions with no mutability keyword can both read and write state.

The "Why": Gas Costs and External Calls

So, why go to the trouble of adding these keywords? The primary reason is gas optimization.

When you call a function from outside the blockchain (e.g., from your dApp's frontend, a script, or a block explorer like Etherscan), you are making an "external call".

  • Calls to state-modifying functions must be broadcast as a transaction, which gets mined into a block and costs gas (eth_sendTransaction).
  • Calls to view and pure functions are simply read operations on your local Ethereum node. They don't need to be mined and are therefore completely free (eth_call).

This is a fundamental concept. It means you can let users check your token's total supply or their own balance as many times as they want without paying any gas fees.

Solidity Tutorial: Function modifier keywords (view, pure, constant)

This video clearly explains the difference in how these functions are called and why it matters for gas.

Watch from 00:30 to 01:05 to see the visual distinction in the Remix IDE, and then watch from 03:01 to 03:37 to understand the difference between eth_call (for view/pure) and eth_sendTransaction.

Important Note: If a view or pure function is called internally by another function that does modify state, it will consume gas as part of that larger transaction. The optimization still helps, as the compiler knows it doesn't need to account for state changes from that part of the code, but it is not free in this context.

Compiler Enforcement

These keywords aren't just suggestions; they are rules enforced by the Solidity compiler. If you declare a function as view and then try to modify a state variable inside it, your code will not compile.

Learn Solidity (0.5) - View and Pure Functions

This video provides a detailed walkthrough of what is and isn't allowed inside view and pure functions, showing the compiler errors you'll get if you break the rules.

Watch the section on view functions (00:16 - 03:53) and pure functions (03:53 - 06:24). Pay close attention to the examples of invalid code and the compiler errors they produce. This will build your intuition for what's allowed.

Furthermore, the compiler is smart. If you write a function that could be declared as view or pure but you forget the keyword, it will give you a warning, encouraging you to be as specific as possible for gas optimization.

Best Practice: Always apply the most restrictive mutability keyword possible.

  • If a function doesn't interact with state at all, make it pure.
  • If it only reads state, make it view.
  • Only if it modifies state should you leave it without a mutability keyword.
Test your understanding!

You are writing a simple Counter contract. For each function below, decide if it should be view, pure, or have no keyword.

  1. function increment() { counter++; }
  2. function get() returns (uint) { return counter; }
  3. function add(uint a, uint b) returns (uint) { return a + b; }
Show answer
  1. No keyword (state-modifying): The increment function modifies the counter state variable by incrementing it. This is a "write" operation.
  2. view: The get function reads the value of the counter state variable and returns it. It doesn't modify anything, so view is appropriate.
  3. pure: The add function takes two numbers and returns their sum. It does not read from or write to the counter state variable. Its logic is completely self-contained, making it pure.

Practical Application

Let's apply this in your Hardhat project.

  1. In VS Code, create a new file in your contracts directory named Mutability.sol.
  2. Add the following code. It contains a state variable and three functions. Your task is to add the correct mutability keyword to getValue and addValues.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract Mutability {

    uint public myValue = 10;

    // This function MODIFIES state. It needs no keyword.
    function setValue(uint _newValue) public {
        myValue = _newValue;
    }

    // This function only READS state. What keyword should it have?
    function getValue() public /* Add keyword here */ returns (uint) {
        return myValue;
    }

    // This function NEITHER reads NOR modifies state. What keyword should it have?
    function addValues(uint _a, uint _b) public /* Add keyword here */ returns (uint) {
        return _a + _b;
    }
}
  1. After adding the keywords you think are correct (view and pure), compile the contract with npx hardhat compile to check your work. If it compiles without warnings related to mutability, you've done it correctly!

Conclusion

Great job! You have now learned how to declare what a function is allowed to do with a contract's state using view and pure. This concept is fundamental to writing efficient, secure, and readable Solidity code.

Key Takeaways:

  • Functions that modify state require gas and are submitted as transactions.
  • view functions promise to only read state, not modify it.
  • pure functions promise to neither read nor modify state.
  • When called externally (off-chain), view and pure functions are free to execute.
  • Always use the most restrictive mutability keyword possible (pure > view > none) for gas efficiency and code clarity.

Preview of the Next Lesson:

We've covered state variables, function visibility, and now function mutability. The next piece of the puzzle is initializing our contract. In the next lesson, we will learn how to implement a constructor to initialize contract state upon deployment. The constructor is a special function that runs only once, when the contract is first created, making it the perfect place to set initial values for our state variables.

Can't find a good explanation? Sign up and we'll make it for you

Sign up