APE Price: $1.27 (+6.80%)

Contract Diff Checker

Contract Name:
HACoin

Contract Source Code:

File 1 of 1 : HACoin

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// ============ OpenZeppelin ERC20 ============
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

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);
}

abstract contract ERC20 is Context, IERC20 {
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;

    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    function name() public view virtual returns (string memory) {
        return _name;
    }

    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");
        _beforeTokenTransfer(from, to, amount);
        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            _balances[to] += amount;
        }
        emit Transfer(from, to, amount);
        _afterTokenTransfer(from, to, amount);
    }

    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");
        _beforeTokenTransfer(address(0), account, amount);
        _totalSupply += amount;
        unchecked {
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);
        _afterTokenTransfer(address(0), account, amount);
    }

    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");
        _beforeTokenTransfer(account, address(0), amount);
        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            _totalSupply -= amount;
        }
        emit Transfer(account, address(0), amount);
        _afterTokenTransfer(account, address(0), amount);
    }

    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}

// ============ OpenZeppelin Ownable ============
abstract contract Ownable is Context {
    address private _owner;

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

    constructor() {
        _transferOwnership(_msgSender());
    }

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

    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the 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);
    }
}

// ============ OpenZeppelin Pausable ============
abstract contract Pausable is Context {
    bool private _paused;

    event Paused(address account);
    event Unpaused(address account);

    constructor() {
        _paused = false;
    }

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

    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    modifier whenPaused() {
        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());
    }
}

// ============ Your Original Interfaces ============
interface IOldToken {
    function balanceOf(address account) external view returns (uint256);
    function totalSupply() external view returns (uint256);
}

// ============ Your Original Structs ============
struct TaxHoliday {
    uint256 startTime;    
    uint256 endTime;      
    uint256 temporaryTaxRate;  
}

