Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xF661EBC9990f0f67e4868A6b96ae7Fa5C5c16cDB
Balance 0 ETH
Nonce 1
Code Size 5208 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

5208 bytes
0x608060405234801561000f575f5ffd5b5060043610610153575f3560e01c8063a6896963116100bf578063e76159ad11610079578063e76159ad146102d4578063e79faa58146102e7578063e7c00f6e146102fa578063f2fde38b14610301578063fc0c546a14610314578063fff8cbd41461033b575f5ffd5b8063a68969631461025c578063a99dc3891461026f578063b0fb48241461027b578063bb036b96146102a3578063cfdbf254146102c3578063d8f163ab146102cb575f5ffd5b806383d892281161011057806383d89228146101e257806383e554a2146101eb5780638afbf669146101fe5780638d1dcca6146102065780638da5cb5b14610219578063a5af246c1461023d575f5ffd5b80632307b44114610157578063317d94531461016c5780633cd33e9a146101875780635c975abb146101aa5780636da66355146101c7578063715018a6146101da575b5f5ffd5b61016a610165366004611160565b610346565b005b6101746106dc565b6040519081526020015b60405180910390f35b61018f610769565b6040805193845260208401929092529082015260600161017e565b5f54600160a01b900460ff165b604051901515815260200161017e565b61016a6101d53660046111cc565b610806565b61016a61087e565b61017460035481565b6101b76101f936600461123a565b6108b2565b61016a610951565b6101b7610214366004611251565b610aea565b5f546001600160a01b03165b6040516001600160a01b03909116815260200161017e565b61017461024b366004611251565b60026020525f908152604090205481565b6101b761026a36600461127e565b610b2e565b6101746402540be40081565b61028e610289366004611160565b610ba0565b6040805192835260208301919091520161017e565b6102b66102b136600461127e565b610d2a565b60405161017e91906112bd565b61017460c881565b61017460045481565b6101746102e2366004611251565b610df3565b61016a6102f53660046111cc565b610e35565b60c8610174565b61016a61030f366004611251565b610ea1565b6102257f00000000000000000000000066aa0e04864f2de0ee44d9e508e68415c04e2f5781565b6402540be400610174565b5f546001600160a01b031633146103785760405162461bcd60e51b815260040161036f906112ff565b60405180910390fd5b610380610f3b565b610388610f87565b82806103c95760405162461bcd60e51b815260206004820152601060248201526f456d70747920726563697069656e747360801b604482015260640161036f565b8082146104075760405162461bcd60e51b815260206004820152600c60248201526b098cadc40dad2e6dac2e8c6d60a31b604482015260640161036f565b60c88111156104435760405162461bcd60e51b8152602060048201526008602482015267546f6f206d616e7960c01b604482015260640161036f565b7f00000000000000000000000066aa0e04864f2de0ee44d9e508e68415c04e2f575f80805b8481101561068f575f89898381811061048357610483611334565b90506020020160208101906104989190611251565b90505f8888848181106104ad576104ad611334565b60200291909101359150506001600160a01b0382166104de5760405162461bcd60e51b815260040161036f90611348565b5f81116105185760405162461bcd60e51b815260206004820152600860248201526716995c9bc8185b5d60c21b604482015260640161036f565b6402540be40081111561055b5760405162461bcd60e51b815260206004820152600b60248201526a08af0c6cacac8e640dac2f60ab1b604482015260640161036f565b60405163a9059cbb60e01b81526001600160a01b038381166004830152602482018390525f919088169063a9059cbb906044016020604051808303815f875af11580156105aa573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105ce919061136b565b90508061060f5760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161036f565b6001600160a01b0383165f908152600260205260408120805484929061063690849061139e565b90915550869050610646816113b1565b96506106549050828661139e565b600380549196505f610665836113b1565b91905055508160045f82825461067b919061139e565b909155505060019093019250610468915050565b5060408051838152602081018390527f3838459cd794256a3c29bb3186da72029a8036c0f596fee1bd526f8eb9493d41910160405180910390a1505050506106d660018055565b50505050565b6040516370a0823160e01b81523060048201525f907f00000000000000000000000066aa0e04864f2de0ee44d9e508e68415c04e2f576001600160a01b0316906370a0823190602401602060405180830381865afa158015610740573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061076491906113c9565b905090565b6040516370a0823160e01b81523060048201525f90819081906001600160a01b037f00000000000000000000000066aa0e04864f2de0ee44d9e508e68415c04e2f5716906370a0823190602401602060405180830381865afa1580156107d1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107f591906113c9565b925060045491506003549050909192565b5f546001600160a01b0316331461082f5760405162461bcd60e51b815260040161036f906112ff565b610837610fe0565b336001600160a01b03167f375c0abd968f4602b557f6ac9a48ffc89820233aa9becc5d7ff1176fd09eafff83836040516108729291906113e0565b60405180910390a25050565b5f546001600160a01b031633146108a75760405162461bcd60e51b815260040161036f906112ff565b6108b05f61103f565b565b5f815f036108c157505f919050565b6040516370a0823160e01b815230600482015282907f00000000000000000000000066aa0e04864f2de0ee44d9e508e68415c04e2f576001600160a01b0316906370a0823190602401602060405180830381865afa158015610925573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061094991906113c9565b101592915050565b5f546001600160a01b0316331461097a5760405162461bcd60e51b815260040161036f906112ff565b610982610f3b565b6040516370a0823160e01b81523060048201527f00000000000000000000000066aa0e04864f2de0ee44d9e508e68415c04e2f57905f906001600160a01b038316906370a0823190602401602060405180830381865afa1580156109e8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a0c91906113c9565b90508015610ae6575f826001600160a01b031663a9059cbb610a355f546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602481018590526044016020604051808303815f875af1158015610a7f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aa3919061136b565b905080610ae45760405162461bcd60e51b815260206004820152600f60248201526e15da5d1a191c985dc819985a5b1959608a1b604482015260640161036f565b505b5050565b5f6001600160a01b038216610b115760405162461bcd60e51b815260040161036f90611348565b506001600160a01b03165f90815260026020526040902054151590565b5f81815b81811015610b9357848482818110610b4c57610b4c611334565b905060200201355f1480610b7c57506402540be400858583818110610b7357610b73611334565b90506020020135115b15610b8b575f92505050610b9a565b600101610b32565b5060019150505b92915050565b5f805481906001600160a01b03163314610bcc5760405162461bcd60e51b815260040161036f906112ff565b8480610c025760405162461bcd60e51b8152602060048201526005602482015264456d70747960d81b604482015260640161036f565b808414610c405760405162461bcd60e51b815260206004820152600c60248201526b098cadc40dad2e6dac2e8c6d60a31b604482015260640161036f565b60c8811115610c7c5760405162461bcd60e51b8152602060048201526008602482015267546f6f206d616e7960c01b604482015260640161036f565b5f5b81811015610d1f575f888883818110610c9957610c99611334565b9050602002016020810190610cae9190611251565b90505f878784818110610cc357610cc3611334565b60200291909101359150506001600160a01b03821615801590610ce557505f81115b8015610cf657506402540be4008111155b15610d1557610d05818761139e565b955084610d11816113b1565b9550505b5050600101610c7e565b505094509492505050565b6060818067ffffffffffffffff811115610d4657610d4661140e565b604051908082528060200260200182016040528015610d6f578160200160208202803683370190505b5091505f5b81811015610deb5760025f868684818110610d9157610d91611334565b9050602002016020810190610da69190611251565b6001600160a01b03166001600160a01b031681526020019081526020015f2054838281518110610dd857610dd8611334565b6020908102919091010152600101610d74565b505092915050565b5f6001600160a01b038216610e1a5760405162461bcd60e51b815260040161036f90611348565b506001600160a01b03165f9081526002602052604090205490565b5f546001600160a01b03163314610e5e5760405162461bcd60e51b815260040161036f906112ff565b610e6661108e565b336001600160a01b03167f5e9efe0320c49a9eb6e0d598cd54a92107df81a70b87c1fff8e2c2a3b803f77483836040516108729291906113e0565b5f546001600160a01b03163314610eca5760405162461bcd60e51b815260040161036f906112ff565b6001600160a01b038116610f2f5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161036f565b610f388161103f565b50565b5f54600160a01b900460ff16156108b05760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b604482015260640161036f565b600260015403610fd95760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015260640161036f565b6002600155565b610fe8610f3b565b5f805460ff60a01b1916600160a01b1790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586110223390565b6040516001600160a01b03909116815260200160405180910390a1565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6110966110c9565b5f805460ff60a01b191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa33611022565b5f54600160a01b900460ff166108b05760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604482015260640161036f565b5f5f83601f840112611128575f5ffd5b50813567ffffffffffffffff81111561113f575f5ffd5b6020830191508360208260051b8501011115611159575f5ffd5b9250929050565b5f5f5f5f60408587031215611173575f5ffd5b843567ffffffffffffffff811115611189575f5ffd5b61119587828801611118565b909550935050602085013567ffffffffffffffff8111156111b4575f5ffd5b6111c087828801611118565b95989497509550505050565b5f5f602083850312156111dd575f5ffd5b823567ffffffffffffffff8111156111f3575f5ffd5b8301601f81018513611203575f5ffd5b803567ffffffffffffffff811115611219575f5ffd5b85602082840101111561122a575f5ffd5b6020919091019590945092505050565b5f6020828403121561124a575f5ffd5b5035919050565b5f60208284031215611261575f5ffd5b81356001600160a01b0381168114611277575f5ffd5b9392505050565b5f5f6020838503121561128f575f5ffd5b823567ffffffffffffffff8111156112a5575f5ffd5b6112b185828601611118565b90969095509350505050565b602080825282518282018190525f918401906040840190835b818110156112f45783518352602093840193909201916001016112d6565b509095945050505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b6020808252600990820152682d32b9379030b2323960b91b604082015260600190565b5f6020828403121561137b575f5ffd5b81518015158114611277575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115610b9a57610b9a61138a565b5f600182016113c2576113c261138a565b5060010190565b5f602082840312156113d9575f5ffd5b5051919050565b60208152816020820152818360408301375f818301604090810191909152601f909201601f19160101919050565b634e487b7160e01b5f52604160045260245ffdfea2646970667358221220c85b75d400db7e7bcfa4fd457f442b01f46526a9a76bc64c0f8e38bed4e5bcc364736f6c634300081e0033

