sherlock-audit / 2023-11-covalent-judging

3 stars 2 forks source link

qmdddd - The coolDown mechanism can be bypassed for some validators #76

Closed sherlock-admin closed 7 months ago

sherlock-admin commented 7 months ago

qmdddd

medium

The coolDown mechanism can be bypassed for some validators

Summary

The coolDown mechanism can be bypassed for some validators

Vulnerability Detail

When a user makes a unstake, the protocol will use a coolDown mechanism to delay the user's actual withdrawal.

function _unstake:

// create unstaking instance
        uint128 coolDownEnd = uint128(v.disabledAtBlock != 0 ? v.disabledAtBlock : block.number);
        unchecked {
            coolDownEnd += (isValidator ? validatorCoolDown : delegatorCoolDown);
        }
        uint128 unstakeId = uint128(v.unstakings[msg.sender].length);
        v.unstakings[msg.sender].push(Unstaking(coolDownEnd, effectiveAmount));

function transferUnstakedOut:

require(uint128(block.number) > us.coolDownEnd, "Cooldown period has not ended");

However, combined with the function redelegateUnstaked, some validators can bypass the coolDown mechanism, thereby completing instant unstakes and withdrawals.

The attack scenario is as follows:

  1. The protocol adds a validator A (the attacker), and initially disabledAtBlock is 1.

  2. Validator A acts as a delegator to stake on other active validators.

  3. Validator A unstake from other active validators (labeled usX for convenience).

  4. For usX, validator A uses the function redelegateUnstaked to delegate it to himself/herself.

    The only check is:

    require(newStaked <= validatorMaxStake, "Validator max stake exceeded");
  5. Unstake from himself/herself. Since disabledAtBlock is 1, coolDownEnd will be 1+validatorCoolDown, which means there is a high probability that it is smaller than block.number. So withdrawals can be made directly.

Impact

The coolDown mechanism can be bypassed for some validators

Code Snippet

https://github.com/sherlock-audit/2023-11-covalent/blob/main/cqt-staking/contracts/OperationalStaking.sol#L523-L536

https://github.com/sherlock-audit/2023-11-covalent/blob/main/cqt-staking/contracts/OperationalStaking.sol#L664-L684

Tool used

Manual Review

Recommendation

In function redelegateUnstaked, disable msg.sender as newValidator.

Duplicate of #78

sherlock-admin2 commented 7 months ago

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

takarez commented:

invalid