31276 - [SC - High] BPT can be locked for only week resulting in u...

Submitted on May 16th 2024 at 03:32:46 UTC by @marchev for Boost | Alchemix

Report ID: #31276

Report type: Smart Contract

Report severity: High

Target: https://github.com/alchemix-finance/alchemix-v2-dao/blob/main/src/VotingEscrow.sol

Impacts:

  • Theft of unclaimed yield

Description

Brief/Intro

The 80/20 ALCX/WETH BPT has a minimum lock period of 1 epoch (2 weeks). However, a flaw allows malicious actors to lock their BPT for just 1 week, resulting in unfair ALCX reward distribution. This means a malicious actor can unfairly claim rewards without meeting the minimum 2-week lock requirement.

Vulnerability Details

The _createLock() function is responsible for creating a lock when depositing Balancer Pool Tokens in VotingEscrow. It should enforce a minimum lock period of 1 epoch (2 weeks):

    function _createLock(
        uint256 _value,
        uint256 _lockDuration,
        bool _maxLockEnabled,
        address _to
    ) internal returns (uint256) {
	    // ...
        uint256 unlockTime = /** ... */ ((block.timestamp + _lockDuration) / WEEK) * WEEK;

        // ...
        require(unlockTime >= (((block.timestamp + EPOCH) / WEEK) * WEEK), "Voting lock must be 1 epoch");

        // ...
    }

However, this check is flawed. A malicious actor can lock BPTs for just 1 week instead of the required 2 weeks. This allows them to unjustly receive rewards as if they had locked their BPTs for a whole epoch, effectively stealing rewards from other participants.

Example Scenario:

  • Next epoch starts at 1717632000 (Thu Jun 06 2024 00:00:00 UTC)

  1. Alice locks 1 BPT for 2 weeks (1 epoch) at block.timestamp = 1716422401 (Thu May 23 2024 00:00:01 UTC)

  2. Bob locks 1 BPT for 7 days + 1 seconds at block.timestamp = 1717027199 (Wed May 29 2024 23:59:59 UTC)

  3. The epoch resets on 1717632000 (Thu Jun 06 2024 00:00:00 UTC)

Expected behavior: Bob should not be able to lock his BPT for less than 1 epoch (2 weeks).

Actual behavior: Alice and Bob receive equal rewards.

Bob circumvents the minimum lock duration check. Here’s why:

The check performed:

The check passes for Bob, even though his lock time is only 7 days + 1 second.

Impact Details

The flawed minimum lock time check allows users to lock BPTs for only 1 week but still receive rewards for a full epoch. This results in unfair reward distribution, with malicious users effectively stealing rewards from others.

References

https://github.com/alchemix-finance/alchemix-v2-dao/blob/f1007439ad3a32e412468c4c42f62f676822dc1f/src/VotingEscrow.sol#L1375-L1381

Proof of Concept

The following coded PoC demonstrates the issue.

Add the following test case to VotingEscrow.t.sol:

Make sure the following entries are updated in Makefile:

Run the PoC via:

PoC output:

Last updated

Was this helpful?