Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: medium
Invalid

Lack of input validation in AssetSwapPath.configure()

Summary

The AssetSwapPath.configure() function lacks proper input validation for the assets and dexSwapStrategyIds arrays. If these arrays are mismatched in length or contain invalid values (e.g., zero addresses or unsupported swap strategy IDs), it could lead to runtime errors, undefined behavior, or incorrect configurations. This vulnerability poses a medium-severity risk as it can disrupt the system's functionality and lead to incorrect asset swap paths.


Vulnerability Details

Code Analysis

The configure() function is defined as follows:

function configure(
Data storage self,
bool enabled,
address[] memory assets,
uint128[] memory dexSwapStrategyIds
)
internal
{
self.enabled = enabled;
self.assets = assets;
self.dexSwapStrategyIds = dexSwapStrategyIds;
}

Key Observations:

  1. No Length Validation : The function does not validate that the lengths of assets and dexSwapStrategyIds match. For example:

    • If assets.length == 3 and dexSwapStrategyIds.length == 2, the configuration will be inconsistent.

    • This mismatch could lead to incorrect swap paths or runtime errors when processing the data.

  2. No Zero Address Check : The function does not verify that all elements in the assets array are non-zero addresses. A zero address could cause issues when interacting with external contracts or performing swaps.

  3. No Swap Strategy ID Validation : The function does not validate that the dexSwapStrategyIds correspond to valid swap strategies. Unsupported or invalid IDs could lead to incorrect behavior during swaps.

Attack Scenario

  1. An attacker or malicious user calls the configure() function with mismatched arrays:

    assets = [address(0x1), address(0x2)];
    dexSwapStrategyIds = [3];

    Here, assets.length == 2 but dexSwapStrategyIds.length == 1.

  2. The function executes without error, storing the mismatched configuration:

    • self.assets = [address(0x1), address(0x2)]

    • self.dexSwapStrategyIds = [3]

  3. When the system attempts to use this configuration for a swap, it encounters an inconsistency:

    • The second asset (address(0x2)) has no corresponding swap strategy ID.

    • This could result in a revert or incorrect swap execution.

  4. Alternatively, an attacker could include a zero address in the assets array:

    assets = [address(0)];
    dexSwapStrategyIds = [1];

    This could cause issues when interacting with external contracts or performing swaps.


Impact

  • Runtime Errors : Mismatched arrays or invalid inputs could cause reverts during swap execution.

  • Incorrect Configurations : Invalid configurations could lead to incorrect asset swap paths, resulting in financial losses or failed trades.

  • System Disruption : If critical swap paths are misconfigured, it could disrupt the system's ability to execute trades.


Tools Used

  1. Manual Code Review : Analyzed the configure() function to identify missing input validation.

  2. Slither : Static analysis tool used to detect potential vulnerabilities related to array handling and input validation.

  3. MythX : Security analysis platform used to verify vulnerabilities in the smart contract.


Recommendations

Short-Term Fix

Add input validation to the configure() function to ensure consistency and correctness of the inputs:

function configure(
Data storage self,
bool enabled,
address[] memory assets,
uint128[] memory dexSwapStrategyIds
)
internal
{
// Validate that the lengths of assets and dexSwapStrategyIds match
require(assets.length == dexSwapStrategyIds.length, "Mismatched array lengths");
// Validate that all assets are non-zero addresses
for (uint256 i = 0; i < assets.length; i++) {
require(assets[i] != address(0), "Zero address not allowed");
}
// Validate that all dexSwapStrategyIds are supported (example: IDs must be > 0)
for (uint256 i = 0; i < dexSwapStrategyIds.length; i++) {
require(dexSwapStrategyIds[i] > 0, "Invalid swap strategy ID");
}
// Update the configuration
self.enabled = enabled;
self.assets = assets;
self.dexSwapStrategyIds = dexSwapStrategyIds;
}

Long-Term Fix

  1. Centralized Validation Logic : Create a helper function to encapsulate input validation logic, making it reusable across similar functions.

  2. Event Logging : Emit events whenever the configure() function is called to provide transparency and enable monitoring:

    event AssetSwapPathConfigured(address[] assets, uint128[] dexSwapStrategyIds);
    function configure(
    Data storage self,
    bool enabled,
    address[] memory assets,
    uint128[] memory dexSwapStrategyIds
    )
    internal
    {
    // Perform input validation (as shown above)
    // Update the configuration
    self.enabled = enabled;
    self.assets = assets;
    self.dexSwapStrategyIds = dexSwapStrategyIds;
    // Emit an event
    emit AssetSwapPathConfigured(assets, dexSwapStrategyIds);
    }
  3. Unit Tests : Write comprehensive unit tests to cover edge cases, such as mismatched arrays, zero addresses, and invalid swap strategy IDs.

Updates

Lead Judging Commences

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

Support

FAQs

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

Give us feedback!