// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IERC20 {
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function transfer(address to, uint256 amount) external returns (bool);
function balanceOf(address account) external view returns (uint256);
}
contract TokenDistributor {
error InvalidRecipients();
error InsufficientBalance();
error TransferFailed();
error DistributionFailed();
function distributeToken(
address token,
address[] calldata recipients,
uint256 amountEach
) external {
// Input validation
if (recipients.length == 0) revert InvalidRecipients();
uint256 total = amountEach * recipients.length;
// Check token balance before attempting transfer
if (IERC20(token).balanceOf(msg.sender) < total) revert InsufficientBalance();
// Transfer tokens to contract
// if (!IERC20(token).transferFrom(msg.sender, address(this), total))
// revert TransferFailed();
// Distribute to recipients
for (uint256 i = 0; i < recipients.length; i++) {
if (recipients[i] == address(0)) revert InvalidRecipients();
if (!IERC20(token).transferFrom(msg.sender, recipients[i], amountEach))
revert DistributionFailed();
}
// If any tokens are stuck (shouldn't happen), return them
// uint256 remaining = IERC20(token).balanceOf(address(this));
// if (remaining > 0) {
// IERC20(token).transfer(msg.sender, remaining);
// }
}
}
{
"compilationTarget": {
"contracts/TokenDistributor.sol": "TokenDistributor"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"name":"DistributionFailed","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidRecipients","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address[]","name":"recipients","type":"address[]"},{"internalType":"uint256","name":"amountEach","type":"uint256"}],"name":"distributeToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]