Dria

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

Denial-of-Service (D oS) Vulnerability : The BuyerAgent.purchase function in the BuyerAgent contract has an external call to swan.getListingPrice(asset) inside a loop, potentially cause the contract to become unavailable due to repeated failure.

Summary : The BuyerAgent.purchase function in the BuyerAgent contract has a low-severity vulnerability due to the presence of external calls inside a loop. Specifically, the swan.getListingPrice(asset) function is called within a loop that iterates over an array of assets.

// we purchase each asset returned
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);
}

Vulnerability Details How can an attacker exploit this vulnerability?:

An attacker can exploit this vulnerability by manipulating the assets array to include assets that have a high likelihood of causing the swan.getListingPrice(asset) function to fail or revert. This could lead to a denial-of-service (DoS) attack, where the BuyerAgent contract is unable to complete its intended function.

Impact : Example Attack Scenario:

  1. An attacker manipulates the assets array to include assets that have a high likelihood of causing the swan.getListingPrice(asset) function to fail or revert.

  2. The BuyerAgent contract attempts to execute the loop, but the swan.getListingPrice(asset) function fails or reverts, causing the loop to fail.

  3. The attacker repeats the attack, causing the BuyerAgent contract to become unavailable due to repeated failures.

Proof of Concept Code : Here is a proof of concept code that demonstrates the vulnerability:

pragma solidity ^0.8.0;
contract Swan {
mapping (address => uint256) public listingPrices;
function getListingPrice(address _asset) public view returns (uint256) {
return listingPrices[_asset];
}
}
contract BuyerAgent {
Swan public swan;
function purchase(address[] memory _assets) public {
for (uint256 i = 0; i < _assets.length; i++) {
address asset = _assets[i];
// external call to swan.getListingPrice(asset)
uint256 price = swan.getListingPrice(asset);
// ...
}
}
}
contract Attacker {
BuyerAgent public buyerAgent;
Swan public swan;
function attack() public {
// manipulate the assets array to include assets that have a high likelihood of causing the swan.getListingPrice(asset) function to fail or revert
address[] memory assets = new address[]();
for (uint256 i = 0; i < 10; i++) {
assets[i] = address(this);
}
// call the buyerAgent.purchase function with the manipulated assets array
buyerAgent.purchase(assets);
}
}

In this example, the Attacker contract manipulates the assets array to include assets that have a high likelihood of causing the swan.getListingPrice(asset) function to fail or revert. The Attacker contract then calls the buyerAgent.purchase function with the manipulated assets array, which causes the swan.getListingPrice(asset) function to fail or revert, leading to a denial-of-service (DoS) attack.

This proof of concept code demonstrates the vulnerability and shows how an attacker can exploit it to cause the BuyerAgent contract to become unavailable.

Affected Code :

BuyerAgent.sol: purchase function (lines 222-256)

Swan.sol: getListingPrice function (lines 258-272)

Tools Used : Slither

Recommendations : To prevent this type of attack, it is essential to:

  1. Use try-catch blocks: Use try-catch blocks to handle external calls within loops, in order to ensure the robustness and reliability of the contract.

  2. Implement input validation: Implement input validation to ensure that the assets array is valid and not under the control of an attacker.

  3. Implement access control: Implement access control to ensure that only authorized addresses can call the BuyerAgent contract.

By taking these precautions, you can prevent an attacker from exploiting this vulnerability and ensure the reliability and robustness of the BuyerAgent contract.

Code Fix:

for (uint256 i = 0; i < assets.length; i++)
{ address asset = assets[i];
try { uint256 price = swan.getListingPrice(asset); // ... }
catch { // handle exception }
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 9 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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