✅True XOR
Idea
To pass the require(msg.sender == tx.origin) check, use vm.prank(msg.sender) in the PoC test case.
For boolean p and q we have to provide a true and a false. The naive idea will be use a storage variable counter to distinguish the first call and the second call. However it does not work because giveBool() must be a view function, which can not modify storage variables.
Here is an interesting observation is that:
bool p = IBoolGiver(target).giveBool(); // more gas left
bool q = IBoolGiver(target).giveBool(); // less gas leftThere must be a difference between the gasleft() after the first call and after the second call. We can utilize this difference and provide different booleans.
For easier debugging, we can send only a small amount of gas when calling callMe() and record the gasleft() after the first call and the second call. For example, sending 10000 gas works:
trueXOR.callMe{gas: 10000}(address(attackContract));In my debugging session the first gasleft() is always larger than 6000:

PoC
Last updated
