The function buy take amount of type uint256 as input. amount is used to check if msg.value is correct depending on the sale price as follows: require(_amount * sale_.price == msg.value, "WRONG PRICE"); but is not casted to uint48 as done to calculate the newId: uint48 newId = uint48(_amount) + sale_.currentId;.
Therefore if the input _amount is greater than type(uint48).max, users will pay a large _amount of NFT but will only get _amount modulo type(uint48).max.
Lines of code
https://github.com/code-423n4/2022-12-escher/blob/5d8be6aa0e8634fdb2f328b99076b0d05fefab73/src/minters/FixedPrice.sol#L57-L74
Vulnerability details
Impact
The function
buy
takeamount
of typeuint256
as input.amount
is used to check if msg.value is correct depending on the sale price as follows:require(_amount * sale_.price == msg.value, "WRONG PRICE");
but is not casted to uint48 as done to calculate thenewId
:uint48 newId = uint48(_amount) + sale_.currentId;
.Therefore if the input
_amount
is greater than type(uint48).max, users will pay a large_amount
of NFT but will only get_amount modulo type(uint48).max
.Proof of Concept
FixedPrice.sol#L57-L74
Foundry code to run with
forge test --match-contract "Bug2" --match-test "BugCast" -vvvvv
:Tools Used
Manual review.
Recommended Mitigation Steps
I recommend to cast
_amount
touint48
earlier in the function.