Closed c4-bot-7 closed 5 months ago
Same pre-condition as #193 so similar doubt on the second part
I'm not sure what the submitter was thinking, but it should be acknowledged that from the first step description of Bob calling exitFarm
with keyId 0
such operation is not possible by design. If you try to call this you will get ERC721: invalid token ID
as most optimistic scenario especially because keys are always burned and only can be incremented over time.
Secondly, even if that would be possible assume keyId exists, then this would still revert because keyId 0
can only point to wiseLending nftId 0
and that nft is not part of the FARM! therefor there is no opened position for wiseLending nftId 0
and entire transaction would revert when _closePosition()
will be triggered with wiseLending nftId 0
The claim here is not sufficient, if author wants to prove his point please provide POC file for foundry to run the scenario. Feel free to try this also on these test contracts:
https://arbiscan.io/address/0xae6396577fa2596cd71e822c85ea615fbd74f879 https://arbiscan.io/address/0x9690eD5006e4B7cdB591B794C339Bd3c18E88e30
See also my comment here: https://github.com/code-423n4/2024-02-wise-lending-findings/issues/193
GalloDaSballo marked the issue as insufficient quality report
trust1995 marked the issue as unsatisfactory: Insufficient proof
Lines of code
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerManager.sol#L210-L252
Vulnerability details
Impact
Loss of user funds that enter the power farms
Proof of Concept
Users who want to leverage their gains enter the power farms by calling;
enterFarm - The NFT id is assigned by calling _getWiseLendingNFT
enterFarmETH - The NFT id is assigned by calling _getWiseLendingNFT
And they call exitFarm function when they want to exit the power farms and withdraw their funds from the farms.
Bob is a malicious actor and he doesn´t possess any Position NFT or Power Farm NFT or any reservations. In addition, for the simplicity, there´s no available Power Farm NFT for the latter assignment (availableNFTCount == 0 condition)
exitFarm
with_keyId = 0
For the call trace,
exitFarm
logic is as follows;onlyKeyOwner(_keyId)
modifier call;32: modifier onlyKeyOwner( 33: uint256 _keyId 34: ) { 35: _onlyKeyOwner( 36: keyId 37: ); 38: ; 39: } 40: 41: function _onlyKeyOwner( 42: uint256 _keyId 43: ) 44: private 45: view 46: { 47: require( 48: > isOwner( 49: _keyId, 50: msg.sender 51: ) == true 52: ); 53: }
keyId = 0
, L: 104 returns to beTrue
, and validation is fulfilled.exitFarm
function, L: 219 parses thewiseLendingNFT
from thefarmingKeys
mapping which is 0 due to supplied keyId doesn´t exist.availableNFTCount
counter and sets it to 0 for the latter assignment. Accordingly, the mapping status is as follows;_closingPosition
function and it results inWISE_LENDING.paybackExactShares
return 1 due to the below as per the call trace;114: function paybackAmount( 115: address _poolToken, 116: uint256 _shares 117: ) 118: public 119: view 120: returns (uint256) 121: { 122: uint256 product = _shares //@audit product results in being 0 123: * borrowPoolData[_poolToken].pseudoTotalBorrowAmount; 124: 125: uint256 totalBorrowShares = borrowPoolData[_poolToken].totalBorrowShares; 126: 127: return product / totalBorrowShares + 1; //@audit Here results in 1 128: }
enterFarm
without holding any position/power farm NFT or reservations and pays 20 WETH.Here´s the function logic to trace the call;
At L: 107, her
wiselendingNFT
is assigned by calling_getWiseLendingNFT
which is as follows;Since there are available NFTs in the system, L: 205 assigns Alice
availableNFTs[2] = 0
and decrements the counter.keyId
is generated by internally calling _reserveKeyAccordingly, this
keyId
is used inreservedKeys
andfarmingKeys
mappings by registering as;The user can manage their position by this
keyId
.enterFarm
after Alice back running her with min WETH as per the declaration.0
== same as Alice´s wiselendingNFT. And there would be no moreavailableNFTs
left.enterFarm
's logic below happens;109: _safeTransferFrom( //@audit WETH is transferred from Bob. 110: WETH_ADDRESS, 111: msg.sender, 112: address(this), 113: _amount 114: ); 115: 116: _openPosition( // @audit 117: _isAave, 118: wiseLendingNFT, 119: _amount, 120: _leverage, 121: _allowedSpread 122: );
So Bob can back run the users while holding Wiselending 0 and call
exitFarm
He does the similar in Arbitrum listening to
FarmEntry(keyId = 0)
events to get into the attack.Bob can exploit every single user entering Farms in ETH main net any many in Arbitrum by simply inflating the
availableNFTs
mapping with 0 id, and callingenterFarm
&exitFarm
with querying his Wiselending NFT will be assigned as 0.Tools Used
Manual Review
Recommended Mitigation Steps
We recommend not allowing
exitFarm
call with 0 id input.Assessed type
Access Control