Beginner FriendlySolidity
100 EXP
View results
Submission Details
Severity: high
Invalid

Fee-on-transfer tokens will block distribution or cause fund loss in withdrawInheritedFunds

Description:

The withdrawInheritedFunds()function fails to account for fee-on-transfer (deflationary) tokens. These tokens take a fee on each transfer, reducing the actual amount received by the recipient. The function calculates distribution amounts based on the total balance but doesn't adjust for fees deducted during transfers:

function withdrawInheritedFunds(address _asset) external {
// ...
uint256 assetAmountAvailable = IERC20(_asset).balanceOf(address(this));
uint256 amountPerBeneficiary = assetAmountAvailable / divisor;
for (uint256 i = 0; i < divisor; i++) {
IERC20(_asset).safeTransfer(beneficiaries[i], amountPerBeneficiary);
}
// ...
}

The function makes a critical assumption that when safeTransfer sends amountPerBeneficiary tokens, the recipient receives exactly that amount. However, with fee-on-transfer tokens, the recipient receives less (e.g., 95% if the fee is 5%).

This creates two serious issues:

  • With each transfer, the contract's balance drops more than expected

  • When processing later beneficiaries, there will be insufficient tokens to complete transfers

Impact:

If the token fee is substantial or the number of beneficiaries is high, the function will revert with an "insufficient balance" error when processing later beneficiaries. This means no beneficiary will receive any tokens since the entire transaction reverts. Since the function always attempts to distribute using the same flawed logic, deflationary tokens will be permanently locked in the contract with no mechanism to recover them.

Numerical example:

  • Contract holds 1000 tokens with 10 beneficiaries (100 tokens each)

  • Token has 5% transfer fee

  • First transfer: Sends 100, beneficiary receives 95, contract has 900 left

  • Second transfer: Sends 100, beneficiary receives 95, contract has 800 left

  • ...

  • Ninth transfer: Sends 100, beneficiary receives 95, contract has 200 left

  • Tenth transfer: Attempts to send 100, but after 9 transfers with fees, only 95 tokens remaining

  • Function reverts, all transfers fail, tokens remain locked

  • No fallback mechanism: The current design provides no way to handle these tokens once inheritance is activated.

Recommended Mitigation:

Implement a pull-based withdrawal pattern that distributes tokens individually to each beneficiary, allowing the distribution to succeed even if some transfers fail

Updates

Lead Judging Commences

0xtimefliez Lead Judge 6 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.