sherlock-audit / 2024-08-cork-protocol-judging

2 stars 2 forks source link

hunter_w3b - Inability to redeem remaining DS+PA after `redeemRaWithCt` call. #208

Closed sherlock-admin2 closed 2 months ago

sherlock-admin2 commented 2 months ago

hunter_w3b

Medium

Inability to redeem remaining DS+PA after redeemRaWithCt call.

Summary

The redeemRaWithCt function resets the RA balances, preventing any remaining RA from being redeemed if redeemRaWithDs is not also called.

Vulnerability Details

When redeemRaWithCt is called, it resets the RA balances to zero by calling _separateLiquidity.

    function redeemWithCt(
        State storage self,
        address owner,
        uint256 amount,
        uint256 dsId,
        bytes memory rawCtPermitSig,
        uint256 deadline
    ) internal returns (uint256 accruedPa, uint256 accruedRa) {
        DepegSwap storage ds = self.ds[dsId];
        Guard.safeAfterExpired(ds);
        if (deadline != 0) {
            DepegSwapLibrary.permit(ds.ct, rawCtPermitSig, owner, address(this), amount, deadline);
        }
        _separateLiquidity(self, dsId);

        uint256 totalCtIssued = self.psm.poolArchive[dsId].ctAttributed;
        PsmPoolArchive storage archive = self.psm.poolArchive[dsId];

        (accruedPa, accruedRa) = _calcRedeemAmount(amount, totalCtIssued, archive.raAccrued, archive.paAccrued);

        _beforeCtRedeem(self, ds, dsId, amount, accruedPa, accruedRa);

        _afterCtRedeem(self, ds, owner, amount, accruedPa, accruedRa);
    }
    function unlockTo(PsmRedemptionAssetManager storage self, address to, uint256 amount) internal {
        decLocked(self, amount);
        unlockToUnchecked(self, amount, to);
    }

    // @audit revert  because  self.locked is zero 
    function decLocked(PsmRedemptionAssetManager storage self, uint256 amount) internal {
        self.locked = self.locked - amount;
    }    

Every call to unlockTo function will revert it.


    function _redeemRaWithCtDs(State storage self, DepegSwap storage ds, address owner, uint256 amount)
        internal
        returns (uint256 ra, uint256 rates)
    {
        rates = ds.exchangeRate();

        ra = MathHelper.calculateRedeemAmountWithExchangeRate(amount, rates);
@>>        self.psm.balances.ra.unlockTo(owner, ra);
         // Revert 

        ERC20Burnable(ds.ct).burnFrom(owner, amount);
        ERC20Burnable(ds._address).burnFrom(owner, amount);
    }
    function _afterRedeemWithDs(
        State storage self,
        DepegSwap storage ds,
        address owner,
        uint256 amount,
        uint256 feePrecentage
    ) internal returns (uint256 received, uint256 _exchangeRate, uint256 fee) {
        IERC20(ds._address).transferFrom(owner, address(this), amount);

        _exchangeRate = ds.exchangeRate();
        received = MathHelper.calculateRedeemAmountWithExchangeRate(amount, _exchangeRate);

        fee = MathHelper.calculatePrecentageFee(received, feePrecentage);
        received -= fee;

        IERC20(self.info.peggedAsset().asErc20()).safeTransferFrom(owner, address(this), amount);
    // Revert 
 @!>>       self.psm.balances.ra.unlockTo(owner, received);
    }

Impact

Users are unable to redeem their full entitled RA amount if they only call redeemRaWithCt and do not also call redeemRaWithDs. This leads to locked funds that cannot be withdrawn.

Code Snippet

https://github.com/sherlock-audit/2024-08-cork-protocol/blob/main/Depeg-swap/contracts/libraries/PsmLib.sol#L448C1-L471C6 https://github.com/sherlock-audit/2024-08-cork-protocol/blob/main/Depeg-swap/contracts/libraries/PsmLib.sol#L188 https://github.com/sherlock-audit/2024-08-cork-protocol/blob/main/Depeg-swap/contracts/libraries/PsmLib.sol#L346

Tool Used

Manual review

Recommendation

Alternatively, develop logic to automatically call redeemRaWithDs if redeemRaWithCt was previously called alone, to ensure full RA entitlement can be withdrawn.

sherlock-admin2 commented 2 months ago

1 comment(s) were left on this issue during the judging contest.

tsvetanovv commented:

It would be user error if they did not also call redeemRaWithDs.