/**
* @title Alpha Gardeners - The Ultimate Degen Trading Toolkit
*
* Join us on Telegram: https://t.me/alphagardeners_lounge
* Follow us on Twitter: https://twitter.com/alpha_gardeners
*
*/
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.19;
import "./Ownable.sol";
import "./Pausable.sol";
import "./IUniswap.sol";
contract AG is Ownable, Pausable {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
// ERC20 events.
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
// This token specific events.
event BlacklistStatusUpdated(address wallet, bool isBlacklisted);
event MarketPairUpdated(address pair, bool isMarketPair);
event ExcludedFromFeesUpdated(address wallet, bool isExcluded);
event TaxRecipientUpdated(address recipient);
event TaxesUpdated(uint256 buyTax, uint256 sellTax, uint256 transferTax);
event LimitsUpdated(uint256 maxBuy, uint256 maxSell, uint256 maxWallet);
event NumTokensToSwapUpdated(uint256 amount);
event ContractSwapEnabledUpdated(bool autoEnabled, bool manualEnabled);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/
string public name;
string public symbol;
uint8 public constant decimals = 18;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/
// No mint or burn means we can just use a constant.
// Total supply must fit in uint128.
uint256 public constant totalSupply = 8_000_000_000 * 10**decimals;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
TOKEN-SPECIFIC
//////////////////////////////////////////////////////////////*/
address public taxRecipient;
uint256 public numTokensToSwap = 2_500_000 * 10**decimals;
bool public contractSwapEnabled = false;
bool public manualSwapEnabled = false;
bool private inSwap;
IUniswapV2Router02 public uniswapV2Router;
// IUniswapV2Pair public uniswapV2Pair;
address private WETH;
event UniswapRouterUpdated(address newRouter);
// When accessing the buy tax, we also access buy limit, and the same applies for
// sell tax and limit. We pack them into a struct to save on gas.
struct taxAndLimit {
uint128 tax;
uint128 limit;
}
taxAndLimit public buyTaxAndLimit = taxAndLimit({
tax: 0,
limit: uint128(totalSupply)
});
taxAndLimit public sellTaxAndLimit = taxAndLimit({
tax: 0,
limit: uint128(totalSupply)
});
uint256 public transferTax = 0;
uint256 public maxWallet = totalSupply;
/// @dev totalSupply * maxTax cannot exceed uint256.
/// @dev maxTax cannot exceed taxDenominator.
uint256 private constant maxTax = 1_000; // 10%, same limit applies to all taxes.
uint256 private constant taxDenominator = 10_000; // 500/10000 = 5%
// Pack it into a struct instead of individual mappings to save on gas.
struct walletState {
bool isBlacklisted;
bool isMarketPair;
bool isExcludedFromFees;
}
mapping (address => walletState) public _walletState;
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
// Start paused.
constructor(
string memory _name,
string memory _symbol,
address _taxRecipient,
address routerAddress
) Ownable(msg.sender) Pausable(true) {
// Require supply to be less than the max uint128 value.
require(totalSupply < type(uint128).max, "TOTAL_SUPPLY_EXCEEDS_MAX");
name = _name;
symbol = _symbol;
taxRecipient = _taxRecipient;
// Setup the Uniswap router used for swapping fees.
uniswapV2Router = IUniswapV2Router02(routerAddress);
_approve(address(this), routerAddress, type(uint256).max);
WETH = uniswapV2Router.WETH();
// Setup for EIP-2612.
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
// Exclude owner and the contract from fees.
_walletState[msg.sender] = walletState({
isBlacklisted: false,
isMarketPair: false,
isExcludedFromFees: true
});
emit ExcludedFromFeesUpdated(msg.sender, true);
_walletState[address(this)] = walletState({
isBlacklisted: false,
isMarketPair: false,
isExcludedFromFees: true
});
emit ExcludedFromFeesUpdated(address(this), true);
// Mint the initial supply.
unchecked {
balanceOf[msg.sender] += totalSupply;
}
emit Transfer(address(0), msg.sender, totalSupply);
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/
function approve(address spender, uint256 amount) public returns (bool) {
_approve(msg.sender, spender, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = msg.sender;
_approve(owner, spender, allowance[owner][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = msg.sender;
uint256 currentAllowance = allowance[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _approve(
address owner,
address spender,
uint256 amount
) internal {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
allowance[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function transfer(address to, uint256 amount) public whenNotPaused returns (bool) {
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public whenNotPaused returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) {
require(allowed >= amount, "ERC20: insufficient allowance");
// Won't overflow since allowed >= amount.
unchecked {
allowance[from][msg.sender] = allowed - amount;
}
}
_transfer(from, to, amount);
return true;
}
function _buyTransfer(address to, uint256 amount) internal view returns (uint256) {
// balanceOf[to]+amount can't exceed uint256 as it can't exceed totalSupply.
// Taxes are capped at 10k and totalSupply is <= uint(128).max, overflow is impossible.
unchecked {
taxAndLimit memory buyConfig = buyTaxAndLimit;
uint256 fees = (amount * buyConfig.tax) / taxDenominator;
require(amount <= buyConfig.limit, "transfer exceeds max buy");
require(balanceOf[to] + amount <= maxWallet, "balance exceeds max wallet");
return fees;
}
}
function _sellTransfer(uint256 amount) internal view returns (uint256) {
unchecked {
taxAndLimit memory sellConfig = sellTaxAndLimit;
uint256 fees = (amount * sellConfig.tax) / taxDenominator;
require(amount <= sellConfig.limit, "transfer exceeds max sell");
// Do not check max wallet as market pairs are allowed to exceed it.
return fees;
}
}
function _baseTransfer(address to, uint256 amount) internal view returns (uint256) {
unchecked {
require(balanceOf[to] + amount <= maxWallet, "balance exceeds max wallet");
return (amount * transferTax) / taxDenominator;
}
}
function _swapTokens() internal {
// Only try to swap fees during a sell transaction.
uint256 numTokens = numTokensToSwap;
bool overMinTokenBalance = balanceOf[address(this)] >= numTokens;
if (
overMinTokenBalance &&
!inSwap &&
contractSwapEnabled
) {
// Try to swap the fees and send them to the tax recipient.
// If this fails, still allow the transfer to go through.
try this.swapFeesAndSend(numTokens, 0) {} catch {}
}
}
function _calcFees(address to, uint256 amount, bool isBuy, bool isSell) internal view returns (uint256) {
if(isBuy) {
return _buyTransfer(to, amount);
}
if(isSell) {
return _sellTransfer(amount);
}
return _baseTransfer(to, amount);
}
function _transfer(address from, address to, uint256 amount) internal {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
uint256 balance = balanceOf[from];
require(balance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
balanceOf[from] = balance - amount;
}
walletState memory fromWalletState = _walletState[from];
walletState memory toWalletState = _walletState[to];
// Don't allow blacklisted wallets to receive or send tokens.
require(!fromWalletState.isBlacklisted && !toWalletState.isBlacklisted, "blacklisted");
uint256 fees = 0;
bool takeFee = !fromWalletState.isExcludedFromFees && !toWalletState.isExcludedFromFees;
// Tax and enforce limits appriopriately.
if(takeFee) {
bool isBuy = fromWalletState.isMarketPair;
bool isSell = toWalletState.isMarketPair;
fees = _calcFees(to, amount, isBuy, isSell);
if(isSell && !isBuy) {
_swapTokens();
}
}
// Add the amount minus fees to the receiver.
uint256 amountMinusFees;
// Cannot overflow because the sum of all user
// balances can't exceed the max uint256 value.
// fees is less than amount, so it can't overflow.
unchecked {
amountMinusFees = amount - fees;
balanceOf[to] += amountMinusFees;
}
emit Transfer(from, to, amountMinusFees);
// Add any fees collected to the contract.
if(fees > 0) {
emit Transfer(from, address(this), fees);
unchecked {
balanceOf[address(this)] += fees;
}
}
}
/*//////////////////////////////////////////////////////////////
SWAP LOGIC
//////////////////////////////////////////////////////////////*/
modifier lockTheSwap {
inSwap = true;
_;
inSwap = false;
}
function swapFeesAndSend(uint256 tokenAmount, uint256 minOut) external lockTheSwap {
if(msg.sender != address(this)) {
require(manualSwapEnabled || msg.sender == owner(), "manual swap disabled");
}
// generate the uniswap pair path of token -> weth
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = WETH;
uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
minOut,
path,
taxRecipient, // Send ETH directly to the tax recipient.
block.timestamp
);
}
/*//////////////////////////////////////////////////////////////
OWNER-ONLY
//////////////////////////////////////////////////////////////*/
function setBlacklisted(address account, bool value) external onlyOwner {
require(account != address(this), "cant change contract");
_walletState[account].isBlacklisted = value;
emit BlacklistStatusUpdated(account, value);
}
function setMarketPair(address account, bool value) external onlyOwner {
require(account != address(this), "cant change contract");
_walletState[account].isMarketPair = value;
emit MarketPairUpdated(account, value);
}
function setExcludedFromFees(address account, bool value) external onlyOwner {
require(account != address(this), "cant change contract");
_walletState[account].isExcludedFromFees = value;
emit ExcludedFromFeesUpdated(account, value);
}
function setTaxRecipient(address account) external onlyOwner {
taxRecipient = account;
emit TaxRecipientUpdated(account);
}
function setTaxes(uint256 _buyTax, uint256 _sellTax, uint256 _transferTax) public onlyOwner {
// Cap any of the taxes to 10% max.
require(_buyTax <= maxTax, "buy is too high");
require(_sellTax <= maxTax, "sell is too high");
require(_transferTax <= maxTax, "transfer is too high");
buyTaxAndLimit.tax = uint128(_buyTax);
sellTaxAndLimit.tax = uint128(_sellTax);
transferTax = _transferTax;
emit TaxesUpdated(_buyTax, _sellTax, _transferTax);
}
// setLimits are in wad of tokens. 1e18 = 1 token.
function setLimits(uint256 _maxBuyWad, uint256 _maxSellWad, uint256 _maxWalletWad) public onlyOwner {
require(_maxBuyWad >= 20_000_000, "buy is too low");
require(_maxSellWad >= 20_000_000, "sell is too low");
require(_maxWalletWad >= 20_000_000, "wallet is too low");
buyTaxAndLimit.limit = uint128(_maxBuyWad * 10**decimals);
sellTaxAndLimit.limit = uint128(_maxSellWad * 10**decimals);
maxWallet = _maxWalletWad * 10**decimals;
emit LimitsUpdated(_maxBuyWad * 10**decimals, _maxSellWad * 10**decimals, _maxWalletWad * 10**decimals);
}
// setNumTokensToSwap is in wad of tokens. 1e18 = 1 token.
function setNumTokensToSwap(uint256 amountWad) external onlyOwner {
require(amountWad > 0, "amount cant be zero");
numTokensToSwap = amountWad * 10**decimals;
emit NumTokensToSwapUpdated(amountWad * 10**decimals);
}
function setContractSwapEnabled(bool _contractSwapEnabled, bool _manualSwapEnabled) public onlyOwner {
contractSwapEnabled = _contractSwapEnabled;
manualSwapEnabled = _manualSwapEnabled;
emit ContractSwapEnabledUpdated(_contractSwapEnabled, _manualSwapEnabled);
}
function Unpause() external onlyOwner {
_unpause();
}
function Pause() external onlyOwner {
_pause();
}
function updateUniswapRouter(address newRouter) external onlyOwner {
address oldRouterAddress = address(uniswapV2Router);
require(oldRouterAddress != newRouter, "can't set the same router address");
uniswapV2Router = IUniswapV2Router02(newRouter);
WETH = uniswapV2Router.WETH();
// Approve the new router to spend contract's tokens.
_approve(address(this), newRouter, type(uint256).max);
// Reset approval on old router.
_approve(address(this), oldRouterAddress, 0);
emit UniswapRouterUpdated(newRouter);
}
function openTrading() external onlyOwner {
// Start with manual swap disabled.
setContractSwapEnabled(true, false);
setLimits(
20_000_000,
20_000_000,
60_000_000
);
setTaxes(1000, 1000, 0);
_unpause();
}
function skimETH(address to, uint256 amount) external onlyOwner {
(bool success,) = to.call{value: amount}("");
require(success, "ETH transfer failed");
}
function safeTransfer(address token, address to, uint value) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length == 0 || abi.decode(data, (bool))), 'TRANSFER_FAILED');
}
function skimTokens(address tokenAddress, address to, uint256 amount) external onlyOwner {
safeTransfer(tokenAddress, to, amount);
}
/*//////////////////////////////////////////////////////////////
PAUSABLE OVERRIDES
//////////////////////////////////////////////////////////////*/
// Override the requireNotPaused implementation to allow the owner
// to interact with the contract while it is paused. This allows the
// owner to airdrop tokens or add liquidity while in a paused state.
function _requireNotPaused() internal view override{
if(paused()) {
if(tx.origin != owner() && msg.sender != owner()) {
revert EnforcedPause();
}
}
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
// Unchecked because the only math done is incrementing
// the owner's nonce which cannot realistically overflow.
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IUniswapV2Router01 {
function factory() external pure returns (address);
function WETH() 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);
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline
) external returns (uint amountA, uint amountB);
function removeLiquidityETH(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountToken, uint amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint liquidity,
uint amountAMin,
uint amountBMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountA, uint amountB);
function removeLiquidityETHWithPermit(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountToken, uint amountETH);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
external
returns (uint[] memory amounts);
function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
external
payable
returns (uint[] memory amounts);
function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
interface IUniswapV2Router02 is IUniswapV2Router01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external returns (uint amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint liquidity,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline,
bool approveMax, uint8 v, bytes32 r, bytes32 s
) external returns (uint amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
}
interface IUniswapV2Factory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
interface IUniswapV2Pair {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(address owner, address spender) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.19;
/// @dev removed context dependency.
/// @author OpenZeppelin https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol
abstract contract Ownable {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != msg.sender) {
revert OwnableUnauthorizedAccount(msg.sender);
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.19;
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
/// @dev edits: pass initial pause state in constructor and removed context dependency.
/// @author OpenZeppelin https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/Pausable.sol
abstract contract Pausable {
bool private _paused;
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
/**
* @dev The operation failed because the contract is paused.
*/
error EnforcedPause();
/**
* @dev The operation failed because the contract is not paused.
*/
error ExpectedPause();
/**
* @dev Initializes the contract in unpaused state.
*/
constructor(bool initialPaused) {
_paused = initialPaused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
if (paused()) {
revert EnforcedPause();
}
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
if (!paused()) {
revert ExpectedPause();
}
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(msg.sender);
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(msg.sender);
}
}
{
"compilationTarget": {
"AlphaGardeners.sol": "AG"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_taxRecipient","type":"address"},{"internalType":"address","name":"routerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","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":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"bool","name":"isBlacklisted","type":"bool"}],"name":"BlacklistStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"autoEnabled","type":"bool"},{"indexed":false,"internalType":"bool","name":"manualEnabled","type":"bool"}],"name":"ContractSwapEnabledUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludedFromFeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxBuy","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxSell","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxWallet","type":"uint256"}],"name":"LimitsUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"bool","name":"isMarketPair","type":"bool"}],"name":"MarketPairUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NumTokensToSwapUpdated","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":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"}],"name":"TaxRecipientUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"buyTax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sellTax","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"transferTax","type":"uint256"}],"name":"TaxesUpdated","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":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newRouter","type":"address"}],"name":"UniswapRouterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"Unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_walletState","outputs":[{"internalType":"bool","name":"isBlacklisted","type":"bool"},{"internalType":"bool","name":"isMarketPair","type":"bool"},{"internalType":"bool","name":"isExcludedFromFees","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","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":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyTaxAndLimit","outputs":[{"internalType":"uint128","name":"tax","type":"uint128"},{"internalType":"uint128","name":"limit","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractSwapEnabled","outputs":[{"internalType":"bool","name":"","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":[{"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":"manualSwapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"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":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numTokensToSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"openTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sellTaxAndLimit","outputs":[{"internalType":"uint128","name":"tax","type":"uint128"},{"internalType":"uint128","name":"limit","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setBlacklisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_contractSwapEnabled","type":"bool"},{"internalType":"bool","name":"_manualSwapEnabled","type":"bool"}],"name":"setContractSwapEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setExcludedFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxBuyWad","type":"uint256"},{"internalType":"uint256","name":"_maxSellWad","type":"uint256"},{"internalType":"uint256","name":"_maxWalletWad","type":"uint256"}],"name":"setLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setMarketPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountWad","type":"uint256"}],"name":"setNumTokensToSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"setTaxRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_buyTax","type":"uint256"},{"internalType":"uint256","name":"_sellTax","type":"uint256"},{"internalType":"uint256","name":"_transferTax","type":"uint256"}],"name":"setTaxes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"skimETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"skimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmount","type":"uint256"},{"internalType":"uint256","name":"minOut","type":"uint256"}],"name":"swapFeesAndSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","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":[],"name":"transferTax","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newRouter","type":"address"}],"name":"updateUniswapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"}]