IllIllI - Sense PTs can never be redeemed
Opened this issue · 1 comments
IllIllI
high
Sense PTs can never be redeemed
Summary
Sense PTs can never be redeemed
Vulnerability Detail
Most of the protocols that require the user of the Converter
contract have code that approves the Converter
for that protocol, but there is no such approval for Sense.
Impact
Permanent freezing of funds
Users will be able to lend and mint using Sense, but when it's time for Illuminate to redeem the Sense PTs, the call will always revert, meaning the associated underlying will be locked in the contract, and users that try to redeem their Illuminate PTs will have lost principal.
While the Illuminate project does have an emergency withdraw()
function that would allow an admin to rescue the funds and manually distribute them, this would not be trustless and defeats the purpose of having a smart contract.
Code Snippet
The Sense flavor of redeem()
requires the use of the Converter
:
// File: src/Redeemer.sol : Redeemer.redeem() #1
366 // Get the starting balance to verify the amount received afterwards
367 uint256 starting = IERC20(u).balanceOf(address(this));
368
369 // Get the divider from the adapter
370 ISenseDivider divider = ISenseDivider(ISenseAdapter(a).divider());
371
372 // Redeem the tokens from the Sense contract
373 ISenseDivider(divider).redeem(a, s, amount);
374
375 // Get the compounding token that is redeemed by Sense
376 address compounding = ISenseAdapter(a).target();
377
378 // Redeem the compounding token back to the underlying
379 @> IConverter(converter).convert(
380 compounding,
381 u,
382 IERC20(compounding).balanceOf(address(this))
383 );
384
385 // Get the amount received
386: uint256 redeemed = IERC20(u).balanceOf(address(this)) - starting;
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Redeemer.sol#L366-L386
But there is no code that approves the Converter
to be able to withdraw from the Redeemer
. The only function available is required to have been called by the MarketPlace
, and is thus not callable by the admin:
// File: src/Redeemer.sol : Redeemer.approve() #2
203 function approve(address i) external authorized(marketPlace) {
204 if (i != address(0)) {
205 @> Safe.approve(IERC20(i), address(converter), type(uint256).max);
206 }
207: }
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Redeemer.sol#L203-L207
Redemptions of Illuminate PTs for underlyings is based on shares of each Illuminate PT's totalSupply()
of the available underlying, not the expect underlying total:
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Redeemer.sol#L422
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Redeemer.sol#L464
https://github.com/sherlock-audit/2022-10-illuminate/blob/main/src/Redeemer.sol#L517
There is a fork test that tests the converter functionalty, but is uses vm.startPrank()
to hack the approval, which wouldn't be available in real life.
Also note that if the admin ever deploys and sets a new converter, that all other redemptions using the converter will break
Tool used
Manual Review
Recommendation
Add the sense yield token to the Redeemer
's Converter
approval during market creation/setting of principal