Part 2

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

Invalid Engine Parameter Allows Arbitrary USD Token Burning Leading to Fund Loss

Summary

The fulfillSwap function accepts an engine parameter from the caller (keeper) without validating it against the vault’s stored engine. This allows malicious keepers to burn an arbitrary USD token (e.g., USDTokenB) instead of the vault’s configured token (USDTokenA), leaving user deposits unburned and enabling theft of protocol reserves.

Vulnerability Details

Looking at the fulfillSwap function:

function fulfillSwap(
address user,
uint128 requestId,
bytes calldata priceData,
address engine // Unvalidated parameter
) external onlyRegisteredSystemKeepers {
// ...
ctx.usdToken = UsdToken(marketMakingEngineConfiguration.usdTokenOfEngine[engine]); // Uses attacker-provided `engine`
ctx.usdToken.burn(ctx.amountIn); // Burns the wrong token
}

The engine parameter is provided by the caller (keeper) and directly used to fetch the USD token address from marketMakingEngineConfiguration.usdTokenOfEngine[engine]. The vault’s actual engine (stored in vault.engine) is never compared to the caller-provided engine. Therefore lets say a malicious keeper can pass an engine address unrelated to the vault, causing the contract to burn an incorrect USD token.

Impact

Attackers can drain reserves of any USD token held by the contract and also burning incorrect tokens disrupts the system’s financial integrity.

Tools Used

  • Manual code review.

Recommendations

Remove the engine parameter and derive it directly from the vault:

function fulfillSwap(
address user,
uint128 requestId,
bytes calldata priceData // Remove `engine` parameter
) external onlyRegisteredSystemKeepers {
// ...
Vault.Data storage vault = Vault.loadLive(ctx.vaultId);
address engine = vault.engine; // Derive from the vault
ctx.usdToken = UsdToken(marketMakingEngineConfiguration.usdTokenOfEngine[engine]);
// ...
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
7 months ago
inallhonesty Lead Judge 6 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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