In the LockManager::_lock function, the transferFrom() is used to actually transfer the tokens from the owner to the contract. According to the ERC20 standard, the transfer function "returns a boolean value indicating whether the operation succeeded" (OZ's Docs). If the transfer fails and returns false, the function will proceed as if the transfer was successful. The impact is that for an arbitrary ERC20 token, this transferFrom() call may return false but the _lock() logic will miss that, and assume it was successfully transferred into the contract and updates the lockedToken.quantity += _quantity accounting accordingly. This will result in the user locking tokens for free.
Lines of code
https://github.com/code-423n4/2024-05-munchables/blob/main/src/managers/LockManager.sol#L374-L377
Vulnerability details
Impact
In the LockManager::_lock function, the
transferFrom()
is used to actually transfer the tokens from the owner to the contract. According to the ERC20 standard, the transfer function "returns a boolean value indicating whether the operation succeeded" (OZ's Docs). If the transfer fails and returns false, the function will proceed as if the transfer was successful. The impact is that for an arbitrary ERC20 token, thistransferFrom()
call may returnfalse
but the_lock()
logic will miss that, and assume it was successfully transferred into the contract and updates thelockedToken.quantity += _quantity
accounting accordingly. This will result in the user locking tokens for free.Proof of Concept
https://github.com/code-423n4/2024-05-munchables/blob/main/src/managers/LockManager.sol#L374-L377
lock()
function.transferFrom
inside_lock
fails due to exceeding the gas limit and returnsfalse
.lockedToken.quantity += _quantity
.Tools Used
Manual Review
Recommended Mitigation Steps
Check the success boolean of the
transferFrom()
call. Alternatively, use OZ’sSafeERC20’s safeTransferFrom()
function.Assessed type
Token-Transfer