Core Contracts

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

Once user crate a lock, user is unable to create a new because he will lose the first

Summary

This due to the fact that if a user create a new lock, it will override the first one as seen here:

function createLock(
LockState storage state,
address user,
uint256 amount,
uint256 duration
) internal returns (uint256 end) {
// Validation logic remains the same
if (state.minLockDuration != 0 && state.maxLockDuration != 0) {
if (duration < state.minLockDuration || duration > state.maxLockDuration)
revert InvalidLockDuration();
}
if (amount == 0) revert InvalidLockAmount();
end = block.timestamp + duration;
@> state.locks[user] = Lock({
amount: amount,
end: end,
exists: true
});
state.totalLocked += amount;
emit LockCreated(user, amount, end);
return end;
}

Vulnerability Details

Imagine the following scenario:

  1. user locks RAAC tokens in the veRAAC contract and receives veRAAC tokens

  2. Then he gets some RAAC token rewards from the StabilityPool and wants to increase his voting power

  3. If he do this he will lose his last lock (since it will be overriden as seen in the LockManager::createLock function), leading to loss of RAAC tokens for the user

This can be bypassed by transferring the tokens to another address and making a lock with it, but the user will lose RAAC tokens again, because of the applied fees in the RAACToken::_update function:

function _update(
address from,
address to,
uint256 amount
) internal virtual override {
uint256 baseTax = swapTaxRate + burnTaxRate;
// Skip tax for whitelisted addresses or when fee collector disabled
if (
baseTax == 0 ||
from == address(0) ||
to == address(0) ||
whitelistAddress[from] ||
whitelistAddress[to] ||
feeCollector == address(0)
) {
super._update(from, to, amount);
return;
}
// All other cases where tax is applied
uint256 totalTax = amount.percentMul(baseTax);
uint256 burnAmount = (totalTax * burnTaxRate) / baseTax;
super._update(from, feeCollector, totalTax - burnAmount);
super._update(from, address(0), burnAmount);
super._update(from, to, amount - totalTax);
}

Impact

This leads to loss of RAAC tokens for the user and practically locked funds since if the user see this and decides to do nothing, his RAAC token is practically useless

Tools Used

Manual review

Recommendations

Implement a multiple lock functionality so the users can create a new lock without losing the old one

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.