feat(invariant): support fuzz with random msg.value#8644
feat(invariant): support fuzz with random msg.value#8644QiuhaoLi wants to merge 2 commits intofoundry-rs:masterfrom
Conversation
|
CC @grandizzy @mds1 |
|
thanks for your PR! Generally this is recommended #8449 but will consider making it automatically (I think we want this only if fuzzed function is payable) |
Thanks for the info, handlers can help! If people don't use handlers, It would be nice if foundry could do that automatically. Yeah, we will use random values only for payable target functions. |
|
Hi @DaniPopes @mattsse , could you help review this PR? |
| // Execute call from the randomly generated sequence without committing state. | ||
| // State is committed only if call is not a magic assume. | ||
| let mut call_result = current_run | ||
| if current_run.executor.get_balance(tx.sender)? < tx.value { |
There was a problem hiding this comment.
@QiuhaoLi I am looking into integrate this approach but I am not sure we should inflate sender's balance with the fuzzed value (nor restore the balance after the call) as it could result in false positives like in forked tests / transfers, etc. Instead we could bound it in (0, current sender balance) but even so for long running campaigns the balance could get spent quickly and then the fuzzed calls will be performed with call value U256::ZERO
@0xalpharush any thoughts re how to deal with this scenario? thank you!
There was a problem hiding this comment.
Are the senders always the same pool of "test" addresses? If the tx.sender is the pranked value here and not the original, it may cause issues. But if it's from the pool, I think it should be fine.
There was a problem hiding this comment.
makes sense, can keep a track of those addresses
…lue support When using the ABI mutation type in coverage-guided fuzzing: - 30% chance to mutate ALL calls in the sequence rather than just one - Mutate sender (15%) using addresses from dictionary - Mutate msg.value (15%) for payable functions Also adds automatic msg.value generation for payable functions during initial call generation, with value shown in sequence output. Value generation is biased towards smaller values to avoid balance issues: - 85% no value, 10% small (0-1000 wei), 4% medium (0.001 ETH), 1% large (1 ETH) Based on foundry-rs#8644 Co-authored-by: QiuhaoLi <qiuhaoli@outlook.com>
…lue support When using the ABI mutation type in coverage-guided fuzzing: - 30% chance to mutate ALL calls in the sequence rather than just one - Mutate sender (15%) using addresses from dictionary - Mutate msg.value (15%) for payable functions Also adds automatic msg.value generation for payable functions during initial call generation, with value shown in sequence output. Value generation is biased towards smaller values to avoid balance issues: - 85% no value, 10% small (0-1000 wei), 4% medium (0.001 ETH), 1% large (1 ETH) Based on foundry-rs#8644 Co-authored-by: QiuhaoLi <qiuhaoli@outlook.com>
…lue support When using the ABI mutation type in coverage-guided fuzzing: - 30% chance to mutate ALL calls in the sequence rather than just one - Mutate sender (15%) using addresses from dictionary - Mutate msg.value (15%) for payable functions Also adds automatic msg.value generation for payable functions during initial call generation, with value shown in sequence output. Value generation is biased towards smaller values to avoid balance issues: - 85% no value, 10% small (0-1000 wei), 4% medium (0.001 ETH), 1% large (1 ETH) Based on foundry-rs#8644 Co-authored-by: QiuhaoLi <qiuhaoli@outlook.com>
Motivation
Currently, the foundry's invariant fuzz testing doesn't support txs with value > 0, which makes it unable to find sequences in some situations. For example, the Pay contract below will only set the
hackedvariable if the calls areC() --> B() --> A()with2, msg.value>0.11 ether, 0, but foundry can't generate such calls.Solution
When generating a tx, we set the
msg.valueas a random number (uint96) if the target function is payable. After applying this strategy, foundry can find the sequence quickly: