stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: medium
Invalid

Loss of reward due to mismatch in timing of effectiveBalance change in secondary chain

Summary

The effectiveBalances are important variables that determine the user's reward.
In the secondary chain, it is executed after the action enters the queue.
However, the user loses the reward due to the fact that the process of changing effectiveBalances at the queue entry stage and the process of changing effectiveBalances at the time of execute are separated.

Vulnerability Details

The following are examples of actions that can change a user's effectiveBalance.

  • initiateUnlock: Changes at the stage of entering queue

      effectiveBalances[msg.sender] -= boostAmount;
      totalEffectiveBalance -= boostAmount;
      queuedLockUpdates[_lockId].push(LockUpdate(updateBatchIndex, lock));
      queuedRESDLSupplyChange -= int256(boostAmount);
    

https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/SDLPoolSecondary.sol#L192-L196

  • withdraw: Changes at the stage of entering queue

      lock.amount = baseAmount - _amount;
      effectiveBalances[msg.sender] -= _amount;
      totalEffectiveBalance -= _amount;
      queuedLockUpdates[_lockId].push(LockUpdate(updateBatchIndex, lock));
      queuedRESDLSupplyChange -= int256(_amount);
    

https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/SDLPoolSecondary.sol#L230-L235

  • mint: Changes at the stage of execute

          locks[lockId] = lock;
          lockOwners[lockId] = _owner;
          balances[_owner] += 1;
          uint256 totalAmount = lock.amount + lock.boostAmount;
          effectiveBalances[_owner] += totalAmount;
          totalEffectiveBalance += totalAmount;
    

https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/SDLPoolSecondary.sol#L397-L403

  • update: Changes at the stage of execute

                  uint256 totalDiff = uint256(baseAmountDiff + boostAmountDiff);
                  effectiveBalances[_owner] += totalDiff;
                  totalEffectiveBalance += totalDiff;
                  emit UpdateLock(
    

https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/SDLPoolSecondary.sol#L486-L489

There are several patterns in user flow.
Consider a simple pattern of minting and then withdrawing.

First, the user transfers sdlToken and tries to mint the lock. At this time, the process is added to queue and there is no change in effectiveBalances. The user must wait until he/she can execute.
The user will eventually execute, at which time effectiveBalances will be added.
The user will not be able to receive the reward generated by this time lag.
After some time has elapsed, the user will attempt to withdraw from the protocol.
At this time, the effectiveBalances changes when enters the queue, and the user loses the right to receive the reward.
There is a time lag until the user is able to execute the request, at which point the effectiveBalances are already gone and the user will not receive the reward.
At this time, the first sdlToken credited is returned.
The user will not receive the reward until the sdlToken is sent for the mint, the process is queued, and then executed. However, in the case of withdrawals, the user will not receive the reward at the queue stage, even though the sdltoken is locked.
In other words, the user receives less reward than he/she should have received.
If effectiveBalances are changed in the minting execution stage, they should also be changed in the withdrawal execution stage.

There are other patterns, but the common denominator is that when users lose effectiveBalances, the timing of processing is faster, and when effectiveBalances increase, the timing of processing is slower.
This is disadvantageous to the user.
In particular, only users in the secondary chain will lose rewards, since the problem does not occur when the same action is taken in the primary chain.
This inconsistency is also problematic.
This is not due to a time lag in CCIP messages, but simply to inconsistent timing in the processing of effectiveBalances.

Impact

Users of the secondary chain lose the rewards they should have received.
It is also inconsistent with the primary chain processing.

Tools Used

Manual

Recommendations

Unify the timing of changes in effectiveBalances.

Updates

Lead Judging Commences

0kage Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.