Users cannot unstake from YiedlETHStakingEtherfi.sol, because YieldAccount.sol is incompatible with ether.fi's WithdrawRequestNFT.sol
criticalLines of code
Vulnerability details
Impact
Users cannot unstake from YiedlETHStakingEtherfi.sol, because YieldAccount.sol is incompatible with ether.fi's WithdrawRequestNFT.sol.
Proof of Concept
In YiedlETHStakingEtherfi::stake, users yieldBorrow WETH, convert it to ETH, and stake in Ether.fi's LiquidityPool. Ether.fi's LiquidityPool will mint eETH (protocol token) to the user's yieldAccount.
Users will unstake() by requesting withdrawal of staked ETH from ether.fi's WithdrawRequestNFT::requestWithdraw.
The problem is WithdrawRequestNFT::requestWithdraw will _safeMint an NFT token to the user's yieldAccount as proof of request withdrawal. But the user's yieldAccount is not compatible with _safeMint because the implementation YieldAcount.sol doesn't have onERC721Received method required by _safeMint.
solidity//src/yield/YieldAccount.sol ... //@audit YieldAcount doesn't inherit openzeppelin's ERC721Holder.sol, neither does it implement onERC721Received. Not compatible with safeMint method required by ether.fi's WithdrawRequestNFT. contract YieldAccount is IYieldAccount, Initializable { ...
Flows: YieldStakingBase::unstake → YieldEthStakingEtherfi::protocolRequestWithdrawal → liquidityPool::requestWithdraw → WithdrawRequestNFT::requestWithdraw → _safeMint(recipient, requestId)
solidity//https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol#L315 function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual { _mint(to, tokenId); require( _checkOnERC721Received(address(0), to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer" ); }
Because yieldAcount.sol is cloned for every user and atomically used as caller address for ether.fi interactions, no one can unstake from YiedlETHStakingEtherfi.sol. User funds, yield and nft collateral's will be locked. When users' positions become unhealthy (e.g. Nft token price drops), yieldBorrow debts compounding can also put the protocol at risks.
Note: in the unit test file for test/yield/YieldEthStakingEtherfi.t.sol, unit tests passed only because a MockEtherfiWithdrawRequestNFT.sol is used that uses _mint() instead of _safeMint().
Tools Used
Manual
Recommended Mitigation Steps
Add onERC721Received support in YieldAccount.sol.
Assessed type
Other
