It is possible to specify some address as a receiver in a deposit function. When a participant deposits assets, this amount is stored in a mapping for a receiver, but shares are minted for a msg.sender. The receiver and mgs.sender may be different addresses. When a participant decides to cancelParticipation, the stakedAsset for msg.sender will be set to zero, and all shares will be burned. But if while deposit, the msg.sender was not equal to receiver, then, depending on who calls the cancelParticipation function - 2 ways are possible:
If cancelParticipation is called by an address equal to receiver from the deposit:
receiver has stackedAsset -> stackedAssets will be transferred from the vault, and the vault balance will decrease;
receiver does not have shares -> no shares will be burned => shares price drops;
If cancelParticipation is called by the address that equals msg.sender from the deposit:
msg.sender doesn't have stackedAssets -> zero assets will be transferred to msg.sender => vault balance will not change;
msg.sender has shares => shares will be burned and shares exchange rate will rise -> possible inflation attack;
Likelihood: MEDIUM
The issue occurs when the msg.sender address is not equal to the receiver address in the deposit function.
Impact: HIGH
The issue may cause unpredictable changes of shares exchange rate, excessive shares burn or assets withdrawal.
POC proves both cases:
When cancelParticipation is called by the msg.sender:
deposit with msg.sender != receiver;
Check that the deposited asset amount is stored for the receiver, not for msgSender;
Check that shares are minted for msgSender after deposit;
Cancel participation by msgSender;
Check that the vault balance has not changed after cancelParticipation;
Check that all shares are burned from the msg.sender and the vault totalSupply decreased.
When cancelParticipation is called by the receiver:
deposit with msg.sender2 != receiver2;
Check that the deposited asset amount is stored for receiver2, not for msgSender2;
Check that shares are minted for msgSender2 after deposit;
Cancel participation by receiver2;
Check that the vault balance decreased after cancelParticipation;
Check that shares are not burned from msg.sender and the vault totalSupply is not changed.
The separate instances of BriVault are used because there is a bug in the shares calculation in deposit function, so consequent deposits mint the wrong amount of shares.
Shares amount to burn should always be calculated depending on the amount of participant's stackedAssets as specified in ERC4626 withdraw function.
Make the signature and logic of the cancelParticipation function clearer:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.