AuditBase
Sign InGet Started
mediumM006

Contracts are vulnerable to fee-on-transfer-token-related accounting issues

Learn about the potential accounting issues in Ethereum contracts due to fee-on-transfer-token mechanics. Discover how failing to measure token balance before and after transfers can lead to vulnerabilities and latent funds within the contract.

Category

medium-severity

Languages

solidity

Analysis Layer

static

Severity

medium

In the cryptocurrency world, fee-on-transfer tokens (FoT tokens) introduce a unique mechanism where transactions automatically incur a fee that is deducted from the amount being transferred. This innovative feature, while beneficial for various use cases, poses significant challenges and vulnerabilities in contract design, particularly related to accounting issues.

Problem

Contracts interacting with fee-on-transfer tokens may incorrectly assume the amount sent is the amount received by the recipient. This assumption can lead to discrepancies in balance tracking and accounting, especially in decentralized finance (DeFi) applications.

Solution

Implementing robust accounting mechanisms within contracts that interact with FoT tokens is crucial. These mechanisms must account for the transaction fee deducted during the transfer, ensuring accurate balance and transaction records.

Example Code

// Example Solidity contract addressing FoT token interactions
pragma solidity ^0.8.0;

interface IFeeOnTransferToken {
    function transfer(address recipient, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

contract AccountingSafeContract {
    IFeeOnTransferToken public feeOnTransferToken;

    constructor(address _tokenAddress) {
        feeOnTransferToken = IFeeOnTransferToken(_tokenAddress);
    }

    // Function to safely transfer FoT tokens accounting for the transfer fee
    function safeTransfer(address recipient, uint256 amount) public {
        uint256 balanceBefore = feeOnTransferToken.balanceOf(address(this));
        require(feeOnTransferToken.transfer(recipient, amount), "Transfer failed");
        uint256 balanceAfter = feeOnTransferToken.balanceOf(address(this));
        uint256 actualTransferAmount = balanceBefore - balanceAfter;

        // Logic to update internal accounting based on actualTransferAmount
        // This can include updating user balances, total supply calculations, etc.
    }
}

Conclusion

Contracts dealing with fee-on-transfer tokens need to meticulously account for the fees deducted during transfers to avoid significant accounting errors. By anticipating these fees and integrating accounting safeguards into the contract's design, developers can ensure more accurate financial operations and maintain the integrity of transaction processes in their applications.