Store event changes into Echidna's corpus#1405
Conversation
lib/Echidna/Campaign.hs
Outdated
| -- Now we try to parse the return values as solidity constants, and add them to 'GenDict' | ||
| resultMap = returnValues results workerState.genDict.rTypes | ||
| -- compute the new events to be stored | ||
| eventDiffs = extractEventValues vm.dappInfo results |
There was a problem hiding this comment.
I'm not sure if this is how it should be done with regards to the dappInfo, since there's vm.dapp and vm.dappInfo. Where can I find more information about them?
…ted logs between them
|
Please provide a small solidity code that shows an assertion failure that needs this new feature. We will show you how to add a test |
Something like this? contract EventAssert {
event ValueSet(uint256 indexed value);
function setValue(uint256 value) public {
emit ValueSet(value);
assert(value != 1295);
}
} |
|
Your example needs to have an event emmited with a value that can be used to trigger the assertion, but it needs to be essential for that. Usually you need to do some computation and emit some value from it, that is normally hidden from the fuzzer. |
|
How about this @gustavo-grieco? contract EventAssert {
uint private secret = 123;
event Output(uint result);
function check(uint x) public {
uint result = x % 200;
emit Output(result);
if (result == secret) {
assert(false);
}
}
} |
|
Uhm it looks bette but I'm not sure the value from the event is useful to break the assertion. Try using a hashed value instead 🤔 |
|
So, something like this: contract EventAssert {
uint private secret;
event Computed(uint result);
constructor() {
secret = uint(keccak256(abi.encodePacked(block.timestamp))) % 1000;
}
function check(uint x) public {
uint result = (x * 3 + 7) % 1000;
emit Computed(result);
if (result == secret) {
assert(false);
}
}
} |
|
So if you remove |
I think so, because if we don't Let me know how to go further with the testing. |
|
Changed the contract following @elopez's suggestion: contract EventAssert {
uint private secret;
event Secret(uint result);
function reset() public {
secret = uint(keccak256(abi.encodePacked(block.timestamp)));
emit Secret(secret);
}
function check(uint x) public {
if (x == secret) {
assert(false);
}
}
} |
|
This looks good, let's add it as a test in the "value" section |
|
The fork doesn't reproduce the revert deterministically though, but I guess that's expected because of the hash being quite a huge one. |
|
You mean that this test is not reliable ? |
gustavo-grieco
left a comment
There was a problem hiding this comment.
This needs to be executed as a test. Check the values.hs file
| extractEventValues :: DappInfo -> VM Concrete s -> VM Concrete s -> Map AbiType (Set AbiValue) | ||
| extractEventValues dappInfo vm vm' = | ||
| let | ||
| oldLogs = vm.logs |
There was a problem hiding this comment.
I think logs are cleaned from one van to the next one 🤔
There was a problem hiding this comment.
Isn't that how it should be?
I wasn't sure if that's expected ir not. It only gives the output I sent a few times and at other times it doesn't revert and says everything passes. |
* descending order is more efficient * Map.unionsWith can elegantly replace foldl
* modify callseq to store event changes into the corpus * fixes crytic#883 * chore: fix imports * fix: simplify extractEventValues to take two vms and return the emmitted logs between them * chore: remove redundant imports * add test * add campaign test to valueTests * modify campaign test to take a seed value * add campaign.yaml * rename test from campaign to events * reduce test limit * fix ordering in callseq for computing additions and constants * descending order is more efficient * Map.unionsWith can elegantly replace foldl

Fixes #883. Only implements the storing of events, not of the entire state's variables etc.
Regards,
Divya.