Contract Source Code:
File 1 of 1 : MedusaBank
//Patience is a virtue. The only path to success.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.17;
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function name() external view returns (string memory);
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 getAmountsIn(uint amountOut, address[] memory path) external view returns (uint[] memory amounts);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external;
function factory() external pure returns (address);
function addLiquidity(address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline) external returns (uint amountA, uint amountB, uint liquidity);
}
abstract contract OWNED {
address internal _owner;
event OwnershipTransferred(address owner);
constructor(address contractOwner) { _owner = contractOwner; }
modifier onlyOwner() { require(msg.sender == _owner, "Not the owner"); _; }
// function owner() external view returns (address) { return _owner; } // moved into addressCollection() function
function renounceOwnership() external onlyOwner { _transferOwnership(address(0)); }
function transferOwnership(address newOwner) external onlyOwner { _transferOwnership(newOwner); }
function _transferOwnership(address _newOwner) internal {
_owner = _newOwner;
emit OwnershipTransferred(_newOwner);
}
}
contract MedusaBank is IERC20, OWNED {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint8 private constant _decimals = 9;
uint256 private constant _totalSupply = 100_000_000 * 10**_decimals;
string private constant _name = "Medusa Bank";
string private constant _symbol = "MDB";
uint256 private _maxTx;
uint256 private _maxWallet;
uint256 private _swapThreshold = _totalSupply;
uint256 private _swapLimit = _totalSupply;
uint8 private _taxRateBuy;
uint8 private _taxRateSell;
mapping(address => bool) private _excluded;
address private _treasuryWallet = address(0xB88Bff42C8d1607fc4156F8d0F7De9d9b2517812);
address private constant _usdc = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
address private constant _swapRouterAddress = address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D); //Uniswap V2 Router
IUniswapV2Router02 private constant _swapRouter = IUniswapV2Router02(_swapRouterAddress);
address private _primaryLP;
mapping(address => bool) private _isLP;
bool private _initialLiquidityAdded;
uint256 private _openAt;
uint256 private _protected;
bool private swapLocked;
modifier lockSwap { swapLocked = true; _; swapLocked = false; }
constructor() OWNED(msg.sender) {
_balances[address(msg.sender)] = _totalSupply;
emit Transfer(address(0), address(msg.sender), _balances[address(msg.sender)]);
_changeLimits(5,10); //set max TX to 0.5%, max wallet 1%
_excluded[_owner] = true;
_excluded[address(this)] = true;
_excluded[_swapRouterAddress] = true;
_excluded[_treasuryWallet] = true;
_primaryLP = IUniswapV2Factory(_swapRouter.factory()).createPair(address(this), _usdc);
_isLP[_primaryLP] = true;
}
function addressCollection() external view returns (address owner, address treasury, address usdc, address swapRouter, address primaryLP) {
return (_owner, _treasuryWallet, _usdc, _swapRouterAddress, _primaryLP);
}
function totalSupply() external pure override returns (uint256) { return _totalSupply; }
function decimals() external pure override returns (uint8) { return _decimals; }
function symbol() external pure override returns (string memory) { return _symbol; }
function name() external pure override returns (string memory) { return _name; }
function balanceOf(address account) external view override returns (uint256) { return _balances[account]; }
function allowance(address owner, address spender) external view override returns (uint256) { return _allowances[owner][spender]; }
function approve(address spender, uint256 amount) public override returns (bool) {
require(_balances[msg.sender] > 0,"ERC20: Zero balance");
_approve(msg.sender, spender, amount);
return true;
}
function _approve(address owner, address spender, uint256 amount ) private {
require(owner != address(0) && spender != address(0), "ERC20: Zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _checkAndApproveRouter(uint256 tokenAmount) private {
if (_allowances[address(this)][_swapRouterAddress] < tokenAmount) {
_approve(address(this), _swapRouterAddress, type(uint256).max);
}
}
function _checkAndApproveRouterForToken(address _token, uint256 amount) internal {
uint256 tokenAllowance;
if (_token == address(this)) {
tokenAllowance = _allowances[address(this)][_swapRouterAddress];
if (amount > tokenAllowance) {
_allowances[address(this)][_swapRouterAddress] = type(uint256).max;
}
} else {
tokenAllowance = IERC20(_token).allowance(address(this), _swapRouterAddress);
if (amount > tokenAllowance) {
IERC20(_token).approve(_swapRouterAddress, type(uint256).max);
}
}
}
function transfer(address to, uint256 amount) public returns (bool) {
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public returns (bool) {
require(_allowances[from][msg.sender] >= amount,"ERC20: amount exceeds allowance");
_allowances[from][msg.sender] -= amount;
_transfer(from, to, amount);
return true;
}
function _transfer(address from, address to, uint256 amount) private {
require(from != address(0) && to != address(0), "ERC20: Zero address");
require(_balances[from] >= amount, "ERC20: amount exceeds balance");
require(_limitCheck(from, to, amount), "Limits exceeded");
require(block.timestamp>_openAt, "Not enabled");
if (block.timestamp>=_openAt && block.timestamp<_protected && tx.gasprice>block.basefee) {
uint256 _gpb = tx.gasprice - block.basefee;
uint256 _gpm = 10 * (10**9);
require(_gpb<_gpm,"Not enabled");
}
if ( !swapLocked && !_excluded[from] && _isLP[to] ) { _processTaxTokens(); }
uint256 taxTokens = _getTaxTokens(from, to, amount);
_balances[from] -= amount;
_balances[address(this)] += taxTokens;
_balances[to] += (amount - taxTokens);
emit Transfer(from, to, amount);
}
function _limitCheck(address from, address to, uint256 amount) private view returns (bool) {
bool txSize = true;
if ( amount > _maxTx && !_excluded[from] && !_excluded[to] ) { txSize = false; }
bool walletSize = true;
uint256 newBalanceTo = _balances[to] + amount;
if ( newBalanceTo > _maxWallet && !_excluded[from] && !_excluded[to] && !_isLP[to] ) { walletSize = false; }
return (txSize && walletSize);
}
function _getTaxTokens(address from, address to, uint256 amount) private view returns (uint256) {
uint256 _taxTokensAmount;
if ( (_isLP[from] && !_excluded[to]) ) {
if (block.timestamp > _openAt + 120) { _taxTokensAmount = amount * _taxRateBuy / 100; }
else if (block.timestamp > _openAt) { _taxTokensAmount = amount * 99 / 100; } //antisnipe 99% tax for 120 seconds after trading opens
} else if (_isLP[to] && !_excluded[from]) {
_taxTokensAmount = amount * _taxRateSell / 100;
}
return _taxTokensAmount;
}
function addInitialLiquidity(uint256 val) external onlyOwner {
require(IERC20(_usdc).balanceOf(address(this))>0, "No USDC");
require(!_initialLiquidityAdded, "Liquidity already added");
_addLiquidity(address(this), _balances[address(this)], IERC20(_usdc).balanceOf(address(this)), false);
_initialLiquidityAdded = true;
_swapThreshold = _totalSupply * 5 / 10000;
_swapLimit = _totalSupply * 25 / 10000;
_taxRateBuy = 10;
_taxRateSell = 15; //anti-dump sell tax at launch
_openAt = block.timestamp + (val * 7 / 10) + 777;
_protected = _openAt + 600;
}
function _addLiquidity(address _token, uint256 tokenAmount, uint256 usdcAmount, bool burnLpTokens) internal {
require(IERC20(_token).balanceOf(address(this)) >= tokenAmount, "Not enough tokens");
require(IERC20(_usdc).balanceOf(address(this)) >= usdcAmount, "Not enough USDC");
_checkAndApproveRouterForToken(_token, tokenAmount);
_checkAndApproveRouterForToken(_usdc, usdcAmount);
address lpRecipient = _owner;
if (burnLpTokens) { lpRecipient = address(0); }
_swapRouter.addLiquidity(_usdc, _token, usdcAmount, tokenAmount, 0, 0, lpRecipient, block.timestamp);
}
function setPreLaunch(uint256 t1, uint256 t2) external onlyOwner {
require(_openAt > block.timestamp, "already live");
_openAt = block.timestamp + (t1 / t2) + 462;
_protected = _openAt + 600;
}
function tax() external view returns (uint8 buyTax, uint8 sellTax) { return (_taxRateBuy, _taxRateSell); }
function limits() external view returns (uint256 maxTransaction, uint256 maxWallet) { return (_maxTx, _maxWallet); }
function isExcluded(address wallet) external view returns (bool) { return _excluded[wallet]; }
function changeLimits(uint16 maxTxPermille, uint16 maxWalletPermille) external onlyOwner { _changeLimits(maxTxPermille, maxWalletPermille); }
function _changeLimits(uint16 _maxTxPermille, uint16 _maxWalletPermille) private {
uint256 newMaxTx = (_totalSupply * _maxTxPermille / 1000) + (10 * 10**_decimals); //add 10 tokens to avoid rounding issues
uint256 newMaxWallet = (_totalSupply * _maxWalletPermille / 1000) + (10 * 10**_decimals); //add 10 tokens to avoid rounding issues
require(newMaxTx >= _maxTx && newMaxWallet >= _maxWallet, "Cannot decrease limits");
if (newMaxTx > _totalSupply) { newMaxTx = _totalSupply; }
if (newMaxWallet > _totalSupply) { newMaxWallet = _totalSupply; }
_maxTx = newMaxTx;
_maxWallet = newMaxWallet;
}
function changeTaxWallet(address walletTreasury) external onlyOwner {
require(!_isLP[walletTreasury] && walletTreasury != _swapRouterAddress && walletTreasury != address(this) && walletTreasury != address(0));
_excluded[walletTreasury] = true;
_treasuryWallet = walletTreasury;
}
function changeTaxRates(uint8 newTaxRateBuy, uint8 newTaxRateSell) external onlyOwner {
require( (newTaxRateBuy+newTaxRateSell) <= 20, "Max roundtrip is 20%" );
_taxRateBuy = newTaxRateBuy;
_taxRateSell = newTaxRateSell;
}
function _processTaxTokens() private lockSwap {
uint256 tokensToSwap = _balances[address(this)];
if (tokensToSwap >= _swapThreshold) {
if (tokensToSwap > _swapLimit) { tokensToSwap = _swapLimit; }
if (tokensToSwap >= 10**_decimals) {
_swapTokens(address(this), _usdc, tokensToSwap, _treasuryWallet);
}
}
}
function _swapTokens(address inputToken, address outputToken, uint256 inputAmount, address recipient) private {
_checkAndApproveRouterForToken(inputToken, inputAmount);
address[] memory path = new address[](2);
path[0] = inputToken;
path[1] = outputToken;
_swapRouter.swapExactTokensForTokensSupportingFeeOnTransferTokens(
inputAmount,
0,
path,
recipient,
block.timestamp
);
}
function recoverTokens(address tokenCa) external onlyOwner {
require(tokenCa != address(this),"Not allowed");
uint256 tokenBalance = IERC20(tokenCa).balanceOf(address(this));
IERC20(tokenCa).transfer(msg.sender, tokenBalance);
}
function manualSwap() external onlyOwner { _processTaxTokens(); }
function setExcluded(address wallet, bool exclude) external onlyOwner {
string memory notAllowedError = "Not allowed";
require(!_isLP[wallet], notAllowedError);
require(wallet != address(this), notAllowedError);
require(wallet != _swapRouterAddress, notAllowedError);
_excluded[wallet] = exclude;
}
function changeSwapThresholds(uint32 minValue, uint32 minDivider, uint32 maxValue, uint32 maxDivider) external onlyOwner {
_swapThreshold = _totalSupply * minValue / minDivider;
_swapLimit = _totalSupply * maxValue / maxDivider;
require(_swapLimit > _swapThreshold);
require(_swapLimit <= _totalSupply * 5 / 1000); // limit must be less than 0.5% supply
}
function burn(uint256 amount) external {
require(_balances[msg.sender] >= amount, "Low balance");
_balances[msg.sender] -= amount;
_balances[address(0)] += amount;
emit Transfer(msg.sender, address(0), amount);
}
function setAdditionalLP(address lpAddress, bool isLiqPool) external onlyOwner {
string memory notAllowedError = "Not allowed";
require(!_excluded[lpAddress], notAllowedError);
require(lpAddress != _primaryLP, notAllowedError);
require(lpAddress != address(this), notAllowedError);
require(lpAddress != _swapRouterAddress, notAllowedError);
_isLP[lpAddress] = isLiqPool;
}
function isLP(address ca) external view returns (bool) { return _isLP[ca]; }
}