DeFiFoundry
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Insecure ParaSwap Integration

Summary

The ParaSwap integration in the ParaSwapUtils library hardcodes the expected ParaSwap contract address (0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57). If ParaSwap upgrades their contract or if the hardcoded address is ever compromised, this validation check becomes outdated, potentially allowing integration with an unintended (and possibly malicious) contract.

Vulnerability Details

  • Issue:
    The library’s _validateCallData function enforces that the target address to must exactly equal the hardcoded ParaSwap address.

require(to == address(0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57), "invalid paraswap callee");
  • Context:
    Relying on a hardcoded address prevents dynamic upgrades or migration if ParaSwap releases a new version. This reduces flexibility and could lead to integration issues or security risks if the external service is compromised.

  • Inter‑Contract Considerations:
    No other part of the system mitigates this risk. A configurable or registry-based approach is absent from this library.

Impact

  • Integration Failure:
    An upgraded or replaced ParaSwap contract will not pass the validation, causing legitimate swaps to fail.

  • Security Risk:
    If the hardcoded ParaSwap address is compromised, attackers could exploit this fixed check to redirect swaps to a malicious contract.

  • Reduced Flexibility:
    The system cannot adapt to changes in the external protocol without redeploying updated contracts.

Proof of Concept for Insecure ParaSwap Integration

Overview

This PoC demonstrates that the hardcoded check in _validateCallData forces the integration to use a fixed address. Changing the expected ParaSwap address in the call data (simulating an upgrade or compromise) will cause the swap function to revert.

Actors

  • Attacker: Not applicable directly this PoC demonstrates a misconfiguration scenario.

  • Legitimate User: Attempts to perform a swap.

  • Protocol: ParaSwapUtils library enforcing the hardcoded check.

Working Test Case

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
// Import the library
import "./ParaSwapUtils.sol";
contract TestParaSwapIntegration {
// Hardcoded address from the library for demonstration.
address constant VALID_PARASWAP = 0xDEF171Fe48CF0115B1d80b88dc8eAB59176FEe57;
// A dummy malicious address (simulating an upgraded or compromised ParaSwap contract)
address constant MALICIOUS_PARASWAP = 0x000000000000000000000000000000000000dEaD;
// Example callData that passes the internal validation:
// For simplicity, we assume callData is structured so that:
// - Bytes 0-67: arbitrary header data.
// - Bytes 68-99: fromToken (address).
// - Bytes 100-131: fromAmount (uint256).
// - Bytes 196-227: receiver address.
bytes public validCallData;
bytes public invalidCallData;
constructor() {
// Prepare valid callData:
// Line 1: Create a byte array with enough length.
validCallData = new bytes(228);
// Line 2: Set a dummy fromToken address at offset 68.
assembly {
mstore(add(validCallData, 68), 0x1111111111111111111111111111111111111111)
}
// Line 3: Set a dummy fromAmount (e.g., 1000 tokens) at offset 100.
assembly {
mstore(add(validCallData, 100), 1000)
}
// Line 4: Set receiver to this contract at offset 196.
assembly {
mstore(add(validCallData, 196), address())
}
// Prepare invalid callData by copying validCallData and simulating a call from MALICIOUS_PARASWAP.
invalidCallData = validCallData;
}
// Test function to demonstrate successful swap with valid ParaSwap address.
function testValidSwap() external returns (string memory) {
// Call the library function 'swap' with the valid ParaSwap address.
// Expect the _validateCallData check to pass.
ParaSwapUtils.swap(VALID_PARASWAP, validCallData);
return "Valid swap executed";
}
// Test function to demonstrate failure when using an invalid (malicious) ParaSwap address.
function testInvalidSwap() external returns (string memory) {
// Expect the _validateCallData check to fail and revert.
// The call below should revert with "invalid paraswap callee".
ParaSwapUtils.swap(MALICIOUS_PARASWAP, invalidCallData);
return "This should never be reached";
}
}

Exploit Scenario Explanation

  • Legitimate Scenario:
    When testValidSwap() is called, the swap function receives the correct hardcoded address, passes the validation, and executes normally.

  • Failure Scenario:
    When testInvalidSwap() is called, the swap function receives a different address (simulating an upgrade or compromise), triggering the require statement and reverting the transaction.

Tools Used

Manual Code Review

Recommendations

  • Configurable Address:
    Replace the hardcoded ParaSwap address with a state variable that can be updated via governance or owner control.

  • Registry-Based Lookup:
    Integrate a registry mechanism where the valid ParaSwap address can be managed and updated dynamically.

  • Defensive Checks:
    Ensure that any update mechanism for the ParaSwap address is secure and audited.

Updates

Lead Judging Commences

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Admin is trusted / Malicious keepers

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point. Keepers are added by the admin, there is no "malicious keeper" and if there is a problem in those keepers, that's out of scope. ReadMe and known issues states: " * System relies heavily on keeper for executing trades * Single keeper point of failure if not properly distributed * Malicious keeper could potentially front-run or delay transactions * Assume that Keeper will always have enough gas to execute transactions. There is a pay execution fee function, but the assumption should be that there's more than enough gas to cover transaction failures, retries, etc * There are two spot swap functionalies: (1) using GMX swap and (2) using Paraswap. We can assume that any swap failure will be retried until success. " " * Heavy dependency on GMX protocol functioning correctly * Owner can update GMX-related addresses * Changes in GMX protocol could impact system operations * We can assume that the GMX keeper won't misbehave, delay, or go offline. " "Issues related to GMX Keepers being DOS'd or losing functionality would be considered invalid."

n0kto Lead Judge 5 months ago
Submission Judgement Published
Invalidated
Reason: Design choice
Assigned finding tags:

Informational or Gas

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point.

Admin is trusted / Malicious keepers

Please read the CodeHawks documentation to know which submissions are valid. If you disagree, provide a coded PoC and explain the real likelihood and the detailed impact on the mainnet without any supposition (if, it could, etc) to prove your point. Keepers are added by the admin, there is no "malicious keeper" and if there is a problem in those keepers, that's out of scope. ReadMe and known issues states: " * System relies heavily on keeper for executing trades * Single keeper point of failure if not properly distributed * Malicious keeper could potentially front-run or delay transactions * Assume that Keeper will always have enough gas to execute transactions. There is a pay execution fee function, but the assumption should be that there's more than enough gas to cover transaction failures, retries, etc * There are two spot swap functionalies: (1) using GMX swap and (2) using Paraswap. We can assume that any swap failure will be retried until success. " " * Heavy dependency on GMX protocol functioning correctly * Owner can update GMX-related addresses * Changes in GMX protocol could impact system operations * We can assume that the GMX keeper won't misbehave, delay, or go offline. " "Issues related to GMX Keepers being DOS'd or losing functionality would be considered invalid."

Support

FAQs

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