function withdrawBounty(uint256[] memory bountyIds) internal {
// withdraw bounties
for (uint256 i = 0; i < bountyIds.length; i++) {
Bounty memory bounty = _bounties[bountyIds[i]];
require(bounty.active);
IERC20(bounty.token).transfer(msg.sender, bounty.amount);
bounty.active = false;
emit BountyClaimed(msg.sender, bounty.token, bounty.amount, bountyIds[i]);
}
}
In the withdrawBounty function, bounty.active should be set to false when the bounty is claimed.
However, since bounty is stored in memory, the state update will not succeed.
Impact
An auction successfully bonded by a regular user won't be able to be settled if they passed seemly active bountyIds, and the bonder will lose the bond.
Proof of Concept
Create an auction;
Add a bounty;
Auction settled with bounty claimed;
Create a new auction;
Add a new bounty;
Calling settleAuction() with the bountyIds of the 2 seemly active bounties always reverts.
Handle
WatchPug
Vulnerability details
https://github.com/code-423n4/2021-09-defiProtocol/blob/main/contracts/contracts/Auction.sol#L143
In the
withdrawBounty
function,bounty.active
should be set tofalse
when the bounty is claimed.However, since
bounty
is stored in memory, the state update will not succeed.Impact
An auction successfully bonded by a regular user won't be able to be settled if they passed seemly active bountyIds, and the bonder will lose the bond.
Proof of Concept
settleAuction()
with the bountyIds of the 2 seemly active bounties always reverts.Recommended Mitigation Steps
Change to: