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