1

From my understanding, a Solidity function running on a compatible EVM that doesn't change the state of the blockchain will not cost any gas. And this indeed appears to be the case, as I have confirmed with this function that is implemented in my smart contract, but which is not consuming any gas when call externally and executed.

 function tokensOwned(address owner) external returns (uint256[] memory) {
    uint256 numOfTok = balanceOf(owner);
    uint256[] memory tokens = new uint256[](numOfTok);
    for (i = 0; i < numOfTok; i++) {
        uint256 token = tokenOfOwnerByIndex(owner, i);
        tokens[i] = token;
    }
    return tokens;
 }

My question is, how could this not be using any gas since there is still some computations being executed by miners? Shouldn't they be compensated? Also, what would stop a malicious actor from deploying a contract with a huge loop, making a routine consume a large amount of resources?

2 Answers 2

4

When you call a view or pure function, the EVM (Ethereum Virtual Machine) executes the function locally on the node that receives the request.

Since the function you have written above don't change the state of the blockchain, there's no need for miners to reach consensus on the result, and thus no gas is consumed.

2
  • Up voted, could maybe add in answer to the last part, that if called on chain from a contract it would consume gas. If think relevant. Though if they are referring to calling the loop from off chain, then I suppose it wouldn't be.
    – Maka
    Apr 23 at 9:37
  • Thank you @talha-sajid-chaudhary What about the last part of my post. What if a malicious actor deploys a long-executing loop, are there any safeguards to prevent such a function from being repetitively launched so that it consumes a lot of resources for the node(s) receiving the request(s)? Surely, there must be a way to prevent this...
    – JF0001
    Apr 23 at 23:29
2

First of all, since your function doesn’t modify the blockchain state, you should mark it with view.

One way to look at it is that calling a view function will always consume a certain amount of computation gas (e.g. let us suppose that tokensOwned(address) always consumes 8000 gas), but whether or not you pay ETH for that gas depends on the execution context:

  • if you query your function from outside the blockchain, e.g. from a web-page, the gasPrice is 0, so you pay nothing
  • if your function is called during an Ethereum transaction that is being executed on the blockchain at a gasPrice of 0.000001 ETH per gas unit, then calling your function will cost the caller a total of 0.008 ETH
3
  • Thank you @dwardu What if I leave the function as is (not specifying it as view), does it/or could it change anything practically, in terms of gas consumption? My contract was already deployed as such (although it is upgradeable, I am not sure if it is worth to upgrade it).
    – JF0001
    Apr 23 at 23:21
  • I am not sure if it is possible, but you can test it yourself in Remix IDE. Create an interface with a function function tokensOwned(address owner) external view returns (uint256[] memory);, load the interface from the deployed address on the correct network, and see what happens if you try and call it.
    – dwardu
    Apr 24 at 16:03
  • 1
    Thank you again @dwardu Yes, I had done this even on the production network and no gas is being charged.
    – JF0001
    Apr 25 at 0:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.