First Flight #21: KittyFi

First Flight #21
Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

Token Approval: Safe Patterns and safeApprove

Summary

When interacting with ERC20 tokens, contracts often require users to approve a certain amount of tokens for spending. However, improper handling of token approvals can lead to vulnerabilities, such as excessive allowances, which can be exploited by attackers.

Some tokens (like the very popular USDT) do not work when changing the allowance from an existing non-zero allowance value (it will revert if the current approval is not zero to protect against front-running changes of approvals). These tokens must first be approved for zero and then the actual allowance can be approved.Furthermore, OZ's implementation of safeApprove would throw an error if an approve is attempted from a non-zero value ("SafeERC20: approve from non-zero to non-zero allowance")Set the allowance to zero immediately before each of the existing allowance calls

Vulnerability Details

Traditional Approval (Vulnerable):

ERC20(token).approve(spender, amount);

Impact

  1. Security Vulnerabilities:

    • Excessive Allowances: If the current allowance is not set to zero before updating, it can lead to excessive allowances. Attackers can exploit this to spend more tokens than intended.

    • Reentrancy Attacks: Without safe methods, the contract might be vulnerable to reentrancy attacks, where an attacker repeatedly calls a function before the previous execution is complete.

  2. Financial Risks:

    • Fund Drain: Attackers could exploit excessive allowances to drain user funds from the contract.

    • Unauthorized Transfers: Malicious actors might be able to transfer more tokens than authorized, leading to significant financial losses.

  3. Operational Issues:

    • State Inconsistency: Improper handling of allowances can lead to inconsistent states, causing operational issues and potential loss of funds.

    • Unexpected Behavior: Without safe approval patterns, the contract might behave unexpectedly, especially in edge cases, leading to potential bugs and vulnerabilities.

  4. User Trust and Reputation:

    • Loss of Confidence: Users may lose trust in the protocol if they experience unauthorized token transfers or financial losses due to security vulnerabilities.

    • Reputation Damage: Security breaches and financial losses can damage the protocol's reputation, making it less attractive to users and investors.

Example Scenario:

Without safe approval patterns, an attacker could exploit the contract by manipulating allowances. For instance:

  1. Initial Approval: A user approves the contract to spend 100 tokens.

  2. Update Allowance: The user attempts to update the allowance to 200 tokens without first setting it to zero.

  3. Exploitation: An attacker exploits this by initiating a transaction that spends the initial 100 tokens and then immediately spends the additional 200 tokens before the allowance is correctly updated. This results in unauthorized spending of 300 tokens instead of the intended 200.

Detailed Impacts:

  1. Security Vulnerabilities:

    • Excessive Allowances: Without resetting the allowance to zero, the contract can end up with an allowance that is higher than intended, allowing attackers to drain more funds.

    • Reentrancy Attacks: Functions that involve external calls (e.g., transferFrom) without proper reentrancy guards can be exploited to repeatedly call the function, leading to multiple unauthorized transactions.

  2. Financial Risks:

    • Fund Drain: Attackers can exploit excessive allowances to withdraw more funds than authorized, potentially draining user accounts and the contract itself.

    • Unauthorized Transfers: Users might find that their tokens are transferred without their consent, leading to financial losses and disputes.

  3. Operational Issues:

    • State Inconsistency: Improper handling of allowances can lead to inconsistent states within the contract, causing operational issues such as incorrect balance tracking and failed transactions.

    • Unexpected Behavior: Contracts might behave unpredictably, especially in edge cases, leading to bugs and vulnerabilities that are difficult to diagnose and fix.

Not using safe approval patterns can expose the contract to significant security vulnerabilities, financial risks, operational issues, and damage to user trust and reputation. Implementing safe approval patterns, such as using OpenZeppelin's SafeERC20 library and the safeApprove function, is essential to mitigate these risks and ensure the security and reliability of the contract.

Tools Used

  • Audit Wizard

  • Read the code

Recommendations

Safe Approval Patterns:

  1. Check-Then-Set Pattern: Ensure that the current allowance is zero before setting a new allowance.

  2. Use safeApprove: Utilize safe approval functions that handle edge cases and prevent common pitfalls.

Safe Approval Using safeApprove:

OpenZeppelin's SafeERC20 library provides a safeApprove function that includes safety checks.

  1. Import SafeERC20:

    import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
  2. Use SafeERC20:

    using SafeERC20 for IERC20;
    function safeTokenApproval(IERC20 token, address spender, uint256 amount) external {
    // Check if the current allowance is zero
    require(token.allowance(msg.sender, spender) == 0, "Current allowance must be zero");
    // Use safeApprove to set the new allowance
    token.safeApprove(spender, amount);
    }

Benefits of Safe Approval:

  1. Prevents Double-Spending: Ensures that the allowance is reset to zero before setting a new value, preventing potential double-spending issues.

  2. Handles Edge Cases: The safeApprove function from OpenZeppelin's SafeERC20 library includes checks that handle common edge cases and prevent unexpected behavior.

  3. Reduces Risk of Excessive Allowances: By requiring the current allowance to be zero before setting a new one, it minimizes the risk of leaving excessive allowances that could be exploited by malicious actors.

Example Implementation in KittyPool:

Here is how you might integrate safe approval patterns into the KittyPool contract when dealing with token approvals for depositing collateral:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { KittyVault, IKittyVault } from "./KittyVault.sol";
contract KittyPool {
using SafeERC20 for IERC20;
// ... (other code remains unchanged)
/**
* @notice Deposits the collateral in the vault
* @param _token token address
* @param _ameownt amount of token to deposit
*/
function depawsitMeowllateral(address _token, uint256 _ameownt) external tokenExists(_token) nonReentrant {
IERC20 token = IERC20(_token);
// Ensure the current allowance is zero before setting a new allowance
require(token.allowance(msg.sender, address(this)) == 0,
"Current allowance must be zero");
// Approve the contract to spend the specified amount of tokens
token.safeApprove(address(this), _ameownt);
// Transfer the tokens from the user to the contract
token.safeTransferFrom(msg.sender, address(this), _ameownt);
// Deposit the collateral into the respective vault
IKittyVault(tokenToVault[_token]).executeDepawsit(msg.sender, _ameownt);
}
// ... (other functions remain unchanged)
}

Explanation:

  1. Import SafeERC20: The SafeERC20 library from OpenZeppelin is imported to provide safe token operations.

  2. Use SafeERC20: The using SafeERC20 for IERC20 directive allows the use of safeApprove and safeTransferFrom methods from the SafeERC20 library.

  3. Check Allowance: Before setting a new allowance, the current allowance is checked to ensure it is zero. This prevents potential issues with changing allowances.

  4. Safe Approve: The safeApprove method is used to safely set the new allowance.

  5. Safe Transfer: The safeTransferFrom method is used to securely transfer the tokens from the user to the contract.

Conclusion:

Using safe approval patterns and the SafeERC20 library helps prevent vulnerabilities associated with token approvals. This approach ensures that allowances are managed securely, reducing the risk of excessive allowances and potential exploits.

Updates

Lead Judging Commences

shikhar229169 Lead Judge 11 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.