Closed c4-bot-9 closed 5 months ago
GalloDaSballo marked the issue as sufficient quality report
GalloDaSballo marked the issue as remove high or low quality report
This line does pass:
if (reservedKeys[_owner] == _keyId) {
I'm not convinced this would yield any value:
withdrawAmount = WISE_LENDING.withdrawExactShares(
_nftId,
PENDLE_CHILD,
_withdrawShares
);
This is invalid report and can be dismissed. It is not possible to call manuallyWithdrawShares
on PendlePowerFarm contract with _keyId
-> this will always revert with NotOwner()
error message.
This is because whoever submitted it didn't pay attention that when powerFarm will call withdrawExactShares
on WISE_LENDING contract then WISE_LENDING contract will perform a check for nftId
parameter (in this case 0
)
see -> _checkOwnerPosition()
function which will make sure that nftId
in this case 0
must be owned by the caller (in this case it requires for nftId 0
to be inside the powerFarm contract, but it is in feeManager contract.
You can run a test and see for yourself.
this function makes sure that nftId 0
must be owner by the caller, and feeManagerNFT (0) is not owned by PowerFarm so the call will fail.
Dismissed.
GalloDaSballo marked the issue as insufficient quality report
trust1995 marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-02-wise-lending/blob/79186b243d8553e66358c05497e5ccfd9488b5e2/contracts/PowerFarms/PendlePowerFarm/PendlePowerManager.sol#L274
Vulnerability details
Impact
Loss of protocol funds
Proof of Concept
The users having positions at the Power Farms can withdraw their shares by calling manuallyWithdrawShares.
The function is below;
Accordingly, the users should pass their
_keyId
and amount of shares that they want to withdraw.The
updatePools
modifier syncs the pools and theonlyKeyOwner
modifier validates the caller being the key owner.Accordingly, the function continues with converting
PENDLE_CHILD
shares to tokens by calling _manuallyWithdrawShares and the shares are cashed out accordingly in Wiselending Contract as below.L: 168 withdraws the tokens using shares and the tokens are transferred afterward.
Finally, in the
PendlePowerManager.manuallyWithdrawShares
function, a debt ratio is checked, accordingly, the call is finalized and the caller receives the funds.Scenario;
manuallyWithdrawShares
with_keyId = 0
updatePools
modifieronlyKeyOwner
modifier validates the keyId ownership as below;And isOwner function is below;
onlyKeyOwner
modifier would be bypassed.157: function _manuallyWithdrawShares( 158: uint256 _nftId, 159: uint256 _withdrawShares 160: ) 161: internal 162: { 163: > uint256 withdrawAmount = WISE_LENDING.cashoutAmount( 164: PENDLE_CHILD, 165: _withdrawShares 166: ); 167: 168: > withdrawAmount = WISE_LENDING.withdrawExactShares( 169: _nftId, 170: PENDLE_CHILD, 171: _withdrawShares 172: ); 173: 174: _safeTransfer( 175: PENDLE_CHILD, 176: msg.sender, 177: withdrawAmount 178: ); 179: }
L: 168 calls
Wiselending
contract´swithdrawExactShares
with NFTid being ZERO. That´s the Id ofFEE_MANAGER_NFT
AndFEE_MANAGER_NFT
also claims the fees in the same fashion;FEE_MANAGER_NFT
doesn´t have any debt, the MEV Bot receives the tokens that theFEE_MANAGER_NFT
is allocated.Tools Used
Manual Review
Recommended Mitigation Steps
Do not allow
manuallyWithdrawShares
to be called with Id = 0.Assessed type
Access Control