stake.link

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

Users are disadvantaged because the timing of `boostAmount` confirmation differs between chains.

Summary

boostAmount gives different results depending on the protocol settings, even if the user's settings are the same.
Because the timing of this calculation differs between the primary and secondary chains, users may lose rewards.

Vulnerability Details

To think simple, let's compare the behavior of mint.

In the primary chain, when the sdl token is sent, the lock is created and the effectiveBalances are raised simultaneously.

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

https://github.com/Cyfrin/2023-12-stake-link/blob/549b2b8c4a5b841686fceb9c311dca9ac58225df/contracts/core/sdlPool/SDLPoolPrimary.sol#L288-L295

In the secondary chain, the lock creation process is put into queue at the same time the sdl token is sent.

    Lock memory lock = _createLock(_amount, _lockingDuration);
    queuedNewLocks[updateBatchIndex].push(lock);
    newLocksByOwner[_owner].push(NewLockPointer(updateBatchIndex, uint128(queuedNewLocks[updateBatchIndex].length - 1)));

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

Users have a waiting period before they can execute.
When the user executes, a lock is created and effectiveBalances is raised.
At this time, boostAmount is not recalculated, and the value of the stage put in queue is adopted.

        Lock memory lock = queuedNewLocks[newLockPointer.updateBatchIndex][newLockPointer.index];
        currentMintLockIdByBatch[newLockPointer.updateBatchIndex] += 1;
        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#L393-L403

Consider the following case.
Assume that the parameters used to create the lock are the same.

1. A user in the secondary chain sends funds and queues the creation of the lock

2. The protocol extends maxLockingDuration (This decreases the value of boostAmount).

3. In the secondary chain, User performs executing the lock creation. In the primary chain, User also sends the sdl token to create the lock.

As a result, the users of the secondary chain and primary chain create locks at the same time, but the value of the secondary user’s boostAmount is smaller than that of the primary chain. (i.e., effectiveBalances is also smaller)

This is not caused by a time lag in CCIP messages, but simply by the timing of the boostAmount calculation.
If the boostAmount of the secondary chain is calculated at the execute(mint) stage, there is no problem.

Impact

Users will be disadvantaged by the chain they use.

Tools Used

Manual

Recommendations

In the secondary chain, boostAmount should be calculated at the execute(mint) stage.

Updates

Lead Judging Commences

0kage Lead Judge almost 2 years ago
Submission Judgement Published
Invalidated
Reason: Design choice

Support

FAQs

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