Open code423n4 opened 1 year ago
Picodes marked the issue as primary issue
Picodes marked the issue as selected for report
drahrealm marked the issue as disagree with severity
To make sure this won't be an issue, we will add the whenNotPaused
modifier to claimUserReward
method in PirexGmx
. Also, as migrateRewards
is going to be updated to also set the pirexRewards
address to 0, it will defer any call to claim the rewards
Picodes marked the issue as satisfactory
To make sure this won't be an issue, we will add the
whenNotPaused
modifier toclaimUserReward
method inPirexGmx
. Also, asmigrateRewards
is going to be updated to also set thepirexRewards
address to 0, it will defer any call to claim the rewards
Seems to be the mitigation for #249
Lines of code
https://github.com/code-423n4/2022-11-redactedcartel/blob/03b71a8d395c02324cb9fdaf92401357da5b19d1/src/PirexRewards.sol#L390-L391
Vulnerability details
Impact
A user (which can also be one of the autocompounding contracts,
AutoPxGlp
orAutoPxGmx
) can loss a reward as a result of reward tokens mismanagement by the owner.Proof of Concept
The protocol defines a short list of reward tokens that are hard coded in the
claimRewards
function of thePirexGmx
contract (PirexGmx.sol#L756-L759):The fact that these addresses are hard coded means that no other reward tokens will be supported by the protocol. However, the
PirexRewards
contract maintains a different list of reward tokens, one per producer token (PirexRewards.sol#L19-L31):These reward tokens can be added (PirexRewards.sol#L151) or removed (PirexRewards.sol#L179) by the owner, which creates the possibility of a mismanagement:
PirexGmx
contract;PirexGmx
contract.Such mismanagement can cause users to lose rewards for two reasons:
PirexRewards
contract that are used to transfer rewards.In the
claim
function:harvest
is called to pull rewards from GMX (PirexRewards.sol#L377):claimReward
is called onPirexGmx
to pull rewards from GMX and get the hard coded lists of producer tokens, reward tokens, and amounts (PirexRewards.sol#L346-L347):claim
function, owner-set reward tokens are read (PirexRewards.sol#L386-L387):the owner-set reward tokens are iterated and the previously recorded rewards are distributed (PirexRewards.sol#L396-L415):
In the above loop, there can be multiple reasons for rewards to not be sent:
PirexGmx
(i.e. it's not in the hard coded reward tokens list);rewardTokens
array of a producer token turns out to be empty due to a mismanagement by the owner.In all of the above situations rewards won't be sent, however user's reward state will still be set to 0.
Also, notice that calling
claim
won't revert if reward tokens are misconfigured, and theClaim
event will be emitted successfully, which makes reward tokens mismanagement hard to detect.The amount of lost rewards can be different depending on how much GMX a user has staked and how often they claim rewards. Of course, if a mistake isn't detected quickly, multiple users can suffer from this issue. The autocompounding contracts (
AutoPxGlp
andAutoPxGmx
) are also users of the protocol, and since they're intended to hold big amounts of real users' deposits (they'll probably be the biggest stakers), lost rewards can be big.Tools Used
Manual review
Recommended Mitigation Steps
Consider having one source of reward tokens. Since they're already hard coded in the
PirexGmx
contract, consider exposing them so thatPirexRewards
could read them in theclaim
function. This change will also mean that theaddRewardToken
andremoveRewardToken
functions won't be needed, which makes contract management simpler. Also, in theclaim
function, consider updating global and user reward states only after ensuring that at least one reward token was distributed.