Created
January 4, 2024 10:53
-
-
Save coderwithsense/288e9418e6f90ce1c664cdfce809ade7 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.23+commit.f704f362.js&optimize=false&runs=200&gist=
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity 0.8.23; | |
import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | |
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "@openzeppelin/contracts/utils/math/SafeMath.sol"; | |
interface IUniswapV2Factory { | |
function createPair(address tokenA, address tokenB) | |
external | |
returns (address pair); | |
} | |
interface IUniswapV2Router02 { | |
function swapExactTokensForETHSupportingFeeOnTransferTokens( | |
uint256 amountIn, | |
uint256 amountOutMin, | |
address[] calldata path, | |
address to, | |
uint256 deadline | |
) external; | |
function factory() external pure returns (address); | |
function WETH() external pure returns (address); | |
function addLiquidityETH( | |
address token, | |
uint256 amountTokenDesired, | |
uint256 amountTokenMin, | |
uint256 amountETHMin, | |
address to, | |
uint256 deadline | |
) | |
external | |
payable | |
returns ( | |
uint256 amountToken, | |
uint256 amountETH, | |
uint256 liquidity | |
); | |
} | |
contract cryptoGradTaxToken is ERC20, ERC20Permit, Ownable { | |
using SafeMath for uint256; | |
mapping(address => bool) private _buyerMap; | |
mapping(address => bool) private _bots; | |
mapping(address => uint256) private _holderLastTransferTimestamp; | |
mapping(address => bool) private _excludedFromFee; | |
address payable private _taxWallet; | |
address public _marketingWallet; | |
address public _devWallet; | |
address public _cexWallet; | |
uint256 private _buyTax = 30; | |
uint256 private _sellTax = 40; | |
uint256 private _finalBuyTax = 5; | |
uint256 private _finalSellTax = 5; | |
uint256 private _reduceBuyTaxAt = 56; | |
uint256 private _reduceSellTaxAt = 56; | |
uint256 private _preventSwapBefore = 20; | |
uint256 public _buyCount = 0; | |
uint256 public tradingStartedTime; | |
uint8 private constant _decimals = 18; | |
uint256 private constant _totalSupply = 100000000 * 10 ** _decimals; // 100 million | |
uint256 public _maxTransaction = (_totalSupply * 3) / 100; // 3% of total supply | |
uint256 public _maxWalletSize = (_totalSupply * 2) / 100; // 2% of total supply | |
uint256 public _taxSwapThreshold = _totalSupply * 5 / 1000; // 0.5% of total supply | |
uint256 public _maxTaxSwap = _totalSupply / 1000; // 0.1% of total supply | |
IUniswapV2Router02 private uniswapV2Router; | |
address private uniswapV2Pair; | |
bool public tradingOpen = false; | |
bool private inSwap = false; | |
bool private swappingOn = false; | |
event MaxTxAmountUpdated(uint _maxTransaction); | |
modifier lockTheSwap { | |
inSwap = true; | |
_; | |
inSwap = false; | |
} | |
// inital mint: dev(5%), marketing(2.5%), cex(2.5%), owner(90%) | |
constructor (address marketingWallet, address cexWallet, address devWallet) ERC20("Crypto Grad Token", "CGT") ERC20Permit("Crypto Grad Token") Ownable(_msgSender()){ | |
_devWallet = devWallet; | |
_marketingWallet = marketingWallet; | |
_cexWallet = cexWallet; | |
_taxWallet = payable(msg.sender); | |
uint256 _supplyInGwei = _totalSupply * 10 ** decimals(); | |
_mint(msg.sender, _supplyInGwei * 90 / 100); | |
_mint(_devWallet, _supplyInGwei * 5 / 100); | |
_mint(_marketingWallet, _supplyInGwei * 25 / 1000); | |
_mint(_cexWallet, _supplyInGwei * 25 / 1000); | |
// set owner, contract address, tax wallet, marketing wallet, cex wallet, dex wallet excluded from fees on buy/sell | |
_excludedFromFee[owner()] = true; | |
_excludedFromFee[address(this)] = true; | |
_excludedFromFee[_taxWallet] = true; | |
_excludedFromFee[_marketingWallet] = true; | |
_excludedFromFee[_cexWallet] = true; | |
_excludedFromFee[_devWallet] = true; | |
} | |
// overriding _transfer function | |
function _transfer(address from, address to, uint256 value) internal override { | |
if (from == address(0)) { | |
revert ERC20InvalidSender(address(0)); | |
} | |
if (to == address(0)) { | |
revert ERC20InvalidReceiver(address(0)); | |
} | |
require(value > 0, "Transfer amount must be greater than zero"); | |
uint256 finalTaxAmountOnTransaction = 0; | |
(uint256 _taxOnBuy, uint256 _taxOnSell) = getCurrentTax(); | |
if (from != owner() && to != owner()) { | |
require(!_bots[from] && !_bots[to], "Bots not allowed to buy"); | |
if (from == uniswapV2Pair && to != address(uniswapV2Router) && !_excludedFromFee[to]) { | |
require(value <= _maxTransaction, "Exceed Max transaction amount"); | |
require(balanceOf(to) + value <= _maxWalletSize, "Exceeds the maxWalletSize."); | |
if (_buyCount < _preventSwapBefore) { | |
require(!isContract(to), "Not allow contract buy now"); | |
} | |
_buyCount++; | |
_buyerMap[to] = true; | |
} | |
// Tax on buy | |
finalTaxAmountOnTransaction = value.mul(_taxOnBuy).div(100); | |
if (to == uniswapV2Pair && from != address(this)) { | |
require(value <= _maxTransaction, "Exceed Max transaction amount."); | |
// Tax on sell | |
finalTaxAmountOnTransaction = value.mul(_taxOnSell).div(100); | |
require(_buyCount > _preventSwapBefore || _buyerMap[from], "Seller is not buyer"); | |
} | |
uint256 contractTokenBalance = balanceOf(address(this)); | |
if (!inSwap && to == uniswapV2Pair && swappingOn && contractTokenBalance > _taxSwapThreshold && _buyCount > _preventSwapBefore) { | |
swapTokensForEth(minOfTwo(value, minOfTwo(contractTokenBalance, _maxTaxSwap))); | |
uint256 ethBalance = address(this).balance; | |
if (ethBalance > 0) { | |
sendETHToFee(address(this).balance); | |
} | |
} | |
} | |
// add liquidity dont charge fee | |
if (_excludedFromFee[to] && to == address(uniswapV2Pair)) { | |
finalTaxAmountOnTransaction = 0; | |
} | |
// no fee when transfer | |
if(from != address(uniswapV2Pair) && to != address(uniswapV2Pair)) { | |
finalTaxAmountOnTransaction = 0; | |
} | |
if (finalTaxAmountOnTransaction > 0) { | |
// _balances[address(this)] = _balances[address(this)].add(finalTaxAmountOnTransaction); | |
_update(from, address(this), finalTaxAmountOnTransaction); | |
// emit Transfer(from, address(this), finalTaxAmountOnTransaction); | |
} | |
// _balances[from] = _balances[from].sub(value); | |
// _balances[to] = _balances[to].add(value.sub(finalTaxAmountOnTransaction)); | |
_update(from, to, value - finalTaxAmountOnTransaction); | |
// emit Transfer(from, to, value.sub(finalTaxAmountOnTransaction)); | |
} | |
// function to return the smart contract address for UNI-V2 pair token | |
function getTradingPairTokenContract() public view returns(address) { | |
require(tradingOpen, "Trading not started yet"); | |
return address(uniswapV2Router); | |
} | |
// function to send eth to the (private function) | |
function sendETHToFee(uint256 amount) private { | |
_taxWallet.transfer(amount); | |
} | |
// function to check if the account address is a bot | |
function isBot(address a) public view returns (bool){ | |
return _bots[a]; | |
} | |
// function to set the account as a bot | |
function setAccountAsBot(address addr) public { | |
_bots[addr] = true; | |
} | |
// function create a liquidity pool on uniswap (WETH/Token), and set the tradingOpen to true | |
function createPoolStartTrading() external onlyOwner() { | |
require(!tradingOpen, "Trading already set to true"); | |
uniswapV2Router = IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); | |
_approve(address(this), address(uniswapV2Router), _totalSupply); | |
uniswapV2Pair = IUniswapV2Factory(uniswapV2Router.factory()).createPair(address(this), uniswapV2Router.WETH()); | |
_excludedFromFee[address(uniswapV2Pair)] = true; | |
uniswapV2Router.addLiquidityETH{value: address(this).balance}(address(this), balanceOf(address(this)), 0, 0, owner(), block.timestamp); | |
IERC20(uniswapV2Pair).approve(address(uniswapV2Router), type(uint).max); | |
_excludedFromFee[address(uniswapV2Pair)] = false; | |
tradingOpen = true; | |
swappingOn = true; | |
tradingStartedTime = block.timestamp; | |
} | |
// function to return the current contract (private function) | |
function isContract(address account) private view returns (bool) { | |
uint256 size; | |
assembly { | |
size := extcodesize(account) | |
} | |
return size > 0; | |
} | |
// function for manualSwapping of tokens to eth in the address | |
function manualSwap() external { | |
require(_msgSender() == _taxWallet); | |
uint256 tokenBalance = balanceOf(address(this)); | |
if (tokenBalance > 0) { | |
swapTokensForEth(tokenBalance); | |
} | |
uint256 ethBalance = address(this).balance; | |
if (ethBalance > 0) { | |
sendETHToFee(ethBalance); | |
} | |
} | |
// funciton for returning current buy/sell tax | |
function getCurrentTax() private view returns (uint, uint) { | |
// buy/sell within 3 minutes of starting the trade (returns initial taxes) | |
if (tradingStartedTime + 60 * 3 > block.timestamp) { | |
return (_buyTax, _sellTax); | |
} | |
// buy/sell within 3 minutes to 11 minutes of starting the trade (returns 20% buy/sell tax) | |
else if (tradingStartedTime + 60 * 3 < block.timestamp && block.timestamp < tradingStartedTime + 60 * 11) { | |
return (20, 20); | |
// buy/sell within 11 minutes to 20 minutes of starting the trade (returns 10% buy/sell tax) | |
} else if (tradingStartedTime + 60 * 11 < block.timestamp && block.timestamp < tradingStartedTime + 60 * 20) { | |
return (10, 10); | |
// buy/sell tax after 20 minutes of trading start (final buy/sell tax) | |
} else if (block.timestamp > tradingStartedTime + 60 * 20) { | |
return (_finalBuyTax, _finalSellTax); | |
} | |
} | |
// function for setting maxTransaction back to default | |
function maxTransactionToDefault() external onlyOwner() { | |
_maxTransaction = _totalSupply.div(100); | |
emit MaxTxAmountUpdated(_maxTransaction); | |
} | |
// function for returning minimum of two numbers (private function) | |
function minOfTwo(uint256 numberA, uint256 numberB) private pure returns (uint256){ | |
return (numberA > numberB) ? numberB : numberA; | |
} | |
// function to swap tokens for eth (private function) | |
function swapTokensForEth(uint256 tokenAmount) private lockTheSwap { | |
if (tokenAmount == 0) {return;} | |
if (!tradingOpen) {return;} | |
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 | |
); | |
} | |
// function for receiving eth in the contract | |
receive() external payable {} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment