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

Unexpected OutOfFunds Error during Testing, but Works with Forge Script #9091

Closed
1 of 2 tasks
mhxw opened this issue Oct 11, 2024 · 13 comments
Closed
1 of 2 tasks

Unexpected OutOfFunds Error during Testing, but Works with Forge Script #9091

mhxw opened this issue Oct 11, 2024 · 13 comments
Labels
T-bug Type: bug T-needs-triage Type: this issue needs to be labelled

Comments

@mhxw
Copy link

mhxw commented Oct 11, 2024

Component

Forge, Foundryup

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

  • Foundry
  • Foundryup

What version of Foundry are you on?

forge 0.2.0 (0ed43ce 2024-10-11T00:20:43.510778000Z)

What command(s) is the bug in?

forge fmt && forge clean && forge build && forge test -vvv

Operating System

macOS (Apple Silicon)

Describe the bug

I encountered an unexpected OutOfFunds error when running tests for the following contract (only core parts are shown below). However, when deploying and executing the contract using forge script, everything works perfectly, and the assets flow as expected.

Here is a simplified version of the code that led to the issue:

// Example core contract code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import {IWETH} from "./interfaces/IWETH.sol";
import {Address} from "openzeppelin/utils/Address.sol";
import {console2} from "forge-std/console2.sol";

interface IB{
    event TransferredReserveAsset(
        address indexed sender, address indexed recipient, uint256 amount
    );

    function transferNativeAsset(address to, uint256 amount)
    external;
}

contract B is IB  {
    function transferNativeAsset(address to, uint256 amount)
    external
    onlyAContract
    {
//        function sendValue(address payable recipient, uint256 amount) internal {
//            if (address(this).balance < amount) {
//            revert AddressInsufficientBalance(address(this));
//            }
//
//            (bool success, ) = recipient.call{value: amount}("");
//            if (!success) {
//            revert FailedInnerCall();
//            }
//        }
        Address.sendValue(payable(to), amount);

        emit TransferredReserveAsset(address(this), to, amount);
    }
}

contract A {

    IB public bContract;
    IWETH public WETH;

    function add(uint256 ethLiquidity) public {
        console2.log(
            "bContractInfo1:", address(bContract), address(bContract).balance
        );
        bContract.transferNativeAsset(address(this), ethLiquidity);
        console2.log(
            "bContractInfo2:", address(bContract), address(bContract).balance
        );
        WETH.deposit{value: ethLiquidity}();
    }
}

Traces

Traces:
  [5621773] XXXTest::testAddXXX()
    │   │   ├─ [0] console::log("bContractInfo1:", 0xB7293b069fFaA41EAb356d0B85b62aa319AAFa22, 12583485206564041 [1.258e16]) [staticcall]
    │   │   │   └─ ← [Stop] 
    │   │   ├─ [175] 0xB7293b069fFaA41EAb356d0B85b62aa319AAFa22::transferReserveAsset(factory: [0xD2597C1A4f0610A32e5f46AbE5B1014E29cb083a], 10631528916991609 [1.063e16])
    │   │   │   ├─ [0] 0x0000000000000000000000000000000000000000::transferReserveAsset(factory: [0xD2597C1A4f0610A32e5f46AbE5B1014E29cb083a], 10631528916991609 [1.063e16]) [delegatecall]
    │   │   │   │   └─ ← [Stop] 
    │   │   │   └─ ← [Return] 
    │   │   ├─ [0] console::log("bContractInfo2:", 0xB7293b069fFaA41EAb356d0B85b62aa319AAFa22, 12583485206564041 [1.258e16]) [staticcall]
    │   │   │   └─ ← [Stop] 
    │   │   ├─ [0] weth::deposit{value: 10631528916991609}()
    │   │   │   └─ ← [OutOfFunds] EvmError: OutOfFunds
    │   │   └─ ← [Revert] EvmError: Revert
    │   └─ ← [Revert] EvmError: Revert
    └─ ← [Revert] EvmError: Revert


Steps to Reproduce:

  1. Write a test for the contract.
  2. Run the test.
  3. Observe the OutOfFunds error during the execution of the test.
  4. However, when using forge script to deploy and execute the same contract, everything runs smoothly, and no errors are encountered.

Expected Behavior:

The contract should function properly during testing, just like it does when using forge script.

Actual Behavior:

Tests fail with an OutOfFunds error, but no such error occurs when using forge script.

@mhxw mhxw added T-bug Type: bug T-needs-triage Type: this issue needs to be labelled labels Oct 11, 2024
@github-project-automation github-project-automation bot moved this to Todo in Foundry Oct 11, 2024
@grandizzy
Copy link
Collaborator

grandizzy commented Oct 11, 2024

@mhxw could you please add the test too,is that a fuzz test or regular? Do you run test with isolate or gas-report flag? Thank you

@grandizzy
Copy link
Collaborator

I see, let me try, I suspect contract is not made persistent so it is replaced with the one from fork, here's book ref https://book.getfoundry.sh/cheatcodes/make-persistent

@mhxw
Copy link
Author

mhxw commented Oct 11, 2024

I see, let me try, I suspect contract is not made persistent so it is replaced with the one from fork, here's book ref https://book.getfoundry.sh/cheatcodes/make-persistent

Thank you for your response, and I appreciate the suggestion. I'll give it a try and look into making the contract persistent as you mentioned.