// ============ Your Original Contract ============
contract HACoin is ERC20, Ownable, Pausable {
    // ============ Events ============
    event MaxTransferAmountUpdated(uint256 newAmount);
    event MaxWalletBalanceUpdated(uint256 newAmount);
    event TaxRateUpdated(uint256 newRate);
    event BurnRateUpdated(uint256 newRate);
    event TaxHolidaySet(uint256 start, uint256 end, uint256 rate);
    event AntiBottingStatusUpdated(bool enabled);
    event ExemptionStatusUpdated(address indexed account, bool status);
    event TradingStatusUpdated(bool enabled);
    event TeamWalletUpdated(address newWallet);
    event BlacklistStatusUpdated(address indexed account, bool status);
    event AntiBottingDurationUpdated(uint256 newDuration);
    event TaxHolidayCleared();

    // ============ Constants ============
    uint256 public constant MAX_ANTI_BOTTING_DURATION = 24 hours;

    // ============ Trading Control Variables ============
    bool public tradingEnabled;
    bool public antiBottingEnabled;
    uint256 public antiBottingDuration;
    uint256 public tradingEnabledAt;
    mapping(address => bool) public blacklisted;
    mapping(address => bool) public isExemptFromLimits;

    // ============ Token Configuration ============
    address public teamWallet;
    uint256 public taxRate;    // Tax rate in basis points (e.g., 100 = 1%)
    uint256 public burnRate;   // Burn rate in basis points (e.g., 100 = 1%)
    uint256 public maxTransferAmount;
    uint256 public maxWalletBalance;
    TaxHoliday public currentHoliday;

    // ============ Snapshot Variables ============
    mapping(address => uint256) public oldTokenBalances;
    address[] public holdersSnapshot;

    // ============ Constructor ============
    constructor(
        string memory name,
        string memory symbol,
        uint256 initialSupply,
        address _teamWallet,
        uint256 _taxRate,
        uint256 _burnRate
    ) ERC20(name, symbol) {
        _mint(msg.sender, initialSupply);
        teamWallet = _teamWallet;
        taxRate = _taxRate;
        burnRate = _burnRate;
        
        // Set initial limits
        maxTransferAmount = initialSupply * 1 / 100; // 1% of total supply
        maxWalletBalance = initialSupply * 2 / 100;  // 2% of total supply
        
        antiBottingDuration = 5 minutes;
        tradingEnabled = false;
        antiBottingEnabled = true;
    }

    // ============ Core Transfer Logic ============
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual override(ERC20) {
        require(!paused(), "Token transfers are paused");
        require(!blacklisted[from] && !blacklisted[to], "Address is blacklisted");
        
        // Skip checks for minting, burning, and exempt addresses
        if (from != address(0) && to != address(0) && 
            !isExemptFromLimits[from] && !isExemptFromLimits[to]) {
            
            // If trading is not enabled, simply block
            if (!tradingEnabled) {
                revert("Trading not enabled");
            }
            
            // Anti-botting checks (modified to not use whitelist)
            if (antiBottingEnabled && tradingEnabled && 
                block.timestamp < tradingEnabledAt + antiBottingDuration) {
                require(amount <= maxTransferAmount / 2, "Anti-bot: Amount too high");
            }
            
            require(amount <= maxTransferAmount, "Transfer amount exceeds limit");

            // Skip check for exempt addresses and exclude burning
            if (to != address(0) && !isExemptFromLimits[to]) { 
                require(balanceOf(to) + amount <= maxWalletBalance, "Balance exceeds wallet limit");
            }
        }
        
        super._beforeTokenTransfer(from, to, amount);
    }

    function _transfer(
        address sender,
        address recipient,
        uint256 amount
    ) internal override {
        uint256 currentTax = getCurrentTaxRate();
        require(currentTax + burnRate <= 10000, "Combined rates exceed 100%");
        
        uint256 taxAmount = (amount * currentTax) / 10000;
        uint256 burnAmount = (amount * burnRate) / 10000;
        uint256 amountAfterTaxBurn = amount - taxAmount - burnAmount;

        // Send the tax amount in HACoin tokens to team wallet
        if (taxAmount > 0) {
            super._transfer(sender, teamWallet, taxAmount);
        }

        // Burn the tokens
        if (burnAmount > 0) {
            _burn(sender, burnAmount);
        }

        // Transfer the remaining tokens
        super._transfer(sender, recipient, amountAfterTaxBurn);
    }

    // ============ View Functions ============
    function getCurrentTaxRate() public view returns (uint256) {
        if (block.timestamp >= currentHoliday.startTime && 
            block.timestamp <= currentHoliday.endTime) {
            return currentHoliday.temporaryTaxRate;
        }
        return taxRate;
    }

    function getAllSnapshotHolders() external view returns (address[] memory) {
        return holdersSnapshot;
    }

    function getSnapshotHoldersCount() external view returns (uint256) {
        return holdersSnapshot.length;
    }

    // ============ Admin Functions ============
    // Pause/Unpause
    function pause() external onlyOwner {
        _pause();
    }

    function unpause() external onlyOwner {
        _unpause();
    }

    // Trading Control
    function enableTrading() external onlyOwner {
        require(!tradingEnabled, "Trading already enabled");
        tradingEnabled = true;
        tradingEnabledAt = block.timestamp;
    }

    function setTradingEnabled(bool _enabled) external onlyOwner {
        tradingEnabled = _enabled;
        emit TradingStatusUpdated(_enabled);
    }

    // Anti-botting Control
    function setAntiBottingEnabled(bool enabled) external onlyOwner {
        antiBottingEnabled = enabled;
        emit AntiBottingStatusUpdated(enabled);
    }

    function setAntiBottingDuration(uint256 duration) external onlyOwner {
        require(duration <= MAX_ANTI_BOTTING_DURATION, "Duration exceeds maximum limit");
        antiBottingDuration = duration;
        emit AntiBottingDurationUpdated(duration);
    }

    // Limits Management
    function setMaxTransferAmount(uint256 amount) external onlyOwner {
        maxTransferAmount = amount;
        emit MaxTransferAmountUpdated(amount);
    }

    function setMaxWalletBalance(uint256 amount) external onlyOwner {
        maxWalletBalance = amount;
        emit MaxWalletBalanceUpdated(amount);
    }

    // Tax and Burn Rate Management
    function setTaxRate(uint256 newTaxRate) external onlyOwner {
        require(newTaxRate <= 10000, "Tax rate cannot exceed 100%");
        taxRate = newTaxRate;
        emit TaxRateUpdated(newTaxRate);
    }

    function setBurnRate(uint256 newBurnRate) external onlyOwner {
        require(newBurnRate <= 10000, "Burn rate cannot exceed 100%");
        burnRate = newBurnRate;
        emit BurnRateUpdated(newBurnRate);
    }

    // Tax Holiday Management
    function setTaxHoliday(uint256 start, uint256 end, uint256 tempRate) external onlyOwner {
        require(end > start, "Invalid time period");
        require(tempRate <= 10000, "Tax rate cannot exceed 100%");
        currentHoliday = TaxHoliday(start, end, tempRate);
        emit TaxHolidaySet(start, end, tempRate);
    }

    function clearTaxHoliday() external onlyOwner {
        delete currentHoliday;
        emit TaxHolidayCleared();
    }

    // Wallet Management
    function setTeamWallet(address newTeamWallet) external onlyOwner {
        require(newTeamWallet != address(0), "Invalid team wallet");
        teamWallet = newTeamWallet;
        emit TeamWalletUpdated(newTeamWallet);
    }

    // Access Control Management
    function setExemptFromLimits(address account, bool exempt) external onlyOwner {
        isExemptFromLimits[account] = exempt;
        emit ExemptionStatusUpdated(account, exempt);
    }

    function setupExemptions(address[] calldata accounts) external onlyOwner {
        for(uint256 i = 0; i < accounts.length; i++) {
            isExemptFromLimits[accounts[i]] = true;
            emit ExemptionStatusUpdated(accounts[i], true);
        }
    }

    function setBlacklist(address account, bool status) external onlyOwner {
        blacklisted[account] = status;
        emit BlacklistStatusUpdated(account, status);
    }

    function batchSetBlacklist(address[] calldata accounts, bool status) external onlyOwner {
        for(uint256 i = 0; i < accounts.length; i++) {
            blacklisted[accounts[i]] = status;
            emit BlacklistStatusUpdated(accounts[i], status);
        }
    }

    // ============ Snapshot and Airdrop Functions ============
    function storeHoldersSnapshot(address[] calldata holders) external onlyOwner {
        delete holdersSnapshot; // Clear previous snapshot to avoid duplicates
        for (uint256 i = 0; i < holders.length; i++) {
            holdersSnapshot.push(holders[i]);
        }
    }

    function snapshotOldTokenBalances(address oldTokenAddress) external onlyOwner {
        IOldToken oldToken = IOldToken(oldTokenAddress);
        for (uint256 i = 0; i < holdersSnapshot.length; i++) {
            address holder = holdersSnapshot[i];
            uint256 balance = oldToken.balanceOf(holder);
            if (balance > 0) {
                oldTokenBalances[holder] = balance;
            }
        }
    }

    function executeAirdrop() external onlyOwner {
        for (uint256 i = 0; i < holdersSnapshot.length; i++) {
            address holder = holdersSnapshot[i];
            uint256 balance = oldTokenBalances[holder];
            if (balance > 0) {
                _mint(holder, balance);
                oldTokenBalances[holder] = 0; // Clear balance to prevent double airdrop
            }
        }
    }

    // ============ Recovery Functions ============
    function recoverToken(address tokenAddress, uint256 amount) external onlyOwner {
        require(tokenAddress != address(this), "Cannot recover native token");
        IERC20(tokenAddress).transfer(owner(), amount);
    }

    function sendRewardsToStaking(address stakingContract, uint256 amount) external onlyOwner {
        // First, ensure the staking contract is exempt from limits
        if (!isExemptFromLimits[stakingContract]) {
            isExemptFromLimits[stakingContract] = true;
            emit ExemptionStatusUpdated(stakingContract, true);
        }
        // Transfer HACoins to staking contract
        transfer(stakingContract, amount);
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):