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

EvmError: OutOfGas with vm.pauseGasMetering() enabled #3971

Closed
2 tasks done
joejordan opened this issue Dec 27, 2022 · 14 comments
Closed
2 tasks done

EvmError: OutOfGas with vm.pauseGasMetering() enabled #3971

joejordan opened this issue Dec 27, 2022 · 14 comments
Labels
A-cheatcodes Area: cheatcodes C-forge Command: forge T-bug Type: bug

Comments

@joejordan
Copy link
Contributor

Component

Forge

Have you ensured that all of these are up to date?

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge 0.2.0 (02cb1c0 2022-12-26T21:26:07.6623747Z)

What command(s) is the bug in?

No response

Operating System

Windows

Describe the bug

I have created a repo to replicate the issue here: https://github.com/joejordan/foundry-OutOfGas-error

My use case was that I was attempting to seed an NFT contract upon deploy with some randomized data. This data was to be stored in bytes chunks on-chain. Past a certain number of entries to seed, Forge fails with an EvmError: OutOfGas error, even when vm.pauseGasMetering() is enabled before any gas is used in the script.

You can tweak the variables in NFT.sol to see the script work successfully. If run as-is the script should fail with an OutOfGas error. More details are included in the repo comments.

@joejordan joejordan added the T-bug Type: bug label Dec 27, 2022
@rkrasiuk rkrasiuk added C-forge Command: forge A-cheatcodes Area: cheatcodes labels Jan 4, 2023
@JuanCoRo
Copy link

Just bumped into this as well. Here's another test to reproduce it. Note that with or without vm.pauseGasMeter(), it fails with an OutOfGas error at the same iteration: 129053.

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.6.2 <0.9.0;

import "forge-std/Test.sol";

contract OutOfGas is Test {

    function testOutOfGas() public {
        vm.pauseGasMetering();

        for(uint256 i = 0; i <= 129100; i++){
            console2.log("Run #", i, gasleft());
        }
    }
}

@brockelmore
Copy link
Member

brockelmore commented Jan 20, 2023

Sorry about this. I've started looking into this. Will try to get this sorted today

@brockelmore
Copy link
Member

Just bumped into this as well. Here's another test to reproduce it. Note that with or without vm.pauseGasMeter(), it fails with an OutOfGas error at the same iteration: 129053.

// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.6.2 <0.9.0;

import "forge-std/Test.sol";

contract OutOfGas is Test {

    function testOutOfGas() public {
        vm.pauseGasMetering();

        for(uint256 i = 0; i <= 129100; i++){
            console2.log("Run #", i, gasleft());
        }
    }
}

turns out, this is solidity just being very dumb with memory:
IMAGE 2023-01-20 10:21:30

adding:

memory_limit = 43554432

to foundry.toml fixes the above. and should probably open an issue on solc cuz this really shouldn't happen.

@brockelmore
Copy link
Member

ethereum/solidity#13885

Creating a solc issue for this. current work around, in your foundry.toml add the following line and adjust as needed:

memory_limit = 33554432

default is 33.5mb, you can bump it up as far as you want

@brockelmore
Copy link
Member

alternatively you can manually memory manage like so:

    function testOutOfGas() public {
        vm.pauseGasMetering();

        bytes32 free_mem;
        assembly ("memory-safe") {
            free_mem := mload(0x40)
        }
        for(uint256 i = 0; i <= 129100; i++){
            console2.log("Run #", i, gasleft());
            assembly ("memory-safe") {
                mstore(0x40, free_mem)
            }
        }
    }

@JuanCoRo
Copy link

Thank you for debugging this! Will use the foundry.toml workaround until the memory leak in loops is fixed. And good to know that second workaround 👌
If you don't mind the newb question, how is the image you posted generated?

@brockelmore
Copy link
Member

brockelmore commented Jan 20, 2023

Not a newb question, i hopped into revm source, adding some debugging prints, and used the patch mechanism in foundry's Cargo.toml pointing to a local version of revm

@JuanCoRo
Copy link

Not newb, indeed. Thanks!

@mds1
Copy link
Collaborator

mds1 commented Mar 10, 2023

Closing this per the above solutions/workarounds, since there are no issues on the forge side here

@jdbertron
Copy link

That workaround doesn't work for me. The function I'm testing works fine on Goerli, but for some reason, it gets a "EvmError: OutOfGas" even when I set
[profile.default]
memory_limit = 1073741824
gas_limit = "18446744073709551615"
with a vm.pauseGasMetering(); right before the call.

@mds1
Copy link
Collaborator

mds1 commented Apr 12, 2023

Did you try both workarounds (the increased memory limit and the manual memory management)? If so can you open a new issue with steps to reproduce?

@jdbertron
Copy link

Yes, sure. There are two problems with this test. One is that one call hangs forge, I'll file a separate issue. The other is the above.
You can simply clone the repo and run

forge test --ffi -vvvv -m "testCanRegisterPuzzle"

In that test the last 2 calls are problematic. Just comment the one that hangs.
As I said, I currently have memory_limit = 1073741824
gas_limit = "18446744073709551615" in my foundry.toml default profile.

I shrank it down to 3 puzzles, but the original has 32, which have been working fine on Goerli so far e.g. https://goerli.etherscan.io/tx/0xc2cb33930b4008252cb934dc796a50e9607ec104dd32b64a6e434a6bcc2c5f71

@drortirosh
Copy link

Another workaround, is open a new context with "external" call:

    function thisIsMyTest() public {
        for(uint256 i = 0; i <= 129100; i++){ 
            // "this" is important: you WANT to open a new context (required if inner function is "external")
            this.innerFunction();
        }
    }

    function innerTest() external {
       // put code that wastes memory here. 
       // uses a fresh memory context each time (with the same storage variables)
    }

@varun-doshi
Copy link

That workaround doesn't work for me. The function I'm testing works fine on Goerli, but for some reason, it gets a "EvmError: OutOfGas" even when I set [profile.default] memory_limit = 1073741824 gas_limit = "18446744073709551615" with a vm.pauseGasMetering(); right before the call.

I've been having the same issue and it turns out on increasing the memory, it works. But I'd like to know whats the effect of increasing the memory on the system running the code and what is the maximum value for the memory_limit ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-cheatcodes Area: cheatcodes C-forge Command: forge T-bug Type: bug
Projects
None yet
Development

No branches or pull requests

8 participants