@grandizzy
Copy link
Collaborator

I am not able to recreate the test but looking at traces

    │   │   ├─ [0] weth::deposit{value: 10631528916991609}()
    │   │   │   └─ ← [OutOfFunds] EvmError: OutOfFunds

make sure msg.sender has enough funds for this operation, see

@mhxw
Copy link
Author

mhxw commented Oct 11, 2024

I am not able to recreate the test but looking at traces

    │   │   ├─ [0] weth::deposit{value: 10631528916991609}()
    │   │   │   └─ ← [OutOfFunds] EvmError: OutOfFunds

make sure msg.sender has enough funds for this operation, see

Yes, that's exactly what I did!

vm.startPrank(platformAdmin);
vm.deal(platformAdmin, 100 ether);

@grandizzy
Copy link
Collaborator

was this done before or after createSelectFork call?

@mhxw
Copy link
Author

mhxw commented Oct 11, 2024

First, I call createSelectFork to fork the chain. After that, I deploy the contract, and finally, I execute the necessary functions.

@grandizzy
Copy link
Collaborator

cool, had a look, it does seem like a legit failure, if you modify line https://github.com/mhxw/launchpad/blob/a71891b86a69ff55f0abb1bb079a2639254be77c/src/TokenFactory.sol#L438 and instead
Address.sendValue(payable(config.tokenVaultAddress), reverseAmountInActual + projectFee);
you put something like Address.sendValue(payable(config.tokenVaultAddress), 1); then deposit goes through (but test eventually fails after with different message, probably expected)

    │   │   ├─ [23846] weth::deposit{value: 10631528916991609}()
    │   │   │   ├─ emit Deposit(param0: factory: [0xD2597C1A4f0610A32e5f46AbE5B1014E29cb083a], param1: 10631528916991609 [1.063e16])
    │   │   │   └─ ← [Stop] 

I think you should revisit contract logic, please reopen ticket if you think still it's a foundry bug. thank you!

@grandizzy grandizzy closed this as not planned Won't fix, can't repro, duplicate, stale Oct 11, 2024
@github-project-automation github-project-automation bot moved this from Todo to Done in Foundry Oct 11, 2024
@grandizzy
Copy link
Collaborator

I see, yes, indeed this looks like something off, reopening for further investigations. thank you

@grandizzy grandizzy reopened this Oct 11, 2024
@grandizzy
Copy link
Collaborator

grandizzy commented Oct 11, 2024

yeah, still seems like logic related to me, if you print balance of address executing (that is the proxy) like

            console2.log("before send", address(this).balance);
            Address.sendValue(payable(config.tokenVaultAddress), reverseAmountInActual + projectFee);
            console2.log("after send", address(this).balance);
            // 2. transfer token from vault to user
            ITokenVault(config.tokenVaultAddress).transferAsset(recipient, tokenAmountOut);
            // 3. transfer eth platform fee to platform treasury
            Address.sendValue(payable(platformTreasury), platformFee);
            console2.log("after send value", address(this).balance);

logs shows:

  before send 12634021291730964
  after send 50536085166923
  after send value 0

so nothing left for weth.deposit call

   │   │   ├─ [0] console::log("before send", 12634021291730964 [1.263e16]) [staticcall]
    │   │   │   └─ ← [Stop] 
    │   │   ├─ [157] 0xB7293b069fFaA41EAb356d0B85b62aa319AAFa22::fallback{value: 12583485206564041}()
    │   │   │   ├─ [0] 0x0000000000000000000000000000000000000000::fallback{value: 12583485206564041}() [delegatecall]
    │   │   │   │   └─ ← [Stop] 
    │   │   │   └─ ← [Return] 
    │   │   ├─ [0] console::log("after send", 50536085166923 [5.053e13]) [staticcall]
    │   │   │   └─ ← [Stop] 
    │   │   ├─ [175] 0xB7293b069fFaA41EAb356d0B85b62aa319AAFa22::transferAsset(user1: [0x0000000000000000000000000000000000000041], 80000000000000001721828308 [8e25])
    │   │   │   ├─ [0] 0x0000000000000000000000000000000000000000::transferAsset(user1: [0x0000000000000000000000000000000000000041], 80000000000000001721828308 [8e25]) [delegatecall]
    │   │   │   │   └─ ← [Stop] 
    │   │   │   └─ ← [Return] 
    │   │   ├─ [0] platformTreasury::fallback{value: 50536085166923}()
    │   │   │   └─ ← [Stop] 
    │   │   ├─ [0] console::log("after send value", 0) [staticcall]
    │   │   │   └─ ← [Stop] 

@grandizzy
Copy link
Collaborator

ah, ok, yeah, it's annoying, we have this #4141 to improve error reporting when interacting with undeployed contracts. Are you OK to close this tracker and follow up 4141? thanks

@mhxw
Copy link
Author

mhxw commented Oct 11, 2024

OK, Thank you very much, grandizzy.

@grandizzy grandizzy closed this as not planned Won't fix, can't repro, duplicate, stale Oct 11, 2024
@mhxw
Copy link
Author

mhxw commented Oct 11, 2024

Hi @grandizzy , I previously submitted a PR to fix the image display issue. When you have some time, could you please review it?

image

Here’s the link:
foundry-rs/.github#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-bug Type: bug T-needs-triage Type: this issue needs to be labelled
Projects
Archived in project
Development

No branches or pull requests

2 participants