Verified Source Code Partial Match

Compiler: v0.8.30+commit.73712a01 EVM: prague Optimization: Yes (200 runs)
Airdrop.sol 478 lines
//
//  ███████╗██╗  ██╗ █████╗     ██████╗ ██████╗  ██████╗ ████████╗ ██████╗  ██████╗ ██████╗ ██╗
//  ██╔════╝╚██╗██╔╝██╔══██╗    ██╔══██╗██╔══██╗██╔═══██╗╚══██╔══╝██╔═══██╗██╔════╝██╔═══██╗██║
//  █████╗   ╚███╔╝ ███████║    ██████╔╝██████╔╝██║   ██║   ██║   ██║   ██║██║     ██║   ██║██║
//  ██╔══╝   ██╔██╗ ██╔══██║    ██╔═══╝ ██╔══██╗██║   ██║   ██║   ██║   ██║██║     ██║   ██║██║
//  ███████╗██╔╝ ██╗██║  ██║    ██║     ██║  ██║╚██████╔╝   ██║   ╚██████╔╝╚██████╗╚██████╔╝███████╗
//  ╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝    ╚═╝     ╚═╝  ╚═╝ ╚═════╝    ╚═╝    ╚═════╝  ╚═════╝ ╚═════╝ ╚══════╝
//
// Project website: https://www.exaprotocol.com
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Begin OpenZeppelin Contracts
// To make this a single-file contract, the necessary OpenZeppelin contracts have been inlined.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 * This is a standard interface and is not expected to change.
 */
