You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on May 26, 2023. It is now read-only.
github-actionsbot opened this issue
Feb 21, 2023
· 0 comments
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
Malicious funders can call refundDeposit() after a bounty is closed to make bounty doesn't have enough fund to pay for the winners.
Summary
Since there is no requirement about when the funder can call refund, they can call it right after the bounty close to make it not enough tokens to pay the competitor.
Vulnerability Detail
Function DepositManagerV1.fundBountyToken() just can be called when the bounty is open, so when a bounty is closed there won't be any deposit be accepted.
function fundBountyToken(
address _bountyAddress,
address _tokenAddress,
uint256 _volume,
uint256 _expiration,
string memory funderUuid
) external payable onlyProxy {
/// ...
/// [#explain] check if a bounty is open or not ?
require(bountyIsOpen(_bountyAddress), Errors.CONTRACT_ALREADY_CLOSED);
/// [#explain] process the deposit
(bytes32 depositId, uint256 volumeReceived) = bounty.receiveFunds{
value: msg.value
}(msg.sender, _tokenAddress, _volume, _expiration);
/// ...
}
Different from the function above, DepositManagerV1.refundDeposit() can be called anytime as long as the deposit is expired. This will create a flaw for malicious funders to trick the bounty to ruin the organization's reputation.
We will consider a scenario with a TieredPercentageBounty.
A bounty need 1000 USDC to distribute rewards for competitors. First winner get 30% pool, second one get 70%.
Alice deposits 300 USDC into the bounty
A Malicious funder deposits 700 USDC into bounty with expiration = 1.
After at least 1 second, bounty's issuer see that there are enough fund to distribute the rewards to the winners, he calls claim reward for first winner with prize = 300 USDC
Before the time the issuer call claim reward for the second winner, Malicious user (can front-run) called DepositManagerV1.refundDeposit() to claim his deposit back.
Now when the issuer tries to call claim reward for the second winner, the tx will fail since there isn't enough fund to execute the claim (The balance of USDC in the contract now is 0 USDC < 1000 * 70% = 70 USDC)
Note that this issue doesn't happen just with TieredPercentageBounty, it also applies for the Atomic and FixedTierBounty by front-running the tx call ClaimManagerV1.claimBounty() to withdraw their deposit to reduce the rewards pool of the bounty.
There is a mitigation for this issue is the issuer can send directly the amount of rewards missing to the bounty (don't need to use DepositManagerV1.fundBountyToken()), but in-case the reward is ETH (native token), it can't be success since the contract implements a auto revert fallback function. So the problem is still remained.
Impact
Bounty won't have enough fund to pay for the competitor.
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
DuplicateA valid issue that is a duplicate of an issue with `Has Duplicates` labelHighA valid High severity issueRewardA payout will be made for this issue
TrungOre
high
Malicious funders can call
refundDeposit()
after a bounty is closed to make bounty doesn't have enough fund to pay for the winners.Summary
Since there is no requirement about when the funder can call refund, they can call it right after the bounty close to make it not enough tokens to pay the competitor.
Vulnerability Detail
Function
DepositManagerV1.fundBountyToken()
just can be called when the bounty is open, so when a bounty is closed there won't be any deposit be accepted.Different from the function above,
DepositManagerV1.refundDeposit()
can be called anytime as long as the deposit is expired. This will create a flaw for malicious funders to trick the bounty to ruin the organization's reputation.We will consider a scenario with a
TieredPercentageBounty
.expiration = 1
.DepositManagerV1.refundDeposit()
to claim his deposit back.Note that this issue doesn't happen just with
TieredPercentageBounty
, it also applies for theAtomic
andFixedTierBounty
by front-running the tx callClaimManagerV1.claimBounty()
to withdraw their deposit to reduce the rewards pool of the bounty.There is a mitigation for this issue is the issuer can send directly the amount of rewards missing to the bounty (don't need to use
DepositManagerV1.fundBountyToken()
), but in-case the reward is ETH (native token), it can't be success since the contract implements a auto revert fallback function. So the problem is still remained.Impact
Bounty won't have enough fund to pay for the competitor.
Code Snippet
https://github.com/sherlock-audit/2023-02-openq/blob/main/contracts/DepositManager/Implementations/DepositManagerV1.sol#L152
Tool used
Manual review
Recommendation
Consider to divide each bounty into 3 periods:
Duplicate of #266
The text was updated successfully, but these errors were encountered: