msg.value reverts in different scenarios
Fuzzing with msg.value provokes different reverts which varies according the scenario:
- This is the safest example and half of times passes and the other half reverts with
merror BalanceTooLow(there's no documentation on that error).
contract D {
function testing() public payable {
E e = new E();
bytes memory data = abi.encodeWithSignature('getNum()');
(bool success, ) = payable(address(e)).call{value: 1 ether}(data);
assert(success);
}
}
contract E {
function getNum() external payable {
require(msg.value > 0);
assert(true);
}
}
Config.yaml
testLimit: 5000
testMode: assertion
sender: ["0x30000"]
balanceAddr: 10000000000000000000 // <----- same behaviour if this gets commented out
- This one reverts on the
requireof Contract E:
contract D {
function testing() public payable {
E e = new E();
bytes memory data = abi.encodeWithSignature('getNum()');
(bool success, ) = payable(address(e)).call{value: msg.value}(data); // <----- change on value
assert(success);
}
}
- And this one also reverts in the
requireas it seems that Echidna is not forwardingmsg.valuelike it should do for thedelegatecallopcode:
contract D {
function testing() public payable {
E e = new E();
bytes memory data = abi.encodeWithSignature('getNum()');
(bool success, ) = payable(address(e)).delegatecall(data); // <----- change on call type
assert(success);
}
}
In the scenario 1, you specify that the contract will have certain balance. Then the code sends 1 ether in each transaction. As expected, the balance will eventually reach zero and the EVM reverts. BalanceTooLow is an internal message from the HEVM to help to debug this, so this work as expected.
In the scenario 2, the code sends msg.value, which can be zero even for payable functions (and it is an import edge case to trigger, in fact). So it is expected to revert on require(msg.value > 0);.
Got it! Thanks @ggrieco-tob
What about the 3rd scenario? That's actually the one that concerns me since I'm using the Diamond pattern which relies heavily on delegatecall.
Another question, in regards to the 1st scenario, how do you suppress that behavior that produces the BalanceTooLow error?
Because if you're fuzzing with thousands of txs, eventually the amount of ether is going to ran out, so BalanceTooLow will always be the error that will revert, not giving any chance to other faulty inputs (if there's any) to produce a different error.
I tried with giving balanceAddr -in the config file- a max uint256 value, both 115792089237316195423570985008687907853269984665640564039457584007913129639935 and 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff but the BalanceTooLow error always gets thrown anyhow.
Any feedback on scenario number 3? @ggrieco-tob