Lucene search

K
code423n4Code4renaCODE423N4:2022-11-REDACTEDCARTEL-FINDINGS-ISSUES-379
HistoryNov 28, 2022 - 12:00 a.m.

Potential PirexReward's producerTokens's rewardToken unsynced with PirexGmx rewardToken can miss calculate the actual reward for user

2022-11-2800:00:00
Code4rena
github.com
4
pirexreward
producertokens
rewardtoken
miscalculation
synchronization
initialization
pirexgmx

Lines of code
<https://github.com/code-423n4/2022-11-redactedcartel/blob/main/src/PirexRewards.sol#L151-L197&gt;

Vulnerability details

Impact

Potential PirexReward’s producerTokens’s rewardToken unsynced with PirexGmx rewardToken can miss calculate the actual reward for user

Proof of Concept

PirexReward initialization does not include rewardToken initialization for producerTokens. Meanwhile inside PirexGmx, it is already hardcoded, the claimRewards will return array of rewardToken contains 4 exact items.

In order for PirexReward to sync or know what are the rewardToken with its producerTokens, there are two functions related to this addRewardToken and removeRewardToken, (also this is prone to issues)

If at some point user do harvest() but the PirexReward only insert 2 rewardToken, or maybe insert 4 rewardToken but one of it is not the correct producerToken, this can raise an issue.

User’ss reward is not being correctly calculated since the rewardToken is missing, and the accounting is not running correctly (until the Owner/Admin correctly input the rewardToken synced with PirexGmx’s)

File: PirexRewards.sol
338:     function harvest()
339:         public
340:         returns (
341:             ERC20[] memory _producerTokens,
342:             ERC20[] memory rewardTokens,
343:             uint256[] memory rewardAmounts
344:         )
345:     {
346:         (_producerTokens, rewardTokens, rewardAmounts) = producer
347:             .claimRewards();
348:         uint256 pLen = _producerTokens.length;
349: 
350:         // Iterate over the producer tokens and update reward state
351:         for (uint256 i; i &lt; pLen; ++i) {
352:             ERC20 p = _producerTokens[i];
353:             uint256 r = rewardAmounts[i];
354: 
355:             // Update global reward accrual state and associate with the update of reward state
356:             ProducerToken storage producerState = producerTokens[p];
357: 
358:             _globalAccrue(producerState.globalState, p);
359: 
360:             if (r != 0) {
361:                 producerState.rewardStates[rewardTokens[i]] += r;
362:             }
363:         }
364: 
365:         emit Harvest(_producerTokens, rewardTokens, rewardAmounts);
366:     }
367: 

from this harvest() function the ProducerToken storage producerState = producerTokens[p]; is not being checked if it exist or not if the token is already being inputed by Admin/Owner.

If user assign to get reward of token X, meanwhile there is no rewardToken X set (or wrongly set) inside PirexRewards the harvest() will skip the user reward accounting, thus decrease the actual reward user should get. (because of delayed userAccrue/globalAccrue, for the token X)

Tools Used

Manual

Recommended Mitigation Steps

Include pirexReward initialization of rewardToken inside initialization function, or check if produceToken (and its rewardToken) inside pirexReward is equal to PirexGmx claimRewards returns data.


The text was updated successfully, but these errors were encountered:

All reactions