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

estimateGas reverts, but the transaction succeeds with a hardcoded gasLimit #664

Closed
platocrat opened this issue Apr 28, 2021 · 29 comments
Closed
Labels
C-bug Category: bugs S-confirmed Status: A confirmed bug

Comments

@platocrat
Copy link
Contributor

platocrat commented Apr 28, 2021

Describe the bug
In ChainLink's LinkToken integration tests, 3/7 tests fail. Those that do fail involve contract calls that should revert. However, instead of a revert message being returned, the familiar cannot estimate gas error is thrown.

To Reproduce
Steps to reproduce the behavior:

  1. git clone https://github.com/smartcontractkit/LinkToken.git
  2. git checkout feature/ovm-integration-upstream-changes
  3. Start the docker containers under optimism/ops to start a local OE network
  4. Back in the LinkToken project directory, run: yarn && yarn setup && yarn test:integration../test/v0.7/bridge/optimism/OVM_L2ERC20Gateway.test.ts
  5. See the familiar error:
Error: cannot estimate gas; transaction may fail or may require manual gas limit

Expected behavior
A transaction that fails estimateGas should not succeed with a hardcoded gasLimit

Related issues
#474
#543

@platocrat platocrat added A-geth C-bug Category: bugs labels Apr 28, 2021
@transmissions11
Copy link
Contributor

Hasn't there been an issue up for this for a while?

@platocrat
Copy link
Contributor Author

Hasn't there been an issue up for this for a while?

yes. #474 is one related issue and #543 is perhaps another

@platocrat
Copy link
Contributor Author

platocrat commented Apr 28, 2021

@K-Ho closing since this is a duplicate of #474

@K-Ho
Copy link
Contributor

K-Ho commented Apr 28, 2021

@platocrat The expected behavior listed here isn't actually right. Chainlink is getting UNPREDICTABLE_GAS_LIMIT when trying to estimateGas but the tx succeeds with a static gasLimit.

@K-Ho K-Ho reopened this Apr 28, 2021
@transmissions11
Copy link
Contributor

transmissions11 commented Apr 28, 2021

@platocrat The expected behavior listed here isn't actually right. Chainlink is getting UNPREDICTABLE_GAS_LIMIT when trying to estimateGas but the tx succeeds with a static gasLimit.

@K-Ho I've noticed that txs always succeed with a static gas limit actually...

Here's a reproduction branch: https://github.com/Rari-Capital/nova/tree/gasLimitNoRevertRepro

@platocrat
Copy link
Contributor Author

@K-Ho just to confirm that this really is the same issue that we see for contract calls that revert, here are the full error messages for the 2 Waffle-based tests that fail with this error:

Screen Shot 2021-04-28 at 2 27 23 PM

I highlighted the code=UNPREDICTABLE_GAS_LIMIT field, which you can see appears in both error messages.

NOTE: I can confirm that specifying the gas limit to 8999999 for the calls in these two tests does makes the txs succeed.

@snario snario changed the title LinkToken: reverting contract calls return familiar cannot estimate gas error estimateGas reverts, but the transaction succeeds with a hardcoded gasLimit Apr 28, 2021
@snario
Copy link
Contributor

snario commented Apr 28, 2021

This is not a duplicate of #474. That issue describes “estimateGas does not provide the revert reason” and this issue describes: “estimateGas reverts, but the transaction succeeds with a hardcoded gasLimit”

@tynes
Copy link
Contributor

tynes commented Apr 30, 2021

I believe the problem is with simulateMessage(). It is the main difference between a regular transaction and eth_call, eth_estimateGas uses eth_call

@platocrat
Copy link
Contributor Author

platocrat commented May 3, 2021

@tynes @snario I re-ran the integration test for the hardhat example in the monorepo and get an odd type error.

