Part 2

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

Unauthorized engine execution bypass in `EngineAccessControl.sol` `onlyRegisteredEngine` modifier allows a previously registered engine to continue executing functions even after deregistration

Summary

The onlyRegisteredEngine modifier allows a previously registered engine to continue executing functions even after deregistration, leading to unauthorized access.

Vulnerability Details

modifier onlyRegisteredEngine(uint128 marketId) {
// load market making engine configuration
MarketMakingEngineConfiguration.Data storage marketMakingEngineConfiguration =
MarketMakingEngineConfiguration.load();
// if `msg.sender` is not a registered engine, revert
if (!marketMakingEngineConfiguration.isRegisteredEngine[msg.sender]) {
revert Errors.Unauthorized(msg.sender);
}
// load market
Market.Data storage market = Market.load(marketId);
// if `msg.sender` is not the market's registered engine, revert
if (market.engine != msg.sender) {
revert Errors.Unauthorized(msg.sender);
}
// continue execution
_;
}

Assume an engine 0xABC is initially registered but later deregistered:

  1. market.engine = 0xABC (engine 0xABC owns a market).

  2. isRegisteredEngine[0xABC] = false (engine is deregistered).

  3. 0xABC can still call onlyRegisteredEngine protected functions because market.engine == 0xABC.

PoC

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
import "forge-std/Test.sol";
import "../src/EngineAccessControl.sol";
import "../src/MarketMakingEngineConfiguration.sol";
contract UnauthorizedEngineExecutionBypassTest is Test {
EngineAccessControl engineAccessControl;
MarketMakingEngineConfiguration marketMakingEngineConfiguration;
address unauthorizedEngine = address(0xABC);
uint128 marketId = 1;
function setUp() public {
engineAccessControl = new EngineAccessControl();
marketMakingEngineConfiguration = MarketMakingEngineConfiguration(engineAccessControl);
// Register and assign engine
marketMakingEngineConfiguration.isRegisteredEngine[unauthorizedEngine] = true;
Market.Data storage market = Market.load(marketId);
market.engine = unauthorizedEngine;
}
function testUnauthorizedEngineExecution() public {
// Deregister engine
marketMakingEngineConfiguration.isRegisteredEngine[unauthorizedEngine] = false;
vm.prank(unauthorizedEngine);
vm.expectRevert(Errors.Unauthorized.selector);
engineAccessControl.someProtectedFunction(marketId);
}
}

Impact

A deregistered engine can continue executing privileged functions, potentially manipulating markets.

Tools Used

Manual review.

Recommendations

Add an explicit check for active registration:

if (!marketMakingEngineConfiguration.isRegisteredEngine[market.engine]) {
revert Errors.Unauthorized(market.engine);
}
Updates

Lead Judging Commences

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

Support

FAQs

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