Part 2

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

Unregistered Engine Exploit in Vault Creation

Summary

The Vault.create() function allows the creation of vaults with unregistered engine addresses. This enables attackers to deploy vaults linked to malicious or untrusted engines, bypassing protocol safeguards and potentially leading to fund theft or system manipulation.


Vulnerability Details

Location

Vault.solcreate() function

Technical Analysis

  1. Root Cause:
    The create() function initializes a vault’s engine parameter directly from user input (params.engine) without validating whether the engine is registered in the protocol’s MarketMakingEngineConfiguration.

    // Vulnerable code in Vault.sol
    function create(CreateParams memory params) internal {
    Data storage self = load(params.vaultId);
    // ...
    self.engine = params.engine; // No validation of engine registration
    }
  2. Expected Behavior:
    The protocol should only allow vaults to be created with engines that have been explicitly registered via MarketMakingEngineConfiguration. This ensures all engines comply with protocol rules and security audits.

  3. Actual Behavior:
    Attackers can specify arbitrary engine addresses (including malicious ones), allowing them to bypass protocol controls.


Impact

  • Critical Severity

    • Fund Theft: Malicious engines can create fake markets, manipulate debt calculations, or siphon vault collateral.

    • System Instability: Unaudited engines may violate protocol invariants, leading to incorrect debt distributions or vault insolvency.

    • Governance Bypass: Attackers can deploy vaults that ignore fee structures, collateral rules, or other protocol-level constraints.


Proof of Concept (PoC)

Attack Scenario

  1. Deploy Malicious Engine:
    An attacker deploys a malicious engine contract that overrides critical functions (e.g., debt distribution, fee collection).

  2. Create Vault with Malicious Engine:

    Vault.CreateParams memory params = Vault.CreateParams({
    vaultId: 123,
    engine: address(maliciousEngine), // Unregistered engine
    // ... other parameters
    });
    Vault.create(params); // Executes without validation
  3. Connect to Fake Market:
    The malicious engine connects the vault to a fake market, allowing the attacker to:

    • Mint unlimited synthetic assets.

    • Drain collateral via manipulated debt settlements.

  4. Exploit Execution:
    The attacker triggers a debt settlement or withdrawal, causing the vault to transfer funds to the malicious engine’s controlled addresses.


Recommendations

Immediate Fix

Add a registration check in the create() function:

function create(CreateParams memory params) internal {
Data storage self = load(params.vaultId);
// Add engine validation
require(
MarketMakingEngineConfiguration.load().isRegisteredEngine(params.engine),
"Engine not registered"
);
// ... rest of the code
}

Additional Mitigations

  1. Registry Event Tracking:
    Emit an event when engines are registered to improve transparency:

    event EngineRegistered(address indexed engine);
Updates

Lead Judging Commences

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

Support

FAQs

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