You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
rayDiv and wadDiv revert too eagerly due to an explicit check written in assembly: LINK
Although true only for very large numbers, the functions revert in cases where mathematically a, b should be acceptable, but in practice, they aren't due to the heuristic used in the implementation.
The check can be seen in the specification written here, and the results can be seen here
Detailed explanation
wadDiv and rayDiv functions in the WadRayMath.sol library revert if and only if the following solidity functions return the value true:
function wadDivRevertingSolidity(uint256 a, uint256 b) public pure returns (bool d) {
if (b != 0)
{
d = (a > ((type(uint256).max - b/2)/WAD));
} else {
d = true;
}
return d;
}
function wadRayRevertingSolidity(uint256 a, uint256 b) public pure returns (bool d) {
if (b != 0)
{
d = (a > ((type(uint256).max - b/2)/RAY));
} else {
d = true;
}
return d;
}
this can be verified via the equivalence checking rules in the prover:
However, this is a logic bug: if we treat a, b as uint256 and consider wadDiv for a moment, then as soon as a > MAX_UINT256/(2 *WAD) we have a*WAD>MAX_UINT256/2, so we can find a very large b <= MAX_UINT256 which would cause a "ghost overflow" in the computation. Nevertheless, it is very possible for a/b*WAD to still give a valid result. (i.e., both a and b can be very large! but their quotient can be small...).
Running an equivalence check produces the counterexample in the image (you can also see in the links of the result above).
After converting these values to decimal, we get: 104212880313584575881213886507819117067942986199076507635512000000000000000000 / 23158417847463239084714197001737581570653996933128112807891555555555555555556 = 4
so the solidity version reverts even though it shouldn't.
The text was updated successfully, but these errors were encountered:
summary
rayDiv
andwadDiv
revert too eagerly due to an explicit check written in assembly: LINKAlthough true only for very large numbers, the functions revert in cases where mathematically
a, b
should be acceptable, but in practice, they aren't due to the heuristic used in the implementation.The check can be seen in the specification written here, and the results can be seen here
Detailed explanation
wadDiv
andrayDiv
functions in theWadRayMath.sol
library revert if and only if the following solidity functions return the value true:this can be verified via the equivalence checking rules in the prover:
However, this is a logic bug: if we treat
a, b
asuint256
and considerwadDiv
for a moment, then as soon asa > MAX_UINT256/(2 *WAD)
we havea*WAD>MAX_UINT256/2
, so we can find a very largeb <= MAX_UINT256
which would cause a "ghost overflow" in the computation. Nevertheless, it is very possible fora/b*WAD
to still give a valid result. (i.e., both a and b can be very large! but their quotient can be small...).Running an equivalence check produces the counterexample in the image (you can also see in the links of the result above).
After converting these values to decimal, we get:
104212880313584575881213886507819117067942986199076507635512000000000000000000 / 23158417847463239084714197001737581570653996933128112807891555555555555555556 = 4
so the solidity version reverts even though it shouldn't.
The text was updated successfully, but these errors were encountered: