Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: high
Valid

Existing Lock Amount Overwritten During New Lock Creation

Summary

The veRAACToken::lock function uses the LockManager::createLock function in the LockManager library. This function has a vulnerability where it overwrites the existing lock amount instead of increasing it when a user creates a new lock while already having an active lock.

Vulnerability Details

In the veRAACToken::lock function, when a user creates a new lock, the function directly assigns a new Lock struct to the state.locks[user] mapping without checking if the user already has an existing lock. This results in the previous lock amount being overwritten, effectively losing the previously locked tokens.

Impact

  1. Loss of user funds when withdrawing
    Users who create a new lock while having an existing lock will lose their previously locked tokens when withdrawing.

  2. Incorrect accounting of locked tokens
    The veRAACToken::_lockState.totalLocked will return the correct total locked amount, but the sum of all the lock amounts will be incorrect.

Proof of Concept

it("Existing Lock Amount Overwritten During New Lock Creation", async () => {
const alice = users[0];
const amount = ethers.parseEther("1000");
const duration = 365 * 24 * 3600 * 4;
// Create first lock for alice
console.log("Creating first lock for alice...");
const alice1Tx = await veRAACToken.connect(alice).lock(amount, duration);
await alice1Tx.wait();
const positionFirstLock = await veRAACToken.getLockPosition(alice.address);
console.log("Alice Position after first lock: ");
console.log(" - amount: ", positionFirstLock.amount);
console.log(" - power: ", positionFirstLock.power);
expect(positionFirstLock.amount).to.equal(amount);
expect(positionFirstLock.power).to.equal(amount);
// Create second lock for alice
console.log("Creating second lock for alice...");
const alice2Tx = await veRAACToken.connect(alice).lock(amount, duration);
await alice2Tx.wait();
const positionSecondLock = await veRAACToken.getLockPosition(alice.address);
console.log("Alice Position after second lock: ");
console.log(" - amount: ", positionSecondLock.amount);
console.log(" - power: ", positionSecondLock.power);
expect(positionSecondLock.amount).to.equal(amount + amount);
expect(positionSecondLock.power).to.equal(amount + amount);
});

and the output of the test is:

Creating first lock for alice...
Alice Position after first lock:
- amount: 1000000000000000000000n
- power: 1000000000000000000000n
Creating second lock for alice...
Alice Position after second lock:
- amount: 1000000000000000000000n
- power: 2000000000000000000000n

Tools Used

Manual Review

Recommendations

To fix this issue, the LockManager::createLock function should check if the user already has an existing lock and either revert or increase the existing lock amount.

Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Validated
Assigned finding tags:

veRAACToken::lock called multiple times, by the same user, leads to loss of funds

Support

FAQs

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