TSender

Cyfrin
DeFiFoundry
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

Blacklisted addresses can cause caller to waste a lot of gas

Summary

The protocol supports USDT and USDC tokens both which support blacklisting functionality. The airdropERC20 function stops executing when encountering a blacklisted address, causing gas wastage and potential attack vectors.

Vulnerability Details

The airdropERC20 function halts if any call to transfer tokens fails, which can happen if an address is blacklisted. This means that for an airdrop to 5000 users, if 20 users are blacklisted (less than 0,5%), the function would need to be executed 20 times, each time removing the blacklisted address until all legitimate addresses receive the airdrop. Also an attacker can setup many blacklisted addresses as legitimate receivers of the airdrop of a protocol. These issues can cause the protocol sender to waste a lot of gas.

Now there might be a way for the protocol sender to know beforehand which address is blacklisted and remove them. Which obviously only a small number would know how to do it. However, in an automated setting, let's say a keeper that is set up to periodically send the airdrop to registered addresses, these issues are still valid in this case.

Current code that is programmed to revert when a call fail :

TSender.sol

// transfer the tokens
if iszero(call(gas(), tokenAddress, 0, 0x00, 0x44, 0, 0)) {
mstore(0x00, 0xfa10ea06) // cast sig "TSender__TransferFailed()"
revert(0x1c, 0x04)
}

Huff contracts

// call(gas(), tokenAddress, 0, 0x00, 0x44, 0, 0)
0x00 0x00 0x44 [TWENTY_EIGHT] 0x00 dup9 gas call // [success, address_offset, end, diff, token_address]
transfer_didnt_fail jumpi // [address_offset, end, diff, token_address]
// cast sig TSender__TransferFailed()
0xfa10ea06 0x00 mstore
0x04 [TWENTY_EIGHT] revert
// increment the address offset
transfer_didnt_fail:

Impact

Gas wastage in case of multiple re-runs especially for a larger number of recipients.

Tools Used

Manual review

Recommendations

Consider modifying the function to continue executing even if a transfer to a specific address fails. Track the failed transfers and return the total amount not sent at the end of the process back to the protocol sender. This method is probably a little bit less gas efficient since there will one more memory variable to track, and one more call (that sends the remainder back to the caller) at the end in case one or more calls failed. However, it makes sure that the caller is not wasting any gas trying to re-run the function.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue
maroutis Submitter
about 1 year ago
patrickalphac Auditor
about 1 year ago
maroutis Submitter
about 1 year ago
maroutis Submitter
about 1 year ago
patrickalphac Auditor
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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