Gas limit on eth_call?

Hello,

I am trying to call a public function of a contract to display some data to the user. I am using web3.js to create a Contract object and call() a method. Everything works on my local node but Infura complains about gas. To be clear, this code is simply running a method call in the node’s local EVM, not sending a transaction to be included in the blockchain, so I’m not sure why a gas limit is relevant. I have tried passing various gas arguments but Infura seems to cap it at 19981536.

If I run estimateGas() on the method, it returns about 39000000. Infura won’t even let estimateGas() finish so I also did that on my local Geth node.

Everything was working with Infura a week ago, so my guess is either the method call recently went over Infura’s call gas limit (due to state changes on mainnet), or Infura recently changed the call gas limit.

So, can Infura comment on whether there is a gas limit for eth_call? Is this in the docs somewhere? Does Infura+ increase it?

Thanks

Hi,

If the method call is not executing transactions on the blockchain, then the gas limit parameter would not be required.

Could you share the contract address and the method you are calling from the contract?

Here is a code sample you can run with web3.js/node.js:

  1. Copy js file to local directory
  2. insert your Infura API key into code (line 3)
  3. run ‘npm install web3’ or ‘yarn add web3’ from directory
  4. run file with ‘node filename.js’
  5. Correct output is some large arrays.

That code sample works with the web3 provider as my local Geth node, but runs out of gas with Infura. Let me know if you need more info. Thanks!

Hi @talkingant . Earlier this week we added a gas cap of double the block gas limit to eth_call and eth_estimateGas to prevent Denial of Service attacks. I apologize that you ran into this without it being clear in the docs. The intention with setting the limit to double the block gas limit was that it shouldn’t effect existing users since no call should take more than the block gas limit.

1 Like

@egalano

The reason this public function exists is to avoid hundreds of individual eth_calls. Essentially there is an array of addresses in the contract storage, and I need to iterate through this array and call a function on each address to get some info about the address. The public function was never intended to be run in a transaction. Instead, it allows one eth_call to the node and it runs that array iteration in the EVM, then returns an array of results. The alternative would be to do many eth_calls like:

  1. eth_call for array length
  2. Inside for loop, eth_call getArrayElement(index) then eth_call getInfo() on that address

If there are 100 elements in the array, then that is 201 eth_calls.

So I think there are many use cases where there is some unbounded array in contract storage, and to minimize HTTP/RPC requests the contract authors create a public view function that bundles the array iteration into one method call.

I understand the need to avoid DoS attacks. If eth_call is going to have a gas limit then we need a new design pattern for these public convenience functions that limit computation while still offering a way to reduce number of RPC requests to the node. I’m not sure what the solution is for the current design pattern. Perhaps you could default eth_call to 2x gaslimit, but allow the requester to specify a larger gas limit, and do more severe rate limiting for eth_calls and eth_estimateGas with custom gas limits.

For now, I humbly ask if you could raise the eth_call limit to 4x the gas limit, which should be enough for my method call at the moment.

Thanks for the detailed response! That was really helpful. I’ll talk to our team about raising the limit and post an update here shortly.

Hi @talkingant after discussing with our team, we’re planning on upping the gas cap limit to 10x the block gas limit but because of the change required we likely won’t be able to update this until the Istanbul fork next week. We pushed the documentation change for now https://infura.io/docs/ethereum/json-rpc/eth_estimateGas to show the limit at 2x block gas limit and we will update the docs when we are able to up this to 10x next week. Are you able to workaround this issue for now? How disruptive is this to your users?

Thanks for the quick response, that sounds good! In the meantime I worked around with some caching.

Hi @egalano, do you have any news regarding the planned update from 2x to 10x?

As far as I can see, the new limit would still be significantly below the 500 million gas limit imposed by the Parity client https://github.com/paritytech/parity-ethereum/pull/8943.

Thanks in advance!

Hi Robert. We released the update in early December to set the limit to 10X. Is that still not sufficient for your purposes? We tried to set a lower limit to start but would be open to raising it if there is a good reason to. We don’t want to set it too high unnecessarily.

Thank you for the quick response @egalano!

I’m sorry, I wasn’t aware that you had already raised it to 10X in December.
According to https://infura.io/docs/ethereum/json-rpc/eth_call, the limit is still at 2x.

We are currently running extensive gas tests for our application. I will let you know if we still run into the limit. Thanks!

Our project is hitting the 10X gascap limit. Can the limit please be made higher?

@mudgen, can you provide more details on what you’re executing that is hitting that gas cap? If you don’t want to discuss in public you can contact us at support@infura.io and we can discuss over email (please mention myself and EG in the email so we are sure it is routed to us). That said, if you’re open to discussing it publicly that’s our preferred method as it helps the rest of the community learn as well.

Hi Ryan, thanks for looking into this.
Try executing the winners function with raffleId 0 here: https://etherscan.io/address/0x144d196bf99a4eca33afe036da577d7d66583db6#readContract
You can see the source code for it in the RaffleContract.sol file on Etherscan.

Getting an out of gas error there. It is a read-only function but it looks like it is hitting Infura’s gas cap limit for read only view functions.

The winners function does a lot of computation to calculate winners of a raffle.

Hi @mudgen, so I’m not very versed in smart contract development, but I think as currently implemented it’ll be very hard to make a version of winners that doesn’t consume a very large amount of gas. I suspect that even if we raised the gas cap enough for the current state to succeed, it’ll just hit the new cap again as new entrants are added.

I think in general smart contract calls need to be very limited in the data they access and should avoid iterating through state data (e.g. raffle.raffleItems and raffle.entrants). Unfortunately since I’m also not a solidity developer I don’t know where best to go for advice on making your contract more gas efficient, but I’ll ask around in the team to see if anyone has pointers on what you could do or where you could go to try to make the contract work within existing gas constraints.

Thanks. I am actually using another version of the winners function that enables me to get information for one winner at a time: winners(uint256 _raffleId, address[] memory _entrants)

It works for all 911 entrants except for 2 which run out of gas. It almost has enough gas.

I know I could rearchitect things to avoid using as much gas in view functions. But it would be useful to have more breathing room, which is why I posted here about it.