0

As far as I am concerned, when a function in a smart contract is defined as pure or view it is possible to invoke it without being charged for the gas consumption that its execution requires. This type of functions do not alter the state of the smart contract and thus not need to be executed and mined as a new block in the blockchain.

However, this behaviour would open the door to abuse. Anyone could try to repeatedly invoke this type of functions on a particular node to put it to work without rewarding it.

So, I would like to know if I am right or wrong in stating:

  1. Pure & view functions can be abused because anyone can invoke them without paying for their execution.

  2. Pure & view functions are executed off-chain since their execution does not alter the state of the contract.

  3. When executing off-chain the function is typically executed on a single node, the one used as provider (e.g., a local geth node or a remote Infura node).

If 1. is correct, is there a way to prevent this from happening? I don't mean a way to to limit long executions but a way to limit multiple invocations of a single function by some accounts. This is something I wanted to clarify since the question was marked as a possible duplicate of View/Pure Gas usage - Cost gas if called internally by another function?

I can think of firewall-based solutions but does Ethereum clients like Geth provide any sort of countermeasure? Can this problem be tackled at solidity level? It comes to my mind making all my functions non-static but this would be detrimental for honest users.

If 2 and 3 are correct, I can think of remote dishonest nodes returning wrong results to the client. So I guess, this is not necessarily true and there is a way to force invocations to pure/view functions to be executed distributedly. In that case, would the execution of the function have any impact on the blockchain if the function is not changing anything on the contract? Would any gas be charged to the client?

Thanks for your comments!

0

Pure & view functions can be abused because anyone can invoke them without paying for their execution.

Not exactly. If they are invoked from a contract that is executing a state-changing transaction, then they are part of the transaction that every full node has to execute. That's okay, though, because gas accounting applies.

Pure & view functions are executed off-chain since their execution does not alter the state of the contract.

Functions that are view/pure may be executed locally, if the user calls them directly. They can do that as much as they want because they are using their own hardware and their own copy of the chain. If the view/pure function is called by a contract, then everyone has to run it and the sender pays for gas.

When executing off-chain the function is typically executed on a single node, the one used as provider (e.g., a local geth node or a remote Infura node).

An off-chain read-only function is executed locally on the caller's computer. The network isn't even informed.

A more detailed explanation: https://blog.b9lab.com/calls-vs-transactions-in-ethereum-smart-contracts-62d6b17d0bc2

Hope it helps.

Elaboration

pragma solidity 0.5.1;

contract ConstantAndTransaction {

    uint trivial;

    function getTrivial() public view returns(uint) {
        // When called directly, this function is run locally and gas is refunded. 
        // The network is not consulted.     
        return trivial;
    }

    function add(uint x) public {
        // This is normally a state-changing transaction. It relies on inspecting a read-only function. 
        // That means all nodes will run the read-only function and the sender will pay for it. 
        trivial += getTrivial() + x;
    }
}
  • Thank you Rob. As for answer (1) I thought pure/view functions were by definition non state-changing transactions. Regarding (2), I don't know I really understood the point you make when saying "if called by a contract". Does it make a difference if a normal account calls a remote view/pure function? And (3) what if you don't have a local node? Then it must be executed by everyone? Thanks for the link I will read it in detail. – rutex Mar 31 at 11:53
  • (1) Correct (2) I added an example. You need to understand the difference between sending transactions to the blockchain, messages between contracts and inspecting functions locally. It's the mode that matters for gas accounting. The blog is about that. (3) The contract must be indifferent to the setup in the outside world. You can construct an API on that basis: the API is a (possibly privileged) user of the contract, and the API presents a service with its own rules to the users. That setup has no line-of-sight from users to your node. Infura is roughly a node-as-a-service. – Rob Hitchens - B9lab Mar 31 at 16:17
  • I just read your blog post. Very nice. Thank you for the link and the last clarifications you provided. Still, it is unclear to me whether one can limit the number of calls to methods by account. Could you shed some light on this? – rutex Apr 1 at 6:43
  • Thank you. I hope it helped. If the method is read-only view or pure then no, you can't because you have no way to count. It shouldn't be important to do that because either a) they're using the own resources or b) they're going through one of your web servers, or similar and you can throttle it there. Thanks for voting and accepting this answer. – Rob Hitchens - B9lab Apr 1 at 13:49
1

I assume you mean public nodes. if this is the case publics node will just limit the number of API request per second as Etherscan do, to about 5 request per second.

Hope this helps

  • Thanks for your reply. For example, if I run a geth node and set it up to listen for RPC messages (flag --rpc) on a public IP. How is this limit of 5 requests per second set? Can this limit be set to consider requests coming from a single node? Thanks again – rutex Mar 29 at 23:32
  • I do not think is a good idea to open your node to the public, if your apps need to access it you should try to restrict the access using third-party software. See this question and this article for more details of using Nginx and UFW in your node, to limit who can access it. Note that the limit cannot be done with only Geth. Etherscan limits the rest API so the limits on the nodes are indirect – Jaime Mar 29 at 23:58
  • I am aware of this type of problems, specially when you have accounts/wallets in your local node. Thanks. I am not thinking of setting up my own public but I wanted to understand whether it was possible to abuse the existence of functions that cost zero gas to the issuer – rutex Mar 30 at 0:15
0

Nodes are not designed to be publicly accessible, at least stock implementations such as geth. I believe public nodes such as Infura or MEW do operate behind some sort of reverse proxy that do protect them from spam and unwanted request.

BTW, whether function is read-only (i.e. pure, view, or constant) or read-write, only defines default calling strategy for the function. One may always invoke read-only function on-chain (via myContract.methods.myMethod.send) or non read-only function off-chain (via myContract.methods.myCethod.call). So declaring all functions as non read-only will not protect them from being executed locally.

  • Thanks for your help. My question is about any node that may be used as provider, namely a local node (e.g., geth) or remote (e.g., infura). I thought that when you invoke a function from a given contract, if the method was static then it was always executed by a single client (the provider?) because it doesn't affect the contract state. Basically, I thought that only transactions modifying the state of a contract were mined and thus executed distributedly. You are saying this is incorrect, right? One decides by issuing call() or send() how it is executed, right? – rutex Mar 29 at 23:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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