foundry-rs / foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.
https://getfoundry.sh
Apache License 2.0
8.12k stars 1.68k forks source link

Forge Test - Library call with calldata args fails (using deployCode) #4943

Open 0xlinus opened 1 year ago

0xlinus commented 1 year ago

Component

Forge

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

What version of Foundry are you on?

forge 0.2.0 (7398b65 2023-03-30T00:08:17.480091977Z)

What command(s) is the bug in?

forge test

Operating System

Linux

Describe the bug

I'm trying to test a library doing the following:

library Library {
    struct Data {
        uint256 a;
        uint256 b;
    }

    function addData(Data calldata _data) external pure returns (uint256) {
        return _data.a + _data.b;
    }
}

contract LibraryTest is Test {
    function testLibraryAddData() public {
        address libAddress = deployCode("Library.sol");
        ILibrary lib = ILibrary(libAddress);
        ILibrary.Data memory _data = ILibrary.Data(1, 2);
        assertTrue(lib.addData(_data) == 3);
    }
}

This reverts with the following logs:

[FAIL. Reason: EvmError: Revert] testLibraryAddData() (gas: 82213)
Traces:
  [82213] LibraryTest::testLibraryAddData() 
    ├─ [0] VM::getCode(Library.sol) [staticcall]
    │   └─ ← 0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000011960e0610039600b82828239805160001a60731461002c57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361060335760003560e01c80630116eeda146038575b600080fd5b60476043366004606e565b6059565b60405190815260200160405180910390f35b60006068602083013583356085565b92915050565b600060408284031215607f57600080fd5b50919050565b6000821982111560a557634e487b7160e01b600052601160045260246000fd5b50019056fea2646970667358221220c9c8498385a8ca65b7e46c0af63403f4fc4f45bd1f7a86d0f3b537166b58e77164736f6c6343000806003300000000000000
    ├─ [44921] → new Library@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
    │   └─ ← 224 bytes of code
    ├─ [88] Library::addData((1, 2)) [staticcall]
    │   └─ ← "EvmError: Revert"
    └─ ← "EvmError: Revert"

This works fine if:

function addData(uint256 _a, uint256 _b) external pure returns (uint256) { return _a + _b };

This also passes if Library is a contract instead of a library

This also passes if deployCode is not used, and tests are:

 Library.Data memory _data = Library.Data(1, 2);
 assertTrue(Library.addData(_data) == 3);

Why is this failing when using calldata arguments + deployCode ?

Thanks

0xlinus commented 1 year ago

Anyone?

0xCooki commented 1 year ago

Might be wrong, but I think it's 'cos the struct, when it's returned, is treated as a tuple rather than the struct type specified. I don't know why this happens with structs but I vaguely recall encountering something like this before.

I think the error is showing you that it's a tuple: Library::addData((1, 2)), where the calldata (1, 2) is a tuple rather than the Data struct

I'm not 100% sure tho