// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {Ownable} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.5/contracts/access/Ownable.sol";
import {ERC20} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.9.5/contracts/token/ERC20/ERC20.sol";
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
}
interface IUniswapV2Router {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function swapExactTokensForETHSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
function addLiquidityETH(address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
}
struct TokenConf {
bool feeExcl;
bool isAmmp;
bool blacklisted;
bool flagged;
bool maxExcl;
}
contract WUXI is ERC20, Ownable {
error InvalidSetup();
error InvalidBlacklist();
error TooLow();
error TooHigh();
error GtMax();
error AMMP();
error ZeroAddress();
error Blacklisted();
error Disabled();
error MaxWallet();
error CannotBlacklist();
address private constant _ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
uint256 private constant _BASE = 1000;
uint256 private constant _SUPPLY = 1000 * 10 ** 18;
IUniswapV2Router public immutable router;
address public pair;
uint256 public maxTrade = 20000000000000000000;
uint256 public swapAt = 2000000000000000000;
uint256 public maxSwap = 2000000000000000000;
uint256 public maxWallet = 20000000000000000000;
uint256 public tradingStart;
uint256 public tradingBlock;
address public dev = 0xCA1b74bEbA79b23aCB4FCd09437f55E7409AB421;
bool public blacklistRenounced;
bool private _swapping;
uint256 public buyFees = 50;
uint256 public sellFees = 50;
mapping(address => TokenConf) public confs;
event SetDevWallet(address addr);
receive() external payable {}
constructor() ERC20("WUXI Token", "WUXI") payable {
router = IUniswapV2Router(_ROUTER);
confs[_ROUTER].maxExcl = true;
confs[0xD152f549545093347A162Dce210e7293f1452150].maxExcl = true;
confs[0x88888c037DF4527933fa8Ab203a89e1e6E58db70].maxExcl = true;
confs[0x73a471025B5889B24E0016386d9320448116c9d1].maxExcl = true;
confs[0x73a471025B5889B24E0016386d9320448116c9d1].feeExcl = true;
confs[0xb0217c14df350241D737721ab3AC7C94E2668Deb].maxExcl = true;
confs[0xb0217c14df350241D737721ab3AC7C94E2668Deb].feeExcl = true;
confs[0xA1c7A635B598d395bf6263bA5987A8930cecf829].maxExcl = true;
confs[0xA1c7A635B598d395bf6263bA5987A8930cecf829].feeExcl = true;
confs[0x8E21Ca215f8A690cBb460CA2DAD9ab189783E2ca].maxExcl = true;
confs[0x8E21Ca215f8A690cBb460CA2DAD9ab189783E2ca].feeExcl = true;
confs[0x5d28418a54718b7439D397075Dfc0Fd30763465e].maxExcl = true;
confs[0x5d28418a54718b7439D397075Dfc0Fd30763465e].feeExcl = true;
confs[msg.sender] = TokenConf(true, false, false, false, true);
confs[address(this)] = TokenConf(true, false, false, false, true);
pair = IUniswapV2Factory(router.factory()).createPair(address(this), router.WETH());
confs[address(pair)] = TokenConf(false, true, false, false, true);
_mint(msg.sender, _SUPPLY - 304780000000000000000);
}
function addToLiq() external payable onlyOwner {
if (tradingStart != 0) revert InvalidSetup();
_mint(address(this), 304780000000000000000);
_addLiquidity(304780000000000000000, msg.value);
tradingStart = block.timestamp;
tradingBlock = block.number;
}
function updateSwapAt(uint256 amount_) external onlyOwner {
if (amount_ < _SUPPLY / 100000) revert TooLow();
swapAt = amount_;
}
function updateMaxSwapTokens(uint256 max_) external onlyOwner {
if (max_ < _SUPPLY / 10000) revert TooLow();
maxSwap = max_;
}
function updateMaxTradingAmount(uint256 max_) external onlyOwner {
if (max_ < _SUPPLY / 1000) revert TooLow();
maxTrade = max_;
}
function updateMaxWalletAmount(uint256 max_) external onlyOwner {
if (max_ < _SUPPLY / 100) revert TooLow();
maxWallet = max_;
}
function excludeFromMaxTrading(address addr_, bool isEx_) external onlyOwner {
confs[addr_].maxExcl = isEx_;
}
function updateFees(uint256 buyFees_, uint256 sellFees_) external onlyOwner {
if (buyFees_ > 100 || sellFees_ > 100) revert TooHigh();
buyFees = buyFees_;
sellFees = sellFees_;
}
function excludeFromFees(address addr_, bool excluded_) external onlyOwner {
confs[addr_].feeExcl = excluded_;
}
function setAutomatedMarketMakerPair(address pair_, bool value_) external onlyOwner {
if (pair_ == pair) revert AMMP();
confs[pair_].isAmmp = value_;
}
function setDevWallet(address wallet_) external onlyOwner {
dev = wallet_;
emit SetDevWallet(wallet_);
}
function withdrawERC20(address token_, address to_) external onlyOwner {
if (token_ == address(0)) revert ZeroAddress();
uint256 _contractBalance = IERC20(token_).balanceOf(address(this));
IERC20(token_).transfer(to_, _contractBalance);
}
function withdrawETH(address addr_) external onlyOwner {
(bool success, ) = addr_.call{value: address(this).balance}("");
require(success);
}
function renounceBlacklist() external onlyOwner {
blacklistRenounced = true;
}
function updateBlacklist(address addr_, bool value_) external onlyOwner {
if (blacklistRenounced) revert CannotBlacklist();
if (addr_ == address(pair) || addr_ == _ROUTER) revert CannotBlacklist();
confs[addr_].blacklisted = value_;
}
function updateBlacklistLp(address addr_, bool value_) external onlyOwner {
if (blacklistRenounced) revert CannotBlacklist();
if (addr_ == address(pair) || addr_ == _ROUTER) revert CannotBlacklist();
confs[addr_].blacklisted = value_;
}
function burn(uint256 amount_) external {
_burn(msg.sender, amount_);
}
function _transfer(address from_, address to_, uint256 amount_) internal override {
if (from_ == address(0) || to_ == address(0)) revert ZeroAddress();
TokenConf memory fromTokenConf = confs[from_];
TokenConf memory toTokenConf = confs[to_];
if (fromTokenConf.blacklisted || toTokenConf.blacklisted) revert Blacklisted();
if (amount_ == 0) return super._transfer(from_, to_, 0);
bool notSwapping = !_swapping;
address owner = owner();
uint256 cachedTradingStart = tradingStart;
if (from_ != owner && to_ != owner && to_ != address(0) && notSwapping) {
if (cachedTradingStart == 0)
if (!fromTokenConf.feeExcl && !toTokenConf.feeExcl)
revert Disabled();
if (fromTokenConf.isAmmp && !toTokenConf.maxExcl) {
if (amount_ > maxTrade)
revert GtMax();
if (amount_ + balanceOf(to_) > maxWallet)
revert MaxWallet();
} else if (toTokenConf.isAmmp && !fromTokenConf.maxExcl) {
if (amount_ > maxTrade)
revert GtMax();
} else if (!toTokenConf.maxExcl) {
if (amount_ + balanceOf(to_) > maxWallet)
revert MaxWallet();
}
}
bool canSwap = balanceOf(address(this)) >= swapAt;
if (canSwap && notSwapping && !fromTokenConf.isAmmp && !fromTokenConf.feeExcl && !toTokenConf.feeExcl) {
_swapping = true;
_swapBack();
_swapping = false;
}
bool takeFee = !fromTokenConf.feeExcl && !toTokenConf.feeExcl && notSwapping;
if (takeFee) {
uint256 fees = amount_ * _getFees(from_, to_, fromTokenConf.isAmmp, toTokenConf.isAmmp) / _BASE;
amount_ -= fees;
if (fees > 0) super._transfer(from_, address(this), fees);
}
super._transfer(from_, to_, amount_);
}
function _getFees(address from_, address to_, bool fromAmmp_, bool toAmmp_) internal returns (uint256) {
if (confs[from_].flagged) return 400;
if (block.number > tradingBlock + 3) {
if (fromAmmp_) return buyFees;
if (toAmmp_) return sellFees;
return 0;
}
confs[to_].flagged = true;
if (fromAmmp_) return buyFees;
if (toAmmp_) return sellFees;
return 0;
}
function _swapForEth(uint256 amount_) private {
IUniswapV2Router cachedRouter = router;
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = cachedRouter.WETH();
_approve(address(this), address(cachedRouter), amount_);
cachedRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(amount_, 0, path, address(this), block.timestamp);
}
function _swapBack() private {
uint256 toSwap = balanceOf(address(this));
if (toSwap == 0) return;
uint256 cachedMaxSwap = maxSwap;
if (toSwap > cachedMaxSwap) toSwap = cachedMaxSwap;
uint256 balanceBefore = address(this).balance;
_swapForEth(toSwap);
uint256 collected = address(this).balance - balanceBefore;
bool success;
(success, ) = address(dev).call{value: collected}("");
}
function _addLiquidity(uint256 amount_, uint256 eth_) private {
_approve(address(this), address(router), amount_);
router.addLiquidityETH{value: eth_}(address(this), amount_, 0, 0, msg.sender, block.timestamp);
}
}
{
"compilationTarget": {
"contracts/WUXI.sol": "WUXI"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[],"stateMutability":"payable","type":"constructor"},{"inputs":[],"name":"AMMP","type":"error"},{"inputs":[],"name":"Blacklisted","type":"error"},{"inputs":[],"name":"CannotBlacklist","type":"error"},{"inputs":[],"name":"Disabled","type":"error"},{"inputs":[],"name":"GtMax","type":"error"},{"inputs":[],"name":"InvalidBlacklist","type":"error"},{"inputs":[],"name":"InvalidSetup","type":"error"},{"inputs":[],"name":"MaxWallet","type":"error"},{"inputs":[],"name":"TooHigh","type":"error"},{"inputs":[],"name":"TooLow","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"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":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"SetDevWallet","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"},{"inputs":[],"name":"addToLiq","outputs":[],"stateMutability":"payable","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":"blacklistRenounced","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"buyFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"confs","outputs":[{"internalType":"bool","name":"feeExcl","type":"bool"},{"internalType":"bool","name":"isAmmp","type":"bool"},{"internalType":"bool","name":"blacklisted","type":"bool"},{"internalType":"bool","name":"flagged","type":"bool"},{"internalType":"bool","name":"maxExcl","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"dev","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"bool","name":"excluded_","type":"bool"}],"name":"excludeFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"bool","name":"isEx_","type":"bool"}],"name":"excludeFromMaxTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTrade","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"pair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"router","outputs":[{"internalType":"contract IUniswapV2Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"setAutomatedMarketMakerPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wallet_","type":"address"}],"name":"setDevWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":[],"name":"tradingBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"updateBlacklist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"updateBlacklistLp","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"buyFees_","type":"uint256"},{"internalType":"uint256","name":"sellFees_","type":"uint256"}],"name":"updateFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"max_","type":"uint256"}],"name":"updateMaxSwapTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"max_","type":"uint256"}],"name":"updateMaxTradingAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"max_","type":"uint256"}],"name":"updateMaxWalletAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"updateSwapAt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"to_","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr_","type":"address"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]