Core Contracts

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

BoostController#updateUserBoost() will revert due to incorrect totalBoost calculation

Summary

In BoostController#updateUserBoost(), totalBoost of poolBoosts[pool] is updated by newBoost. Since in delegateBoost() it has never increased, this line:

poolBoost.totalBoost = poolBoost.totalBoost - (oldBoost - newBoost);

will revert.

Vulnerability Details

In delegateBoost(), there's no increasing totalBoost of poolBoosts[pool] even new boost is deligated.

function updateUserBoost(address user, address pool) external override nonReentrant whenNotPaused {
...
// Update pool totals safely
if (newBoost >= oldBoost) {
poolBoost.totalBoost = poolBoost.totalBoost + (newBoost - oldBoost);
} else {
@> poolBoost.totalBoost = poolBoost.totalBoost - (oldBoost - newBoost);
}
...
}

As a result, if poolBoost.totalBoost = 0, update for this user and pool will revert due to arithmetic operation overflowed.

Proof Of Code

Test code is written in BoostController.test.js

describe("Delegation System", () => {
it("after delegation, update reverts", async () => {
const amount = ethers.parseEther("500");
const duration = 7 * 24 * 3600;
const newPool = await (await ethers.getContractFactory("MockPool")).deploy();
await expect(boostController.connect(manager).modifySupportedPool(newPool.getAddress(), true))
.to.emit(boostController, "PoolAdded")
.withArgs(newPool.getAddress());
await boostController.connect(user1).delegateBoost(newPool.getAddress(), amount, duration);
// Move time forward
await time.increase(duration);
await expect(
boostController.connect(user2).updateUserBoost(user1.address, newPool.getAddress())
).to.emit(boostController, "UpdateBoostFailed")
.withArgs(user1.address, newPool.getAddress(), amount);
});
}

Impact

updateUserBoost() is broken.

Tools Used

manual, hardhat

Recommendations

Increase totalBoost with amount when delegateBoost().

function delegateBoost(
address to,
uint256 amount,
uint256 duration
) external override nonReentrant {
...
delegation.amount = amount;
delegation.expiry = block.timestamp + duration;
delegation.delegatedTo = to;
delegation.lastUpdateTime = block.timestamp;
+ poolBoosts[to].totalBoost += amount;
emit BoostDelegated(msg.sender, to, amount, duration);
}
Updates

Lead Judging Commences

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

BoostController removes pool boost on delegation removal without adding it on delegation creation, leading to accounting inconsistencies and potential underflows

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

BoostController removes pool boost on delegation removal without adding it on delegation creation, leading to accounting inconsistencies and potential underflows

Support

FAQs

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

Give us feedback!