DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: low
Invalid

`Listing._fillListing()` can leave unfillable listing after execution

Summary

Struct Podlisting contains field minFillAmount which indicates minimum amount to fulfill in listing. On partial fulfillments it deletes previous listing and instead creatse new listing with the same parameters and remaining amount.

However during fulfillment it only checks that fulfilled amount is greater than minFillAmount. It allows to leave dust amount in listing which will be newly created after partial fulfillment.

Vulnerability Details

Here you can see that it can create listing with dust amount after partial fulfillment:
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/beanstalk/market/MarketplaceFacet/Listing.sol#L125-L147

function _fillListing(
PodListing calldata podListing,
address filler,
uint256 beanPayAmount
) internal {
...
require(
@> podReceiveAmount >= podListing.minFillAmount,
"Marketplace: Fill must be >= minimum amount."
);
// Remove old listing and create new listing if necessary.
delete s.sys.podListings[podListing.fieldId][podListing.index];
if (podReceiveAmount < podListing.podAmount) {
uint256 newIndex = podListing.index + podReceiveAmount + podListing.start;
@> s.sys.podListings[podListing.fieldId][newIndex] = _hashListing(
PodListing(
podListing.lister,
podListing.fieldId,
newIndex,
0,
podListing.podAmount - podReceiveAmount,
podListing.pricePerPod,
podListing.maxHarvestableIndex,
podListing.minFillAmount,
podListing.mode
)
);
}
...
}

Impact

During listing creation user specifies minFillAmount. After partial fulfillment it always creates listing with remaining amount despite the fact it can be less than minFillAmount. In other words it has 2 impacts:

  1. Unfillable listing is created

  2. Lister's Plot can have dust amount left which is contrary to purpose of minFillAmount

Tools Used

Manual Review

Recommendations

Require to left more than minFillAmount in case it is partial filling:

function _fillListing(
PodListing calldata podListing,
address filler,
uint256 beanPayAmount
) internal {
...
require(
- podReceiveAmount >= podListing.minFillAmount,
+ podReceiveAmount >= podListing.minFillAmount &&
+ (podReceiveAmount == podListing.podAmount || podListing.podAmount - podReceiveAmount > podListing.minFillAmount)
"Marketplace: Fill must be >= minimum amount."
);
...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Lack of Validation for minFillAmount Less Than or Equal to podAmount in pod listing

Appeal created

inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Lack of Validation for minFillAmount Less Than or Equal to podAmount in pod listing

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.