dapphub / dapphub/dapptools

Test function that takes a struct argument breaks fuzzer/symbolic executor

Open
#820 3 comments 2 reactions 0 assignees View on GitHub
Dominant language
Haskell
Stars
2.1k
Forks
320
PR merge metrics
No merged PRs in 30d

Description

I have a small test contract like this:

```solidity
pragma solidity 0.7.6;
pragma abicoder v2;

import {DSTestPlus} from "solmate/src/tests/utils/DSTestPlus.sol";

import {MockCrossDomainMessenger} from "nova/contracts/mocks/MockCrossDomainMessenger.sol";

import {L1_NovaExecutionManager} from "nova/contracts/L1_NovaExecutionManager.sol";

contract ExecutionManagerTest is DSTestPlus {
L1_NovaExecutionManager executionManager;
MockCrossDomainMessenger mockCrossDomainMessenger;

function setUp() public {
mockCrossDomainMessenger = new MockCrossDomainMessenger();
executionManager = new L1_NovaExecutionManager(DEAD_ADDRESS, mockCrossDomainMessenger);
}

function proveUpdatingGasConfig(L1_NovaExecutionManager.GasConfig calldata newGasConfig) public {}
}
```

https://github.com/Rari-Capital/nova-invariants/blob/proveUpdatingGasConfig-demo/src/ExecutionManager.t.sol

`L1_NovaExecutionManager.GasConfig` is a struct like so:

```solidity
struct GasConfig {
uint32 calldataByteGasEstimate;
uint96 missingGasEstimate;
uint96 strategyCallGasBuffer;
uint32 execCompletedMessageGasLimit;
}
```

https://github.com/Rari-Capital/nova/blob/3252ceea5e50d3c29be69861b77908a5b4f28815/contracts/L1_NovaExecutionManager.sol#L90-L103

Running `dapp test` yields:

```
❯ dapp test -m proveUpdatingGasConfig
+ dapp clean
+ rm -rf out
Running 1 tests for src/ExecutionManager.t.sol:ExecutionManagerTest
[FAIL] proveUpdatingGasConfig(tuple)

Failure: proveUpdatingGasConfig(tuple)

Counterexample:

result: Revert
calldata: proveUpdatingGasConfig((0, 0, 0, 0))

src/ExecutionManager.t.sol:ExecutionManagerTest
├╴constructor
├╴setUp()
│ ├╴create MockCrossDomainMessenger@0xCe71065D4017F316EC606Fe4422e11eB2c47c246 (src/ExecutionManager.t.sol:16)
│ │ └╴← 1244 bytes of code
│ └╴create L1_NovaExecutionManager@0x185a4dc360CE69bDCceE33b3784B0282f7961aea (src/ExecutionManager.t.sol:17)
│ ├╴OwnerUpdated() (lib/nova/contracts/L1_NovaExecutionManager.sol:60)
│ ├╴create L1_NovaApprovalEscrow@0x9cC6334F1A7Bc20c9Dde91Db536E194865Af0067 (lib/nova/contracts/L1_NovaExecutionManager.sol:16)
│ │ └╴← 878 bytes of code
│ └╴← 8066 bytes of code
└╴proveUpdatingGasConfig(tuple)
```

Even when switching the test from `prove` to `test` it still unexpectedly reverts:

```
❯ dapp test -m testUpdatingGasConfig
+ dapp clean
+ rm -rf out
Running 1 tests for src/ExecutionManager.t.sol:ExecutionManagerTest
*** Failed! Falsified (after 1 test):
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b7ba4a4
[FAIL] testUpdatingGasConfig(tuple). Counterexample: ((0, 1, 0, 1266394276))
Run:
dapp test --replay '("testUpdatingGasConfig(tuple)","0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b7ba4a4")'
to test this case again, or
dapp debug --replay '("testUpdatingGasConfig(tuple)","0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004b7ba4a4")'
to debug it.

Failure:
src/ExecutionManager.t.sol:ExecutionManagerTest
├╴constructor
├╴setUp()
│ ├╴create MockCrossDomainMessenger@0xCe71065D4017F316EC606Fe4422e11eB2c47c246 (src/ExecutionManager.t.sol:16)
│ │ └╴← 1244 bytes of code
│ └╴create L1_NovaExecutionManager@0x185a4dc360CE69bDCceE33b3784B0282f7961aea (src/ExecutionManager.t.sol:17)
│ ├╴OwnerUpdated() (lib/nova/contracts/L1_NovaExecutionManager.sol:60)
│ ├╴create L1_NovaApprovalEscrow@0x9cC6334F1A7Bc20c9Dde91Db536E194865Af0067 (lib/nova/contracts/L1_NovaExecutionManager.sol:16)
│ │ └╴← 878 bytes of code
│ └╴← 8066 bytes of code
└╴testUpdatingGasConfig(tuple)
└╴error Revert 0x (src/ExecutionManager.t.sol:10)
```

Does hevm not support generating args for functions that take structs?

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.