Beginner FriendlyDeFiFoundry
100 EXP
View results
Submission Details
Severity: low
Invalid

Doesn't validate if the token transfer was successful so the contract could be deployed without having the USDC to pay the airdrop to the users.

[H-4] Doesn't validate if the token transfer was successful so the contract could be deployed without having the USDC to pay the airdrop to the users.

Description: It does not validate if the token transfer was successful, it would not notice if the token transfer failed and the contract could be deployed without USDC balance that will be used to pay the airdrop to the users.

Impact: Users would consume gas to receive the airdrop.

Proof of Concept:

Code

This test was added in MerkleAirdrop.t.test

function testFailTransferTokenToContract() public {
MockBlacListed blacklist = new MockBlacListed();
MerkleAirdrop airdrop2 = new MerkleAirdrop(merkleRoot, blacklist);
token.mint(address(this), amountToSend);
bool succ = blacklist._transfer(address(airdrop2), amountToSend);
console.log("success?", succ);
vm.deal(collectorOne, airdrop.getFee());
vm.startPrank(collectorOne);
airdrop2.claim{ value: airdrop.getFee() }(collectorOne, amountToCollect, proof);
}
[PASS] testFailTransferTokenToContract() (gas: 1118200)
Logs:
success? false

And use this mock token for the test, and is added in MerkleAirdrop.t.test

contract MockBlacListed is ERC20 {
mapping(address => bool) internal _deprecatedBlacklisted;
modifier notBlacklisted(address _account) {
require(
!_isBlacklisted(_account),
"Blacklistable: account is blacklisted"
);
_;
}
constructor() ERC20("BlackList Token", "BLT") {
_mint(0x20F41376c713072937eb02Be70ee1eD0D639966C, 100 * 1e6);
}
function decimals() public view virtual override returns (uint8) {
return 6;
}
function isBlacklisted(address _account) external view returns (bool) {
return _isBlacklisted(_account);
}
function blacklist(address _account) external {
_blacklist(_account);
}
function _isBlacklisted(address _account)
internal
view
returns (bool) {
return _deprecatedBlacklisted[_account];
}
function _blacklist(address _account) internal {
_setBlacklistState(_account, true);
}
function _setBlacklistState(address _account, bool _shouldBlacklist)
internal
virtual
{
_deprecatedBlacklisted[_account] = _shouldBlacklist;
}
function transfer(address to, uint256 value) public virtual override
notBlacklisted(msg.sender)
notBlacklisted(to)
returns (bool){
return super.transfer(to,value);
}
}
function _transfer(address /* to */, uint256 /* value */) public returns (bool){
return false;
}

Recommended Mitigation: It's necessary to validate the transfer of tokens to prevent a contract deployment without a balance. Either by validating the transfer, which would be the correct approach, or by checking the contract once deployed and if its balance is zero, transferring the tokens manually.

+ error Transfer_Token_Fail();
- IERC20(0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4).transfer(address(airdrop), s_amountToAirdrop);
+ bool success = IERC20(0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4).transfer(address(airdrop), s_amountToAirdrop);
+ if (!success){
+ revert Transfer_Token_Fail();
+}
Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

Info

Support

FAQs

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