Summary
MathMasters::mulWadUp and MathMasters::mulWad functions are using incorrect memory offsets and error signatures to revert on overflow.
Vulnerability Details
https://github.com/Cyfrin/2024-01-math-master/blob/main/src/MathMasters.sol#L34-L59
function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
if mul(y, gt(x, div(not(0), y))) {
@> mstore(0x40, 0xbac65e5b)
revert(0x1c, 0x04)
}
z := div(mul(x, y), WAD)
}
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
if mul(y, gt(x, or(div(not(0), y), x))) {
@> mstore(0x40, 0xbac65e5b)
revert(0x1c, 0x04)
}
if iszero(sub(div(add(z, x), y), 1)) { x := add(x, 1) }
z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
}
}
The MathMasters__MulWadFailed() error signature is 0xa56044f7, but the functions are using 0xbac65e5b as the error signature.
The 0xbac65e5b error signature is being stored at memory offset 0x40, and revert(0x1c, 0x04) returns data mem[0x1c…(0x1c+0x04)], which is empty.
Impact
No custom error is thrown when the MathMasters::mulWadUp and MathMasters::mulWad functions overflow.
Tools Used
Manual review
Recommendations
/// @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) {
/// @solidity memory-safe-assembly
assembly {
// Equivalent to `require(y == 0 || x <= type(uint256).max / y)`.
if mul(y, gt(x, or(div(not(0), y), x))) {
- mstore(0x40, 0xbac65e5b) // `MathMasters__MulWadFailed()`.
+ mstore(0x00, 0xa56044f7) // `MathMasters__MulWadFailed()`.
revert(0x1c, 0x04)
}
if iszero(sub(div(add(z, x), y), 1)) { x := add(x, 1) }
z := add(iszero(iszero(mod(mul(x, y), WAD))), div(mul(x, y), WAD))
}
}