Summary
In veRAACToken::increase voting power is calculated with the users locked amount and the locks end time passed to the calculateAndUpdatePower function, in the case of increase the amount increased is incorrectly being added to the already updated locked amount.
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
userLock.amount + amount,
userLock.end
);
This means that voting power is calculated with the previously locked amount + double the new amount being locked in the increase.
Vulnerability Details
PoC, this test is a modified unit test from veRAACToken.test.js:
it("should allow users to increase lock amount", async () => {
const initialAmount = ethers.parseEther("1000");
const additionalAmount = ethers.parseEther("500");
const duration = 365 * 24 * 3600;
await veRAACToken.connect(users[0]).lock(initialAmount, duration);
console.log("Balance before increase: " + await veRAACToken.balanceOf(users[0]));
await expect(veRAACToken.connect(users[0]).increase(additionalAmount))
.to.emit(veRAACToken, "LockIncreased")
.withArgs(users[0].address, additionalAmount);
console.log("Balance after increase: " + await veRAACToken.balanceOf(users[0]));
const position = await veRAACToken.getLockPosition(users[0].address);
expect(position.amount).to.equal(initialAmount + additionalAmount);
});
In the logs we can see that the veRAACToken balance for the user almost doubles when it should be around 1.5x the amount after the increase:
Balance before increase: 250000000000000000000
Balance after increase: 499999952435312024353
✔ should allow users to increase lock amount (3345ms)
Impact
More tokens minted to user than actually deserved
Tools Used
Manual review + hardhat tests.
Recommendations
(int128 newBias, int128 newSlope) = _votingState.calculateAndUpdatePower(
msg.sender,
- userLock.amount + amount,
+ userLock.amount,
userLock.end
);