interface IERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

/**
 * @dev Provides information about the current execution context.
 * Useful for meta-transactions.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }
}

/**
 * @dev Contract module for basic access control.
 * The owner is set during construction and can transfer ownership.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );

    constructor(address initialOwner) {
        require(
            initialOwner != address(0),
            "Ownable: initial owner is the zero address"
        );
        _transferOwnership(initialOwner);
    }

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    function owner() public view virtual returns (address) {
        return _owner;
    }

    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(
            newOwner != address(0),
            "Ownable: new owner is the zero address"
        );
        _transferOwnership(newOwner);
    }

    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @dev Contract module that allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 */
abstract contract Pausable is Context {
    event Paused(address account);
    event Unpaused(address account);

    bool private _paused;

    constructor() {
        _paused = false;
    }

    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    modifier whenPaused() {
        _requirePaused();
        _;
    }

    function paused() public view virtual returns (bool) {
        return _paused;
    }

    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 */
abstract contract ReentrancyGuard {
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        _status = _NOT_ENTERED;
    }

    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// End OpenZeppelin Contracts
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

/**
 * @title Airdrop
 * @dev This contract facilitates airdropping a specific ERC20 token to a list of addresses.
 * The contract owner can set individual airdrop amounts for each recipient and trigger the airdrop.
 * Tokens are transferred immediately from this contract's balance.
 * The owner should ensure this contract has a sufficient token balance before starting the airdrop.
 *
 * Security features:
 * - Reentrancy protection
 * - Emergency pause mechanism
 * - Gas limit protection via batch size limits
 * - Comprehensive input validation
 * - Proper checks-effects-interactions pattern
 * - Maximum amount validation per recipient
 * - Allows multiple airdrops to same address
 */
contract Airdrop is Ownable, Pausable, ReentrancyGuard {
    // The ERC20 token to be airdropped.
    IERC20 public immutable token;

    // Maximum number of recipients per batch to prevent gas limit issues
    uint256 public constant MAX_BATCH_SIZE = 200;

    // Maximum airdrop amount per recipient to prevent misconfiguration
    // Token has 8 decimal places, so 100 tokens = 100 * 10^8
    uint256 public constant MAX_AIRDROP_AMOUNT = 100 * 10 ** 8; // 100 tokens with 8 decimals

    // Mapping to track total amounts received by each address
    mapping(address => uint256) public totalReceivedByAddress;

    // Total number of successful airdrops executed
    uint256 public totalAirdropsExecuted;

    // Total amount of tokens distributed
    uint256 public totalTokensDistributed;

    // Removed Airdropped event to rely on ERC20 Transfer logs for per-recipient records
    event BatchProcessed(uint256 recipientCount, uint256 totalAmount);
    event EmergencyPaused(address indexed by, string reason);
    event EmergencyUnpaused(address indexed by, string reason);

    /**
     * @dev The contract's constructor.
     * It initializes the contract with the ERC20 token address and sets the owner.
     * @param _tokenAddress The address of the ERC20 token contract (e.g., XAP token).
     */
    constructor(address _tokenAddress) Ownable(msg.sender) {
        require(_tokenAddress != address(0), "Zero token");
        token = IERC20(_tokenAddress);
    }

    /**
     * @dev Airdrops tokens to a list of recipients with individual amounts.
     * The contract must be funded with enough tokens to cover the airdrop.
     * Recipients can receive multiple airdrops.
     * @param _recipients An array of addresses to receive the airdrop.
     * @param _amounts An array of amounts corresponding to each recipient.
     */
    function airdropToWallets(
        address[] calldata _recipients,
        uint256[] calldata _amounts
    ) public onlyOwner whenNotPaused nonReentrant {
        uint256 len = _recipients.length;
        require(len > 0, "Empty recipients");
        require(len == _amounts.length, "Len mismatch");
        require(len <= MAX_BATCH_SIZE, "Too many");

        IERC20 _token = token;

        // Single pass: validate and transfer per recipient
        uint256 successfulTransfers = 0;
        uint256 totalTransferred = 0;

        for (uint256 i = 0; i < len; ) {
            address recipient = _recipients[i];
            uint256 amount = _amounts[i];

            require(recipient != address(0), "Zero addr");
            require(amount > 0, "Zero amt");
            require(amount <= MAX_AIRDROP_AMOUNT, "Exceeds max");

            bool success = _token.transfer(recipient, amount);
            require(success, "Transfer failed");

            totalReceivedByAddress[recipient] += amount;
            successfulTransfers++;
            totalTransferred += amount;
            totalAirdropsExecuted++;
            totalTokensDistributed += amount;

            unchecked {
                ++i;
            }
        }

        emit BatchProcessed(successfulTransfers, totalTransferred);
    }

    /**
     * @dev Allows the owner to withdraw any remaining ERC20 tokens from this contract.
     * This is a safety measure to recover funds.
     */
    function withdrawRemainingTokens() public onlyOwner whenNotPaused {
        IERC20 _token = token;
        uint256 remainingBalance = _token.balanceOf(address(this));
        if (remainingBalance > 0) {
            bool success = _token.transfer(owner(), remainingBalance);
            require(success, "Withdraw failed");
        }
    }

    /**
     * @dev Emergency function to pause the contract.
     * Can only be called by the owner.
     * @param reason The reason for pausing the contract.
     */
    function pause(string calldata reason) public onlyOwner {
        _pause();
        emit EmergencyPaused(msg.sender, reason);
    }

    /**
     * @dev Function to unpause the contract.
     * Can only be called by the owner.
     * @param reason The reason for unpausing the contract.
     */
    function unpause(string calldata reason) public onlyOwner {
        _unpause();
        emit EmergencyUnpaused(msg.sender, reason);
    }

    /**
     * @dev Returns the current contract balance of the airdrop token.
     * @return The current token balance of this contract.
     */
    function getContractTokenBalance() public view returns (uint256) {
        return token.balanceOf(address(this));
    }

    /**
     * @dev Returns the total amount of tokens received by a specific address.
     * @param _recipient The address to check.
     * @return The total amount of tokens received by the address.
     */
    function getTotalReceivedByAddress(
        address _recipient
    ) public view returns (uint256) {
        require(_recipient != address(0), "Zero addr");
        return totalReceivedByAddress[_recipient];
    }

    /**
     * @dev Checks if an address has received any airdrops (backward compatibility).
     * @param _recipient The address to check.
     * @return Whether the address has received any airdrops.
     */
    function hasAddressReceivedAirdrop(
        address _recipient
    ) public view returns (bool) {
        require(_recipient != address(0), "Zero addr");
        return totalReceivedByAddress[_recipient] > 0;
    }

    /**
     * @dev Calculates the total tokens required for a batch of recipients with their amounts.
     * Only accessible by owner to prevent information disclosure.
     * @param _recipients The array of recipient addresses.
     * @param _amounts The array of amounts for each recipient.
     * @return totalRequired The total amount of tokens needed.
     * @return validCount The number of valid recipients.
     */
    function calculateBatchRequirement(
        address[] calldata _recipients,
        uint256[] calldata _amounts
    )
        public
        view
        onlyOwner
        returns (uint256 totalRequired, uint256 validCount)
    {
        uint256 len = _recipients.length;
        require(len > 0, "Empty");
        require(len == _amounts.length, "Len mismatch");
        require(len <= MAX_BATCH_SIZE, "Too many");

        for (uint256 i = 0; i < len; ) {
            address recipient = _recipients[i];
            uint256 amount = _amounts[i];

            if (
                recipient != address(0) &&
                amount > 0 &&
                amount <= MAX_AIRDROP_AMOUNT
            ) {
                totalRequired += amount;
                validCount++;
            }

            unchecked {
                ++i;
            }
        }
    }

    /**
     * @dev Returns the maximum allowed airdrop amount per recipient.
     * @return The maximum airdrop amount constant.
     */
    function getMaxAirdropAmount() public pure returns (uint256) {
        return MAX_AIRDROP_AMOUNT;
    }

    /**
     * @dev Returns the maximum batch size for airdrops.
     * @return The maximum batch size constant.
     */
    function getMaxBatchSize() public pure returns (uint256) {
        return MAX_BATCH_SIZE;
    }

    /**
     * @dev Checks if the contract has sufficient balance for a specific total amount.
     * @param _totalAmount The total amount needed.
     * @return Whether the contract has sufficient balance.
     */
    function hasSufficientBalance(
        uint256 _totalAmount
    ) public view returns (bool) {
        if (_totalAmount == 0) {
            return false;
        }

        return token.balanceOf(address(this)) >= _totalAmount;
    }

    /**
     * @dev Validates that all amounts in an array are within allowed limits.
     * @param _amounts Array of amounts to validate.
     * @return Whether all amounts are valid.
     */
    function validateAmounts(
        uint256[] calldata _amounts
    ) public pure returns (bool) {
        uint256 len = _amounts.length;
        for (uint256 i = 0; i < len; ) {
            if (_amounts[i] == 0 || _amounts[i] > MAX_AIRDROP_AMOUNT) {
                return false;
            }
            unchecked {
                ++i;
            }
        }
        return true;
    }

    /**
     * @dev Returns comprehensive statistics about the airdrop contract.
     * @return contractBalance Current token balance of the contract.
     * @return totalDistributed Total tokens distributed so far.
     * @return totalAirdrops Total number of airdrops executed.
     */
    function getAirdropStatistics()
        public
        view
        returns (
            uint256 contractBalance,
            uint256 totalDistributed,
            uint256 totalAirdrops
        )
    {
        contractBalance = token.balanceOf(address(this));
        totalDistributed = totalTokensDistributed;
        totalAirdrops = totalAirdropsExecuted;
    }

    /**
     * @dev Returns a list of total amounts received by multiple addresses.
     * @param _addresses Array of addresses to check.
     * @return amounts Array of total amounts received by each address.
     */
    function getBatchReceivedAmounts(
        address[] calldata _addresses
    ) public view returns (uint256[] memory amounts) {
        uint256 len = _addresses.length;
        amounts = new uint256[](len);
        for (uint256 i = 0; i < len; ) {
            amounts[i] = totalReceivedByAddress[_addresses[i]];
            unchecked {
                ++i;
            }
        }
    }
}

Read Contract

MAX_AIRDROP_AMOUNT 0xa99dc389 → uint256
MAX_BATCH_SIZE 0xcfdbf254 → uint256
calculateBatchRequirement 0xb0fb4824 → uint256, uint256
getAirdropStatistics 0x3cd33e9a → uint256, uint256, uint256
getBatchReceivedAmounts 0xbb036b96 → uint256[]
getContractTokenBalance 0x317d9453 → uint256
getMaxAirdropAmount 0xfff8cbd4 → uint256
getMaxBatchSize 0xe7c00f6e → uint256
getTotalReceivedByAddress 0xe76159ad → uint256
hasAddressReceivedAirdrop 0x8d1dcca6 → bool
hasSufficientBalance 0x83e554a2 → bool
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
token 0xfc0c546a → address
totalAirdropsExecuted 0x83d89228 → uint256
totalReceivedByAddress 0xa5af246c → uint256
totalTokensDistributed 0xd8f163ab → uint256
validateAmounts 0xa6896963 → bool

Write Contract 6 functions

These functions modify contract state and require a wallet transaction to execute.

airdropToWallets 0x2307b441
address[] _recipients
uint256[] _amounts
pause 0x6da66355
string reason
renounceOwnership 0x715018a6
No parameters
transferOwnership 0xf2fde38b
address newOwner
unpause 0xe79faa58
string reason
withdrawRemainingTokens 0x8afbf669
No parameters

Recent Transactions

No transactions found for this address