`vm.resumeGasMetering` can cause tests with expected reverts to fail with an `OutOfGas` error
Component
Forge
Have you ensured that all of these are up to date?
- [X] Foundry
- [X] Foundryup
What version of Foundry are you on?
forge 0.2.0 (6672134 2023-08-08T00:21:59.824374000Z)
What command(s) is the bug in?
forge test
Operating System
macOS (Apple Silicon)
Describe the bug
After calling vm.pauseGasMetering, calling vm.resumeGasMetering within a reverting external call causes tests to fail with an OutOfGas error.
There seem to broadly be inconsistencies and unexpected behavior with the GasMetering functions; see #5491 as possibly related.
A reproduction, which eliminates self-external-calls as the issue.
import {Test, Vm} from "forge-std/Test.sol";
contract RevertingExternalContract {
error MyError();
Vm private constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
function externalReverts() external {
vm.resumeGasMetering();
revert MyError();
}
}
contract MeteringTest is Test {
error MyError();
RevertingExternalContract externalContract;
function setUp() public {
externalContract = new RevertingExternalContract();
}
function testSelfNormalRevert() public {
vm.expectRevert(MeteringTest.MyError.selector);
this.selfReverts();
}
function testSelfMeteringRevert() public {
vm.pauseGasMetering();
vm.expectRevert(MeteringTest.MyError.selector);
this.selfReverts();
}
function testExternalNormalRevert() public {
vm.expectRevert(RevertingExternalContract.MyError.selector);
externalContract.externalReverts();
}
function testExternalMeteringRevert() public {
vm.pauseGasMetering();
vm.expectRevert(RevertingExternalContract.MyError.selector);
externalContract.externalReverts();
}
function testExternalMeteringManualCheck() public {
vm.pauseGasMetering();
(bool success,) = address(this).call(abi.encodeWithSelector(this.selfReverts.selector));
assertEq(success, false);
}
function selfReverts() external {
vm.resumeGasMetering();
revert MyError();
}
}
Output of running these tests:
[PASS] testSelfNormalRevert() (gas: 3953)
Test result: FAILED. 2 passed; 3 failed; 0 skipped; finished in 402.42µs
Ran 1 test suites: 2 tests passed, 3 failed, 0 skipped (5 total tests)
Failing tests:
Encountered 3 failing tests in test/Metering.t.sol:MeteringTest
[FAIL. Reason: EvmError: OutOfGas] testExternalMeteringManualCheck() (gas: 9223372036854754743)
[FAIL. Reason: EvmError: OutOfGas] testExternalMeteringRevert() (gas: 9223372036854754743)
[FAIL. Reason: EvmError: OutOfGas] testSelfMeteringRevert() (gas: 9223372036854754743)
Unable to reproduce the OutOfGas error but am able to reproduce the huge gas consumption described in https://github.com/foundry-rs/foundry/issues/5491
Ran 5 tests for test/Metering.t.sol:MeteringTest
[PASS] testExternalMeteringManualCheck() (gas: 18302628885633699948)
[PASS] testExternalMeteringRevert() (gas: 18302628885633699399)
[PASS] testExternalNormalRevert() (gas: 8627)
[PASS] testSelfMeteringRevert() (gas: 18302628885633699354)
[PASS] testSelfNormalRevert() (gas: 4005)
Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 3.72ms (611.34µs CPU time)
With the --isolate flag
Ran 5 tests for test/Metering.t.sol:MeteringTest
[PASS] testExternalMeteringManualCheck() (gas: 6248)
[PASS] testExternalMeteringRevert() (gas: 3200)
[PASS] testExternalNormalRevert() (gas: 32191)
[PASS] testSelfMeteringRevert() (gas: 3156)
[PASS] testSelfNormalRevert() (gas: 27569)
Leaving the open as it is clear this kind of gas consumption could lead to and OutOfGas error