It is possible for a tokenOwner to liquidate their collaterized tokenId rather then repaying the borrowed funds.
Since the V3Vault.liquidate() function does not check that the caller is not the token owner, then it is possible for the tokenOwner[tokenId] to be the caller liquidating their own borrowed funds to get back their nonfungiblePositionManager position token and extra erc20 assets
Alice has collaterized her tokenId for her position and borrowed USDC assets on it.
After a while, LiquidateState of the tokenId is unhealthy.
Alice then calls the liquidate() function in the V3Vault contract, pays the liquidatorCost for the tokenId, receives position tokens for the liquidation, receives the remainder position tokens meant for the tokenOwner
loan is cleared, and tokenId is sent back to Alice
Tools Used
Manual
Recommended Mitigation Steps
Apply a check to ensure that the caller is not owner of the tokenId, i.e require(msg.sender != tokenOwner[tokenId]) .
Lines of code
https://github.com/code-423n4/2024-03-revert-lend/blob/435b054f9ad2404173f36f0f74a5096c894b12b7/src/V3Vault.sol#L685-L757
Vulnerability details
Impact
It is possible for a tokenOwner to liquidate their collaterized tokenId rather then repaying the borrowed funds.
Since the V3Vault.liquidate() function does not check that the caller is not the token owner, then it is possible for the tokenOwner[tokenId] to be the caller liquidating their own borrowed funds to get back their nonfungiblePositionManager position token and extra erc20 assets
Proof of Concept
In https://github.com/code-423n4/2024-03-revert-lend/blob/435b054f9ad2404173f36f0f74a5096c894b12b7/src/V3Vault.sol#L685-L757 , there is no check for caller to not be the tokenOwner.
Tools Used
Manual
Recommended Mitigation Steps
Apply a check to ensure that the caller is not owner of the tokenId, i.e
require(msg.sender != tokenOwner[tokenId])
.Assessed type
Other