Open code423n4 opened 1 year ago
kirk-baird marked the issue as duplicate of #22
kirk-baird changed the severity to 2 (Med Risk)
kirk-baird marked the issue as satisfactory
kirk-baird marked the issue as selected for report
waynehoover marked the issue as disagree with severity
This is only an issue if the owner withdraws the remaining tokens before everyone has withdrawn their tokens. The owner will not do this.
I agree that the owner should not do this.
However, determining if everyone has minted their tokens yet or not straight forward as user's may not want to pay gas fees or mint / claim receipts immediately. I believe medium severity is a fair rating as there is the potential to accidentally locks funds in the contract.
Lines of code
https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/QuestFactory.sol#L219-L229 https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/Erc20Quest.sol#L81-L87
Vulnerability details
After completing a task in the context of a quest, a user receives a signed hash that needs to be redeemed on-chain for a receipt that can later be claimed for a reward.
The receipt is minted in the
mintReceipt
function present in theQuestFactory
contract:https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/QuestFactory.sol#L219-L229
This function doesn't check if the quest has ended, and the hash doesn't contain any kind of deadline. A user may receive a signed hash and mint the receipt at any point in time.
The quest owner can withdraw remaining tokens after the quest end time using the
withdrawRemainingTokens
present in the quests contracts. This is the implementation forErc20Quest
:https://github.com/rabbitholegg/quest-protocol/blob/8c4c1f71221570b14a0479c216583342bd652d8d/contracts/Erc20Quest.sol#L81-L87
The function calculates how many receipts have been minted but are pending to be claimed, in order to leave the funds in the contract so the user can still claim those. However, this won't take into account receipts that are still pending to be minted.
Impact
A user can mint the receipt for completing the task after the quest has ended, and in particular, if this is done after the owner of the quest has called
withdrawRemainingTokens
, then the user won't be able to claim the reward associated with that receipt.This occurs because the user can mint the receipt after the quest end time, while the owner may have already withdrawn the remaining tokens, which only accounts for previously minted receipts.
Given this scenario, the user won't be able to claim the rewards, the contract won't have the required funds.
PoC
In the following test, Alice mints her receipt after the quest owner has called
withdrawRemainingTokens
. Her call toquest.claim()
will be reverted due to insufficient funds in the contract.Recommendation
Since tasks are verified off-chain by the indexer, given the current architecture it is not possible to determine on-chain how many tasks have been completed. In this case the recommendation is to prevent the minting of the receipt after the quest end time. This can be done in the
mintReceipt
by checking theendTime
property which would need to be added to theQuest
struct or by including it as a deadline in the signed hash.