Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
Submission Details
Severity: medium
Invalid

Users Can Delegate Boosts to Themselves

Author Revealed upon completion

Summary

The delegateBoost function lets users send boost power to themselves, which doesn’t do anything useful. There’s no rule stopping msg.sender from being the same as to, so users can waste gas on a pointless action that doesn’t increase their boost.

Vulnerability Details

This issue happens because the delegateBoost function doesn’t check if the person giving the boost (msg.sender) is the same as the person getting it (to). Let’s look at the code.

Here’s the delegateBoost function:

function delegateBoost(
address to,
uint256 amount,
uint256 duration
) external override nonReentrant {
if (paused()) revert EmergencyPaused();
if (to == address(0)) revert InvalidPool();
if (amount == 0) revert InvalidBoostAmount();
if (duration < MIN_DELEGATION_DURATION || duration > MAX_DELEGATION_DURATION)
revert InvalidDelegationDuration();
uint256 userBalance = IERC20(address(veToken)).balanceOf(msg.sender);
if (userBalance < amount) revert InsufficientVeBalance();
UserBoost storage delegation = userBoosts[msg.sender][to];
if (delegation.amount > 0) revert BoostAlreadyDelegated();
delegation.amount = amount;
delegation.expiry = block.timestamp + duration;
delegation.delegatedTo = to;
delegation.lastUpdateTime = block.timestamp;
emit BoostDelegated(msg.sender, to, amount, duration);
}
  • No Self-Check: It checks if to isn’t zero (if (to == address(0))) and if there’s already a delegation (if (delegation.amount > 0)), but it doesn’t say, “Hey, you can’t delegate to yourself!” So, if msg.sender equals to, it still works.

  • What Happens: It saves the delegation in userBoosts[msg.sender][msg.sender]—like User A delegating to User A. It sets the amount, expiry, and delegatedTo to their own address.

Now, look at how boosts are calculated:

solidity

function _calculateBoost(address user, address pool, uint256 amount) internal view returns (uint256) {
// ... (checks)
uint256 userBalance = IERC20(address(veToken)).balanceOf(user);
// ... (uses userBalance for boost)
}
  • Boost Ignores It: This only uses userBalance—the user’s own veTokens. It doesn’t check userBoosts[user][user] for self-delegations, so the delegated amount doesn’t help.

Why It’s Pointless

  • Normally, delegation means giving your boost to someone else to help them—like sharing power. Delegating to yourself should either be blocked or add to your boost, but here it just sits in userBoosts doing nothing.

  • Later, in removeBoostDelegation:

    solidity

    PoolBoost storage poolBoost = poolBoosts[msg.sender];
    poolBoost.totalBoost -= delegation.amount;
    • It tries to subtract from poolBoosts[msg.sender] (already a bug, as msg.sender isn’t a pool), but since the boost wasn’t added anywhere useful, this subtraction is meaningless too.

Impact

  1. Someone might self-delegate expecting a benefit (since it’s allowed), then get frustrated when nothing happens.

Tools Used

manual review

Recommendations
Stop users from delegating to themselves

Updates

Lead Judging Commences

inallhonesty Lead Judge 13 days ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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