Contract Source Code:
File 1 of 1 : LIQR
// Official Links for LIQR Token
// Telegram: https://t.me/liquidityrush
// X: https://x.com/liquidityrush
// Website: https://liquidityrush.com/
// File: LIQR Contracts/liqr-2/contracts/interfaces/ILIQRStaking.sol
pragma solidity ^0.8.19;
interface ILIQRStaking {
struct UserInfo {
uint256 amount;
uint256 rewardDebt;
uint256 totalEarned;
}
function getUserInfo(address) external view returns (UserInfo memory);
}
// File: LIQR Contracts/liqr-2/contracts/interfaces/IDexFactory.sol
pragma solidity ^0.8.19;
interface IDexFactory {
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;
}
// File: LIQR Contracts/liqr-2/contracts/interfaces/IDexRouter.sol
pragma solidity ^0.8.19;
interface IDexRouter01 {
function factory() external pure returns (address);
function WETH() external pure returns (address);
function addLiquidity(
address tokenA,
address tokenB,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
function addLiquidityETH(
address token,
uint256 amountTokenDesired,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
)
external
payable
returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
function removeLiquidity(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETH(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountToken, uint256 amountETH);
function removeLiquidityWithPermit(
address tokenA,
address tokenB,
uint256 liquidity,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountA, uint256 amountB);
function removeLiquidityETHWithPermit(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountToken, uint256 amountETH);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapTokensForExactETH(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapETHForExactTokens(
uint256 amountOut,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external pure returns (uint256 amountB);
function getAmountOut(
uint256 amountIn,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountsOut(
uint256 amountIn,
address[] calldata path
) external view returns (uint256[] memory amounts);
function getAmountsIn(
uint256 amountOut,
address[] calldata path
) external view returns (uint256[] memory amounts);
}
interface IDexRouter is IDexRouter01 {
function removeLiquidityETHSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline
) external returns (uint256 amountETH);
function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
address token,
uint256 liquidity,
uint256 amountTokenMin,
uint256 amountETHMin,
address to,
uint256 deadline,
bool approveMax,
uint8 v,
bytes32 r,
bytes32 s
) external returns (uint256 amountETH);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
function swapExactTokensForETHSupportingFeeOnTransferTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external;
}
// File: LIQR Contracts/liqr-2/contracts/interfaces/DividendPayingTokenOptionalInterface.sol
pragma solidity ^0.8.19;
interface DividendPayingTokenOptionalInterface {
/// @notice View the amt of dividend in wei that an address can withdraw.
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` can withdraw.
function withdrawableDividendOf(address _owner) external view returns(uint256);
/// @notice View the amt of dividend in wei that an address has withdrawn.
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` has withdrawn.
function withdrawnDividendOf(address _owner) external view returns(uint256);
/// @notice View the amt of dividend in wei that an address has earned in total.
/// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` has earned in total.
function accumulativeDividendOf(address _owner) external view returns(uint256);
}
// File: LIQR Contracts/liqr-2/contracts/interfaces/DividendPayingTokenInterface.sol
pragma solidity ^0.8.19;
interface DividendPayingTokenInterface {
/// @notice View the amt of dividend in wei that an address can withdraw.
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` can withdraw.
function dividendOf(address _owner) external view returns(uint256);
/// @notice Distributes ether to token holders as dividends.
/// @dev SHOULD distribute the paid ether to token holders as dividends.
/// SHOULD NOT directly transfer ether to token holders in this function.
/// MUST emit a `DividendsDistributed` event when the amt of distributed ether is greater than 0.
function distributeDividends() external payable;
/// @notice Withdraws the ether distributed to the sender.
/// @dev SHOULD transfer `dividendOf(msg.sender)` wei to `msg.sender`, and `dividendOf(msg.sender)` SHOULD be 0 after the transfer.
/// MUST emit a `DividendWithdrawn` event if the amt of ether transferred is greater than 0.
function withdrawDividend() external;
/// @dev This event MUST emit when ether is distributed to token holders.
/// @param from The address which sends ether to this contract.
/// @param weiAmt The amt of distributed ether in wei.
event DividendsDistributed(
address indexed from,
uint256 weiAmt
);
/// @dev This event MUST emit when an address withdraws their dividend.
/// @param to The address which withdraws ether from this contract.
/// @param weiAmt The amt of withdrawn ether in wei.
event DividendWithdrawn(
address indexed to,
uint256 weiAmt
);
}
// File: @openzeppelin/contracts/utils/math/SafeMath.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/SafeMath.sol)
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
// File: @openzeppelin/contracts/utils/Address.sol
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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, it is bubbled up by this
* function (like regular Solidity function calls).
*
* 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.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @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`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);
}
}
}
// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @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.
*/
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].
*/
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);
}
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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;
}
}
// File: @openzeppelin/contracts/access/Ownable.sol
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
/**
* @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.
*
* By default, the owner account will be the one that deploys the contract. 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;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @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 {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @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 {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_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);
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount) external returns (bool);
}
// File: @openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 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);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @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.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @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, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @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.isContract(address(token));
}
}
// File: LIQR Contracts/liqr-2/contracts/DividendPayingToken.sol
pragma solidity ^0.8.19;
library SafeMathUint {
function toInt256Safe(uint256 a) internal pure returns (int256) {
int256 b = int256(a);
require(b >= 0);
return b;
}
}
library SafeMathInt {
int256 private constant MIN_INT256 = int256(1) << 255;
int256 private constant MAX_INT256 = ~(int256(1) << 255);
/**
* @dev Multiplies two int256 variables and fails on overflow.
*/
function mul(int256 a, int256 b) internal pure returns (int256) {
int256 c = a * b;
// Detect overflow when multiplying MIN_INT256 with -1
require(c != MIN_INT256 || (a & MIN_INT256) != (b & MIN_INT256));
require((b == 0) || (c / b == a));
return c;
}
/**
* @dev Division of two int256 variables and fails on overflow.
*/
function div(int256 a, int256 b) internal pure returns (int256) {
// Prevent overflow when dividing MIN_INT256 by -1
require(b != -1 || a != MIN_INT256);
// Solidity already throws when dividing by 0.
return a / b;
}
/**
* @dev Subtracts two int256 variables and fails on overflow.
*/
function sub(int256 a, int256 b) internal pure returns (int256) {
int256 c = a - b;
require((b >= 0 && c <= a) || (b < 0 && c > a));
return c;
}
/**
* @dev Adds two int256 variables and fails on overflow.
*/
function add(int256 a, int256 b) internal pure returns (int256) {
int256 c = a + b;
require((b >= 0 && c >= a) || (b < 0 && c < a));
return c;
}
/**
* @dev Converts to absolute value, and fails on overflow.
*/
function abs(int256 a) internal pure returns (int256) {
require(a != MIN_INT256);
return a < 0 ? -a : a;
}
function toUint256Safe(int256 a) internal pure returns (uint256) {
require(a >= 0);
return uint256(a);
}
}
contract DividendPayingToken is
DividendPayingTokenInterface,
DividendPayingTokenOptionalInterface,
Ownable
{
using SafeMath for uint256;
using SafeMathUint for uint256;
using SafeMathInt for int256;
// With `magnitude`, we can properly distribute dividends even if the amt of received ether is small.
// For more discussion about choosing the value of `magnitude`,
// see https://github.com/ethereum/EIPs/issues/1726#issuecomment-472352728
uint256 internal constant magnitude = 2 ** 128;
uint256 internal magnifiedDividendPerShare;
address public token;
// About dividendCorrection:
// If the token balance of a `_user` is never changed, the dividend of `_user` can be computed with:
// `dividendOf(_user) = dividendPerShare * balanceOf(_user)`.
// When `balanceOf(_user)` is changed (via minting/burning/transferring tokens),
// `dividendOf(_user)` should not be changed,
// but the computed value of `dividendPerShare * balanceOf(_user)` is changed.
// To keep the `dividendOf(_user)` unchanged, we add a correction term:
// `dividendOf(_user) = dividendPerShare * balanceOf(_user) + dividendCorrectionOf(_user)`,
// where `dividendCorrectionOf(_user)` is updated whenever `balanceOf(_user)` is changed:
// `dividendCorrectionOf(_user) = dividendPerShare * (old balanceOf(_user)) - (new balanceOf(_user))`.
// So now `dividendOf(_user)` returns the same value before and after `balanceOf(_user)` is changed.
mapping(address => int256) internal magnifiedDividendCorrections;
mapping(address => uint256) internal withdrawnDividends;
mapping(address => uint256) public holderBalance;
uint256 public totalBalance;
uint256 public totalDividendsDistributed;
/// @dev Distributes dividends whenever ether is paid to this contract.
receive() external payable {
distributeDividends();
}
/// @notice Distributes ether to token holders as dividends.
/// @dev It reverts if the total supply of tokens is 0.
/// It emits the `DividendsDistributed` event if the amt of received ether is greater than 0.
/// About undistributed ether:
/// In each distribution, there is a small amt of ether not distributed,
/// the magnified amt of which is
/// `(msg.value * magnitude) % totalSupply()`.
/// With a well-chosen `magnitude`, the amt of undistributed ether
/// (de-magnified) in a distribution can be less than 1 wei.
/// We can actually keep track of the undistributed ether in a distribution
/// and try to distribute it in the next distribution,
/// but keeping track of such data on-chain costs much more than
/// the saved ether, so we don't do that.
function distributeDividends() public payable override {
require(
false,
"Cannot send BNB directly to tracker as it is unrecoverable"
); //
}
function distributeTokenDividends(uint256 amt) public onlyOwner {
require(totalBalance > 0);
if (amt > 0) {
magnifiedDividendPerShare = magnifiedDividendPerShare.add(
(amt).mul(magnitude) / totalBalance
);
emit DividendsDistributed(msg.sender, amt);
totalDividendsDistributed = totalDividendsDistributed.add(amt);
}
}
/// @notice Withdraws the ether distributed to the sender.
/// @dev It emits a `DividendWithdrawn` event if the amt of withdrawn ether is greater than 0.
function withdrawDividend() public virtual override {
_withdrawDividendOfUser(payable(msg.sender));
}
/// @notice Withdraws the ether distributed to the sender.
/// @dev It emits a `DividendWithdrawn` event if the amt of withdrawn ether is greater than 0.
function _withdrawDividendOfUser(
address payable user
) internal returns (uint256) {
uint256 _withdrawableDividend = withdrawableDividendOf(user);
if (_withdrawableDividend > 0) {
withdrawnDividends[user] = withdrawnDividends[user].add(
_withdrawableDividend
);
emit DividendWithdrawn(user, _withdrawableDividend);
SafeERC20.safeTransfer(IERC20(token), user, _withdrawableDividend);
return _withdrawableDividend;
}
return 0;
}
/// @notice View the amt of dividend in wei that an address can withdraw.
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` can withdraw.
function dividendOf(address _owner) public view override returns (uint256) {
return withdrawableDividendOf(_owner);
}
/// @notice View the amt of dividend in wei that an address can withdraw.
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` can withdraw.
function withdrawableDividendOf(
address _owner
) public view override returns (uint256) {
return accumulativeDividendOf(_owner).sub(withdrawnDividends[_owner]);
}
/// @notice View the amt of dividend in wei that an address has withdrawn.
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` has withdrawn.
function withdrawnDividendOf(
address _owner
) public view override returns (uint256) {
return withdrawnDividends[_owner];
}
/// @notice View the amt of dividend in wei that an address has earned in total.
/// @dev accumulativeDividendOf(_owner) = withdrawableDividendOf(_owner) + withdrawnDividendOf(_owner)
/// = (magnifiedDividendPerShare * balanceOf(_owner) + magnifiedDividendCorrections[_owner]) / magnitude
/// @param _owner The address of a token holder.
/// @return The amt of dividend in wei that `_owner` has earned in total.
function accumulativeDividendOf(
address _owner
) public view override returns (uint256) {
return
magnifiedDividendPerShare
.mul(holderBalance[_owner])
.toInt256Safe()
.add(magnifiedDividendCorrections[_owner])
.toUint256Safe() / magnitude;
}
/// @dev Internal function that increases tokens to an account.
/// Update magnifiedDividendCorrections to keep dividends unchanged.
/// @param account The account that will receive the created tokens.
/// @param value The amt that will be created.
function _increase(address account, uint256 value) internal {
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
account
].sub((magnifiedDividendPerShare.mul(value)).toInt256Safe());
}
/// @dev Internal function that reduces an amt of the token of a given account.
/// Update magnifiedDividendCorrections to keep dividends unchanged.
/// @param account The account whose tokens will be burnt.
/// @param value The amt that will be burnt.
function _reduce(address account, uint256 value) internal {
magnifiedDividendCorrections[account] = magnifiedDividendCorrections[
account
].add((magnifiedDividendPerShare.mul(value)).toInt256Safe());
}
function _setBalance(address account, uint256 newBalance) internal {
uint256 currentBalance = holderBalance[account];
holderBalance[account] = newBalance;
if (newBalance > currentBalance) {
uint256 increaseAmt = newBalance.sub(currentBalance);
_increase(account, increaseAmt);
totalBalance += increaseAmt;
} else if (newBalance < currentBalance) {
uint256 reduceAmt = currentBalance.sub(newBalance);
_reduce(account, reduceAmt);
totalBalance -= reduceAmt;
}
}
}
// File: LIQR Contracts/liqr-2/contracts/DividendTracker.sol
pragma solidity ^0.8.19;
contract DividendTracker is DividendPayingToken {
using SafeMath for uint256;
using SafeMathInt for int256;
Map private tokenHoldersMap;
uint256 public lastProcessedIndex;
mapping(address => bool) public excludedFromDividends;
mapping(address => uint256) public lastClaimTimes;
uint256 public claimWait;
uint256 public immutable minimumTokenBalanceForDividends;
event ExcludeFromDividends(address indexed account);
event IncludeInDividends(address indexed account);
event ClaimWaitUpdated(uint256 indexed newValue, uint256 indexed oldValue);
event Claim(address indexed account, uint256 amt, bool indexed automatic);
constructor(address _token) {
claimWait = 1200;
minimumTokenBalanceForDividends = 1;
token = _token;
}
struct Map {
address[] keys;
mapping(address => uint) values;
mapping(address => uint) indexOf;
mapping(address => bool) inserted;
}
function get(address key) private view returns (uint) {
return tokenHoldersMap.values[key];
}
function getIndexOfKey(address key) private view returns (int) {
if (!tokenHoldersMap.inserted[key]) {
return -1;
}
return int(tokenHoldersMap.indexOf[key]);
}
function getKeyAtIndex(uint index) private view returns (address) {
return tokenHoldersMap.keys[index];
}
function size() private view returns (uint) {
return tokenHoldersMap.keys.length;
}
function set(address key, uint val) private {
if (tokenHoldersMap.inserted[key]) {
tokenHoldersMap.values[key] = val;
} else {
tokenHoldersMap.inserted[key] = true;
tokenHoldersMap.values[key] = val;
tokenHoldersMap.indexOf[key] = tokenHoldersMap.keys.length;
tokenHoldersMap.keys.push(key);
}
}
function remove(address key) private {
if (!tokenHoldersMap.inserted[key]) {
return;
}
delete tokenHoldersMap.inserted[key];
delete tokenHoldersMap.values[key];
uint index = tokenHoldersMap.indexOf[key];
uint lastIndex = tokenHoldersMap.keys.length - 1;
address lastKey = tokenHoldersMap.keys[lastIndex];
tokenHoldersMap.indexOf[lastKey] = index;
delete tokenHoldersMap.indexOf[key];
tokenHoldersMap.keys[index] = lastKey;
tokenHoldersMap.keys.pop();
}
function excludeFromDividends(address account) external onlyOwner {
excludedFromDividends[account] = true;
_setBalance(account, 0);
remove(account);
emit ExcludeFromDividends(account);
}
function includeInDividends(address account) external onlyOwner {
require(excludedFromDividends[account]);
excludedFromDividends[account] = false;
emit IncludeInDividends(account);
}
function updateClaimWait(uint256 newClaimWait) external onlyOwner {
require(
newClaimWait >= 1200 && newClaimWait <= 86400,
"Dividend_Tracker: claimWait must be updated to between 1 and 24 hours"
);
require(
newClaimWait != claimWait,
"Dividend_Tracker: Cannot update claimWait to same value"
);
emit ClaimWaitUpdated(newClaimWait, claimWait);
claimWait = newClaimWait;
}
function getLastProcessedIndex() external view returns (uint256) {
return lastProcessedIndex;
}
function getNumberOfTokenHolders() external view returns (uint256) {
return tokenHoldersMap.keys.length;
}
function getAccount(
address _account
)
public
view
returns (
address account,
int256 index,
int256 iterationsUntilProcessed,
uint256 withdrawableDividends,
uint256 totalDividends,
uint256 lastClaimTime,
uint256 nextClaimTime,
uint256 secondsUntilAutoClaimAvailable
)
{
account = _account;
index = getIndexOfKey(account);
iterationsUntilProcessed = -1;
if (index >= 0) {
if (uint256(index) > lastProcessedIndex) {
iterationsUntilProcessed = index.sub(
int256(lastProcessedIndex)
);
} else {
uint256 processesUntilEndOfArray = tokenHoldersMap.keys.length >
lastProcessedIndex
? tokenHoldersMap.keys.length.sub(lastProcessedIndex)
: 0;
iterationsUntilProcessed = index.add(
int256(processesUntilEndOfArray)
);
}
}
withdrawableDividends = withdrawableDividendOf(account);
totalDividends = accumulativeDividendOf(account);
lastClaimTime = lastClaimTimes[account];
nextClaimTime = lastClaimTime > 0 ? lastClaimTime.add(claimWait) : 0;
secondsUntilAutoClaimAvailable = nextClaimTime > block.timestamp
? nextClaimTime.sub(block.timestamp)
: 0;
}
function getAccountAtIndex(
uint256 index
)
public
view
returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
if (index >= size()) {
return (
0x0000000000000000000000000000000000000000,
-1,
-1,
0,
0,
0,
0,
0
);
}
address account = getKeyAtIndex(index);
return getAccount(account);
}
function canAutoClaim(uint256 lastClaimTime) private view returns (bool) {
if (lastClaimTime > block.timestamp) {
return false;
}
return block.timestamp.sub(lastClaimTime) >= claimWait;
}
function setBalance(
address payable account,
uint256 newBalance
) external onlyOwner {
if (excludedFromDividends[account]) {
return;
}
if (newBalance >= minimumTokenBalanceForDividends) {
_setBalance(account, newBalance);
set(account, newBalance);
} else {
_setBalance(account, 0);
remove(account);
}
processAccount(account, true);
}
function process(uint256 gas) public returns (uint256, uint256, uint256) {
uint256 numberOfTokenHolders = tokenHoldersMap.keys.length;
if (numberOfTokenHolders == 0) {
return (0, 0, lastProcessedIndex);
}
uint256 _lastProcessedIndex = lastProcessedIndex;
uint256 gasUsed = 0;
uint256 gasLeft = gasleft();
uint256 iterations = 0;
uint256 claims = 0;
while (gasUsed < gas && iterations < numberOfTokenHolders) {
_lastProcessedIndex++;
if (_lastProcessedIndex >= tokenHoldersMap.keys.length) {
_lastProcessedIndex = 0;
}
address account = tokenHoldersMap.keys[_lastProcessedIndex];
if (canAutoClaim(lastClaimTimes[account])) {
if (processAccount(payable(account), true)) {
claims++;
}
}
iterations++;
uint256 newGasLeft = gasleft();
if (gasLeft > newGasLeft) {
gasUsed = gasUsed.add(gasLeft.sub(newGasLeft));
}
gasLeft = newGasLeft;
}
lastProcessedIndex = _lastProcessedIndex;
return (iterations, claims, lastProcessedIndex);
}
function processAccount(
address payable account,
bool automatic
) public onlyOwner returns (bool) {
uint256 amt = _withdrawDividendOfUser(account);
if (amt > 0) {
lastClaimTimes[account] = block.timestamp;
emit Claim(account, amt, automatic);
return true;
}
return false;
}
}
// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
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);
}
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
// File: LIQR Contracts/liqr-2/contracts/LIQR.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
contract TokenHandler is Ownable {
function sendTokenToOwner(address token) external onlyOwner {
if (IERC20(token).balanceOf(address(this)) > 0) {
SafeERC20.safeTransfer(
IERC20(token),
owner(),
IERC20(token).balanceOf(address(this))
);
}
}
}
contract LIQR is ERC20, Ownable {
uint256 public maxTransaction;
uint256 public maxWallet;
DividendTracker public immutable dividendTracker;
IDexRouter public immutable dexRouter;
address public lpPair;
bool private swapping;
uint256 public swapTokensAtAmt;
TokenHandler public tokenHandler;
bool public limitsInEffect = true;
bool public tradingActive;
uint256 public constant FEE_DIVISOR = 10000;
address public LIQRStakingCA;
// Tax info
uint256 public buyRewardTax;
uint256 public buyMarketingTax;
uint256 public buyBurnTax;
uint256 public buyLiquidityTax;
uint256 public sellRewardTax;
uint256 public sellMarketingTax;
uint256 public sellBurnTax;
uint256 public sellLiquidityTax;
uint256 public tokensForReward;
uint256 public tokensForMarketing;
uint256 public tokensForLiquidity;
uint256 public tokensForBurn;
uint256 public buyTotalTax;
uint256 public sellTotalTax;
address public rewardWallet;
address public marketingWallet;
mapping(address => bool) private exemptFromTax;
mapping(address => bool) public exemptFromLimits;
mapping(address => bool) public automatedMarketMakerPairs;
event SetAutomatedMarketMakerPair(address indexed pair, bool indexed value);
event StartedTrading();
event RemovedLimits();
event SetExemptFromTax(address indexed _address, bool _isExempt);
event SetExemptFromLimits(address _address, bool _isExempt);
event UpdatedMaxTransaction(uint256 newAmt);
event UpdatedMaxWallet(uint256 newAmt);
event UpdatedBuyTax(
uint256 rewardTax,
uint256 marketingTax,
uint256 liquidityTax,
uint256 burnTax
);
event UpdatedSellTax(
uint256 rewardTax,
uint256 marketingTax,
uint256 liquidityTax,
uint256 burnTax
);
event UpdatedRewardWallet(address rewardWallet);
event UpdatedMarketingWallet(address marketingWallet);
event OwnerForcedSwapBack(uint256 timestamp);
event CaughtEarlyBuyer(address sniper);
event TransferForeignToken(address token, uint256 amt);
constructor(
string memory _name,
string memory _symbol,
uint256 _totalSupplyInTokens
) ERC20(_name, _symbol) {
address newOwner = msg.sender; // can leave alone if owner is deployer.
_mint(newOwner, _totalSupplyInTokens * (10 ** decimals()));
address _dexRouter;
// @dev assumes WETH pair
if (block.chainid == 1) {
_dexRouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
} else if (block.chainid == 5) {
_dexRouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
}else if (block.chainid == 56) {
_dexRouter = 0x10ED43C718714eb63d5aA57B78B54704E256024E;
} else if (block.chainid == 97) {
_dexRouter = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1;
} else if (block.chainid == 42161) {
_dexRouter = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506;
} else {
revert("Chain not configured");
}
dexRouter = IDexRouter(_dexRouter);
maxTransaction = (totalSupply() * 20) / 1000;
maxWallet = (totalSupply() * 20) / 1000;
swapTokensAtAmt = (totalSupply() * 25) / 100000;
tokenHandler = new TokenHandler();
buyRewardTax = 0; // 0%
buyMarketingTax = 300; // 3%
buyLiquidityTax = 300; // 3%
buyBurnTax = 0;
buyTotalTax =
buyRewardTax +
buyMarketingTax +
buyLiquidityTax +
buyBurnTax;
sellRewardTax = 0; // 0%
sellMarketingTax = 200; // 2%
sellLiquidityTax = 300; // 3%
sellBurnTax = 100; // 1%
sellTotalTax =
sellRewardTax +
sellMarketingTax +
sellLiquidityTax +
sellBurnTax;
rewardWallet = newOwner;
marketingWallet = newOwner;
// create pair
lpPair = IDexFactory(dexRouter.factory()).createPair(
address(this),
dexRouter.WETH()
);
dividendTracker = new DividendTracker(address(lpPair));
setAutomatedMarketMakerPair(address(lpPair), true);
exemptFromLimits[lpPair] = true;
exemptFromLimits[newOwner] = true;
exemptFromLimits[address(this)] = true;
exemptFromLimits[address(0xdead)] = true;
exemptFromTax[newOwner] = true;
exemptFromTax[address(this)] = true;
exemptFromTax[address(0xdead)] = true;
// exclude from receiving dividends
dividendTracker.excludeFromDividends(address(dividendTracker));
dividendTracker.excludeFromDividends(address(this));
dividendTracker.excludeFromDividends(newOwner);
dividendTracker.excludeFromDividends(address(dexRouter));
dividendTracker.excludeFromDividends(address(0xdead));
transferOwnership(newOwner);
_approve(address(this), address(dexRouter), type(uint256).max);
_approve(address(owner()), address(dexRouter), totalSupply());
}
function getClaimWait() external view returns (uint256) {
return dividendTracker.claimWait();
}
function getTotalDividendsDistributed() external view returns (uint256) {
return dividendTracker.totalDividendsDistributed();
}
function withdrawableDividendOf(
address account
) public view returns (uint256) {
return dividendTracker.withdrawableDividendOf(account);
}
function dividendTokenBalanceOf(
address account
) public view returns (uint256) {
return dividendTracker.holderBalance(account);
}
function getAccountDividendsInfo(
address account
)
external
view
returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
return dividendTracker.getAccount(account);
}
function getAccountDividendsInfoAtIndex(
uint256 index
)
external
view
returns (
address,
int256,
int256,
uint256,
uint256,
uint256,
uint256,
uint256
)
{
return dividendTracker.getAccountAtIndex(index);
}
function claim() external {
dividendTracker.processAccount(payable(msg.sender), false);
}
function getLastProcessedIndex() external view returns (uint256) {
return dividendTracker.getLastProcessedIndex();
}
function getNumberOfDividendTokenHolders() external view returns (uint256) {
return dividendTracker.getNumberOfTokenHolders();
}
function getNumberOfDividends() external view returns (uint256) {
return dividendTracker.totalBalance();
}
function _balanceWithStakedOf(
address account
) internal view returns (uint256) {
uint256 balance = balanceOf(account);
if (LIQRStakingCA != address(0) && LIQRStakingCA != account) {
ILIQRStaking.UserInfo memory userInfo = ILIQRStaking(LIQRStakingCA)
.getUserInfo(account);
balance = balance + userInfo.amount;
}
if (LIQRStakingCA == account) {
balance = 0;
}
return balance;
}
function _transfer(
address from,
address to,
uint256 amt
) internal override {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
if (amt == 0) {
super._transfer(from, to, 0);
return;
}
if (exemptFromTax[from] || exemptFromTax[to] || swapping) {
super._transfer(from, to, amt);
dividendTracker.setBalance(
payable(from),
_balanceWithStakedOf(from)
);
dividendTracker.setBalance(payable(to), _balanceWithStakedOf(to));
return;
}
require(tradingActive, "Trading is not active.");
checkLimits(from, to, amt);
if (
balanceOf(address(this)) >= swapTokensAtAmt &&
automatedMarketMakerPairs[to] &&
!swapping &&
!exemptFromTax[from] &&
!exemptFromTax[to]
) {
swapping = true;
swapBack();
swapping = false;
}
bool takeFee = !swapping;
// if any account belongs to exemptFromTax account then remove the fee
if (exemptFromTax[from] || exemptFromTax[to]) {
takeFee = false;
}
uint256 tax = 0;
uint256 rewardTax = 0;
uint256 marketingTax = 0;
uint256 liquidityTax = 0;
// only take fees on buys/sells, do not take on wallet transfers
if (takeFee) {
// on sell
if (automatedMarketMakerPairs[to] && sellTotalTax > 0) {
tax = (amt * sellTotalTax) / FEE_DIVISOR;
rewardTax = (tax * sellRewardTax) / sellTotalTax;
marketingTax = (tax * sellMarketingTax) / sellTotalTax;
liquidityTax = (tax * sellLiquidityTax) / sellTotalTax;
tokensForReward += rewardTax;
tokensForMarketing += marketingTax;
tokensForLiquidity += liquidityTax;
unchecked {
tokensForBurn += (tax -
rewardTax -
marketingTax -
liquidityTax);
}
}
// on buy
else if (automatedMarketMakerPairs[from] && buyTotalTax > 0) {
tax = (amt * buyTotalTax) / FEE_DIVISOR;
rewardTax = (tax * buyRewardTax) / buyTotalTax;
marketingTax = (tax * buyMarketingTax) / buyTotalTax;
liquidityTax = (tax * buyLiquidityTax) / buyTotalTax;
tokensForReward += rewardTax;
tokensForMarketing += marketingTax;
tokensForLiquidity += liquidityTax;
unchecked {
tokensForBurn += (tax -
rewardTax -
marketingTax -
liquidityTax);
}
}
if (tax > 0) {
super._transfer(from, address(this), tax);
}
amt -= tax;
}
super._transfer(from, to, amt);
dividendTracker.setBalance(payable(from), _balanceWithStakedOf(from));
dividendTracker.setBalance(payable(to), _balanceWithStakedOf(to));
}
function checkLimits(address from, address to, uint256 amt) internal view {
if (limitsInEffect) {
//when buy
if (automatedMarketMakerPairs[from] && !exemptFromLimits[to]) {
require(amt <= maxTransaction, "Buy transfer amount exceeded");
require(
amt + balanceOf(to) <= maxWallet,
"Unable to exceed Max Wallet"
);
}
//when sell
else if (automatedMarketMakerPairs[to] && !exemptFromLimits[from]) {
require(amt <= maxTransaction, "Sell transfer amount exceeded");
} else if (!exemptFromLimits[to]) {
require(
amt + balanceOf(to) <= maxWallet,
"Unable to exceed Max Wallet"
);
}
}
}
function swapTokensForEth(uint256 tokenAmount) private {
// generate the uniswap pair path of token -> weth
address[] memory path = new address[](2);
path[0] = address(this);
path[1] = dexRouter.WETH();
_approve(address(this), address(dexRouter), tokenAmount);
// make the swap
dexRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
tokenAmount,
0, // accept any amount of ETH
path,
address(this),
block.timestamp
);
}
function addLiquidity(uint256 tokenAmount, uint256 ethAmount) private {
// approve token transfer to cover all possible scenarios
_approve(address(this), address(dexRouter), tokenAmount);
// add the liquidity
dexRouter.addLiquidityETH{value: ethAmount}(
address(this),
tokenAmount,
0, // slippage is unavoidable
0, // slippage is unavoidable
address(tokenHandler),
block.timestamp
);
tokenHandler.sendTokenToOwner(address(lpPair));
}
function swapBack() private {
uint256 totalTokensToSwap = tokensForReward +
tokensForMarketing +
tokensForLiquidity;
if (tokensForBurn > 0) {
super._burn(address(this), tokensForBurn);
tokensForBurn = 0;
}
uint256 contractBalance = balanceOf(address(this));
if (contractBalance == 0 || totalTokensToSwap == 0) {
return;
}
if (contractBalance > swapTokensAtAmt * 40) {
contractBalance = swapTokensAtAmt * 40;
}
// Halve the amount of liquidity tokens
uint256 liquidityTokens = (contractBalance * tokensForLiquidity) /
totalTokensToSwap /
2;
totalTokensToSwap = tokensForLiquidity / 2;
totalTokensToSwap = totalTokensToSwap + tokensForReward + tokensForMarketing;
uint256 amountToSwapForETH = 0;
unchecked {
amountToSwapForETH = contractBalance - liquidityTokens;
}
uint256 initialETHBalance = address(this).balance;
swapTokensForEth(amountToSwapForETH);
uint256 ethBalance = 0;
unchecked {
ethBalance = address(this).balance - initialETHBalance;
}
uint256 ethForReward = (ethBalance * tokensForReward) /
totalTokensToSwap;
uint256 ethForMarketing = (ethBalance * tokensForMarketing) /
totalTokensToSwap;
uint256 ethForLiquidity = 0;
unchecked {
ethForLiquidity = ethBalance - ethForReward - ethForMarketing;
}
tokensForReward = 0;
tokensForMarketing = 0;
tokensForLiquidity = 0;
payable(rewardWallet).transfer(ethForReward);
payable(marketingWallet).transfer(ethForMarketing);
if (liquidityTokens > 0 && ethForLiquidity > 0) {
addLiquidity(liquidityTokens, ethForLiquidity);
}
uint256 receivedTokens = IERC20(lpPair).balanceOf(address(this));
if (receivedTokens > 0) {
SafeERC20.safeTransfer(
IERC20(lpPair),
address(dividendTracker),
receivedTokens
);
dividendTracker.distributeTokenDividends(receivedTokens);
}
}
// owner functions
// excludes wallets and contracts from dividends (such as CEX hotwallets, etc.)
function excludeFromDividends(address account) external onlyOwner {
dividendTracker.excludeFromDividends(account);
}
// removes exclusion on wallets and contracts from dividends (such as CEX hotwallets, etc.)
function includeInDividends(address account) external onlyOwner {
dividendTracker.includeInDividends(account);
}
function updateClaimWait(uint256 claimWait) external onlyOwner {
dividendTracker.updateClaimWait(claimWait);
}
function enableTrading() external onlyOwner {
tradingActive = true;
emit StartedTrading();
}
function updateRewardWallet(address wallet) external onlyOwner {
rewardWallet = wallet;
emit UpdatedRewardWallet(wallet);
}
function updateMarketingWallet(address wallet) external onlyOwner {
marketingWallet = wallet;
emit UpdatedMarketingWallet(wallet);
}
function updateMaxTransaction(uint256 newNumInTokens) external onlyOwner {
require(
newNumInTokens >= ((totalSupply() * 5) / 1000) / (10 ** decimals()),
"Too low"
);
maxTransaction = newNumInTokens * (10 ** decimals());
emit UpdatedMaxTransaction(maxTransaction);
}
function updateMaxWallet(uint256 newNumInTokens) external onlyOwner {
require(
newNumInTokens >=
((totalSupply() * 15) / 1000) / (10 ** decimals()),
"Too low"
);
maxWallet = newNumInTokens * (10 ** decimals());
emit UpdatedMaxWallet(maxWallet);
}
// 100 = 1%
function updateBuyTax(
uint256 _rewardTax,
uint256 _marketingTax,
uint256 _liquidityTax,
uint256 _burnTax
) external onlyOwner {
buyRewardTax = _rewardTax;
buyMarketingTax = _marketingTax;
buyLiquidityTax = _liquidityTax;
buyBurnTax = _burnTax;
buyTotalTax = _rewardTax + _marketingTax + _liquidityTax + _burnTax;
require(buyTotalTax <= 600, "Keep tax below 6%");
emit UpdatedBuyTax(_rewardTax, _marketingTax, _liquidityTax, _burnTax);
}
// 100 = 1%
function updateSellTax(
uint256 _rewardTax,
uint256 _marketingTax,
uint256 _liquidityTax,
uint256 _burnTax
) external onlyOwner {
sellRewardTax = _rewardTax;
sellMarketingTax = _marketingTax;
sellLiquidityTax = _liquidityTax;
sellBurnTax = _burnTax;
sellTotalTax = _rewardTax + _marketingTax + _liquidityTax + _burnTax;
require(sellTotalTax <= 600, "Keep tax below 6%");
emit UpdatedSellTax(_rewardTax, _marketingTax, _liquidityTax, _burnTax);
}
function updateSwapTokensAtAmt(uint256 newAmt) external onlyOwner {
require(
newAmt >= (totalSupply() * 1) / 1000000,
"Swap amt cannot be lower than 0.0001% total supply."
);
require(
newAmt <= (totalSupply() * 1) / 1000,
"Swap amt cannot be higher than 0.1% total supply."
);
swapTokensAtAmt = newAmt;
}
function removeLimits() external onlyOwner {
limitsInEffect = false;
maxTransaction = totalSupply();
maxWallet = totalSupply();
emit RemovedLimits();
}
function setExemptFromTax(
address _address,
bool _isExempt
) external onlyOwner {
require(_address != address(0), "Zero Address");
exemptFromTax[_address] = _isExempt;
emit SetExemptFromTax(_address, _isExempt);
}
function setExemptFromLimits(
address _address,
bool _isExempt
) external onlyOwner {
require(_address != address(0), "Zero Address");
if (!_isExempt) {
require(_address != lpPair, "Cannot remove pair");
}
exemptFromLimits[_address] = _isExempt;
emit SetExemptFromLimits(_address, _isExempt);
}
function setAutomatedMarketMakerPair(
address pair,
bool value
) public onlyOwner {
require(
pair != lpPair || value,
"The pair cannot be removed from automatedMarketMakerPairs"
);
automatedMarketMakerPairs[pair] = value;
exemptFromLimits[pair] = value;
if (value) {
dividendTracker.excludeFromDividends(pair);
}
emit SetAutomatedMarketMakerPair(pair, value);
}
function setLIQRStakingCA(address stakingCA) external onlyOwner {
LIQRStakingCA = stakingCA;
}
// force Swap back if slippage issues.
function forceSwapBack() external onlyOwner {
require(
balanceOf(address(this)) >= swapTokensAtAmt,
"Can only swap when token amt is at or higher than restriction"
);
swapping = true;
swapBack();
swapping = false;
emit OwnerForcedSwapBack(block.timestamp);
}
function rescueTokens(address _token, address _to) external onlyOwner {
require(_token != address(0), "_token address cannot be 0");
uint256 _contractBalance = IERC20(_token).balanceOf(address(this));
SafeERC20.safeTransfer(IERC20(_token), _to, _contractBalance);
emit TransferForeignToken(_token, _contractBalance);
}
function airdropToWallets(
address[] memory wallets,
uint256[] memory amountsInWei
) external onlyOwner {
require(
wallets.length == amountsInWei.length,
"Arrays length mismatch"
);
for (uint256 i = 0; i < wallets.length; i++) {
super._transfer(msg.sender, wallets[i], amountsInWei[i]);
dividendTracker.setBalance(
payable(wallets[i]),
_balanceWithStakedOf(wallets[i])
);
}
}
receive() external payable {}
}