Exploit for the Beanstalk vulnerability to cancel all orders in the marketplace (fixed by Beanstalk)
Reported to Beanstalk via Immunefi on October 23, 2022
Fixed by Beanstalk October 25, 2022: https://etherscan.io/tx/0xcdefd8f7b9a16595c6d56922286c92c89869101230f5d48ceeb47f92a469c516
The Marketplace UI leverages the farm(bytes[]) to help facilitate fulfillment of listings. This process includes invocations to WrapEth -> Wrap which will fail if the currency being supplied is 0. However, one can just call fillPodListing() directly without any allowance for bean tokens and setting the beanAmount parameter to zero(0). In this case, the:
amount = receiveToken(token, amount, msg.sender, fromMode);
value of amount will be zero(0).
Then in function __fillListing():
if (l.amount > amount)
s.podListings[l.index.add(amount).add(l.start)] = hashListing(
0,
l.amount.sub(amount),
l.pricePerPod,
l.maxHarvestableIndex,
l.mode
);
emit PodListingFilled(l.account, to, l.index, l.start, amount);
delete s.podListings[l.index];
- In the case where start =0 (and amount is 0), it will create
s.podListings[l.index.add(0).add(0)]
which is basically the original listing s.podListings[l.index].
and then it deletes the listing after the emit.
So the user's listing is cancelled and the attacker (who invoked PodListingFilled) didn't have to pay any beans (just gas).
- In the case where start!=0 (and amount is 0):
s.podListings[l.index.add(0).add(l.start)]
will be created, and the value of start will be set to 0. In this case the attacker will have to call fillPodListing() on this new order once more so that is is fully cancelled (per the logic in step 1 above). In this manner, an attacker can go through all the active marketplace pod listings and cancel them repeatedly until the smart contract logic is corrected.