Description:Description\
There is a discrepancy in how fees are managed within the system, specifically between withdrawal and deposit fees:
Withdrawal Fees: These fees have a clearly defined path for collection and processing, ensuring that the user's assets are not adversely affected when the fees are collected. This approach effectively isolates the fee handling from the user's core assets.
Deposit Fees: In contrast, deposit fees lack a specific path for collection. As a result, there is no defined mechanism for handling these fees, potentially leading to confusion or early and unprogrammed asset extraction in the deposit process. The absence of a dedicated collection process for deposit fees can result in these fees being either overlooked or improperly managed, which could impact the user's assets and the system's overall integrity.
If we look at the NativeMinterWithdrawal's (the one which is inherited by the stROSEMinter) deposit function, we can see how the asset is collected:
As it is clear from above, the fee amount is subtracted from the initial deposit amount (msg.value for the native version), and the rest is minted for the user.
The problem lies in the fee distribution mechanism. The deposit fees lack a separate collection function and recipient, which makes the fee-splitting hard.
As opposed to the withdrawal process, which clearly has a distinct stream together with its collection function (with the option of choosing a recipient), the deposit fees lack such a mechanism.
Also, the overrided withdraw() function, which is the only way of extracting deposit fees, just checks for a positive balance of the contract after subtracting the unclaimed withdrawals and transfers the ETH to the desired receiver. By doing so, the recently deposited assets, without extracting the fee stream, are transferred to the receiver address by the owner. This leads to loss of assets and balance drainage of the contract which causes protocol insolvency, in the case of the recipient address couldn't provide the assets back in the next withdrawal batch.
Impact\
The deposit fees stream together with their collection mechanism is not defined and in the case, if the owner wants to extract it, this act may lead to unintended balance extraction of the recently deposited assets and even a drastic reduction of protocol balance which may lead to insolvency.
The impacts to be simplified:
Improper tracking of deposit fees
Temporary (or maybe permanently) loss of assets
Protocol insolvency
Attack Scenario\
A possible scenario would be:
The deposit fees equal to 5e18 are accumulated in the contract Minter.
The owner decides to collect these fees by calling the withdraw().
Recently staked amounts that are not requested for a withdrawal are equal to 55e18.
The owner sends the total amount of 60e18 to the receiver.
The depositors want to withdraw their assets and submit a withdrawal request
The receiver is unable to pay back the initially received assets
Thus, the withdrawal process will not happen due to insufficient balance.
Attachments
Revised Code File (Optional)
Consider adding a collection mechanism for deposit fees as it is for withdrawal fees. This requires the deposit fees being separated from the initial deposit amount. I mean adding something like this:
Github username: @MatinR1 Twitter username: MatinRezaii1 Submission hash (on-chain): 0xd9f2d633647659b18b4f3593fb29e1ead5a69ed1b9611969de1c0ab20022c352 Severity: high
Description: Description\ There is a discrepancy in how fees are managed within the system, specifically between withdrawal and deposit fees:
Withdrawal Fees: These fees have a clearly defined path for collection and processing, ensuring that the user's assets are not adversely affected when the fees are collected. This approach effectively isolates the fee handling from the user's core assets.
Deposit Fees: In contrast, deposit fees lack a specific path for collection. As a result, there is no defined mechanism for handling these fees, potentially leading to confusion or early and unprogrammed asset extraction in the deposit process. The absence of a dedicated collection process for deposit fees can result in these fees being either overlooked or improperly managed, which could impact the user's assets and the system's overall integrity.
If we look at the
NativeMinterWithdrawal
's (the one which is inherited by thestROSEMinter
) deposit function, we can see how the asset is collected:As it is clear from above, the fee amount is subtracted from the initial deposit amount (
msg.value
for the native version), and the rest is minted for the user. The problem lies in the fee distribution mechanism. The deposit fees lack a separate collection function and recipient, which makes the fee-splitting hard. As opposed to the withdrawal process, which clearly has a distinct stream together with its collection function (with the option of choosing a recipient), the deposit fees lack such a mechanism.Also, the overrided
withdraw()
function, which is the only way of extracting deposit fees, just checks for a positive balance of the contract after subtracting the unclaimed withdrawals and transfers the ETH to the desired receiver. By doing so, the recently deposited assets, without extracting the fee stream, are transferred to the receiver address by the owner. This leads to loss of assets and balance drainage of the contract which causes protocol insolvency, in the case of the recipient address couldn't provide the assets back in the next withdrawal batch.Impact\ The deposit fees stream together with their collection mechanism is not defined and in the case, if the owner wants to extract it, this act may lead to unintended balance extraction of the recently deposited assets and even a drastic reduction of protocol balance which may lead to insolvency.
The impacts to be simplified:
Attack Scenario\ A possible scenario would be:
5e18
are accumulated in the contract Minter.withdraw()
.55e18
.60e18
to the receiver.Attachments
Consider adding a collection mechanism for deposit fees as it is for withdrawal fees. This requires the deposit fees being separated from the initial deposit amount. I mean adding something like this: