Stratax Contracts

First Flight #57
Beginner FriendlyDeFi
100 EXP
Submission Details
Impact: low
Likelihood: low

No Pause Mechanism — Protocol Cannot Be Halted During Emergency

Author Revealed upon completion

Root + Impact

Location: Both contracts

Description

Neither Stratax nor StrataxOracle implements a pause mechanism. If a vulnerability is being actively exploited, oracle prices become corrupted, or an external dependency behaves unexpectedly, there is no way to stop new positions from being opened or incorrectly unwound.

// src/Stratax.sol:314 — no whenNotPaused modifier
function createLeveragedPosition(...) public onlyOwner { ... }
// src/Stratax.sol:236 — no whenNotPaused modifier
function unwindPosition(...) external onlyOwner { ... }
// src/StrataxOracle.sol:64 — no whenNotPaused modifier
function getPrice(address _token) public view returns (uint256 price) { ... }

Risk

Likelihood:

  • DeFi protocols regularly face emergency scenarios where the only protective response is to halt operations

  • Oracle manipulation, flash loan attacks on dependent protocols, and bridge exploits all create windows requiring emergency halts

Impact:

  • Owner cannot prevent position creation during an active exploit — attacker continues opening positions with manipulated prices

  • No ability to freeze oracle price consumption if a Chainlink feed is actively compromised

Proof of Concept

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test} from "forge-std/Test.sol";
import {Stratax} from "../../src/Stratax.sol";
contract NoPausePoCTest is Test {
Stratax stratax;
function test_cannotHaltDuringExploit() public {
// Simulate: oracle returning manipulated price (10x inflated)
// Owner detects the exploit and wants to stop new positions
// There is no pause() function to call
// The following call demonstrates no halting mechanism exists:
address owner = stratax.owner();
vm.prank(owner);
(bool success,) = address(stratax).call(abi.encodeWithSignature("pause()"));
assertFalse(success); // @> no pause function — call fails
// Attacker can still open positions with manipulated prices
// Owner's only option is to front-run every attacker tx — not feasible
}
}

Recommended Mitigation

Inherit from OpenZeppelin's Pausable and add whenNotPaused to createLeveragedPosition and unwindPosition. This gives the owner a single-transaction emergency stop that can halt all new position activity while leaving existing positions intact and withdrawable by other means.

+ import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
- contract Stratax is Initializable {
+ contract Stratax is Initializable, Pausable {
- function createLeveragedPosition(...) public onlyOwner {
+ function createLeveragedPosition(...) public onlyOwner whenNotPaused {
- function unwindPosition(...) external onlyOwner {
+ function unwindPosition(...) external onlyOwner whenNotPaused {
+ function pause() external onlyOwner { _pause(); }
+ function unpause() external onlyOwner { _unpause(); }

Support

FAQs

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

Give us feedback!