The error is below:

   Error: invalid BigNumber string (argument="value", value="auto", code=INVALID_ARGUMENT, version=bignumber/5.1.0)
      at Logger.makeError (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/logger/src.ts/index.ts:205:28)
      at Logger.throwError (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/logger/src.ts/index.ts:217:20)
      at Logger.throwArgumentError (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/logger/src.ts/index.ts:221:21)
      at Function.BigNumber.from (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/bignumber/src.ts/bignumber.ts:240:27)
      at JsonRpcProvider.provider.getGasPrice (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/packages/hardhat-ovm/src/index.ts:225:26)
      at Wallet.<anonymous> (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/abstract-signer/src.ts/index.ts:139:36)
      at step (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/abstract-signer/lib/index.js:48:23)
      at Object.next (/Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/abstract-signer/lib/index.js:29:53)
      at /Users/platocrat/Documents/GitHub/OptimismPBC/Optimism/optimism/node_modules/@ethersproject/abstract-signer/lib/index.js:23:71
      at new Promise (<anonymous>)

The error points to optimism/packages/hardhat-ovm/src/index.ts:225:26.
Note that this error is received after pulling and building @tynes's branch from ethereum-optimism/optimism/pull/721.

@K-Ho From this new error shown above, I believe ethereum-optimism/optimism/pull/721 should warrant a separate GH issue to document this error in hardhat-ovm
I also think we can conclude that the original issue here is resolved as per Kevin's response earlier:

@platocrat The expected behavior listed here isn't actually right. Chainlink is getting UNPREDICTABLE_GAS_LIMIT when trying to estimateGas but the tx succeeds with a static gasLimit.

@gakonst
Copy link
Contributor

gakonst commented May 3, 2021

@platocrat this error you got is because there is no gasPrice: 0 parameter in your hardhat config here, whereas the examples now all use it.

@platocrat
Copy link
Contributor Author

I'm confirming that this issue is fixed by ethereum-optimism/optimism/pull/721!!

@gakonst
Copy link
Contributor

gakonst commented May 3, 2021

What's the exact fix by 721? Do you get proper revert messages?

@platocrat
Copy link
Contributor Author

What's the exact fix by 721? Do you get proper revert messages?

The fix appears to be that we no longer need to specify a hardcoded gasLimit.

@tynes
Copy link
Contributor

tynes commented May 4, 2021

The fix appears to be that we no longer need to specify a hardcoded gasLimit.

This is the result of the fix

What's the exact fix by 721? Do you get proper revert messages?

The problem was that the interface between userland and the system contracts was not defined. ExecutionManager.run returned a different ABI encoded returndata compared to ExecutionManager.simulateMessage. The returndata was parsed by simply slicing bytes which worked when the returndata was a single type but then broke when it was multiple types.

eth_estimateGas calls eth_call under the hood a bunch of times, so the problem was also present in eth_call - basically the return value of the eth_call wouldn't be deserialized correctly by l2geth and it would interpret the returndata as indicating that the transaction reverted when it actually didn't. This would result in the message Error: cannot estimate gas; transaction may fail or may require manual gas limit because l2geth thought that the tx would revert

@platocrat
Copy link
Contributor Author

platocrat commented May 4, 2021

@K-Ho @tynes @snario
Re-ran integration tests of ChainLink's old LinkToken branch feature/ovm-integration-upstream-changes using a newly fetched and rebuilt version of the optimism/ops containers.

The tests that are supposed to revert still revert with the same UNPREDICTABLE_GAS_LIMIT error:

Error: cannot estimate gas; transaction may fail or may require manual gas limit

I also confirmed that adding a hardcoded gasLimit of 8999999 is still a workaround.

