Open hats-bug-reporter[bot] opened 10 months ago
Thank you for the submission and inclusion of the test reproducing the issue. Afer initial assessment we confirm the finding. We will follow-up with more details after the audit challange ends.
Hey @0xmahdirostami, for your information - I've just opened a PR against the main repository with your finding (split up your repro into two independent cases) and suggested fix.
Hey @0xmahdirostami, for your information - I've just opened a PR against the main repository with your finding (split up your repro into two independent cases) and suggested fix.
@deuszx, You're setting the reward rate for the token that the owner wants to withdraw and making sure that in all reward rates, there is at least one reward rate higher than 0. But there is one issue here, the owner couldn't get all the tokens from the contract. (you are limiting the owner to have at least one reward rate higher than 0).
I think it's better to stop the farm instead of returning Err
here.
if self.farm_reward_rates.iter().all(|rr| *rr == 0) {
return Err(FarmError::AllRewardRatesZero);
}
In this case, the owner can withdraw all tokens, and if he does, the farm will stop.
Besides that, I think as you are resetting the reward rate to zero, there is no need for the following check. https://github.com/hats-finance/AlephZeroAMM-0x0d88a9ece90994ecb3ba704730819d71c139f60f/blob/b097173adc9966bcbed72c6a4f1b50fcc52fe0ef/farm/contract/lib.rs#L308
Hi @0xmahdirostami , thanks for the reply. Let me answer with some context first...
The way farm's designed is that farm owner can "renew" the farm w/o the need of its farmers to do any actions. I.e. a farm owner sets it once and then, once it ends, feeds more tokens into it and starts afresh while the farmers continue earning rewards from new instances.
It is required though to create the "farm factory" first, including defining which tokens will be used for rewards - note that reward rates are not specified at that point (see Farm::new
constructor). Only in farm.start(...)
the rewards transferred and the reward rates are calculated. To avoid a situation where farmer owner creates the factory first and then tries to start it w/o any rewards, at least one reward rate has to be positive (note that this also covers the case when the reward_amount / duration == 0
).
This has the additional benefit that farm owner can plan ahead which reward tokens he will pay out, without having to do that in every farm instance. For example:
Now, to your latest comment:
The owner_withdraw_token
prohibits withdrawing all rewards so that the owner cannot "rug pull" the farm from under the farmers feet, leaving the farmers locked up in the farm for free. Current logic of owner_withdraw_token
is aligned with the Farm::owner_start_new_farm
as well.
Do you see any other vulnerabilities with the proposed approach? Or is it just an idea for alternative design?
Let me know if any of this is still unclear or I misunderstood your concerns.
Thank you for participation. After carefully reviewing the submission we've decided to accept it as VALID and the suggested severity level HIGH.
We hope to see you in the future ink! codebase audits.
Github username: @0xmahdirostami Twitter username: 0xmahdirostami Submission hash (on-chain): 0xfde1e9599918b97294459a45717d1e565040ae24f105c21ba9e8d412041f6953 Severity: high
Description: Description\
In the farm contract, the farm contract owner can unintentionally or Intentionally prevent users from claiming granted rewards. The issue arises when attempting to withdraw tokens while the farm is inactive. The current check has a flaw; the check passes if the farm is set for the future. As a result, users' unclaimed rewards update in the future, but without actual reward tokens in the contract, the
claim_rewards
function fails, preventing users from retrieving even their previous rewards.Impact\ One of the important roles in a farm contract is that the owner isn't able to steal or prevent users from claiming granted rewards. In the following Scenario, users aren't able to get their granted rewards.
Scenario\ Consider the following scenario:
Attachments
Include the following test in tests.rs:
owner_withdraw_token
instead of checking!self.is_active()
, callowner_stop_farm
.