Tadle

Tadle
DeFiFoundry
27,750 USDC
View results
Submission Details
Severity: medium
Valid

The Token manager does not support Fee on Transfer tokens

Summary

According to the contest details, any token that follows the ERC20 standard can be whitelisted as collateral, Fee on Transfer Tokens are ERC20 tokens that charge a fee on every transfer so, the total amount received is less than the amount transferred.

Vulnerability Details

The transfer functions checked that the from balance after the transfer must be equal to fromBalanceAft != fromBalanceBef - _amount)and the to the balance should be equal to toBalanceAft != toBalanceBef + _amount , if they are not equal it is going to revert the transaction. For the fee on transfer token, the balance of the receiver is always less than the sent amount.

function _transfer(
address _token,
address _from,
address _to,
uint256 _amount,
address _capitalPoolAddr
) internal {
uint256 fromBalanceBef = IERC20(_token).balanceOf(_from);
uint256 toBalanceBef = IERC20(_token).balanceOf(_to);
if (
_from == _capitalPoolAddr &&
IERC20(_token).allowance(_from, address(this)) == 0x0
) {
ICapitalPool(_capitalPoolAddr).approve(address(this));
}
_safe_transfer_from(_token, _from, _to, _amount);
uint256 fromBalanceAft = IERC20(_token).balanceOf(_from);
uint256 toBalanceAft = IERC20(_token).balanceOf(_to);
@-> if (fromBalanceAft != fromBalanceBef - _amount) {
revert TransferFailed();
}
@-> if (toBalanceAft != toBalanceBef + _amount) {
revert TransferFailed();
}
}

Impact

It is not going to work the transaction will revert.

Tools Used

Manual Analysis

Recommendations

  1. Don't Whitelist fees on transfer tokens

  2. Modify the transfer function to this.

    function _transfer(
    address _token,
    address _from,
    address _to,
    uint256 _amount,
    address _capitalPoolAddr
    - ) internal {
    + ) internal returns(uint256) {
    uint256 fromBalanceBef = IERC20(_token).balanceOf(_from);
    uint256 toBalanceBef = IERC20(_token).balanceOf(_to);
    if (
    _from == _capitalPoolAddr &&
    IERC20(_token).allowance(_from, address(this)) == 0x0
    ) {
    ICapitalPool(_capitalPoolAddr).approve(address(this));
    }
    _safe_transfer_from(_token, _from, _to, _amount);
    uint256 fromBalanceAft = IERC20(_token).balanceOf(_from);
    uint256 toBalanceAft = IERC20(_token).balanceOf(_to);
    - if (fromBalanceAft != fromBalanceBef - _amount) {
    - revert TransferFailed();
    - }
    - if (toBalanceAft != toBalanceBef + _amount) {
    - revert TransferFailed();
    - }
    + return toBalanceBef - toBalanceAft;
    }
Updates

Lead Judging Commences

0xnevi Lead Judge 12 months ago
Submission Judgement Published
Validated
Assigned finding tags:

finding-TokenManager-FOT-Rebasing

Valid medium, there are disruptions to the ability to take market actions. The following functions will be disrupted without the possibiliy of reaching settlement, since the respective offers cannot be created/listed regardless of mode when transferring collateral token required to the CapitalPool contract or when refunding token from user to capital pool during relisting. So withdrawal is not an issue - `createOffer()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L96-L102) - `listOffer()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L355-L362) - `relistOffer()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L515-L521) - `createTaker()` - reverts [here](https://github.com/Cyfrin/2024-08-tadle/blob/04fd8634701697184a3f3a5558b41c109866e5f8/src/core/PreMarkets.sol#L831-L836) I believe medium severity is appropriate although the likelihood is high and impact is medium (only some level of disruption i.e. FOT tokens not supported and no funds at risk)

Support

FAQs

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