// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
// Liquid Agent
//
// The natural language layer for Web3 autonomy.
//
// Website : liquidagent.ai
// X : x.com/liquidagentai
// TG : t.me/liquidagentai
//
//
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
// OpenZeppelin imports
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
// Uniswap V2 Router interface
interface IUniswapV2Router {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external;
function addLiquidityETH(
address token,
uint amountTokenDesired,
uint amountTokenMin,
uint amountETHMin,
address to,
uint deadline
) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}
// Uniswap V2 Factory interface
interface IUniswapV2Factory {
function createPair(address tokenA, address tokenB) external returns (address pair);
function getPair(address tokenA, address tokenB) external view returns (address pair);
}
/**
* @title LiquidAgent
* @dev ERC20 token
*/
contract LiquidAgent is IERC20, IERC20Metadata, Ownable, ReentrancyGuard {
using Address for address payable;
using SafeERC20 for IERC20;
// Token configuration
mapping(address => uint256) private _tokenBalances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalTokenSupply;
string private _tokenName;
string private _tokenSymbol;
uint8 private _tokenDecimals;
// Tax configuration structure
struct TaxConfiguration {
uint256 buyTaxRate;
uint256 sellTaxRate;
uint256 transferTaxRate;
bool isConfigurationLocked;
}
// Tax wallet distribution structure
struct WalletDistribution {
address payable firstWallet;
address payable secondWallet;
address payable thirdWallet;
uint256 firstPercentage;
uint256 secondPercentage;
// Third wallet gets the remainder
}
// State variables
TaxConfiguration public taxConfig;
WalletDistribution public walletConfig;
// Tax reduction tracking
bool public hasTaxReachedMaxLimit;
bool public launchTaxActivated;
// Trading and exemption mappings
mapping(address => bool) private _isExcludedFromTax;
mapping(address => bool) private _isAutomatedMarketMaker;
// Uniswap integration
IUniswapV2Router public immutable uniswapRouter;
address public immutable tradingPair;
address public immutable wrappedETH;
// Trading controls
bool public tradingEnabled;
bool public hasLiquidityBeenAdded;
uint256 public launchStamp;
// Wallet limits
bool public limitsEnabled = true;
uint256 public maxWalletAmount;
mapping(address => bool) private _isExcludedFromLimits;
// Tax swap configuration
uint256 public taxSwapThreshold;
uint256 private maxTaxSwapTokens;
// MEV protection and gas optimization for tax swaps
bool private inSwap;
uint256 public taxSwapCount;
uint256 public lastTaxSwapBlock;
uint256 public maxTaxSwapsPerBlock = 10;
// Circuit breaker for tax swaps
uint256 public maxTaxSwapAmount;
// Constants
uint256 public constant MAX_TAX_RATE = 500; // 5%
uint256 public constant TAX_DENOMINATOR = 10000; // 100%
uint256 public constant LAUNCH_BUY_TAX = 3000; // 30%
uint256 public constant LAUNCH_SELL_TAX = 3000; // 30%
// Unicrypt vesting contract
address public constant UNICRYPT_VESTING = 0xDba68f07d1b7Ca219f78ae8582C213d975c25cAf;
// Modifiers
modifier validAddress(address addr) {
require(addr != address(0), "Invalid: zero address provided");
_;
}
modifier lockTheSwap {
inSwap = true;
_;
inSwap = false;
}
// Events
event TradingActivated(uint256 timestamp);
event LaunchTaxActivated(uint256 buyTax, uint256 sellTax, uint256 timestamp);
event TaxRatesUpdated(uint256 buyTax, uint256 sellTax, uint256 transferTax);
event WalletConfigurationUpdated(
address firstWallet,
address secondWallet,
address thirdWallet,
uint256 firstPercentage,
uint256 secondPercentage
);
event TaxSwapExecuted(uint256 tokensSwapped, uint256 ethReceived);
event TaxConfigurationLocked();
event MaxWalletUpdated(uint256 newMaxWallet);
event LimitsRemoved();
event ExcludedFromLimits(address account, bool isExcluded);
event CircuitBreakerUpdated(uint256 newMaxTaxSwapAmount);
event CircuitBreakerTriggered(uint256 attemptedAmount, uint256 limitedTo);
event TaxReachedMaxLimit(uint256 timestamp, string message);
event MaxTaxSwapsPerBlockUpdated(uint256 maxTaxSwapsPerBlock);
event LiquidityDetected(uint256 timestamp);
/**
* @dev Constructor sets up the token with initial parameters
* @param name_ Token name
* @param symbol_ Token symbol
* @param totalSupply_ Total supply (will be multiplied by 10^18)
* @param firstWallet_ First tax wallet address
* @param secondWallet_ Second tax wallet address
* @param thirdWallet_ Third tax wallet address
*/
constructor(
string memory name_,
string memory symbol_,
uint256 totalSupply_,
address firstWallet_,
address secondWallet_,
address thirdWallet_
) Ownable(msg.sender)
validAddress(firstWallet_)
validAddress(secondWallet_)
validAddress(thirdWallet_) {
_tokenName = name_;
_tokenSymbol = symbol_;
_tokenDecimals = 18;
_totalTokenSupply = totalSupply_ * 10**_tokenDecimals;
// Initialize tax configuration
taxConfig = TaxConfiguration({
buyTaxRate: 0,
sellTaxRate: 0,
transferTaxRate: 0,
isConfigurationLocked: false
});
// Initialize wallet distribution
walletConfig = WalletDistribution({
firstWallet: payable(firstWallet_),
secondWallet: payable(secondWallet_),
thirdWallet: payable(thirdWallet_),
firstPercentage: 2500,
secondPercentage: 1275
// Third wallet gets remainder
});
// Initialize tax reduction tracking - start with max limit reached (flexible phase)
hasTaxReachedMaxLimit = true;
launchTaxActivated = false;
// Setup Uniswap V2 integration
// Mainnet Router: 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
IUniswapV2Router router = IUniswapV2Router(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
uniswapRouter = router;
wrappedETH = router.WETH();
tradingPair = IUniswapV2Factory(router.factory()).createPair(address(this), wrappedETH);
_isAutomatedMarketMaker[tradingPair] = true;
// Set tax swap thresholds
taxSwapThreshold = _totalTokenSupply / 2000; // 0.05%
maxTaxSwapTokens = _totalTokenSupply / 200; // 0.5%
// Set circuit breaker for tax swaps
maxTaxSwapAmount = _totalTokenSupply / 100; // 1% max per tax swap
// Set max wallet to 2% of total supply initially
maxWalletAmount = _totalTokenSupply * 2 / 100;
// Exempt owner, contract, router from taxes
_isExcludedFromTax[owner()] = true;
_isExcludedFromTax[address(this)] = true;
_isExcludedFromTax[address(router)] = true;
// Exempt critical addresses from limits
_isExcludedFromLimits[owner()] = true;
_isExcludedFromLimits[address(this)] = true;
_isExcludedFromLimits[address(router)] = true;
_isExcludedFromLimits[tradingPair] = true;
_isExcludedFromLimits[address(0xdead)] = true;
_isExcludedFromLimits[0x5cD13f71219461f4a7E94E818276076FA4c59C10] = true; // Exempt liquid-protocol
_isExcludedFromLimits[0xbDaC83D36D9f24B8e1CF4e16f507Bd2ac95e81aA] = true; // Exempt liquid-marketing
_isExcludedFromLimits[0x4d6a1087F96F1F2f88C0a67C0B60253251eE8f4d] = true; // Exempt liquid-rewards
_isExcludedFromLimits[0x3BE34c82750885FD26C7aAd8D8ad0559B34a5E69] = true; // Exempt liquid-team
// Exempt Unicrypt vesting contract from wallet limits
_isExcludedFromLimits[UNICRYPT_VESTING] = true;
// Mint total supply to owner
_tokenBalances[owner()] = _totalTokenSupply;
emit Transfer(address(0), owner(), _totalTokenSupply);
// Approve router for swaps
_approve(address(this), address(router), type(uint256).max);
}
// ERC20 standard functions
function name() public view override returns (string memory) {
return _tokenName;
}
function symbol() public view override returns (string memory) {
return _tokenSymbol;
}
function decimals() public view override returns (uint8) {
return _tokenDecimals;
}
function totalSupply() public view override returns (uint256) {
return _totalTokenSupply;
}
function balanceOf(address account) public view override returns (uint256) {
return _tokenBalances[account];
}
function transfer(address recipient, uint256 amount) public override returns (bool) {
_executeTransfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "Transfer: amount exceeds allowance");
_executeTransfer(sender, recipient, amount);
_approve(sender, _msgSender(), currentAllowance - amount);
return true;
}
/**
* @dev Internal approval function
*/
function _approve(address owner, address spender, uint256 amount) internal {
require(owner != address(0), "Approve: from zero address");
require(spender != address(0), "Approve: to zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Main transfer function with tax logic
*/
function _executeTransfer(address sender, address recipient, uint256 amount) internal {
require(sender != address(0), "Transfer: from zero address");
require(recipient != address(0), "Transfer: to zero address");
require(amount > 0, "Transfer: amount must be greater than zero");
require(_tokenBalances[sender] >= amount, "Transfer: amount exceeds balance");
bool shouldTakeTax = _shouldApplyTax(sender, recipient);
// Handle tax swap on sells
if (shouldTakeTax && _isAutomatedMarketMaker[recipient]) {
_processTaxSwap();
}
uint256 transferAmount = amount;
if (shouldTakeTax) {
uint256 taxAmount = _calculateTaxAmount(sender, recipient, amount);
if (taxAmount > 0) {
transferAmount = amount - taxAmount;
_tokenBalances[sender] -= taxAmount;
_tokenBalances[address(this)] += taxAmount;
emit Transfer(sender, address(this), taxAmount);
}
}
// Check wallet limits after tax calculation using received amount
if (limitsEnabled && !_isExcludedFromLimits[recipient]) {
_checkWalletLimits(recipient, transferAmount);
}
_tokenBalances[sender] -= transferAmount;
_tokenBalances[recipient] += transferAmount;
emit Transfer(sender, recipient, transferAmount);
// Check for initial liquidity addition
if (!hasLiquidityBeenAdded && recipient == tradingPair) {
_checkLiquidityAdd();
}
}
/**
* @dev Checks and marks when initial liquidity is added
*/
function _checkLiquidityAdd() internal {
if (!hasLiquidityBeenAdded) {
// Check if there's meaningful liquidity in the trading pair
uint256 pairBalance = _tokenBalances[tradingPair];
if (pairBalance > _totalTokenSupply / 10000) { // More than 0.01% of supply
hasLiquidityBeenAdded = true;
emit LiquidityDetected(block.timestamp);
}
}
}
/**
* @dev Checks wallet limits for recipients - now uses actual received amount
*/
function _checkWalletLimits(address recipient, uint256 amount) internal view {
if (!_isExcludedFromLimits[recipient]) {
require(
_tokenBalances[recipient] + amount <= maxWalletAmount,
"Transfer: exceeds max wallet limit"
);
}
}
/**
* @dev Determines if tax should be applied to a transfer
*/
function _shouldApplyTax(address sender, address recipient) internal view returns (bool) {
return !_isExcludedFromTax[sender] && !_isExcludedFromTax[recipient] && tradingEnabled;
}
/**
* @dev Calculates tax amount based on transfer type
*/
function _calculateTaxAmount(address sender, address recipient, uint256 amount) internal view returns (uint256) {
uint256 taxRate = 0;
if (_isAutomatedMarketMaker[sender]) {
// Buy transaction
taxRate = taxConfig.buyTaxRate;
} else if (_isAutomatedMarketMaker[recipient]) {
// Sell transaction
taxRate = taxConfig.sellTaxRate;
} else {
// Regular transfer
taxRate = taxConfig.transferTaxRate;
}
return (amount * taxRate) / TAX_DENOMINATOR;
}
/**
* @dev tax swap mechanism with MEV protection
*/
function _processTaxSwap() internal {
uint256 contractTokenBalance = balanceOf(address(this));
// Simple conditions for tax swap
if (!inSwap && contractTokenBalance > taxSwapThreshold) {
// Reset tax swap count on new block
if (block.number > lastTaxSwapBlock) {
taxSwapCount = 0;
}
// Limit tax swaps per block
if (taxSwapCount >= maxTaxSwapsPerBlock) {
return;
}
uint256 tokensToSwap = _calculateOptimalSwapAmount(contractTokenBalance);
_swapTokensForETH(tokensToSwap);
uint256 contractETHBalance = address(this).balance;
if (contractETHBalance > 0) {
_distributeTaxETH(contractETHBalance);
emit TaxSwapExecuted(tokensToSwap, contractETHBalance);
}
taxSwapCount++;
lastTaxSwapBlock = block.number;
}
}
/**
* @dev Calculate optimal swap amount with safety checks
*/
function _calculateOptimalSwapAmount(uint256 contractBalance) internal view returns (uint256) {
uint256 tokensToSwap = contractBalance;
// Apply maximum swap limit
if (tokensToSwap > maxTaxSwapTokens) {
tokensToSwap = maxTaxSwapTokens;
}
// Apply circuit breaker
if (tokensToSwap > maxTaxSwapAmount) {
tokensToSwap = maxTaxSwapAmount;
}
return tokensToSwap;
}
/**
* @dev Swap tokens for ETH with reentrancy protection
*/
function _swapTokensForETH(uint256 tokenAmount) internal lockTheSwap {
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = wrappedETH;
try uniswapRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0,
path,
address(this),
block.timestamp + 300
) {
// Swap succeeded
} catch {
// Swap failed - tokens remain in contract for next attempt
}
}
/**
* @dev Safe ETH distribution using OpenZeppelin's sendValue
*/
function _distributeTaxETH(uint256 ethAmount) internal {
uint256 firstAmount = (ethAmount * walletConfig.firstPercentage) / 10000;
uint256 secondAmount = (ethAmount * walletConfig.secondPercentage) / 10000;
uint256 thirdAmount = ethAmount - firstAmount - secondAmount;
if (firstAmount > 0) {
walletConfig.firstWallet.sendValue(firstAmount);
}
if (secondAmount > 0) {
walletConfig.secondWallet.sendValue(secondAmount);
}
if (thirdAmount > 0) {
walletConfig.thirdWallet.sendValue(thirdAmount);
}
}
// Owner functions
/**
* @dev Enables trading
*/
function enableTrading() external onlyOwner {
require(!tradingEnabled, "Trading already enabled!");
require(hasLiquidityBeenAdded, "Liquidity must be added.");
tradingEnabled = true;
launchStamp = block.timestamp;
emit TradingActivated(block.timestamp);
}
/**
* @dev NEW: Activates launch tax and enables reduction phase
*/
function activateLaunchTax() external onlyOwner {
require(!launchTaxActivated, "Launch tax already activated");
require(!taxConfig.isConfigurationLocked, "Tax configuration is locked");
// Set launch tax rates
taxConfig.buyTaxRate = LAUNCH_BUY_TAX;
taxConfig.sellTaxRate = LAUNCH_SELL_TAX;
taxConfig.transferTaxRate = 0;
// Enable reduction phase (taxes can only be reduced until reaching 5%)
hasTaxReachedMaxLimit = false;
launchTaxActivated = true;
emit LaunchTaxActivated(LAUNCH_BUY_TAX, LAUNCH_SELL_TAX, block.timestamp);
emit TaxRatesUpdated(LAUNCH_BUY_TAX, LAUNCH_SELL_TAX, 0);
}
/**
* @dev Manually mark liquidity as added (fallback)
*/
function setLiquidityAdded() external onlyOwner {
hasLiquidityBeenAdded = true;
}
/**
* @dev Update tax rates
*/
function updateTaxRates(
uint256 newBuyTax,
uint256 newSellTax,
uint256 newTransferTax
) external onlyOwner {
require(!taxConfig.isConfigurationLocked, "Tax: configuration is locked");
require(newTransferTax <= MAX_TAX_RATE, "Tax: transfer tax exceeds maximum");
if (hasTaxReachedMaxLimit) {
// Phase 2: Flexible phase - can move freely between 0-5%
require(newBuyTax <= MAX_TAX_RATE, "Tax: buy tax exceeds 5% maximum");
require(newSellTax <= MAX_TAX_RATE, "Tax: sell tax exceeds 5% maximum");
} else {
// Phase 1: Reduction phase - can only reduce taxes
require(newBuyTax <= taxConfig.buyTaxRate, "Tax: can only reduce buy tax");
require(newSellTax <= taxConfig.sellTaxRate, "Tax: can only reduce sell tax");
// Check if we're transitioning to flexible phase
if (newBuyTax <= MAX_TAX_RATE && newSellTax <= MAX_TAX_RATE) {
hasTaxReachedMaxLimit = true;
emit TaxReachedMaxLimit(block.timestamp, "Tax reduction phase complete - now flexible between 0-5%");
}
}
// Update rates
taxConfig.buyTaxRate = newBuyTax;
taxConfig.sellTaxRate = newSellTax;
taxConfig.transferTaxRate = newTransferTax;
emit TaxRatesUpdated(newBuyTax, newSellTax, newTransferTax);
}
/**
* @dev Locks tax configuration to prevent further changes
*/
function lockTaxConfiguration() external onlyOwner {
taxConfig.isConfigurationLocked = true;
emit TaxConfigurationLocked();
}
/**
* @dev Updates tax wallet configuration and distribution
*/
function updateWalletConfiguration(
address newFirstWallet,
address newSecondWallet,
address newThirdWallet,
uint256 newFirstPercentage,
uint256 newSecondPercentage
) external onlyOwner
validAddress(newFirstWallet)
validAddress(newSecondWallet)
validAddress(newThirdWallet) {
require(newFirstPercentage + newSecondPercentage <= 10000, "Wallet: percentages exceed 100%");
walletConfig.firstWallet = payable(newFirstWallet);
walletConfig.secondWallet = payable(newSecondWallet);
walletConfig.thirdWallet = payable(newThirdWallet);
walletConfig.firstPercentage = newFirstPercentage;
walletConfig.secondPercentage = newSecondPercentage;
emit WalletConfigurationUpdated(
newFirstWallet,
newSecondWallet,
newThirdWallet,
newFirstPercentage,
newSecondPercentage
);
}
/**
* @dev Updates circuit breaker parameters
*/
function updateCircuitBreaker(uint256 newMaxTaxSwapAmount) external onlyOwner {
require(newMaxTaxSwapAmount >= _totalTokenSupply / 10000, "Circuit breaker: minimum 0.01%");
require(newMaxTaxSwapAmount <= _totalTokenSupply / 100, "Circuit breaker: maximum 1%");
maxTaxSwapAmount = newMaxTaxSwapAmount;
emit CircuitBreakerUpdated(newMaxTaxSwapAmount);
}
/**
* @dev Updates MEV protection setting for tax swaps
*/
function updateMaxTaxSwapsPerBlock(uint256 _maxTaxSwapsPerBlock) external onlyOwner {
require(_maxTaxSwapsPerBlock >= 1 && _maxTaxSwapsPerBlock <= 10, "Invalid tax swaps per block");
maxTaxSwapsPerBlock = _maxTaxSwapsPerBlock;
emit MaxTaxSwapsPerBlockUpdated(_maxTaxSwapsPerBlock);
}
/**
* @dev Sets limit exemption status for an address
*/
function setLimitExemption(address account, bool isExempt) external onlyOwner validAddress(account) {
_isExcludedFromLimits[account] = isExempt;
emit ExcludedFromLimits(account, isExempt);
}
/**
* @dev Updates maximum wallet amount
*/
function updateMaxWallet(uint256 newMaxWallet) external onlyOwner {
require(newMaxWallet >= _totalTokenSupply / 1000, "Max wallet: cannot be less than 0.1%");
maxWalletAmount = newMaxWallet;
emit MaxWalletUpdated(newMaxWallet);
}
/**
* @dev Removes all wallet limits permanently
*/
function removeLimits() external onlyOwner {
require(limitsEnabled, "Limits: already removed");
limitsEnabled = false;
emit LimitsRemoved();
}
/**
* @dev Sets tax exemption status for an address
*/
function setTaxExemption(address account, bool isExempt) external onlyOwner validAddress(account) {
_isExcludedFromTax[account] = isExempt;
}
/**
* @dev Sets automated market maker pair status
*/
function setAutomatedMarketMaker(address pair, bool isAMM) external onlyOwner validAddress(pair) {
_isAutomatedMarketMaker[pair] = isAMM;
}
/**
* @dev Updates tax swap threshold parameters
*/
function updateTaxSwapConfiguration(uint256 newThreshold, uint256 newMaxSwap) external onlyOwner {
require(newThreshold > 0, "Tax swap: threshold must be greater than zero");
require(newMaxSwap >= newThreshold, "Tax swap: max must be greater than or equal to threshold");
taxSwapThreshold = newThreshold;
maxTaxSwapTokens = newMaxSwap;
}
/**
* @dev Manually triggers tax swap with reentrancy protection
*/
function manualTaxSwap() external onlyOwner nonReentrant {
_processTaxSwap();
}
/**
* @dev Emergency function to recover stuck ETH with safe transfers
*/
function rescueETH() external onlyOwner nonReentrant {
uint256 balance = address(this).balance;
require(balance > 0, "Rescue: no ETH to rescue");
payable(owner()).sendValue(balance);
}
/**
* @dev Emergency function to recover stuck tokens using SafeERC20
*/
function rescueTokens(address tokenAddress, uint256 amount) external onlyOwner nonReentrant {
require(tokenAddress != address(this), "Rescue: cannot rescue own tokens");
IERC20(tokenAddress).safeTransfer(owner(), amount);
}
// View functions
function isExcludedFromTax(address account) external view returns (bool) {
return _isExcludedFromTax[account];
}
function isExcludedFromLimits(address account) external view returns (bool) {
return _isExcludedFromLimits[account];
}
function isAutomatedMarketMaker(address pair) external view returns (bool) {
return _isAutomatedMarketMaker[pair];
}
function getTaxRates() external view returns (uint256 buyTax, uint256 sellTax, uint256 transferTax) {
return (taxConfig.buyTaxRate, taxConfig.sellTaxRate, taxConfig.transferTaxRate);
}
/**
* @dev Returns wallet configuration
*/
function getWalletConfiguration() external view returns (
address first,
address second,
address third,
uint256 firstPercentage,
uint256 secondPercentage,
uint256 thirdPercentage
) {
uint256 remainingPercentage = 10000 - walletConfig.firstPercentage - walletConfig.secondPercentage;
return (
walletConfig.firstWallet,
walletConfig.secondWallet,
walletConfig.thirdWallet,
walletConfig.firstPercentage,
walletConfig.secondPercentage,
remainingPercentage
);
}
function getLimitStatus() external view returns (bool enabled, uint256 maxWallet) {
return (limitsEnabled, maxWalletAmount);
}
function getCircuitBreakerStatus() external view returns (uint256 maxSwapAmount, uint256 lastSwapBlock) {
return (maxTaxSwapAmount, lastTaxSwapBlock);
}
function getTaxSwapConfiguration() external view returns (uint256 threshold, uint256 maxSwap) {
return (taxSwapThreshold, maxTaxSwapTokens);
}
/**
* @dev Returns the current tax reduction phase status
*/
function getTaxReductionStatus() external view returns (bool hasReachedMaxLimit, string memory phase) {
if (hasTaxReachedMaxLimit) {
return (true, "Flexible Phase: Tax can move freely between 0-5%");
} else {
return (false, "Reduction Phase: Tax can only be reduced until reaching 5%");
}
}
/**
* @dev NEW: Returns launch tax activation status
*/
function getLaunchTaxStatus() external view returns (bool activated, uint256 launchBuyTax, uint256 launchSellTax) {
return (launchTaxActivated, LAUNCH_BUY_TAX, LAUNCH_SELL_TAX);
}
/**
* @dev View function for tax swap MEV protection
*/
function getTaxSwapStats() external view returns (
uint256 currentTaxSwapCount,
uint256 currentBlock,
uint256 lastBlock,
bool canSwap
) {
bool canSwapNow = (block.number > lastTaxSwapBlock) || (taxSwapCount < maxTaxSwapsPerBlock);
return (taxSwapCount, block.number, lastTaxSwapBlock, canSwapNow);
}
// Fallback to receive ETH
receive() external payable {}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
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) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_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() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @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 v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
{
"compilationTarget": {
"src/LiquidAgent.sol": "LiquidAgent"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"viaIR": true
}
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint256","name":"totalSupply_","type":"uint256"},{"internalType":"address","name":"firstWallet_","type":"address"},{"internalType":"address","name":"secondWallet_","type":"address"},{"internalType":"address","name":"thirdWallet_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","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":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"attemptedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"limitedTo","type":"uint256"}],"name":"CircuitBreakerTriggered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxTaxSwapAmount","type":"uint256"}],"name":"CircuitBreakerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"ExcludedFromLimits","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":"timestamp","type":"uint256"}],"name":"LaunchTaxActivated","type":"event"},{"anonymous":false,"inputs":[],"name":"LimitsRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"LiquidityDetected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxTaxSwapsPerBlock","type":"uint256"}],"name":"MaxTaxSwapsPerBlockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newMaxWallet","type":"uint256"}],"name":"MaxWalletUpdated","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":[],"name":"TaxConfigurationLocked","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":"TaxRatesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"TaxReachedMaxLimit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokensSwapped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethReceived","type":"uint256"}],"name":"TaxSwapExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"TradingActivated","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"firstWallet","type":"address"},{"indexed":false,"internalType":"address","name":"secondWallet","type":"address"},{"indexed":false,"internalType":"address","name":"thirdWallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"firstPercentage","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"secondPercentage","type":"uint256"}],"name":"WalletConfigurationUpdated","type":"event"},{"inputs":[],"name":"LAUNCH_BUY_TAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LAUNCH_SELL_TAX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TAX_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TAX_DENOMINATOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"UNICRYPT_VESTING","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activateLaunchTax","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","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":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"enableTrading","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCircuitBreakerStatus","outputs":[{"internalType":"uint256","name":"maxSwapAmount","type":"uint256"},{"internalType":"uint256","name":"lastSwapBlock","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLaunchTaxStatus","outputs":[{"internalType":"bool","name":"activated","type":"bool"},{"internalType":"uint256","name":"launchBuyTax","type":"uint256"},{"internalType":"uint256","name":"launchSellTax","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLimitStatus","outputs":[{"internalType":"bool","name":"enabled","type":"bool"},{"internalType":"uint256","name":"maxWallet","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxRates","outputs":[{"internalType":"uint256","name":"buyTax","type":"uint256"},{"internalType":"uint256","name":"sellTax","type":"uint256"},{"internalType":"uint256","name":"transferTax","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxReductionStatus","outputs":[{"internalType":"bool","name":"hasReachedMaxLimit","type":"bool"},{"internalType":"string","name":"phase","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxSwapConfiguration","outputs":[{"internalType":"uint256","name":"threshold","type":"uint256"},{"internalType":"uint256","name":"maxSwap","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTaxSwapStats","outputs":[{"internalType":"uint256","name":"currentTaxSwapCount","type":"uint256"},{"internalType":"uint256","name":"currentBlock","type":"uint256"},{"internalType":"uint256","name":"lastBlock","type":"uint256"},{"internalType":"bool","name":"canSwap","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWalletConfiguration","outputs":[{"internalType":"address","name":"first","type":"address"},{"internalType":"address","name":"second","type":"address"},{"internalType":"address","name":"third","type":"address"},{"internalType":"uint256","name":"firstPercentage","type":"uint256"},{"internalType":"uint256","name":"secondPercentage","type":"uint256"},{"internalType":"uint256","name":"thirdPercentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasLiquidityBeenAdded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hasTaxReachedMaxLimit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"}],"name":"isAutomatedMarketMaker","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromLimits","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isExcludedFromTax","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastTaxSwapBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchStamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launchTaxActivated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitsEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockTaxConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"manualTaxSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxTaxSwapAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxTaxSwapsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWalletAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"removeLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rescueETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pair","type":"address"},{"internalType":"bool","name":"isAMM","type":"bool"}],"name":"setAutomatedMarketMaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isExempt","type":"bool"}],"name":"setLimitExemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"setLiquidityAdded","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"isExempt","type":"bool"}],"name":"setTaxExemption","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxConfig","outputs":[{"internalType":"uint256","name":"buyTaxRate","type":"uint256"},{"internalType":"uint256","name":"sellTaxRate","type":"uint256"},{"internalType":"uint256","name":"transferTaxRate","type":"uint256"},{"internalType":"bool","name":"isConfigurationLocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxSwapCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxSwapThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tradingPair","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","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":"uniswapRouter","outputs":[{"internalType":"contract IUniswapV2Router","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxTaxSwapAmount","type":"uint256"}],"name":"updateCircuitBreaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxTaxSwapsPerBlock","type":"uint256"}],"name":"updateMaxTaxSwapsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMaxWallet","type":"uint256"}],"name":"updateMaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newBuyTax","type":"uint256"},{"internalType":"uint256","name":"newSellTax","type":"uint256"},{"internalType":"uint256","name":"newTransferTax","type":"uint256"}],"name":"updateTaxRates","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newThreshold","type":"uint256"},{"internalType":"uint256","name":"newMaxSwap","type":"uint256"}],"name":"updateTaxSwapConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFirstWallet","type":"address"},{"internalType":"address","name":"newSecondWallet","type":"address"},{"internalType":"address","name":"newThirdWallet","type":"address"},{"internalType":"uint256","name":"newFirstPercentage","type":"uint256"},{"internalType":"uint256","name":"newSecondPercentage","type":"uint256"}],"name":"updateWalletConfiguration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"walletConfig","outputs":[{"internalType":"address payable","name":"firstWallet","type":"address"},{"internalType":"address payable","name":"secondWallet","type":"address"},{"internalType":"address payable","name":"thirdWallet","type":"address"},{"internalType":"uint256","name":"firstPercentage","type":"uint256"},{"internalType":"uint256","name":"secondPercentage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wrappedETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]