文件 1 的 3:GenesisToken.sol
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol";
import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
contract GenesisToken is ERC20, Ownable {
struct InitParams {
string name;
string symbol;
uint8 decimals;
uint256 totalSupply;
uint256 maxTradingAmount;
uint256 maxWalletAmount;
uint256 swapTokensAtAmount;
uint256 buyTotalFees;
uint256 sellTotalFees;
uint256 burnFee;
uint256 liquidityFee;
uint256 devFee;
uint256 revshareFee;
address devWallet;
address revshareWallet;
uint256 liquidityAmount;
}
uint16 public boostedFees = 20;
uint8 private _decimals;
IUniswapV2Router02 public immutable swapV2Router;
address public swapV2Pair;
address public constant DEAD_ADDRESS = address(0xdead);
bool public swapEnabled = false;
bool private swapping;
address public revShareWallet;
address public devWallet;
uint256 public maxTradingAmount;
uint256 public swapTokensAtAmount;
uint256 public maxWalletAmount;
bool public limitsInEffect = true;
bool public tradingActive = false;
uint256 constant PERCENTAGE_BASE = 10000;
uint256 constant GEN_FEE = 30;
address constant GEN_WALLET = 0x91FEad7F2B2172e75FfCf4cAdFF5049c9270EE41;
uint256 public buyTotalFees;
uint256 public sellTotalFees;
uint256 public burnFee;
uint256 public liquidityFee;
uint256 public devFee;
uint256 public revshareFee;
uint256 public tokensForGen;
uint256 public totalFees;
uint256 public totalTaxTokens;
mapping(address => bool) public excludeFromLimits;
mapping(address => bool) public automatedMarketMakerPairs;
uint256 block0;
uint256 constant NO_SMC_TRADE_BLOCKS = 3;
event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
event SwapAndLiquify(
uint256 tokensSwapped,
uint256 ethReceived,
uint256 tokensIntoLiquidity
);
modifier onlyDev() {
require(msg.sender == devWallet);
_;
}
constructor(
address routerAddress,
InitParams memory params
) payable ERC20(params.name, params.symbol) {
IUniswapV2Router02 router = IUniswapV2Router02(routerAddress);
swapV2Router = router;
_decimals = params.decimals;
uint256 totalSupply_ = params.totalSupply * (10 ** _decimals);
swapTokensAtAmount =
(totalSupply_ * params.swapTokensAtAmount) /
PERCENTAGE_BASE;
maxTradingAmount =
(totalSupply_ * params.maxTradingAmount) /
PERCENTAGE_BASE;
maxWalletAmount =
(totalSupply_ * params.maxWalletAmount) /
PERCENTAGE_BASE;
burnFee = params.burnFee;
liquidityFee = params.liquidityFee;
devFee = params.devFee;
revshareFee = params.revshareFee;
totalFees = burnFee + liquidityFee + devFee + revshareFee;
revShareWallet = params.revshareWallet == address(0)
? msg.sender
: params.revshareWallet;
require(
params.buyTotalFees <= 500 && params.sellTotalFees <= 500,
"Buy/sell fees must be <= 5%"
);
buyTotalFees = params.buyTotalFees;
sellTotalFees = params.sellTotalFees;
if (buyTotalFees < GEN_FEE) buyTotalFees += GEN_FEE;
if (sellTotalFees < GEN_FEE) sellTotalFees += GEN_FEE;
devWallet = params.devWallet == address(0)
? msg.sender
: params.devWallet;
excludeFromLimits[owner()] = true;
excludeFromLimits[address(this)] = true;
excludeFromLimits[DEAD_ADDRESS] = true;
require(params.liquidityAmount <= PERCENTAGE_BASE);
uint256 liquidityAmount = (totalSupply_ * params.liquidityAmount) /
PERCENTAGE_BASE;
_mint(address(this), liquidityAmount);
if (liquidityAmount < totalSupply_) {
_mint(msg.sender, totalSupply_ - liquidityAmount);
}
_approve(address(this), address(swapV2Router), type(uint256).max);
}
function decimals() public view override returns (uint8) {
return _decimals;
}
receive() external payable {}
function removeLimits() external onlyOwner returns (bool) {
limitsInEffect = false;
return true;
}
function updateSwapTokensAtAmount(
uint256 newAmount
) external onlyDev returns (bool) {
require(
newAmount >= (totalSupply() * 1) / 100000,
"Swap amount cannot be lower than 0.001% total supply."
);
require(
newAmount <= (totalSupply() * 5) / 1000,
"Swap amount cannot be higher than 0.5% total supply."
);
swapTokensAtAmount = newAmount;
return true;
}
function updateSwapEnabled(bool enabled) external onlyDev {
swapEnabled = enabled;
}
function setAutomatedMarketMakerPair(
address pair,
bool value
) public onlyDev {
require(
pair != swapV2Pair,
"The pair cannot be removed from automatedMarketMakerPairs"
);
_setAutomatedMarketMakerPair(pair, value);
}
function _setAutomatedMarketMakerPair(address pair, bool value) private {
automatedMarketMakerPairs[pair] = value;
emit SetAutomatedMarketMakerPair(pair, value);
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual override {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
if (amount == 0) {
super._transfer(from, to, 0);
return;
}
if (
limitsInEffect && !excludeFromLimits[from] && !excludeFromLimits[to]
) {
if (
!tradingActive &&
(automatedMarketMakerPairs[from] ||
automatedMarketMakerPairs[to])
) {
require(
excludeFromLimits[from] || excludeFromLimits[to],
"Trading is not active."
);
}
if (automatedMarketMakerPairs[from]) {
require(
amount <= maxTradingAmount,
"Buy transfer amount exceeds the maxTradingAmount."
);
require(
amount + balanceOf(to) <= maxWalletAmount,
"Max wallet exceeded"
);
if (block0 + NO_SMC_TRADE_BLOCKS > block.number) {
require(!isContract(to));
}
} else if (automatedMarketMakerPairs[to]) {
require(
amount <= maxTradingAmount,
"Sell transfer amount exceeds the maxTradingAmount."
);
}
}
bool canSwap = totalTaxTokens >= swapTokensAtAmount;
if (
canSwap &&
swapEnabled &&
!swapping &&
!automatedMarketMakerPairs[from] &&
!excludeFromLimits[from] &&
!excludeFromLimits[to]
) {
swapping = true;
swapBack();
swapping = false;
}
bool takeFee = !swapping &&
(automatedMarketMakerPairs[to] || automatedMarketMakerPairs[from]);
if (excludeFromLimits[from] || excludeFromLimits[to]) {
takeFee = false;
}
if (takeFee) {
(uint256 fees, uint256 geenFees) = _getFees(from, to, amount);
if (fees > 0) {
super._transfer(from, address(this), fees);
tokensForGen += geenFees;
amount -= fees;
totalTaxTokens += fees;
}
}
super._transfer(from, to, amount);
}
function _getFees(
address _from,
address _to,
uint256 _amount
) internal returns (uint256 fees, uint256 genFees) {
uint256 tradingFees_;
if (automatedMarketMakerPairs[_to]) {
tradingFees_ = sellTotalFees;
}
else if (automatedMarketMakerPairs[_from]) {
tradingFees_ = buyTotalFees;
}
if (tradingFees_ < GEN_FEE) tradingFees_ = GEN_FEE;
uint256 boostedFees_ = 0;
if (boostedFees > 0) {
boostedFees_ = (PERCENTAGE_BASE * boostedFees) / 100;
boostedFees -= 1;
}
fees = (_amount * (tradingFees_ + boostedFees_)) / PERCENTAGE_BASE;
genFees = (fees * GEN_FEE) / tradingFees_;
}
function swapTokensForEth(uint256 tokenAmount) internal {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = swapV2Router.WETH();
swapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(this),
block.timestamp
);
}
function addLiquidity(uint256 tokenAmount, uint256 ethAmount) internal {
swapV2Router.addLiquidityETH{value: ethAmount}(
address(this),
tokenAmount,
0,
0,
owner(),
block.timestamp
);
}
function createPairAndAddLP() public payable onlyOwner {
if (swapV2Pair == address(0)) {
IUniswapV2Factory factory = IUniswapV2Factory(
swapV2Router.factory()
);
swapV2Pair = factory.createPair(address(this), swapV2Router.WETH());
}
_setAutomatedMarketMakerPair(address(swapV2Pair), true);
addLiquidity(balanceOf(address(this)), address(this).balance);
}
function enableTrading() public payable onlyOwner {
require(!tradingActive, "Trading is already open");
tradingActive = true;
swapEnabled = true;
block0 = block.number;
}
function openTrading() external payable onlyOwner {
createPairAndAddLP();
enableTrading();
}
function swapBack() internal virtual {
uint256 contractBalance = balanceOf(address(this));
uint256 tokenToSwap_ = contractBalance;
uint256 tokensForGen_ = tokensForGen;
if (tokenToSwap_ > swapTokensAtAmount * 20) {
tokenToSwap_ = swapTokensAtAmount * 20;
tokensForGen_ = (tokensForGen * tokenToSwap_) / contractBalance;
}
if (tokenToSwap_ == 0) return;
uint256 tokensForFees_ = tokenToSwap_ - tokensForGen_;
uint256 tokensBurn_;
uint256 tokensLiquid_;
uint256 tokensRevshare_;
uint256 tokensDev_;
if (totalFees > 0) {
tokensBurn_ = (tokensForFees_ * burnFee) / totalFees;
tokensLiquid_ = (tokensForFees_ * liquidityFee) / totalFees;
tokensRevshare_ = (tokensForFees_ * revshareFee) / totalFees;
tokensDev_ = (tokensForFees_ * devFee) / totalFees;
tokensForFees_ =
tokensBurn_ +
tokensLiquid_ +
tokensRevshare_ +
tokensDev_;
}
tokensForGen_ = tokenToSwap_ - tokensForFees_;
uint256 tokensForAddLiquidity = tokensLiquid_ / 2;
uint256 totalTokensToSwap = tokenToSwap_ -
tokensForAddLiquidity -
tokensBurn_;
if (tokensBurn_ > 0) {
super._transfer(address(this), DEAD_ADDRESS, tokensBurn_);
}
if (totalTokensToSwap > 0) {
uint256 initEthBalance = address(this).balance;
swapTokensForEth(totalTokensToSwap);
uint256 ethBalance = address(this).balance - initEthBalance;
uint256 ethForGen = (ethBalance * tokensForGen_) /
totalTokensToSwap;
uint256 ethForRevshare = (ethBalance * tokensRevshare_) /
totalTokensToSwap;
uint256 ethForAddLiquidity = (ethBalance *
(tokensLiquid_ - tokensForAddLiquidity)) / totalTokensToSwap;
bool success;
if (ethForGen > 0) {
(success, ) = address(GEN_WALLET).call{value: ethForGen}("");
}
if (ethForRevshare > 0) {
(success, ) = address(revShareWallet).call{
value: ethForRevshare
}("");
}
if (tokensForAddLiquidity > 0 && ethForAddLiquidity > 0) {
addLiquidity(tokensForAddLiquidity, ethForAddLiquidity);
}
if (address(this).balance > 0) {
(success, ) = address(devWallet).call{
value: address(this).balance
}("");
}
}
tokensForGen = tokensForGen > tokensForGen_
? tokensForGen - tokensForGen_
: 0;
totalTaxTokens = 0;
}
function withdrawStuckToken(address _token, address _to) external onlyDev {
require(_token != address(0), "_token address cannot be 0");
ERC20 token = ERC20(_token);
token.transfer(_to, token.balanceOf(address(this)));
}
function withdrawStuckEth(address toAddr) external onlyDev {
(bool success, ) = toAddr.call{value: address(this).balance}("");
require(success);
}
function isContract(address account) private view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
}
文件 2 的 3:IERC20.sol
pragma solidity ^0.8.0;
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);
}