DeFiFoundrySolidity
16,653 OP
View results
Submission Details
Severity: high
Invalid

No Mechanism to Recover Unexpected Tokens

Issue:

The StrategyMainnet contract does not include a mechanism to recover tokens inadvertently sent to the contract that are not part of the strategy's operations (e.g., tokens other than underlying or asset). Over time, this can result in stray tokens being permanently locked within the contract.


Impact:

Medium to High.

  1. Locked Tokens:

    Any unexpected tokens sent to the contract (e.g., as a mistake or through malicious means) cannot be recovered without deploying a new contract or modifying the existing one.

  2. Operational Inefficiencies:

    Locked tokens contribute to inefficiencies by reducing the recoverable funds available to the protocol.

  3. Trust and User Experience:

    Users or third-party protocols might accidentally transfer tokens, leading to dissatisfaction if recovery is not possible.


Evidence from Code:

The contract does not include any rescueTokens or equivalent function to handle unexpected tokens:

// No dedicated function to recover stray tokens.

Potential Attack / Problem Scenario:

  1. Accidental Transfers:

    • A user mistakenly transfers unrelated tokens to the strategy contract.

  2. Malicious Token Transfers:

    • An attacker sends tokens to inflate the contract’s perceived balance to manipulate audits or confuse accounting.

  3. Locked Tokens:

    • Without a recovery mechanism, these tokens remain inaccessible and unusable.


Proposed Solution:

Implement a function to recover non-strategy tokens, restricted to authorized roles such as onlyManagement. This ensures that tokens not part of the strategy’s operations can be safely returned.

Rescue Function Implementation:

function rescueTokens(address _token, uint256 _amount, address _recipient) external onlyManagement {
require(_token != address(asset) && _token != address(underlying), "Cannot rescue strategy tokens");
IERC20(_token).transfer(_recipient, _amount);
}

Mitigation Steps:

  1. Implement a Rescue Function:

    • Allow authorized roles to retrieve tokens that are not part of the strategy.

  2. Prevent Strategy Token Misuse:

    • Include safeguards to ensure asset and underlying tokens cannot be "rescued" or transferred unintentionally.

Enhanced Rescue Function with Safeguards:

event TokensRescued(address token, uint256 amount, address recipient);
function rescueTokens(address _token, uint256 _amount, address _recipient) external onlyManagement {
require(_token != address(asset) && _token != address(underlying), "Cannot rescue strategy tokens");
IERC20(_token).safeTransfer(_recipient, _amount);
emit TokensRescued(_token, _amount, _recipient);
}

Proof of Concept (PoC):

  1. Unexpected Token Transfer:

    • A user mistakenly sends USDC to the strategy contract.

  2. Execute Rescue Function:

    • The rescueTokens function is invoked by the management role to transfer the USDC back to the user.

    rescueTokens(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, 1000e6, 0xRecipientAddress);
  3. Expected Outcome:

    • USDC tokens are successfully transferred back to the user without affecting the strategy’s asset or underlying balances.

Updates

Appeal created

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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