Stratax Contracts

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

Arbitrary Token Recovery (Centralization Risk)

Author Revealed upon completion

Root + Impact

Description

  • Normal Behavior: The recoverTokens() function is intended as an emergency mechanism to recover stray ERC20 tokens sent to the contract accidentally. Normally, it should only recover tokens not used for user positions.

  • Issue: Currently, the function allows the owner to withdraw any ERC20 token, including tokens deposited by users as collateral or borrowed tokens in leveraged positions. This creates a direct fund-loss vector, as the owner can drain all protocol-held tokens at any time.

// Root cause in the codebase with @> marks to highlight the relevant section
function recoverTokens(address _token, uint256 _amount) external onlyOwner {
@> IERC20(_token).transfer(owner, _amount);
}

Risk

Likelihood:

  • Owner has access to the contract and can call recoverTokens() at any time.

  • All user collateral and borrowed tokens are held in the contract, so any call will transfer real funds.

Impact:

  • Immediate loss of all user funds held in the contract.

  • Open leveraged positions can be disrupted, potentially leaving users in unsafe states.

Proof of Concept

// Assume USDC is used as collateral and held in contract
address userCollateralToken = 0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48; // USDC
// Owner calls recoverTokens
stratax.recoverTokens(userCollateralToken, IERC20(userCollateralToken).balanceOf(address(stratax)));
// Result: All USDC held by contract is transferred to owner

The PoC shows that all tokens in the contract, including user-supplied collateral, are transferable by the owner. This proves a direct fund-loss vulnerability and confirms the high severity.

Recommended Mitigation

- function recoverTokens(address _token, uint256 _amount) external onlyOwner {
- IERC20(_token).transfer(owner, _amount);
- }
+ function recoverTokens(address _token, uint256 _amount) external onlyOwner {
+ require(!_isPositionToken(_token), "Cannot recover user collateral or debt tokens");
+ IERC20(_token).transfer(owner, _amount);
+ }
+
+ // Helper function to track position tokens
+ function _isPositionToken(address token) internal view returns (bool) {
+ // Return true if token is used as collateral or borrowed in any open position
+ }

The mitigation prevents the owner from withdrawing tokens that are part of user positions, while still allowing recovery of stray / unrelated tokens.
This reduces centralization risk and protects user funds while keeping emergency recovery functionality intact.

Support

FAQs

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

Give us feedback!