Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: medium
Valid

A single seller can prevent buyer from making any puchases in a round

Summary

A seller can make the purchase call to revert by not approving Swan to transfer the asset, or by simply sending the asset to another address.
The result is that the BuyerAgent won't be able to purchase any other asset of other sellers for that round, and the royalty fee paid by those sellers will go to waste

Vulnerability Details

Here is the BuyerAgent#purchase function:

function purchase() external onlyAuthorized {
...
for (uint256 i = 0; i < assets.length; i++) {
address asset = assets[i];
// must not exceed the roundly buy-limit
uint256 price = swan.getListingPrice(asset);
spendings[round] += price;
if (spendings[round] > amountPerRound) {
revert BuyLimitExceeded(spendings[round], amountPerRound);
}
// add to inventory
inventory[round].push(asset);
// make the actual purchase
swan.purchase(asset);
}
...
}

The function loops through assets submitted by oracle and attempts to purchase them via swan.purchase().
Here is Swan#purchase function:

function purchase(address _asset) external {
...
SwanAsset(_asset).transferFrom(listing.seller, address(this), 1);
SwanAsset(_asset).transferFrom(address(this), listing.buyer, 1);
...
}

The function attempts to transfer the asset nft from seller to the Swan contract.
Seller can easily make that to revert by not approving Swan contract to transfer the token, or by simply sending the asset nft to another address.

Now, the buyer will be unable to purchase other assets listed by other sellers for that round.

Attacker can do this repeatedly, with 0 priced asset, leading to loss of funds(in form of royalties) of the other sellers that listed under that buyer

Impact

A malicious seller can list 0 priced asset, and trigger a revert when Swan wants to transfer the asset during purchase.
The result is that the whole purchase call in the BuyerAgent will revert. Other Sellers that listed under the BuyerAgent for that round will not have their assets purchased, leading to loss of the royalty they paid

Tools Used

Manual Review

Recommendations

Include each purchase within the for loop in a try catch block.
Failure to purchase an asset should not stop BuyerAgent from making other purchases

Updates

Lead Judging Commences

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

DoS in BuyerAgent::purchase

Support

FAQs

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