Perfect Currant Cow
High
As said here in Readme
DISTRIBUTION_OPERATOR_ROLE is required to call the distributeUsualToBuckets every 24 hours to calculate the new emissions and distribute them to the on-chain buckets and increase the off-chain buckets mint cap that can be claimed after successful approval of the off-chain distribution that is unchallenged and in the queue for more than USUAL_DISTRIBUTION_CHALLENGE_PERIOD.
The likelihood of a user being eligible for multiple distributions is high, given that distributions occur at 24-hour intervals. If this happens, a malicious user could potentially drain all funds allocated to the offchain distribution.
In DistributionModule.sol#L386, when user claims offchain distribution, its updates the claimedByOffChainClaimer[user]
to track internally claimed amount. Each time user claims, the claimedByOffChainClaimer[user]
is deducted from the claim amount, to avoid double claims.
There is a high likelihood that the user could be eligible for multiple distributions, where each distribution with different merkleRoot has different claimable amount for the user. The attack goes like;
- Operator calls distributeUsualToBuckets() at t=0, then queues it until the challenge period(i.e. 7 days) ends. Distribution goes unchallenged, and approved on day 7th.
- Bob as claimant claims 50 unit of usual tokens via
claimOffChainDistribution()
, andclaimedByOffChainClaimer[bob]
changes to 50 - Operator launch another distribution, which get approved also. And this time, the bob eligible for higher amount, say 150
- Bobs claims 150 unit, but got
150 - claimedByOffChainClaimer[bob]
(i.e. 100 unit) in his account andclaimedByOffchainClaimer[bob]
is set back 100. Note that the 2nd distribution still allow Bob to go for another 50 unit claim since proof was generated for 150 unit tokens amount. - On 3rd claim, the
claimedByOffChainClaimer[bob]
is set back to 50, instead of 150, causingclaimedByOffChainClaimer[bob]
to be transitioning b/w 50 and 100 always, alternatively, allowing bob to claim either 100 unit or 50 unit every single time. This will drained the DistributionModule funds allocated to offchain distribution.
- Its required claimers to be eligible in more than one distribution with different claimable amount.
See RC.
Infinite minting of usual tokens upto offChainDistributionMintCap
Modify to below,
function claimOffChainDistribution(address account, uint256 amount, bytes32[] calldata proof)
external
whenNotPaused
nonReentrant
{
...snip...
- $.claimedByOffChainClaimer[account] = amount;
+ $.claimedByOffChainClaimer[account] += amount;
emit OffChainDistributionClaimed(account, amountToSend);
$.usual.mint(account, amountToSend);
}