In the _getPoolAccumulators function, the values of totalBurnedLatest and totalInterestLatest are not checked for underflow before subtracting totalBurnedAtBlock and totalInterestAtBlock, respectively, this could result in an arithmetic underflow if totalBurnedAtBlock or totalInterestAtBlock is greater than totalBurnedLatest or totalInterestLatest, respectively.
In this case, an underflow could occur if totalBurnedAtBlock or totalInterestAtBlock is greater than totalBurnedLatest or totalInterestLatest, respectively, which can happen if the contract's state is manipulated or if the contract's logic contains a bug.
If an attacker is able to trigger an underflow, they could potentially steal tokens or cause the contract to malfunction. For example, an attacker could manipulate the contract's state to set totalBurnedAtBlock or totalInterestAtBlock to a very large value, causing an underflow when the function attempts to subtract them from totalBurnedLatest or totalInterestLatest, respectively. The resulting negative value could then be used by the attacker to steal tokens or perform other malicious actions.
Proof of Concept
The _getPoolAccumulators function, the values of totalBurnedLatest and totalInterestLatest are not checked for underflow before subtracting totalBurnedAtBlock and totalInterestAtBlock, respectively. This could result in an arithmetic underflow if either totalBurnedAtBlock or totalInterestAtBlock is greater than its corresponding value in totalBurnedLatest or totalInterestLatest, respectively.
For instance, let's consider the following scenario:
totalBurnedLatest = 100, totalBurnedAtBlock = 200
totalInterestLatest = 500, totalInterestAtBlock = 600
When the function attempts to compute totalBurned, it would subtract totalBurnedAtBlock from totalBurnedLatest, which would result in a negative value (-100). Similarly, when it attempts to compute totalInterest, it would subtract totalInterestAtBlock from totalInterestLatest, which would result in a negative value (-100).
Add a check to ensure that totalBurnedLatest is greater than or equal to totalBurnedAtBlock and that totalInterestLatest is greater than or equal to totalInterestAtBlock before subtracting the latter from the former.
Lines of code
https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L636-L661
Vulnerability details
Impact
In the _getPoolAccumulators function, the values of
totalBurnedLatest
andtotalInterestLatest
are not checked for underflow before subtractingtotalBurnedAtBlock
andtotalInterestAtBlock
, respectively, this could result in an arithmetic underflow iftotalBurnedAtBlock
or totalInterestAtBlock is greater thantotalBurnedLatest
ortotalInterestLatest
, respectively.In this case, an underflow could occur if
totalBurnedAtBlock
ortotalInterestAtBlock
is greater thantotalBurnedLatest
ortotalInterestLatest
, respectively, which can happen if the contract's state is manipulated or if the contract's logic contains a bug.If an attacker is able to trigger an underflow, they could potentially steal tokens or cause the contract to malfunction. For example, an attacker could manipulate the contract's state to set
totalBurnedAtBlock
ortotalInterestAtBlock
to a very large value, causing an underflow when the function attempts to subtract them fromtotalBurnedLatest
ortotalInterestLatest
, respectively. The resulting negative value could then be used by the attacker to steal tokens or perform other malicious actions.Proof of Concept
The _getPoolAccumulators function, the values of
totalBurnedLatest
andtotalInterestLatest
are not checked for underflow before subtractingtotalBurnedAtBlock
andtotalInterestAtBlock
, respectively. This could result in an arithmetic underflow if eithertotalBurnedAtBlock
ortotalInterestAtBlock
is greater than its corresponding value intotalBurnedLatest
ortotalInterestLatest
, respectively.For instance, let's consider the following scenario:
totalBurnedLatest
= 100,totalBurnedAtBlock
= 200totalInterestLatest
= 500,totalInterestAtBlock
= 600 When the function attempts to computetotalBurned
, it would subtracttotalBurnedAtBlock
fromtotalBurnedLatest
, which would result in a negative value (-100). Similarly, when it attempts to computetotalInterest
, it would subtracttotalInterestAtBlock
fromtotalInterestLatest
, which would result in a negative value (-100).Reference code of the
_getPoolAccumulators
function: https://github.com/code-423n4/2023-05-ajna/blob/276942bc2f97488d07b887c8edceaaab7a5c3964/ajna-core/src/RewardsManager.sol#L636-L661Tools Used
vscode
Recommended Mitigation Steps
Add a check to ensure that
totalBurnedLatest
is greater than or equal tototalBurnedAtBlock
and thattotalInterestLatest
is greater than or equal tototalInterestAtBlock
before subtracting the latter from the former.Assessed type
Under/Overflow