Skip to content
This repository has been archived by the owner on Oct 1, 2023. It is now read-only.

0xnirlin - Loss of funds if triggerNullEpoch is called late. #493

Closed
sherlock-admin opened this issue Mar 28, 2023 · 0 comments
Closed

0xnirlin - Loss of funds if triggerNullEpoch is called late. #493

sherlock-admin opened this issue Mar 28, 2023 · 0 comments
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue

Comments

@sherlock-admin
Copy link
Contributor

sherlock-admin commented Mar 28, 2023

0xnirlin

medium

Loss of funds if triggerNullEpoch is called late.

Summary

If triggerNullEpoch() is not called within time slot of epoch by keepers , it can lead to calling triggerEndEpoch() at the end of the epoch and funds will be lost.

Vulnerability Detail

Take the following condition

  1. User deposits into premium and no one deposits into collateral.
  2. So collateral has 0 tvl.
  3. In such case if triggerNullEpoch() is not called within timeperiod and later triggerEndEpoch() is called funds from premium will be transferred to collateral where there are no depositors so all the funds will be stucked.
  4. Also as other issue opened that user cannot even withdraw before epochEnd so premium are stuck too.

Impact

Loss of funds as they will be permanently locked in collateral, as epoch will be resolved after triggering triggerEndEpoch() it will prevent from other functions to be called too.. Marking this as medium because chances of that happening are low but if happened funds can be locked and lost.

Code Snippet

Following function will be most impacted:

    function triggerEndEpoch(uint256 _marketId, uint256 _epochId) public {
        address[2] memory vaults = vaultFactory.getVaults(_marketId);

        if (vaults[0] == address(0) || vaults[1] == address(0))
            revert MarketDoesNotExist(_marketId);

        IVaultV2 premiumVault = IVaultV2(vaults[0]);
        IVaultV2 collateralVault = IVaultV2(vaults[1]);

        if (
            premiumVault.epochExists(_epochId) == false ||
            collateralVault.epochExists(_epochId) == false
        ) revert EpochNotExist();

        (, uint40 epochEnd, ) = premiumVault.getEpochConfig(_epochId);

        if (block.timestamp <= uint256(epochEnd)) revert EpochNotExpired();

        //require this function cannot be called twice in the same epoch for the same vault
        if (premiumVault.epochResolved(_epochId)) revert EpochFinishedAlready();
        if (collateralVault.epochResolved(_epochId))
            revert EpochFinishedAlready();

        premiumVault.resolveEpoch(_epochId);
        collateralVault.resolveEpoch(_epochId);

        uint256 epochFee = vaultFactory.getEpochFee(_epochId);

        uint256 premiumTVL = premiumVault.finalTVL(_epochId);
        uint256 collateralTVL = collateralVault.finalTVL(_epochId);

        uint256 premiumFee = calculateWithdrawalFeeValue(premiumTVL, epochFee);

        uint256 premiumTVLAfterFee = premiumTVL - premiumFee;
        uint256 collateralTVLAfterFee = collateralTVL + premiumTVLAfterFee;

        // strike price is not reached so premium is entiled to 0
        premiumVault.setClaimTVL(_epochId, 0);
        // strike price is not reached so collateral is entitled to collateralTVL + premiumTVLAfterFee
        collateralVault.setClaimTVL(_epochId, collateralTVLAfterFee);

        // send premium fees to treasury and remaining TVL to collateral vault
        premiumVault.sendTokens(_epochId, premiumFee, treasury);
        // strike price reached so collateral is entitled to collateralTVLAfterFee
        premiumVault.sendTokens(
            _epochId,
            premiumTVLAfterFee,
            address(collateralVault)
        );

        emit EpochResolved(
            _epochId,
            _marketId,
            VaultTVL(collateralTVLAfterFee, collateralTVL, 0, premiumTVL),
            false,
            block.timestamp,
            0           
        );
    }

Tool used

Manual Review

Recommendation

Add zero TVL revert check as in triggerDepeg()

        if (
            premiumVault.totalAssets(_epochId) == 0 ||
            collateralVault.totalAssets(_epochId) == 0
        ) {
            revert VaultZeroTVL();
        }

https://github.com/sherlock-audit/2023-03-Y2K/blob/main/Earthquake/src/v2/Controllers/ControllerPeggedAssetV2.sol#L81

Duplicate of #108

@github-actions github-actions bot closed this as completed Apr 3, 2023
@github-actions github-actions bot added Medium A valid Medium severity issue Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label labels Apr 3, 2023
@sherlock-admin sherlock-admin added the Reward A payout will be made for this issue label Apr 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate A valid issue that is a duplicate of an issue with `Has Duplicates` label Medium A valid Medium severity issue Reward A payout will be made for this issue
Projects
None yet
Development

No branches or pull requests

1 participant