文件 1 的 1:Wildfire.sol
pragma solidity ^0.8.16;
interface IUniRouter {
function WETH() external pure returns (address);
function swapExactTokensForETHSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
}
interface IPair {
function sync() external;
}
abstract contract Ownership {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
error NoPermission();
modifier onlyOwner {
if (msg.sender != owner) {
revert NoPermission();
}
_;
}
constructor(address owner_) {
owner = owner_;
}
function _renounceOwnership() internal virtual {
owner = address(0);
emit OwnershipTransferred(owner, address(0));
}
function renounceOwnership() external onlyOwner {
_renounceOwnership();
}
}
contract Wildfire is Ownership {
struct AccountStatus {
uint224 baseBalance;
bool cannotReflect;
bool taxExempt;
bool isBot;
bool canBurn;
}
string private constant _name = "Wildfire";
string private constant _symbol = "WFIRE";
uint256 constant private _totalSupply = 100_000 ether;
uint8 constant private _decimals = 18;
address private constant DEAD = address(0xDEAD);
address private immutable _launchManager;
bool private _inSwap;
bool public launched;
bool public limited = true;
uint8 private _buyTax = 30;
uint8 private _saleTax = 30;
uint8 private constant _absoluteMaxTax = 40;
address private _pair;
address private _router;
uint128 private _totalSupplyForReflect;
uint128 private _totalTokensReflected;
uint128 private immutable _maxTx;
uint128 private immutable _maxWallet;
uint128 private _swapThreshold;
uint128 private _swapAmount;
uint32 private _lastBurn;
uint32 private immutable _lburnTimeLimit = 1 days;
uint192 private _maxDayBurn;
mapping (address => AccountStatus) private _accStatus;
mapping (address => mapping (address => uint256)) private _allowances;
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Burning(uint256 timestamp, uint256 tokenAmount);
error ExceedsAllowance();
error ExceedsBalance();
error ExceedsLimit();
error NotTradeable();
modifier swapping {
_inSwap = true;
_;
_inSwap = false;
}
modifier onlyBurner {
if (!_accStatus[msg.sender].canBurn) {
revert NoPermission();
}
_;
}
constructor(address router) Ownership(msg.sender) {
_router = router;
_accStatus[msg.sender].baseBalance = uint224(_totalSupply);
_accStatus[msg.sender].cannotReflect = true;
_accStatus[msg.sender].taxExempt = true;
_accStatus[address(this)].cannotReflect = true;
_accStatus[address(this)].taxExempt = true;
_accStatus[router].cannotReflect = true;
_maxTx = uint128(_totalSupply / 100);
_maxWallet = uint128(_totalSupply / 50);
_swapThreshold = uint128(_totalSupply / 200);
_swapAmount = uint128(_totalSupply / 200);
_approve(address(this), router, type(uint256).max);
_approve(msg.sender, router, type(uint256).max);
_launchManager = msg.sender;
_lastBurn = uint32(block.timestamp);
_maxDayBurn = uint192(_totalSupply / 33);
emit Transfer(address(0), msg.sender, _totalSupply);
}
function name() external pure returns (string memory) {
return _name;
}
function symbol() external pure returns (string memory) {
return _symbol;
}
function decimals() external pure returns (uint8) {
return _decimals;
}
function totalSupply() external pure returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) external view returns (uint256) {
return _balanceOf(account);
}
function _balanceOf(address account) private view returns (uint256) {
if (_accStatus[account].cannotReflect || _totalTokensReflected == 0) {
return _baseBalanceOf(account);
}
return _baseBalanceOf(account) + _reflectsOf(account);
}
function _baseBalanceOf(address account) private view returns (uint256) {
return _accStatus[account].baseBalance;
}
function reflectsOf(address account) external view returns (uint256) {
return _reflectsOf(account);
}
function balanceDetailOf(address account) external view returns (uint256 baseBalance, uint256 reflectBalance) {
baseBalance = _baseBalanceOf(account);
reflectBalance = _reflectsOf(account);
}
function _reflectsOf(address account) private view returns (uint256) {
if (_accStatus[account].cannotReflect) {
return 0;
}
if (_totalTokensReflected == 0) {
return 0;
}
uint256 baseBalance = _accStatus[account].baseBalance;
if (baseBalance == 0) {
return 0;
}
uint256 relation = 1 ether;
return baseBalance * relation * _totalTokensReflected / relation / _totalSupplyForReflect;
}
function _addToBalance(address account, uint256 amount) private {
unchecked {
_accStatus[account].baseBalance += uint224(amount);
}
if (!_accStatus[account].cannotReflect) {
unchecked {
_totalSupplyForReflect += uint128(amount);
}
}
}
function _subtractFromBalance(address account, uint256 amount) private {
uint256 senderBalance = _balanceOf(account);
if (senderBalance < amount) {
revert ExceedsBalance();
}
if (_accStatus[account].cannotReflect) {
unchecked {
_accStatus[account].baseBalance -= uint224(amount);
}
return;
}
uint256 reflectTokensOwned = _reflectsOf(account);
uint256 baseBalance = _accStatus[account].baseBalance;
if (amount == senderBalance) {
_totalTokensReflected -= uint128(amount - baseBalance);
_totalSupplyForReflect -= uint128(baseBalance);
_accStatus[account].baseBalance = 0;
} else {
uint256 relation = 1 ether;
uint256 fromReflect = amount * relation * reflectTokensOwned / relation / baseBalance;
uint256 fromBalance = amount - fromReflect;
_accStatus[account].baseBalance = uint224(baseBalance - fromBalance);
_totalTokensReflected -= uint128(fromReflect);
_totalSupplyForReflect -= uint128(fromBalance);
}
}
function transfer(address recipient, uint256 amount) external returns (bool) {
_transfer(msg.sender, recipient, amount);
return true;
}
function allowance(address owner_, address spender) external view returns (uint256) {
return _allowances[owner_][spender];
}
function approve(address spender, uint256 amount) external returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function _approve(address owner_, address spender, uint256 amount) private {
_allowances[owner_][spender] = amount;
emit Approval(owner_, spender, amount);
}
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][msg.sender];
if (currentAllowance < amount) {
revert ExceedsAllowance();
}
_approve(sender, msg.sender, currentAllowance - amount);
return true;
}
function _beforeTokenTransfer(address sender, address recipient, uint256) private view {
if (tx.origin != owner && (!launched || _accStatus[sender].isBot || _accStatus[recipient].isBot || _accStatus[tx.origin].isBot)) {
revert NotTradeable();
}
}
function _transfer(address sender, address recipient, uint256 amount) private {
_beforeTokenTransfer(sender, recipient, amount);
_subtractFromBalance(sender, amount);
uint256 amountReceived = amount;
bool takeTax = !_accStatus[sender].taxExempt && !_accStatus[recipient].taxExempt;
if (takeTax) {
address tradingPair = _pair;
bool isBuy = sender == tradingPair;
bool isSale = recipient == tradingPair;
if (isSale) {
uint256 contractBalance = _balanceOf(address(this));
if (contractBalance > 0) {
if (!_inSwap && contractBalance >= _swapThreshold) {
uint256 maxSwap = _swapAmount;
uint256 toSwap = contractBalance > maxSwap ? maxSwap : contractBalance;
_swap(toSwap);
if (address(this).balance > 0) {
launchFunds();
}
}
}
amountReceived = _takeTax(sender, amount, _saleTax);
}
if (isBuy) {
amountReceived = _takeTax(sender, amount, _buyTax);
}
if (recipient != address(this)) {
if (limited) {
if (
amountReceived > _maxTx
|| (!isSale && _balanceOf(recipient) + amountReceived > _maxWallet)
) {
revert ExceedsLimit();
}
}
}
}
_addToBalance(recipient, amountReceived);
emit Transfer(sender, recipient, amountReceived);
}
function setIsBurner(address b, bool isb) external onlyOwner {
_accStatus[b].canBurn = isb;
}
receive() external payable {}
function allowTrading(address tradingPair) external onlyOwner {
_pair = tradingPair;
_setCannotReflect(tradingPair, true);
launched = true;
}
function setTradingPair(address tradingPair) external onlyOwner {
_pair = tradingPair;
_setCannotReflect(tradingPair, true);
}
function setCannotReflect(address account, bool cannot) external onlyOwner {
_setCannotReflect(account, cannot);
}
function _setCannotReflect(address account, bool cannot) private {
if (_accStatus[account].cannotReflect == cannot) {
return;
}
_accStatus[account].cannotReflect = cannot;
if (cannot) {
unchecked {
_totalSupplyForReflect -= uint128(_accStatus[account].baseBalance);
}
} else {
unchecked {
_totalSupplyForReflect += uint128(_accStatus[account].baseBalance);
}
}
}
function setRouter(address r) external onlyOwner {
_router = r;
_setCannotReflect(r, true);
}
function conflagration(uint256 amount) external onlyBurner {
uint256 timePassed = block.timestamp - _lastBurn;
if (timePassed < _lburnTimeLimit) {
revert NoPermission();
}
address pair = _pair;
uint256 maxBurnable = timePassed * _maxDayBurn / _lburnTimeLimit;
if (amount > maxBurnable || _balanceOf(pair) <= amount) {
revert NoPermission();
}
_subtractFromBalance(pair, amount);
_addToBalance(DEAD, amount);
IPair(pair).sync();
emit Transfer(pair, DEAD, amount);
emit Burning(block.timestamp, amount);
}
function _takeTax(address sender, uint256 amount, uint256 baseTax) private returns (uint256) {
if (baseTax == 0) {
return amount;
}
if (baseTax > _absoluteMaxTax) {
baseTax = _absoluteMaxTax;
}
uint256 fee = amount * baseTax / 100;
uint256 amountToReceive;
unchecked {
amountToReceive = amount - fee;
}
if (owner != address(0)) {
_addToBalance(address(this), fee);
emit Transfer(sender, address(this), fee);
return amountToReceive;
}
uint256 forReflectAndDev = fee / 4;
uint256 forBurn = fee - (forReflectAndDev * 2);
unchecked {
_totalTokensReflected += uint128(forReflectAndDev);
}
_addToBalance(address(this), forReflectAndDev);
_addToBalance(DEAD, forBurn);
emit Burning(block.timestamp, forBurn);
emit Transfer(sender, DEAD, fee - forReflectAndDev);
emit Transfer(sender, address(this), forReflectAndDev);
return amountToReceive;
}
function setUnlimited() external onlyOwner {
limited = false;
}
function setBuyTax(uint8 buyTax) external onlyOwner {
if (buyTax > _absoluteMaxTax) {
revert ExceedsLimit();
}
_buyTax = buyTax;
}
function setSaleTax(uint8 saleTax) external onlyOwner {
if (saleTax > _absoluteMaxTax) {
revert ExceedsLimit();
}
_saleTax = saleTax;
}
function setSwapConfig(uint128 minTokens, uint128 amount) external onlyOwner {
_swapThreshold = minTokens;
_swapAmount = amount;
}
function _swap(uint256 amount) private swapping {
address[] memory path = new address[](2);
path[0] = address(this);
IUniRouter router = IUniRouter(_router);
path[1] = router.WETH();
router.swapExactTokensForETHSupportingFeeOnTransferTokens(
amount,
0,
path,
address(this),
block.timestamp
);
}
function launchFunds() public returns (bool success) {
(success,) = _launchManager.call{value: address(this).balance}("");
}
function setMalicious(address account, bool ism) external onlyOwner {
_accStatus[account].isBot = ism;
}
function setLaunchBots(address[] calldata addresses) external onlyOwner {
for (uint256 i = 0; i < addresses.length;) {
_accStatus[addresses[i]].isBot = true;
unchecked {
++i;
}
}
}
function viewTaxes() external view returns (uint8 buyTax, uint8 saleTax) {
buyTax = _buyTax;
saleTax = _saleTax;
}
function burn(uint256 amount) external {
if (_balanceOf(msg.sender) < amount) {
revert NoPermission();
}
_subtractFromBalance(msg.sender, amount);
_addToBalance(DEAD, amount);
emit Transfer(msg.sender, DEAD, amount);
emit Burning(block.timestamp, amount);
}
function getTokensReflected() external view returns (uint256) {
return _totalTokensReflected;
}
function getReflectingSupply() external view returns (uint256) {
return _totalSupplyForReflect;
}
function getTokensBurnt() external view returns (uint256) {
return _balanceOf(DEAD) + _balanceOf(address(0));
}
}