Update

  1. Running the tests again without specifying a hardcoded gasLimit nor gasPrice results in the UNPREDICTABLE_GAS_LIMIT error in all tests.
  2. Adding a hardcoded gasPrice: 0 to all contract calls still results in all tests failing with the error above.
  3. Finally, adding a hardcoded gasPrice: 0 and gasLimit: 8999999 to all contract calls results in the familiar error described in ethereum-optimism/optimism/issues/717 in 2/4 of the failing tests (the other 2 that fail are dependent on the first succeeding.

What's odd about point 3 is that only 3/7 tests pass, and of those that pass, they involve contract calls that revert, which is the opposite of what was happening previously.
Previously, 4/7 tests were passing, but those that were failing involved contract calls that revert.

@K-Ho
Copy link
Contributor

K-Ho commented May 4, 2021

@platocrat - are you still seeing this estimateGas error with the Waffle ERC20 Example tests? If so, I think the next step would be to comment out parts of execution until we nail down the exact section that causes estimateGas to fail

@platocrat
Copy link
Contributor Author

Regarding #664 and #721:

  1. l1-l2-deposit-withdrawal outside of monorepo (because of current issue with installing @eth-optimism/contracts as a dep when inside monorepo)
    a. I ran the optimism/ops containers from the l2geth/fix-returndata branch (from pull/721) and ran the l1-l2-deposit-withdrawal script.
    b. Without specifying gasPrice: 0 nor gasLimit: 8999999, none of the transactions in the example.js script will be submitted successfully.
    c. Specifying only gasPrice: 0 in every contract call results in the errors thrown, as in issue/664, for every call
    d. Specifying both gasPrice: 0 nor gasLimit: 8999999 results in the script working as expected, all transactions are submitted successfully
  2. Waffle-ERC20-Example within monorepo
    e. [Tests] As @K-Ho pointed out when running the Waffle tests in optimism/examples/waffle, all tests pass without any changes.
    f. This means that we do NOT need to hardcode a gasPrice nor gasLimit anywhere
  3. Truffle-ERC20-Example outside of monorepo (no concerning reason, just quicker for me -- I believe we can now finalize docs: add truffle example + ci #666 ):
    g. [Tests] TL;DR is that tests fail ONLY if gasPrice: 0 is not set everywhere, including in all migrations scripts, when running tests
    h. [Deployments] Running migrations is successful after settinggasPrice: 0 in migrations file(s).
  4. optimism-tutorial within monorepo
    i. [Tests] Will only pass if we set gasPrice: 0 in the hardhat.config.*
    j. [Deployments] Successful even WITHOUT a hardcoded gasLimit and gasPrice

cc: @snario @gakonst @K-Ho @tynes

@platocrat
Copy link
Contributor Author

platocrat commented May 10, 2021

@K-Ho @snario
Was able to repro this error in a couple of ChainLink's integration tests.

Repro case:

  1. Git clone LinkToken: git clone https://github.com/smartcontractkit/LinkToken.git
  2. Checkout branch: git checkout feature/oe-token
  3. Install deps: yarn
  4. Clean setup: yarn clean && yarn setup
  5. Comment out line 8 in test/helpers/optimism/index.ts
  6. Run tests: yarn test --network optimism ./test/v0.7/bridge/token/LinkTokenChild.test.ts
  7. See error in 2/3 tests

Screen Shot 2021-05-10 at 2 28 14 PM

@smartcontracts
Copy link
Contributor

@platocrat I'll take a look at this in an hour or so.

@smartcontracts
Copy link
Contributor

smartcontracts commented May 10, 2021

@platocrat I'm unable to reproduce this on v0.3.0-rc. We might've fixed the problem in that branch.

I was able to reproduce on v0.3.0-rc by commenting out this line: https://github.com/smartcontractkit/LinkToken/blob/8731d538f1290ac6bf6bdcd6a5aa92ae8a8125d5/test/helpers/optimism/index.ts#L8

@platocrat
Copy link
Contributor Author

platocrat commented May 10, 2021

You need to comment out line 8 in LinkToken/test/helpers/optimism/index.ts

@smartcontracts smartcontracts added the S-confirmed Status: A confirmed bug label May 10, 2021
@snario
Copy link
Contributor

snario commented May 10, 2021

The above ChainLink test failure seems unrelated to what this Github issue was created for. ChainLink is seeing #474 (reference) I believe — revert reasons not propagating up correctly.

@smartcontracts
Copy link
Contributor

I was able to fix this problem by using v0.3.0 (now merged into master!) and changing the tests as follows:

  1. Remove https://github.com/smartcontractkit/LinkToken/blob/8731d538f1290ac6bf6bdcd6a5aa92ae8a8125d5/test/helpers/optimism/index.ts#L8
  2. Modify tests:
     it('can NOT deposit without  access (gateway role)', async () => {
-      const depositTx = await l2Token.deposit(oe.l2Wallet.address, 100, h.optimism.TX_OVERRIDES_OE_BUG)
-      // TODO: fetch revert reason
-      // revert: LinkTokenChild: missing role
-      await h.txRevert(depositTx.wait())
+      await expect(
+        l2Token.deposit(oe.l2Wallet.address, 100, h.optimism.TX_OVERRIDES_OE_BUG)
+      ).to.be.revertedWith('No access')
     })
     it('owner can migrate to a new gateway', async () => {
@@ -221,10 +220,11 @@ describe(`LinkTokenChild ${Versions.v0_7}`, () => {
       const removeAccessTx = await l2Token.removeAccess(owner.address)
       await removeAccessTx.wait()
       // Owner deposit fails
-      const depositTx = await l2Token.deposit(owner.address, 100, h.optimism.TX_OVERRIDES_OE_BUG)
       // TODO: fetch revert reason
       // revert: LinkTokenChild: missing role
-      await h.txRevert(depositTx.wait())
+      await expect(
+        l2Token.deposit(owner.address, 100, h.optimism.TX_OVERRIDES_OE_BUG)
+      ).to.be.revertedWith('No access')
       // TODO: owner renounce ownership
     })

@snario
Copy link
Contributor

snario commented May 10, 2021

I'm going to close this issue. If something from the above conversation is still unclear, let's open a new issue.

@snario snario closed this as completed May 10, 2021
@gakonst
Copy link
Contributor

gakonst commented May 11, 2021

Of note, Kelvin's approach above is the correct way to do it in JS. The way the tests were written before, they'd fail even in EVM mode because you're awaiting a failing transaction with an overridden gas limit.

@K-Ho
Copy link
Contributor

K-Ho commented May 12, 2021

re-opening this issue - here's Chainlink still seeing this issue appear:
This PR is green with static gasLimit: smartcontractkit/LinkToken#33
This PR is red with NO static gasLimit: smartcontractkit/LinkToken#37 (just this one change)
This is the failure: https://github.com/smartcontractkit/LinkToken/runs/2569267264?check_suite_focus=true (UNPREDICTABLE_GAS_LIMIT)

@K-Ho K-Ho reopened this May 12, 2021
@platocrat
Copy link
Contributor Author

platocrat commented May 12, 2021

I was able to repro smartcontractkit/LinkToken#37 locally.
Going to inspect further

@platocrat
Copy link
Contributor Author

platocrat commented May 12, 2021

I resolved the UNPREDICTABLE_GAS_LIMIT errors in the two tests in smartcontractkit/LinkToken#37 using Kelvin's approach earlier above:

      it('can NOT deposit without  access (gateway role)', async () => {
-      const mintTx = await l2Token.mint(oe.l2Wallet.address, 100, optimism.TX_OVERRIDES_BUG)
-      // TODO: fetch revert reason
-      // revert: 'No access'
-      await h.txRevert(mintTx.wait())
+      const mintTx = l2Token.mint(oe.l2Wallet.address, 100, optimism.TX_OVERRIDES_BUG)
+      await expect(mintTx).to.be.revertedWith('No access')
})
      it('owner can migrate to a new gateway', async () => {
-      const mintTx = await l2Token.mint(owner.address, 100, optimism.TX_OVERRIDES_BUG)
-      // TODO: fetch revert reason
-      // revert: 'No access'
-      await h.txRevert(mintTx.wait())
+      const mintTx = l2Token.mint(owner.address, 100, optimism.TX_OVERRIDES_BUG)
+      await expect(mintTx).to.be.revertedWith('No access')
})

Note
The above changes were communicated to @krebernisak in the #optimism-chainlink channel in Synthetix's discord

@snario
Copy link
Contributor

snario commented May 12, 2021

As @gakonst mentioned, it looks like the test was just written incorrectly.

@snario snario closed this as completed May 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: bugs S-confirmed Status: A confirmed bug
Projects
None yet
Development

No branches or pull requests

7 participants