Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Undocumented change in eth_call behavior? #21108

Closed
swaldman opened this issue May 21, 2020 · 4 comments
Closed

Undocumented change in eth_call behavior? #21108

swaldman opened this issue May 21, 2020 · 4 comments

Comments

@swaldman
Copy link
Contributor

swaldman commented May 21, 2020

System information

Geth version: v1.9.13
OS & Version: Linux

Expected behaviour

In prior versions, eth_call (with gas price and limit explicitly set) succeeded regardless of the actual eth balance of the calling account. One could access return values in a read only way, even when the sender account had no gas.

Actual behaviour

After upgrading to v1.9.13 (from an earlier version, alas I'm not sure which), eth_call transactions from accounts with no gas fail with "insufficient balance to pay for gas [code=-32000]"

Comment

The new behavior is a significant break from prior behavior, where applications (well, my applications) specified arbitrary unfunded accounts to hit accessor methods without intending to modify blockchain state.

For many applications, the issue is mostly mitigated by the fact that, post-v1.9.12, when sender is unspecified, the sender defaults to 0x0000000000000000000000000000000000000000, which turns out to be a very well funded account. eth_call transactions from this address won't fail for lack of gas unless they specify very large quantities in the value field of the transaction.

But for applications which did specify a sender account, gas price, and gas limit, this is a significant breaking change of behavior. From my perspective, the new behavior is inconvenient. My preference would be that the original behavior be restored. If the new behavior is retained -- one might argue it's "correct", in that it more accurately simulates what would occur if a true transaction were attempted -- the change should at least be prominently documented.

There is a documented breaking change to eth_call in v1.9.12, for the case in which the sender account is unspecified. No breaking change is documented or warned for the case where a sender is specified.

For an example of what the new behavior might break, see https://www.sbt-ethereum.io/tutorials/using-a-smart-contract-i.html#accessing-read-only-methods-of-an-smart-contract. People following this tutorial from the start will have defined a specific sender account (in Getting Started), but not funded it. Previously, they could hit methods for read-only access from their new accounts without issue. Now those attempts will fail.

Thank you!

@swaldman
Copy link
Contributor Author

The source of the undocumented breaking change is this commit: 39f5023

Previously, when the EVM in which eth_call is executed was created, the sender's balance was set to math.MaxBig256. Now the sender's balance is left alone, but gasPrice is set to 0 if and only if gasPrice is not explicitly specified as an argument.

So previously, calls to eth_call with gasPrice and gas both set would always succeed (or at least they would never fail for lack of gas). Now the same calls will fail if the sender account is unfunded, unless gasPrice is left unspecified or explicitly set to zero.

swaldman added a commit to swaldman/consuela that referenced this issue May 24, 2020
…geStrict, leaving gasPrice unset in the nonstrict version. See ethereum/go-ethereum#21108
@holiman
Copy link
Contributor

holiman commented Jul 2, 2020

We changed this in the commit you found, for several reasons (see e.g. #16999)

  • We now do the same thing parity does, which is nice,
  • Previously, the return value from the call would vary depending on whatever accounts the local node had. This is quirky, especially when using a remote node for RPC calls.

So now we do use the 0x00 account when it's unspecified, and we use gasPrice of zero, so that even an unfunded account can do gas-measurements and test-calls. If you need to actually have some 'ether' for the call, you can just specify a sender, and add an override to how much ether you want the sender-account to have.

@holiman holiman closed this as completed Jul 2, 2020
@swaldman
Copy link
Contributor Author

swaldman commented Jul 3, 2020

I agree the dependency-on-local-node accounts when a sender account was unspecified was bad. Fixing that was documented and good. That when an account was specified, calls that used to succeed suddenly failed was not so good, and I think should have been documented, as far as I can tell was not. In any case, once found the PR and understood the behavior, it was easy to modify my code to work again by not setting a gas price unless a new strict flag is set. So I'm over it, and always very grateful for work.

@fjl fjl removed the status:triage label Aug 27, 2020
@MicahZoltu
Copy link
Contributor

MicahZoltu commented Feb 15, 2021

Any chance this could get revisited? Specifically, if you specify a gasPrice (because some contracts have behavior changes based on GASPRICE opcode) but you do not specify a gasLimit then a gasLimit of 125,000,000 will be supplied which will result in a 12.5 ETH gas requirement (at today's gas prices) and cause a failure for most average users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants