Dria

Swan
NFTHardhat
21,000 USDC
View results
Submission Details
Severity: high
Invalid

Reentrancy in purchase Function Leading to Unauthorized Repeated Purchases and Potential Fund Drain

Summary

https://github.com/Cyfrin/2024-10-swan-dria/blob/main/contracts/swan/BuyerAgent.sol

The purchase function in the Swan contract is vulnerable to a reentrancy attack, as it lacks protection against reentrant calls. The function is responsible for transferring both the asset and payment during a purchase transaction. Without adequate reentrancy protection, an attacker could exploit this function to perform multiple unauthorized transactions, potentially resulting in multiple asset transfers or fund drains before the function completes its execution.

Vulnerability Details

function purchase(address _asset) external {
AssetListing storage listing = listings[_asset];
if (listing.status != AssetStatus.Listed) {
revert InvalidStatus(listing.status, AssetStatus.Listed);
}
if (listing.buyer != msg.sender) {
revert Unauthorized(msg.sender);
}
listing.status = AssetStatus.Sold;
SwanAsset(_asset).transferFrom(listing.seller, address(this), 1);
SwanAsset(_asset).transferFrom(address(this), listing.buyer, 1);
token.transferFrom(listing.buyer, address(this), listing.price);
token.transfer(listing.seller, listing.price);
emit AssetSold(listing.seller, msg.sender, _asset, listing.price);
}

Impact

The lack of reentrancy protection in the purchase function allows an attacker to:

  1. Repeat the purchase operation multiple times before the listing.status is updated to Sold, resulting in multiple unauthorized asset and fund transfers.

  2. Drain funds from the buyer’s account by repeatedly triggering the function, which repeatedly transfers tokens, potentially depleting the buyer’s balance.

  3. Double-Spend Attack: Since the function can be called multiple times within a single transaction, the attacker could “double spend” by purchasing the same asset multiple times while only meeting the transfer conditions once.

Exploit Scenario
  1. The attacker lists an asset and sets themselves as the buyer.

  2. The attacker calls the purchase function but, before it finishes, they call it again, exploiting the absence of reentrancy protection.

  3. This allows the attacker to execute the transferFrom and transfer operations repeatedly without updating the listing.status, potentially transferring multiple assets or tokens.

  4. It can lead to exceeding maxassetlis

Tools Used

Manual Review

Recommendations

To mitigate this vulnerability, apply the nonReentrant modifier to the purchase function. This will prevent the function from being called multiple times before its first execution completes.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Lack of quality

Support

FAQs

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