Closed c4-bot-10 closed 3 months ago
This is intentional, as in the rewards are supposed to start at the next accounting period and should not account for new rewards in the current period. Essentially, the rewards start from when the accounting begins, and we ensure that rewards are paid out in distinct periods. (which is also why payoutRewards
returns and not reverts)
It will take until the next reward distribution for the additional rewards to be registered.
This is exactly the outcome we intended with it, and also why the first reward distribution begins after the first unstake/stake action post reward accumulation.
thereksfour marked the issue as unsatisfactory: Invalid
Lines of code
https://github.com/code-423n4/2024-07-reserve/blob/main/contracts/p1/StRSR.sol#L594 https://github.com/code-423n4/2024-07-reserve/blob/main/contracts/p1/Furnace.sol#L66 https://github.com/code-423n4/2024-07-reserve/blob/main/contracts/p1/Distributor.sol#L194-L198
Vulnerability details
This issue is related to the TRST-M-4 finding from the Trust Security audit of v3.1.0 of the protocol. While a mitigation for the original issue was introduced, the current implementation still leads to reward accounting functions being bypassed under certain conditions.
The original TRST-M-4 finding highlighted that reward accounting functions were not called after sending reward tokens in
BackingManager.forwardRevenue()
andDistributor.distribute()
. This could lead to unintended reward distribution due to outdated pending reward balances.The team implemented a fix by calling the missing reward accounting functions. However, the current implementation of the reward distribution functions in the
StRSRP1
andFurnaceP1
contracts lead to the issue only being mitigated under some conditions.In the
StRSRP1
contract, the_payoutRewards()
function contains this check:Similarly, in the
FurnaceP1
contract, themelt()
function has:These checks, while intended to prevent multiple reward calculations within the same block, can lead to bypassing of reward accounting if certain functions are called within the same block (technically, in the same second, as the block time on Arbitrum is 250 ms).
For instance, if
stRSR.payoutRewards()
,stake()
,unstake()
, orcancelUnstake()
, orseizeRSR()
, which all call_payoutRewards()
internally, are executed in the same block, subsequent calls will not update the reward accounting variables. This will result in inaccurate reward calculations and distributions, to the same extent as the original TRST-M-4 issue. It will take until the next reward distribution for the additional rewards to be registered.Impact
Inaccurate reward calculations and distributions for stakers and RToken holders. The impact of rewards not being accounted was shown in great detail in the original finding:
Where PERIOD is now effectively 1s. In this case, we have:
Proof of Concept
stRSR.stake()
Distributor.distribute()
is called, sending a large amount of rewards to StRSR and callingstRSR.payoutRewards()
Tools Used
Manual review
Recommended Mitigation Steps
To fully address the issue, consider updating the relevant accounting variables even when multiple calls occur within the same block. For the
StRSRP1
contract:For the
FurnaceP1
contract:Assessed type
Other