The Standard

The Standard
DeFiHardhat
20,000 USDC
View results
Submission Details
Severity: low
Valid

burn() Function Can Be Front-runned to Earn Fees

Summary

An attacker can front-run the burn() function if the amount passed as an argument is substantial, and then back-run the transaction to call distributeFees() in the LiquidationPoolManager.

Vulnerability Details

Bob, Alice, and John are borrowers. They have minted 500,000 euros, 1,000,000 euros, and 500,000 euros, respectively. Each of them burns their euros simultaneously. Considering the current burn fee is 0.5%, and the total amount burned is 2,000,000 euros, the quantity sent to the LiquidationPoolManager will be 10,000 euros. A malicious actor could front-run the euro transfers and call the increasePosition() function in the LiquidationPool.

He can then back-run these transactions by calling distributeFees() in the LiquidationPoolManager to collect fees. The malicious actor only needs to wait for a day to receive the fees from the burns.

The issue here is that the LiquidationPool distribute fees to all the TST holders and not only the ones that have a position.

uint256 tstTotal = getTstTotal();
if (tstTotal > 0) {
IERC20(EUROs).safeTransferFrom(msg.sender, address(this), _amount);
for (uint256 i = 0; i < holders.length; i++) {
address _holder = holders[i];
positions[_holder].EUROs += _amount * positions[_holder].TST / tstTotal;
}
for (uint256 i = 0; i < pendingStakes.length; i++) {
pendingStakes[i].EUROs += _amount * pendingStakes[i].TST / tstTotal;
}
}
}

Impact

A malicious actor can take a part of the fees without taking any risk and take a part of the TST holders' fees without taking any risk.

Tools Used

Manual review

Recommendations

Refactor in the Liquidation Pool the distributeFees() and getTstTotal()(L55-L62)

function getTstTotal() private view returns (uint256 _tst) {
for (uint256 i = 0; i < holders.length; i++) {
_tst += positions[holders[i]].TST;
}
}
function distributeFees(uint256 _amount) external onlyManager {
consolidatePendingStack();
uint256 tstTotal = getTstTotal();
if (tstTotal > 0) {
IERC20(EUROs).safeTransferFrom(msg.sender, address(this), _amount);
for (uint256 i = 0; i < holders.length; i++) {
address _holder = holders[i];
positions[_holder].EUROs += _amount * positions[_holder].TST / tstTotal;
}
}
}
Updates

Lead Judging Commences

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

frontrun-distrubutefees

hrishibhat Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

frontrun-feedist-low

Support

FAQs

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