Stratax Contracts

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

Arbitrary Token Recovery (Centralization Risk)

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.

Updates

Lead Judging Commences

izuman Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!