Summary
The revert branch of the MulWad and MulWadUp functions doesn't use one of the relevant error's selector. Beside that the free memory pointer is used to store the selector however the revert function uses correctly the scratch space.
Vulnerability Details
If the MulWad function should revert with the MathMasters__MulWadFailed()
error than a relevant test should be passed:
function testRevert() public {
vm.expectRevert(MathMasters.MathMasters__MulWadFailed.selector);
MathMasters.mulWad(type(uint256).max, 2);
}
# Result:
# [FAIL. Reason: Error != expected error: != 0xa56044f7] testRevert() (gas: 3145)
# Test result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 3.16ms
Impact
Contracts that use this libary can't rely on the revert messages.
Tools Used
Manual review, Forge test
Recommendations
Both in MulWad and MulWadUp functions should use one of the relevant error's selector and store the selector in the scratch space to not override free memory pointer:
...
/// @dev Equivalent to `(x * y) / WAD` rounded down.
function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
// @solidity memory-safe-assembly
assembly {
// Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
if mul(y,gt(x, div(not(0), y)))
{
- mstore(0x40, 0xbac65e5b) // `MathMasters__MulWadFailed()`.
+ mstore(0x00, 0xa56044f7) // `MathMasters__MulWadFailed()`.
revert(0x1c, 0x04)
}
z := div(mul(x, y), WAD)
}
}
...
/// @dev Equivalent to `(x * y) / WAD` rounded up.
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
...
{
- mstore(0x40, 0xbac65e5b) // `MathMasters__MulWadFailed()`.
+ mstore(0x00, 0xa56044f7) // `MathMasters__MulWadFailed()`.
revert(0x1c, 0x04)
}
...
}