- Contract name:
- Tendies
- Optimization enabled
- true
- Compiler version
- v0.8.6+commit.11564f7e
- Optimization runs
- 20000
- EVM Version
- default
- Verified at
- 2021-11-29T02:04:38.610454Z
Contract source code
// SPDX-License-Identifier: Unlicensed /** * Henlo frens! * * The Tendies contract itself has been heavily annotated to allow all frens * to understand what is going on. It is meant to be as transparent * as possible in explaining what each privileged function does, why it's needed, * the foreseen risks they present and the mitigation of those risks. * * To that end, each privileged function is annotated in 4 parts as follows: * * Function: [What the function does]. * * Justification: [Why it's in the contract]. * * Risk statement: [What the risks in principle are]. * * Mitigation: [How the risks are to be minimized]. * * The following global mitigation applies to the notion that the owner's private keys could * be compromised and the malicious actor could call any number of the many privileged functions * or dump from the Fren Co. wallets: * * "The owner recognises that its private keys are a potential single point of failure * since they could be compromised by a malicious actor. The owner is experienced in security * and assures that the private keys will be carefully guarded and stored on an airgapped Qubes * machines. A multisig wallet could also be used in the future to provide additional assurance. * A time-lock is unlikely to be added as the owner feels it would hamstring the project's agility, * and ability to resolve issues that may arise, such as an individual unable to withdraw tokens * from a pool because it would violate the max Tx or max wallet rules. Being able to adjust the * tokenomics on demand is a core tenet of the project. No privileged function has been added * without careful consideration of its risk profile". */ // File: SafeMath.sol pragma solidity 0.8.6; // 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 no longer needed starting with Solidity 0.8. The compiler * now has built in overflow checking. Retained for backwards-compatibility. */ 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 substraction 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: Context.sol pragma solidity 0.8.6; /* * @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. */ contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } } // File: IDEXRouter02.sol pragma solidity 0.8.6; interface IDEXRouter02 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity(address tokenA, address tokenB, uint amountADesired, uint amountBDesired, uint amountAMin, uint amountBMin, address to, uint deadline) external returns (uint amountA, uint amountB, uint liquidity); function addLiquidityETH(address token, uint amountTokenDesired, uint amountTokenMin, uint amountETHMin, address to, uint deadline) external payable returns (uint amountToken, uint amountETH, uint liquidity); function removeLiquidity(address tokenA, address tokenB, uint liquidity, uint amountAMin, uint amountBMin, address to, uint deadline) external returns (uint amountA, uint amountB); function removeLiquidityETH(address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline) external returns (uint amountToken, uint amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB,uint liquidity,uint amountAMin,uint amountBMin,address to,uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s) external returns (uint amountA, uint amountB); function removeLiquidityETHWithPermit(address token, uint liquidity,uint amountTokenMin,uint amountETHMin,address to,uint deadline,bool approveMax, uint8 v, bytes32 r, bytes32 s) external returns (uint amountToken, uint amountETH); function swapExactTokensForTokens(uint amountIn,uint amountOutMin,address[] calldata path,address to,uint deadline) external returns (uint[] memory amounts); function swapTokensForExactTokens(uint amountOut,uint amountInMax,address[] calldata path,address to,uint deadline) external returns (uint[] memory amounts); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB); function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut); function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn); function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts); function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts); function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline ) external returns (uint amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint liquidity, uint amountTokenMin, uint amountETHMin, address to, uint deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint amountOutMin, address[] calldata path, address to, uint deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external; } // File: IDEXFactory.sol pragma solidity 0.8.6; interface IDEXFactory { // Creates pair with CRO. event PairCreated(address indexed token0, address indexed token1, address pair, uint); // Gives a fee to the LP provider. function feeTo() external view returns (address); // Gives a fee to the LP setter. function feeToSetter() external view returns (address); // Gets the address of the LP token pair. function getPair(address tokenA, address tokenB) external view returns (address pair); // Gets address of all pairs. function allPairs(uint) external view returns (address pair); // Gets the length of pairs. function allPairsLength() external view returns (uint); // Creates the pair. function createPair(address tokenA, address tokenB) external returns (address pair); // Sets a fee to an address. function setFeeTo(address) external; // Sets fee to the setter address. function setFeeToSetter(address) external; function INIT_CODE_PAIR_HASH() external view returns (bytes32); } // File: ICRC20.sol pragma solidity 0.8.6; interface ICRC20 { /* Functions */ // Returns the amount of tokens in existence. function totalSupply() external view returns (uint256); // Returns the token decimals. function decimals() external view returns (uint8); // Returns the token symbol. function symbol() external view returns (string memory); // Returns the token name. function name() external view returns (string memory); // Returns the token owner. function getOwner() external view returns (address); // Returns the amount of tokens owned by `account`. function balanceOf(address account) external view returns (uint256); // Transfers tokens to addr, emits a {Transfer} event. function transfer(address recipient, uint256 amount) external returns (bool); // Returns remaining tokens that spender is allowed during {approve} or {transferFrom}. function allowance(address _owner, address spender) external view returns (uint256); // Sets amount of allowance, emits {approval} event. function approve(address spender, uint256 amount) external returns (bool); // Moves amount, then reduce allowance and emits a {transfer} event. function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /* Events */ // Emits when value tokens moved, value can be zero. event Transfer(address indexed from, address indexed to, uint256 value); // Emits when allowance of spender for owner is set by a call to approve. Value is new allowance. event Approval(address indexed owner, address indexed spender, uint256 value); } // File: Address.sol pragma solidity 0.8.6; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 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://diligence.consensys.net/posts/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.5.11/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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (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 functionCall(target, data, "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 a CRO 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"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(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) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(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) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: SafeCRC20.sol pragma solidity 0.8.6; /** * @title SafeCRC20 * @dev Wrappers around CRC20 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 SafeCRC20 for ICRC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeCRC20 { using Address for address; function safeTransfer(ICRC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(ICRC20 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 * {ICRC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(ICRC20 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' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeCRC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(ICRC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(ICRC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeCRC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @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(ICRC20 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, "SafeCRC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeCRC20: CRC20 operation did not succeed"); } } } // File: Tendies.sol pragma solidity 0.8.6; contract Tendies is Context, ICRC20 { /* LIBRARIES */ using SafeMath for uint256; using SafeCRC20 for ICRC20; using Address for address; /* BASIC TOKEN CONSTANTS */ string private constant TOKEN_NAME = "Tendies"; string private constant TOKEN_TICKER = "TENDIES"; uint8 private constant TOKEN_DECIMALS = 9; uint256 private constant TOKEN_MAX_SUPPLY = 1000000 * 10**9; uint256 private constant MAXintNum = ~uint256(0); /* RELEASE TIME STAMP VARIABLE */ uint256 deployedUNIXTimeStamp; /* TRACKING VARIABLES */ mapping(address => mapping(address => uint256)) private allowanceAmount; mapping(address => uint256) private reflectTokensOwned; mapping(address => uint256) private totalTokensOwned; /* RFI VARIABLES */ uint256 private _rTotal; uint256 private totalFeeAmount; uint256 public reflectFeePercent; uint256 private previousReflectFeePercent; uint256 public charityFeePercent; uint256 private previousCharityFeePercent; uint256 public burnFeePercent; uint256 private previousBurnFeePercent; uint256 public funFeePercent; uint256 private previousFunFeePercent; uint256 public liquidityFeePercent; uint256 private previousLiquidityFeePercent; IDEXRouter02 public DEXRouter; address public DEXPair; address private previousDEXPair; address public DEXRouterAddress; address private previousDEXRouterAddress; bool private inAutoLiquidity; bool public isAutoLiquidityEnabled; uint256 public maxTxAmount; uint256 private previousMaxTxAmount; uint256 public maxWallet; uint256 private previousMaxWallet; uint256 public autoLiquidityThreshold; uint256 private previousAutoLiquidityThreshold; /* KEY ADDRESS VARIABLES */ address public constant deadAddress = 0x000000000000000000000000000000000000dEaD; address private ownerOfToken; address private previousOwnerOfToken; address public growthAddress; address private previousGrowthAddress; address public funAddress; address private previousFunAddress; address public charityAddress; address private previousCharityAddress; address public dexPadTokenLockerAddress; address public dexPadLPLockerAddress; address public dexPadAirdropperAddress; /* SPECIAL VARIABLES */ mapping(address => bool) private isAddressExcludedFromReflections; address[] private excludedFromReflectionsAddresses; mapping(address => bool) private isAccountExcludedFromTax; mapping(address => bool) private isAccountExcludedFromMaxWallet; mapping(address => bool) private isAccountExcludedFromMaxTxAmount; /* EVENTS */ /** * Here events are defined that will be called in privileged functions * so that the changes made are clearly broadcasted on the explorer * and cannot be obfuscated. The names of the events are intended * to make them self-explanatory. */ event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); event AutoLiquidity( uint256 tokensSwapped, uint256 croReceived, uint256 tokensIntoLiquidity ); event AutoLiquidityEnabledUpdated(bool enabled); event AutoLiquidityThresholdChanged( uint256 indexed previousAutoLiquidityThreshold, uint256 indexed newAutoLiquidityThreshold ); event GrowthAddressChanged( address indexed previousGrowthAddress, address indexed newGrowthAddress ); event FunAddressChanged( address indexed previousFunAddress, address indexed newFunAddress ); event CharityAddressChanged( address indexed previousCharityAddress, address indexed newCharityAddress ); event MaxTxAmountChanged( uint256 indexed previousMaxTxAmount, uint256 indexed newMaxTxAmount ); event MaxWalletChanged( uint256 indexed previousMaxWallet, uint256 indexed newMaxWallet ); event ReflectFeePercentChanged( uint256 indexed previousReflectFeePercent, uint256 indexed newReflectFeePercent ); event CharityFeePercentChanged( uint256 indexed previousCharityFeePercent, uint256 indexed newCharityFeePercent ); event BurnFeePercentChanged( uint256 indexed previousBurnFeePercent, uint256 indexed newBurnFeePercent ); event FunFeePercentChanged( uint256 indexed previousFunFeePercent, uint256 indexed newFunFeePercent ); event LiquidityFeePercentChanged( uint256 indexed previousLiquidityFeePercent, uint256 indexed newLiquidityFeePercent ); event RouterAddressChanged( address indexed previousRouterAddress, address indexed newRouterAddress ); event PairAddressChanged( address indexed previousDEXPair, address indexed newDEXPair ); event AddressExcludedFromReflections( address indexed excludedAddress ); event AddressIncludedInReflections( address indexed includedAddress ); event AddressWhitelistedFromTax( address indexed whitelistedAddress ); event AddressIncludedInTax( address indexed includedAddress ); event AddressWhitelistedFromMaxWallet( address indexed whitelistedAddress ); event AddressIncludedInMaxWallet( address indexed includedAddress ); event AddressWhitelistedFromMaxTx( address indexed whitelistedAddress ); event AddressIncludedInMaxTx( address indexed addressIncludedInMaxTx ); event TendiesRecovered( address indexed recipient, uint256 indexed amount ); event CRC20Recovered( address indexed token, address indexed recipient, uint256 indexed amount ); event CRORecovered( address indexed recipient, uint256 indexed amount ); constructor (){ // This function is executed once when the contract is deployed // and it sets the values for important addresses and variables. // Sets Tendie Fren Co. wallets. growthAddress = 0x6c8fC09De5ff53dd0cE360574e3485aa734Fd125; funAddress = 0xD67c5FEC4c9B70Ce7045B181B542068220EBBB5E; charityAddress = 0x0c8F0ab88AC430b536BDA383a59d99FD48c5aF56; // Sets owner. ownerOfToken = _msgSender(); emit OwnershipTransferred(address(0), _msgSender()); // Sets _rTotal. _rTotal = (MAXintNum - (MAXintNum % TOKEN_MAX_SUPPLY)); // Sets initial max Tx which acts as anti-snipe. maxTxAmount = 0 * 10**9; previousMaxTxAmount = maxTxAmount; // Sets initial max wallet which will be changed to 10000 after initial liquidty // is added but before trading is enabled, where it will act as anti-whale. maxWallet = 1000000 * 10**9; previousMaxWallet = maxWallet; // Sets initial reflection tax %. reflectFeePercent = 7; previousReflectFeePercent = reflectFeePercent; // Sets initial auto-liquidity tax %. liquidityFeePercent = 3; previousLiquidityFeePercent = liquidityFeePercent; // Sets initial fun tax % for competitions/giveaways etc. funFeePercent = 2; previousFunFeePercent = funFeePercent; // Sets initial charity tax %. charityFeePercent = 1; previousCharityFeePercent = charityFeePercent; // Sets initial burn tax %. burnFeePercent = 1; previousBurnFeePercent = burnFeePercent; // Enables auto-liquidity and sets initial LP conversion threshold. isAutoLiquidityEnabled = true; autoLiquidityThreshold = 300 * 10**9; // Tracks minting of tokens. reflectTokensOwned[owner()] = _rTotal; emit Transfer(address(0), owner(), TOKEN_MAX_SUPPLY); // Sets router address DEXRouterAddress = 0xdADaae6cDFE4FA3c35d54811087b3bC3Cd60F348; // Gets the router. IDEXRouter02 DEXRouterLocal = IDEXRouter02(DEXRouterAddress); // Creates the WCRO-TENDIES pair on the DEX. DEXPair = IDEXFactory( DEXRouterLocal.factory()).createPair(address(this), DEXRouterLocal.WETH() ); // Sets the rest of the contract variables in the global router variable to the local one. DEXRouter = DEXRouterLocal; // Sets DexPad addresses to eliminate need to manually whitelist after deploying. dexPadTokenLockerAddress = 0x2EC4e8617AB86C05CB0Be6E303BB71eBaeDf0C3E; dexPadAirdropperAddress = 0xF85ED2faef90dB86935061016bdEE08C33017107; // Whitelists key addresses from tax. isAccountExcludedFromTax[owner()] = true; isAccountExcludedFromTax[address(this)] = true; isAccountExcludedFromTax[growthAddress] = true; isAccountExcludedFromTax[funAddress] = true; isAccountExcludedFromTax[charityAddress] = true; isAccountExcludedFromTax[deadAddress] = true; isAccountExcludedFromTax[dexPadTokenLockerAddress] = true; isAccountExcludedFromTax[dexPadAirdropperAddress] = true; // Whitelists key addresses from max wallet limit. isAccountExcludedFromMaxWallet[owner()] = true; isAccountExcludedFromMaxWallet[address(this)] = true; isAccountExcludedFromMaxWallet[growthAddress] = true; isAccountExcludedFromMaxWallet[funAddress] = true; isAccountExcludedFromMaxWallet[charityAddress] = true; isAccountExcludedFromMaxWallet[deadAddress] = true; isAccountExcludedFromMaxWallet[dexPadTokenLockerAddress] = true; isAccountExcludedFromMaxWallet[dexPadAirdropperAddress] = true; // Whitelists key addresses from max Tx limit. isAccountExcludedFromMaxTxAmount[owner()] = true; isAccountExcludedFromMaxTxAmount[address(this)] = true; isAccountExcludedFromMaxTxAmount[growthAddress] = true; isAccountExcludedFromMaxTxAmount[funAddress] = true; isAccountExcludedFromMaxTxAmount[charityAddress] = true; isAccountExcludedFromMaxTxAmount[deadAddress] = true; isAccountExcludedFromMaxTxAmount[dexPadTokenLockerAddress] = true; isAccountExcludedFromMaxTxAmount[dexPadAirdropperAddress] = true; // Gets the block timestamp of when the contract is deployed. deployedUNIXTimeStamp = block.timestamp; } /* CUSTOM TRANSFER FUNCTIONS */ /** Transfer function that checks for whitelisting and processes transfers appropriately. * It applies the max Tx and max wallet limit rules. It allows frens to send or sell * (but not buy or receive) TENDIES even if their balance exceeds the max wallet limit. * It correctly exempts the owner from the max Tx limit in order to prevent Tx failures * if withdrawing large amounts from token lockers. It does not allow frens to withdraw * TENDIES from a pool if the withdrawal would violate the max Tx or max wallet limits. * This is not deemed to be an issue because the max Tx and max wallet amounts will * gradually be raised after launch. As the market cap matures, it becomes less likely * that max Tx and max wallet amounts are exceeded. Any potential issues can be resolved * by the owner temporarily whitelisting an address from these limits. */ function transferTokens(address sender, address recipient, uint256 transferAmount, bool takeFee) private { if (!takeFee) { removeAllFee(); } (uint256 reflectAmount, uint256 reflectTransferAmount,uint256 reflectFee, uint256[6] memory reflectLiqCharityBurnFunFeeArray) = getTaxAndReflectionValues(transferAmount); if(isAddressExcludedFromReflections[sender]){ totalTokensOwned[sender] = totalTokensOwned[sender].sub(transferAmount); } reflectTokensOwned[sender] = reflectTokensOwned[sender].sub(reflectAmount); if(isAddressExcludedFromReflections[recipient]){ totalTokensOwned[recipient] = totalTokensOwned[recipient].add(reflectLiqCharityBurnFunFeeArray[5]); } reflectTokensOwned[recipient] = reflectTokensOwned[recipient].add(reflectTransferAmount); takeLiquidityFee(reflectLiqCharityBurnFunFeeArray[1]); takeCharityFee(reflectLiqCharityBurnFunFeeArray[2]); takeBurnFee(reflectLiqCharityBurnFunFeeArray[3]); takeFunFee(reflectLiqCharityBurnFunFeeArray[4]); takeReflectFee(reflectFee, reflectLiqCharityBurnFunFeeArray[0]); emit Transfer(sender, recipient, reflectLiqCharityBurnFunFeeArray[5]); if (!takeFee){ restoreAllFee(); } if(!isAccountExcludedFromMaxTxAmount[sender] && recipient != ownerOfToken){ require(transferAmount <= maxTxAmount, "Max Tx violation"); } require(sender != address(0) && recipient != address(0), "Zero address"); if(!isAccountExcludedFromMaxWallet[recipient]){ require(balanceOf(recipient) < maxWallet, "Max wallet violation"); } } /** Internal transfer function e.g. for executing recover functions. */ function transferInternal(address senderAddr, address receiverAddr, uint256 amount) private { require(senderAddr != address(0) && receiverAddr != address(0), "Zero address"); require(amount > 0, "Transfer amount must be greater than 0"); uint256 contractStoredReflectionTokenBalance = balanceOf(address(this)); bool overMinContractStoredReflectionTokenBalance = false; if(contractStoredReflectionTokenBalance >= autoLiquidityThreshold){ overMinContractStoredReflectionTokenBalance = true; } if (overMinContractStoredReflectionTokenBalance && !inAutoLiquidity && senderAddr != DEXPair && isAutoLiquidityEnabled) { contractStoredReflectionTokenBalance = autoLiquidityThreshold; autoLiquidity(contractStoredReflectionTokenBalance); } bool takeFee = true; if (isAccountExcludedFromTax[receiverAddr] || isAccountExcludedFromTax[senderAddr]) { takeFee = false; } transferTokens(senderAddr, receiverAddr, amount, takeFee); } /* BASIC TRANSFER FUNCTIONS */ /** Simple transfer to function with taxes applied. */ function transfer(address recipient, uint256 amount) external override returns (bool) { transferInternal(_msgSender(), recipient, amount); return true; } /** Simple transfer from function with approval. */ function transferFrom(address sender, address recipient, uint256 amount) external override returns (bool) { transferInternal(sender, recipient, amount); approveInternal(sender, _msgSender(), allowanceAmount[sender][_msgSender()].sub(amount, "Transfer amount exceeds allowance")); return true; } /* LIQUIDITY FUNCTIONS */ /** * Adds liquidity having approved both tokens. The LP generated stays in this contract address. * As with the autoLiquidity function, it presents a centralization risk over time. Thus, the LP * generated will be recovered and locked before built up enough to warrant sufficient concern. */ function addLiquidity(uint256 tokenAmount, uint256 croAmount) private { approveInternal(address(this), address(DEXRouter), tokenAmount); DEXRouter.addLiquidityETH{value: croAmount}(address(this),tokenAmount, 0, 0, address(this), block.timestamp); } /** Swaps tokens for CRO having grabbed the router address and approved both tokens. */ function swapTokensForCRO(uint256 tokenAmount) private { address[] memory path = new address[](2); path[0] = address(this); path[1] = DEXRouter.WETH(); approveInternal(address(this), address(DEXRouter), tokenAmount); DEXRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(tokenAmount, 0, path, address(this), block.timestamp); } /** * A typical auto-liquidity function often called swapAndLiquify. * It sells half of the TENDIES queued for LP conversion when the threshold is reached, triggered by sells. * It then grabs the amount of CRO the swap creates. * Finally it combines the CRO with TENDIES to add liquidity to the main WCRO-TENDIES pool to the DEX. * Over time, it will cause a build-up of TENDIES in this contract address. * This happens because swapping half the TENDIES into CRO reduces the price a bit. * In order to mitigate any centralization risk, TENDIES built up in the contract will be recovered and locked * or distributed to the community. */ function autoLiquidity(uint256 contractStoredReflectionTokenBalance) private { inAutoLiquidity = true; uint256 half1 = contractStoredReflectionTokenBalance.div(2); uint256 half2 = contractStoredReflectionTokenBalance.sub(half1); uint256 initialBalance = address(this).balance; swapTokensForCRO(half1); uint256 newBalance = address(this).balance.sub(initialBalance); addLiquidity(half2, newBalance); emit AutoLiquidity(half1, newBalance, half2); inAutoLiquidity = false; } /* PRIVATE CALCULATION FUNCTIONS */ /** Calculates tax from transfer amount. */ function getTaxValues(uint256 transferAmount) private view returns (uint256[6] memory) { uint256[6] memory reflectLiqCharityBurnFunFeeArray; reflectLiqCharityBurnFunFeeArray[0] = transferAmount.mul(reflectFeePercent).div(10**2); reflectLiqCharityBurnFunFeeArray[1] = transferAmount.mul(liquidityFeePercent).div(10**2); reflectLiqCharityBurnFunFeeArray[2] = transferAmount.mul(charityFeePercent).div(10**2); reflectLiqCharityBurnFunFeeArray[3] = transferAmount.mul(burnFeePercent).div(10**2); reflectLiqCharityBurnFunFeeArray[4] = transferAmount.mul(funFeePercent).div(10**2); reflectLiqCharityBurnFunFeeArray[5] = transferAmount.sub(reflectLiqCharityBurnFunFeeArray[0]).sub(reflectLiqCharityBurnFunFeeArray[1]) .sub(reflectLiqCharityBurnFunFeeArray[2]).sub(reflectLiqCharityBurnFunFeeArray[3]).sub(reflectLiqCharityBurnFunFeeArray[4]); return (reflectLiqCharityBurnFunFeeArray); } /** Calculates reflections from transfer amount and tax fees. */ function getReflectionValues(uint256 transferAmount, uint256 taxReflect, uint256 taxLiquidity, uint256 taxCharityFee, uint256 taxBurnFee, uint256 taxFunFee, uint256 currentRate) private pure returns (uint256, uint256, uint256){ uint256 reflectionAmount = transferAmount.mul(currentRate); uint256 reflectionFee = taxReflect.mul(currentRate); uint256 reflectionLiquidity = taxLiquidity.mul(currentRate); uint256 reflectionFeeCharity = taxCharityFee.mul(currentRate); uint256 reflectionFeeBurn = taxBurnFee.mul(currentRate); uint256 reflectionFeeFun = taxFunFee.mul(currentRate); uint256 reflectionTransferAmount = reflectionAmount.sub(reflectionFee).sub(reflectionLiquidity); reflectionTransferAmount = reflectionTransferAmount.sub(reflectionFeeCharity).sub(reflectionFeeBurn).sub(reflectionFeeFun); return (reflectionAmount, reflectionTransferAmount, reflectionFee); } /** Gets the total tax and reflection values from transfer amount. */ function getTaxAndReflectionValues(uint256 tAmount) private view returns (uint256,uint256,uint256, uint256[6] memory) { (uint256[6] memory reflectLiqCharityBurnFunFeeArray) = getTaxValues(tAmount); (uint256 reflectAmount, uint256 reflectTransferAmount, uint256 reflectFee) = getReflectionValues(tAmount, reflectLiqCharityBurnFunFeeArray[0], reflectLiqCharityBurnFunFeeArray[1], reflectLiqCharityBurnFunFeeArray[2], reflectLiqCharityBurnFunFeeArray[3], reflectLiqCharityBurnFunFeeArray[4], getReflectRate()); return (reflectAmount, reflectTransferAmount, reflectFee, reflectLiqCharityBurnFunFeeArray); } /** Gets the reflect rate by dividing the reflect supply by the total token supply. */ function getReflectRate() private view returns (uint256) { (uint256 reflectSupply, uint256 tokenSupply) = getCurrentSupplyTotals(); return reflectSupply.div(tokenSupply); } /** Subtracts the tax from the reflect totals and adds to the total tax amount. */ function takeReflectFee(uint256 reflectFee, uint256 taxReflect) private { _rTotal = _rTotal.sub(reflectFee); totalFeeAmount = totalFeeAmount.add(taxReflect); } /** Takes the liquidity tax - used for calculating transactions. */ function takeLiquidityFee(uint256 tLiquidity) private { uint256 currentRate = getReflectRate(); uint256 rLiquidity = tLiquidity.mul(currentRate); reflectTokensOwned[address(this)] = reflectTokensOwned[address(this)].add(rLiquidity); if (isAddressExcludedFromReflections[address(this)]){ totalTokensOwned[address(this)] = totalTokensOwned[address(this)].add(tLiquidity); } } /** Takes the charity tax - used for calculating transactions. */ function takeCharityFee(uint256 taxCharityFee) private { uint256 currentRate = getReflectRate(); uint256 rCharityTaxFee = taxCharityFee.mul(currentRate); reflectTokensOwned[charityAddress] = reflectTokensOwned[charityAddress].add(rCharityTaxFee); if (isAddressExcludedFromReflections[charityAddress]){ totalTokensOwned[charityAddress] = totalTokensOwned[charityAddress].add(taxCharityFee); } } /** Takes the burn tax - used for calculating transactions. */ function takeBurnFee(uint256 taxBurnFee) private { uint256 currentRate = getReflectRate(); uint256 rBurnTaxFee = taxBurnFee.mul(currentRate); reflectTokensOwned[deadAddress] = reflectTokensOwned[deadAddress].add(rBurnTaxFee); if (isAddressExcludedFromReflections[deadAddress]){ totalTokensOwned[deadAddress] = totalTokensOwned[deadAddress].add(taxBurnFee); } } /** Takes the fun tax - used for calculating transactions. */ function takeFunFee(uint256 taxFunFee) private { uint256 currentRate = getReflectRate(); uint256 rFunTaxFee = taxFunFee.mul(currentRate); reflectTokensOwned[funAddress] = reflectTokensOwned[funAddress].add(rFunTaxFee); if (isAddressExcludedFromReflections[funAddress]){ totalTokensOwned[funAddress] = totalTokensOwned[funAddress].add(taxFunFee); } } /** Removes all taxes - used to correctly process transactions for whitelisted addresses. */ function removeAllFee() private { previousReflectFeePercent = reflectFeePercent; previousCharityFeePercent = charityFeePercent; previousBurnFeePercent = burnFeePercent; previousFunFeePercent = funFeePercent; previousLiquidityFeePercent = liquidityFeePercent; reflectFeePercent = 0; charityFeePercent = 0; burnFeePercent = 0; funFeePercent = 0; liquidityFeePercent = 0; } /** Restores all taxes - used to correctly process transactions for non-whitelisted addresses. */ function restoreAllFee() private { reflectFeePercent = previousReflectFeePercent; charityFeePercent = previousCharityFeePercent; burnFeePercent = previousBurnFeePercent; funFeePercent = previousFunFeePercent; liquidityFeePercent = previousLiquidityFeePercent; } /* PUBLIC RFI FUNCTIONS */ /** Returns the total TENDIES supply in uint256 format - 1000000000000000 i.e. 1,000,000 tokens. */ function totalSupply() external pure override returns (uint256){ return TOKEN_MAX_SUPPLY; } /** Returns the number of decimals the token - 9. */ function decimals() external pure override returns (uint8) { return TOKEN_DECIMALS; } /** Returns the token ticker - TENDIES. */ function symbol() external pure override returns (string memory) { return TOKEN_TICKER; } /** Returns the token name - Tendies. */ function name() external pure override returns (string memory) { return TOKEN_NAME; } /** Returns the TENDIES balance of the address queried in uint256 format e.g. 5000000000000 = 5,000 tokens. */ function balanceOf(address account) public view override returns (uint256) { if (isAddressExcludedFromReflections[account]) { return totalTokensOwned[account]; } return tokenFromReflection(reflectTokensOwned[account]); } /** Returns the current block timestamp in unix format e.g. 1635354360. * Use https://time.is/Unix_time_converter to convert to human time. */ function getNowBlockTime() external view returns (uint) { return block.timestamp; } /** Returns the timestamp the contract was deployed in unix format as above. */ function releaseUnixTimeDate() external view returns (uint256) { return deployedUNIXTimeStamp; } /** Returns the total amount of tokens taxed in uint256 format. */ function totalFees() external view returns (uint256) { return totalFeeAmount; } /** Returns the total amount of reflect tokens in uint256 format from a transfer amount with or without tax fees deducted. */ function reflectionFromToken(uint256 tAmount, bool deductTransferFee) external view returns (uint256) { require(tAmount <= TOKEN_MAX_SUPPLY, "Amount exceeds max supply"); (uint256 rAmount, uint256 rTransferAmount, , ) = getTaxAndReflectionValues(tAmount); if(deductTransferFee){ return rTransferAmount; } else{ return rAmount; } } /** Returns the amount of reflect tokens in uint256 format from the current reflect supply. */ function tokenFromReflection(uint256 rAmount) public view returns (uint256){ require(rAmount <= _rTotal, "Amount exceeds total reflections"); uint256 currentRate = getReflectRate(); return rAmount.div(currentRate); } /** Gets the current supply totals by calculating from every address. */ function getCurrentSupplyTotals() public view returns (uint256, uint256) { uint256 rSupply = _rTotal; uint256 tSupply = TOKEN_MAX_SUPPLY; for (uint256 i = 0; i < excludedFromReflectionsAddresses.length; i++) { if ((reflectTokensOwned[excludedFromReflectionsAddresses[i]] > rSupply) || (totalTokensOwned[excludedFromReflectionsAddresses[i]] > tSupply)){ return (_rTotal, TOKEN_MAX_SUPPLY); } rSupply = rSupply.sub(reflectTokensOwned[excludedFromReflectionsAddresses[i]]); tSupply = tSupply.sub(totalTokensOwned[excludedFromReflectionsAddresses[i]]); } if (rSupply < _rTotal.div(TOKEN_MAX_SUPPLY)){ return (_rTotal, TOKEN_MAX_SUPPLY); } return (rSupply, tSupply); } /** Queries whether an address is excluded from receiving reflections and gives a boolean return. */ function isExcludedFromReflections(address account) external view returns (bool) { return isAddressExcludedFromReflections[account]; } /** Queries whether an address is whitelisted from tax fees and gives a boolean return. */ function isExcludedFromTax(address account) external view returns (bool) { return isAccountExcludedFromTax[account]; } /** Queries whether an address is whitelisted from the max wallet amount and gives a boolean return. */ function isExcludedFromMaxWallet(address account) external view returns (bool) { return isAccountExcludedFromMaxWallet[account]; } /** Queries whether an address is whitelisted from the max Tx amount and gives a boolean return. */ function isExcludedFromMaxTxAmount(address account) external view returns (bool) { return isAccountExcludedFromMaxTxAmount[account]; } /* FALLBACK AND RECEIVE FUNCTIONS */ // To receive CRO from the router when swapping. receive() external payable {} fallback() external payable {} /* ACCESS CONTROL FUNCTIONS */ /** Returns the address of the current owner. */ function owner() public view returns (address) { return ownerOfToken; } /** As above. */ function getOwner() external view override returns (address) { return owner(); } /** Enables use of privileged functions that can only be called by the owner. */ modifier onlyOwner() { require(ownerOfToken == _msgSender(), "Requires owner"); _; } /** Allows the owner to change the owner address e.g. to a multisig wallet. */ function transferOwnership(address _newAddress) external onlyOwner() { require(_newAddress != address(0), "Zero address"); emit OwnershipTransferred(ownerOfToken, _newAddress); previousOwnerOfToken = ownerOfToken; ownerOfToken = _newAddress; } /* ALLOWANCE FUNCTIONS */ /** Returns number of tokens remaining in uint256 format that spender is allowed to approve or transfer. */ function allowance(address ownerAddr, address spender) external view override returns (uint256) { return allowanceAmount[ownerAddr][spender]; } /** Approves token spend for the spender address. */ function approve(address spender, uint256 amount) external override returns (bool){ approveInternal(_msgSender(), spender, amount); return true; } /** Increases the token spend allowance for the spender address. */ function increaseAllowance(address spender, uint256 addedValue) external virtual returns (bool){ approveInternal(_msgSender(), spender, allowanceAmount[_msgSender()][spender].add(addedValue)); return true; } /** Decreases the token spend allowance for the spender address. */ function decreaseAllowance(address spender, uint256 subtractedValue) external virtual returns (bool){ approveInternal(_msgSender(),spender,allowanceAmount[_msgSender()][spender].sub(subtractedValue,"Cannot decrease allowance below 0.")); return true; } /** Internal function to approve token spend. */ function approveInternal(address ownerAddr, address spender, uint256 amount) private { require(ownerAddr != address(0) && spender != address(0), "Zero address"); allowanceAmount[ownerAddr][spender] = amount; emit Approval(ownerAddr, spender, amount); } /* PRIVILEGED DEX-UPDATING FUNCTIONS */ /** * Function: Allows the owner to change the DEX router address the contract uses. * * Justification: It would be called in the unlikely event that the DEX re-deploys its router * or if there is ever a need to desire to move over to a different DEX. This kind of Function * would not be necessary on an established chain using an established and trusted DEX such as * Uniswap, however the owner believes that having this function is necessary because the * Cronos chain is new at the time this contract is deployed, and there will be no established * DEX as a result. * * Risk statement: Owner could change the router address maliciously to a honeypot. * * Mitigation: Safeguard prevents router being set to the zero address. * Function emits an event on the explorer when called, clearly broadcasting * the new router address for everytone to see. */ function setRouterAddress(address _newAddress) external onlyOwner() { require(_newAddress != address(0), "Zero address"); emit RouterAddressChanged(DEXRouterAddress, _newAddress); previousDEXRouterAddress = DEXRouterAddress; DEXRouterAddress = _newAddress; IDEXRouter02 DEXRouterLocal = IDEXRouter02(DEXRouterAddress); DEXPair = IDEXFactory(DEXRouterLocal.factory()).createPair(address(this), DEXRouterLocal.WETH()); DEXRouter = DEXRouterLocal; } /** * Function: Allows the owner to change the liquidity pair the contract uses. * * Justification: It would be called in the plausible event that was ever a need or desire * to move over to a different DEX, which would have its own LP addresses. In a likely * situation where we have liquidity in more than one LP pair or on more than one DEX, * it could be called to change which pair automatic liquidity is added to. * * Risk statement: Owner could change the LP address maliciously in order to change where * liquidity is added. * * Mitigation: Function emits an event on the explorer when called, clearly broadcasting * the new pair address for everyone to see. */ function setPairAddress(address _newAddress) external onlyOwner() { require(_newAddress != address(0), "Zero address"); emit PairAddressChanged(DEXPair, _newAddress); previousDEXPair = DEXPair; DEXPair = _newAddress; } /* PRIVILEGED PROJECT ADDRESS-UPDATING FUNCTIONS */ /** * These allow the owner to change the Charity, Growth or Fun wallets to any address. * * Justification: They would be called in the unlikely event that access to the original * wallets are lost, or if there is a plausible need to change them due to security concerns. * * Risk statement: Owner could change them to different addresses to obfuscate where the * taxed tokens are sent and then dump them undetected. * * Mitigation: Functions emit an event on the explorer when called, clearly broadcasting * the change of addresses. Any such events will be made clear to the community. */ function updateCharityAddress(address _newAddress) external onlyOwner() { require(_newAddress != address(0), "Zero address"); require(_newAddress != charityAddress, "Address already set"); emit CharityAddressChanged(charityAddress, _newAddress); previousCharityAddress = charityAddress; charityAddress = _newAddress; } /** Allows the owner to change the Growth wallet address as above. */ function updateGrowthAddress(address _newGrowthAddress) external onlyOwner() { require(_newGrowthAddress != address(0), "Zero address"); require(_newGrowthAddress != growthAddress, "Address already set"); emit GrowthAddressChanged(growthAddress, _newGrowthAddress); previousGrowthAddress = growthAddress; growthAddress = _newGrowthAddress; } /* Allows the owner to change the Fun wallet address as above. */ function updateFunAddress(address _newFunAddress) external onlyOwner() { require(_newFunAddress != address(0), "Zero address"); require(_newFunAddress != funAddress, "Address already set"); emit FunAddressChanged(funAddress, _newFunAddress); previousFunAddress = funAddress; funAddress = _newFunAddress; } /* PRIVILEGED FLEXIBLE TOKENOMICS FUNCTIONS */ /** * Function: Allows the owner to set the max Tx limit to any value above 1000. * * Justification: This is an indispensible element of our flexible tokenomics. * The max Tx amount is initially set at 0 as an anti-snipe measure while the owner * sets the conditions for a fair launch. It will then be set to 1000 for launch, * and is intended to even the playing field and reduce Tx failure due to price impact. * The limit will then gradually be raised shortly after launch to 2500 and then 5000. * Any changes thereafter will be decided with the input of the FrenDAO. * * Risk statement: Owner could change the max Tx limit to any value above 1000 at any * time due to the absence of a time-lock. * * Mitigation: Safeguard added so that the limit cannot be changed to below 1000. * Function emits an event on the explorer when called, clearly broadcasting * the limit change. Limit will not be changed after being raised to 5000 without * the input of the FrenDAO. The owner, Charity, Growth and Fun addresses are * whitelisted from this limit by default, therefore this function does not pose an * additional risk to the community. */ function setMaxTxAmount (uint256 _newValue) external onlyOwner() { require(_newValue >= 1000 * 10**9, "Min limit 1000 tokens"); require(_newValue != maxTxAmount, "Value already set"); emit MaxTxAmountChanged(maxTxAmount, _newValue); previousMaxTxAmount = maxTxAmount; maxTxAmount = _newValue; } /** * Function: Allows the owner to set the max wallet limit to any value above 10000. * * Justification: This is an indispensible element of our flexible tokenomics. * The max wallet is initially set at 1000000 so that the owner can add initial * liquidity without the Tx failing. It will then be set to 10000 before trading * is enabled and will function as an anti-whale measure. Owner will gradually * increase the limit in 2500 or 5000 intervals up to 25000 with the input of the * FrenDAO. These measures ensure that the launch is as fair as possible. * * Risk statement: Owner could change the max wallet limit at any time to any value * between 5-10% due to the absence of a time-lock. * * Mitigation: Safeguard added so that the limit cannot be changed to below 10000. * Function emits an event on the explorer when called, clearly broadcasting * the limit change. Limit will not be raised without the input of the FrenDAO. */ /** Allows the owner to adjust the max wallet to an amount that must be greater than 10,000 tokens. */ function setMaxWallet (uint256 _newValue) external onlyOwner() { require(_newValue >= 10000 * 10**9, "Min limit 10000 tokens"); require(_newValue != maxWallet, "Value already set"); emit MaxWalletChanged(maxWallet, _newValue); previousMaxWallet = maxWallet; maxWallet = _newValue; } /** * Function: Allows the owner to set the reflection tax between 5-10%. * * Justification: This is an indispensible element of our flexible tokenomics. * The reflection tax may be adjusted at the will of the FrenDAO. * * Risk statement: Owner could change the reflection tax at any time to any value * between 5-10% due to the absence of a time-lock. * * Mitigation: Reasonable lower and upper bounds of 5% and 10% were chosen to ensure * the tax cannot be raised to a prohibitively high or unfairly low value. Function emits * an event on the explorer when called, clearly broadcasting the tax change. Tax will not * be changed unilaterally without the input of the FrenDAO. The owner, Charity, Growth * and Fun addresses are whitelisted from all taxes by default, therefore there is no * financial incentive for a malicious actor to decrease them. */ function setReflectFeePercent(uint256 _newPercent) external onlyOwner() { require(_newPercent >= 5 && _newPercent <= 10, "Reflect fee must be between 5-10"); require(_newPercent != reflectFeePercent, "Value already set"); emit ReflectFeePercentChanged(reflectFeePercent, _newPercent); previousReflectFeePercent = reflectFeePercent; reflectFeePercent = _newPercent; } /** * Function: Allows the owner to set the charity tax between 0-3%. * * Justification: As above. The lower bound is 0% in case there is a need to simplify * the tokenomics in the distant future as CEXes do not tend to comply with non-liquidity * taxes. In this case, the charity mechanism could be achieved by mobilizing TENDIES or * LP generated from the auto-liquidity function. * * Risk statement: Owner could change the charity tax at any time to any value * between 0-3% due to the absence of a time-lock. * * Mitigation: As above, with 0-3% bounds. */ function setCharityFeePercent(uint256 _newPercent) external onlyOwner() { require(_newPercent >= 0 && _newPercent <= 3, "Charity fee must be between 0-3"); require(_newPercent != charityFeePercent, "Value already set"); emit CharityFeePercentChanged(charityFeePercent, _newPercent); previousCharityFeePercent = charityFeePercent; charityFeePercent = _newPercent; } /** * Function: Allows the owner to set the burn tax between 0-5%. * * Justification: As above. Changing the burn tax is potentially one of the most * fun and effective ways of altering the token's dynamics, therefore the upper * bound is higher at 5%. TENDIES can be deflationary or not - frens decide. * * Risk statement: Owner could change the burn tax at any time to any value * between 0-5% due to the absence of a time-lock. * * Mitigation: As above, with 0-5% bounds. */ function setBurnFeePercent(uint256 _newPercent) external onlyOwner() { require(_newPercent >= 0 && _newPercent <= 5, "Burn fee must be between 0-5"); require(_newPercent != burnFeePercent, "Value already set"); emit BurnFeePercentChanged(burnFeePercent, _newPercent); previousBurnFeePercent = burnFeePercent; burnFeePercent = _newPercent; } /** * Function: Allows the owner to set the fun tax between 0-3%. * * Justification: As above. Frens can decide how much they want given back * to the community directly. * * Risk statement: Owner could change the fun tax at any time to any value * between 0-3% due to the absence of a time-lock. * * Mitigation: As above, with 0-3% bounds. */ function setFunFeePercent(uint256 _newPercent) external onlyOwner() { require(_newPercent >= 0 && _newPercent <= 3, "Fun fee must be between 0-3"); require(_newPercent != funFeePercent, "Value already set"); emit FunFeePercentChanged(funFeePercent, _newPercent); previousFunFeePercent = funFeePercent; funFeePercent = _newPercent; } /** * Function: Allows the owner to set the liquidity tax between 1-5%. * * Justification: As above. Managing liquidity carefully is crucial and this * is achieved by adjusting the liquidity tax along with the conversion threshold. * If liquidity is particularly strong, the FrenDAO may wish to prioritize * other aspects of the tokenomics. * * Risk statement: Owner could change the liquidty tax at any time to any value * between 1-5% due to the absence of a time-lock. * * Mitigation: As above, with 1-5% bounds. The owner believes that there * should always be some amount of auto-liquidity, therefore the lower bound * is 1% rather than 0%. */ function setLiquidityFeePercent(uint256 _newPercent) external onlyOwner() { require(_newPercent >= 1 && _newPercent <= 5, "Liquidity fee must be between 1-5"); require(_newPercent != liquidityFeePercent, "Value already set"); emit LiquidityFeePercentChanged(liquidityFeePercent, _newPercent); previousLiquidityFeePercent = liquidityFeePercent; liquidityFeePercent = _newPercent; } /** * Function: Allows the owner to toggle automatic liquidity on and off. * * Justification: Though deemed unlikely, being able to momentarily disable * auto-liquidity is important to be able to resolve hypothetical issues * that may arise, such as being unable to withdraw TENDIES from a token * locker because the tokenomics cause the Tx to fail, or gas estimation * issues on sells due to the additional gas burden auto-liquidity adds. * * Risk statement: Owner could toggle auto-liquidity off for an extended period * which would result in a significant build-up of TENDIES in this contract address * due to the tax and reflections gained. The TENDIES could then be recovered from * the contract by the owner and dumped. * * Mitigation: Function emits an event on the explorer when called, clearly broadcasting * when auto-liquidity is toggled on or off. */ function setAutoLiquidityEnabled(bool enableAutoLiquidity) external onlyOwner() { isAutoLiquidityEnabled = enableAutoLiquidity; emit AutoLiquidityEnabledUpdated(enableAutoLiquidity); } /** * Function: Allows the owner to set the amount of TENDIES in the token contract * that will trigger auto-liquidity betweeen 50-500. * * Justification: Being able to adjust the auto-liquidity threshold is essential for * a number of reasons: at launch when the market cap is low and the number of TENDIES * traded is high, given that the initial liquidity tax is 3%, a max Tx of 5000 tokens * would send roughly 150 tokens to the contract address. If the threshold was set too * low, at 50 for example, TENDIES would build up over time and then as the market cap * increases, the LP conversion would cause significant sell pressure. It is therefore * appropriate that the threshold is set at a rate proportional to the max Tx initially, * and then gradually reduced over time as the market cap increases and the number of * TENDIES in the average Tx decreases relative to the max supply. * * Risk statement: Owner could set threshold as low as possible in order to increase the * number of TENDIES that accumulate in the TENDIES contract, then recover them from them * contract and dump them. * * Mitigation: Reasonable lower and upper bounds of 50 and 500 were chosen to minimize the * potential impact that can be caused when the function is called. Function emits an event * on the explorer when called, clearly broadcasting when auto-liquidity is toggled on or off. */ function setAutoLiquidityThreshold(uint256 _newValue) external onlyOwner() { require(_newValue >= 50 * 10**9 && _newValue <= 500 * 10**9, "Threshold must be between 50-500"); emit AutoLiquidityThresholdChanged(autoLiquidityThreshold, _newValue); previousAutoLiquidityThreshold = autoLiquidityThreshold; autoLiquidityThreshold = _newValue; } /* PRIVILEGED WHITELISTING FUNCTIONS */ /** * Function: Allows the owner to exclude any address from receiving reflections. * * Justification: The most important use of this function is to exclude LP addresses * from reflections, otherwise they would swallow up the vast majority of them * because they hold most of the TENDIES. The burn address is also excluded for The * same reason. Finally, the function exists to deter anyone from attempting to * circumvent the anti-whale measures by filling multiple wallets with the max amount * on launch. It will only be used for this purpose if the abuser in question is * deemed to threaten the future of the project by holding more TENDIES than intended, * and will never be used without fair warning first. * * Risk statement: Owner could toggle auto-liquidity off for an extended period * which would result in a significant build-up of TENDIES in this contract address * due to the tax and reflections gained. The TENDIES could then be recovered from * the contract by the owner and dumped. * * Mitigation: There is no mitigation for this in principle. The owner recognises that * it is a powerful permission that must not ever be abused. */ function excludeFromReflections(address _address) external onlyOwner() { require(_address != DEXRouterAddress, "Router exclusion disallowed"); require(!isAddressExcludedFromReflections[_address], "Address is already excluded"); emit AddressExcludedFromReflections(_address); if (reflectTokensOwned[_address] > 0) { totalTokensOwned[_address] = tokenFromReflection(reflectTokensOwned[_address]); } isAddressExcludedFromReflections[_address] = true; excludedFromReflectionsAddresses.push(_address); } /** * Function: Allows the owner to re-include any address in receiving reflections. * * Justification: As above - this function could be called to re-include an abuser * in reflections. * * Risk statement: Owner could include the main TENDIES LP address in reflections to * significantly reduce reflections earned by everyone else, but there would be no * incentive for doing so. * * Mitigation: There is no mitigation for this in principle. This include function is * of much less importance than the exclude function. */ function includeInReflections(address _address) external onlyOwner() { require(isAddressExcludedFromReflections[_address], "Address is already included"); emit AddressIncludedInReflections(_address); for (uint256 i = 0; i < excludedFromReflectionsAddresses.length; i++) { if (excludedFromReflectionsAddresses[i] == _address) { excludedFromReflectionsAddresses[i] = excludedFromReflectionsAddresses[excludedFromReflectionsAddresses.length - 1]; totalTokensOwned[_address] = 0; isAddressExcludedFromReflections[_address] = false; excludedFromReflectionsAddresses.pop(); break; } } } /** * Function: Allows the owner to whitelist any address from all taxes. * * Justification: This function exists primarily to whitelist TENDIES pools so that * frens do not get hammered by tax from staking and unstaking. It can also be used * to whitelist the Fren Co. wallet addresses should they ever be changed. Moreover, * to whitelist a zapper contract so that frens can use farms completely tax-free. * * Risk statement: No additional risk posed due to the fact that the owner, Growth, * Charity and Fun wallets are already whitelisted from taxes by default. * * Mitigation: N/A. */ function excludeFromTax(address _address) external onlyOwner() { isAccountExcludedFromTax[_address] = true; emit AddressWhitelistedFromTax(_address); } /** * Function: Allows the owner to re-include any address in all taxes. * * Justification: As above - this function will rarely be called, in order to * de-whitelist a wallet address from taxes after having been temporarily * whitelisted. * * Risk statement: Owner could de-whitelist the contract addresses of pools, farms * or zappers, resulting in unexpected tax fees. The additional revenue could then * be siphoned off, but there would be little incentive in doing so as a malicious * actor could operate in simpler ways to have a greater impact. * * Mitigation: N/A. */ function includeInTax(address _address) external onlyOwner() { isAccountExcludedFromTax[_address] = false; emit AddressIncludedInTax(_address); } /** * Function: Allows the owner to whitelist any address from the max wallet limit. * * Justification: This function is critical to be able to solve a number of potential * issues: a fren may be unable to unstake TENDIES from a pool, harvest from a farm or * break LP if the Tx would take them over the max wallet limit; a fren may be unable * to receive TENDIES from giveaways and competitions. These isues are only expected to * arise if at all shortly after launch before the market cap has matured. Thereafter, * it is expected that the majority of wallets will not exceed the max wallet amount, * which will have been raised since launch. It could also be used to whitelist new * Fren Co. addresses and LP addresses if the need arises. * * Risk statement: No additional risk posed due to the fact that the owner, Growth, * Charity and Fun wallets are already whitelisted from the max wallet limit by default. * * Mitigation: N/A. */ function excludeFromMaxWallet(address _address) external onlyOwner() { isAccountExcludedFromMaxWallet[_address] = true; emit AddressWhitelistedFromMaxWallet(_address); } /** * Function: Allows the owner to re-include any address in the max wallet limit. * * Justification: As above - this function will rarely be called, in order to * de-whitelist a wallet address from the max wallet limit after having been * temporarily whitelisted. * * Risk statement: Owner could de-whitelist the contract addresses for pools * to break deposits but not withdrawals, but there would be little incentive * to do so. * * Mitigation: N/A. */ function includeInMaxWallet(address _address) external onlyOwner() { isAccountExcludedFromMaxWallet[_address] = false; emit AddressIncludedInMaxWallet(_address); } /** * Function: Allows the owner to whitelist any address from the max Tx limit. * * Justification: This function may be called to resolve issues where frens are unable * to unstake TENDIES or break LP due to it violating the max Tx limit. It can also be used * to whitelist new Fren Co. addresses should the need ever arise to change them. * * Risk statement: No additional risk posed due to the fact that the owner, Growth, * Charity and Fun wallets are already whitelisted from the max Tx limit by default. * Only the owner address is able to evade the max Tx limit while swapping, whereas * all the above addresses can evade it while sending. * * Mitigation: N/A. */ function excludeFromMaxTxAmount(address _address) external onlyOwner() { isAccountExcludedFromMaxTxAmount[_address] = true; emit AddressWhitelistedFromMaxTx(_address); } /** * Function: Allows the owner to re-include any address in the max Tx limit. * * Justification: As above - this function will rarely be called, in order to * de-whitelist a wallet address from the max Tx limit after having been * temporarily whitelisted. * * Risk statement: No additional risk posed due to the fact that the owner, Growth, * Charity and Fun wallets are already whitelisted from the max Tx limit by default. * * Mitigation: N/A. */ function includeInMaxTxAmount(address _address) external onlyOwner() { isAccountExcludedFromMaxTxAmount[_address] = false; emit AddressIncludedInMaxTx(_address); } /* PRIVILEGED TOKEN RECOVER FUNCTIONS */ /** * Function: Allows the owner to recover a specific amount of TENDIES from the TENDIES * contract. * * Justification: Someone ending TENDIES to the contract address will almost certainly happen * at some point. This function allows the owner to recover the TENDIES lost so they can be * returned to the sender. * * Risk statement: It is not expected that the contract will hold TENDIES unless someone * accidentally sends them. Owner could choose not to return the TENDIES but there would * be little incentive to do so. * * Mitigation: N/A. */ function recoverTendies(uint256 _amount) external onlyOwner() { require (_amount <= balanceOf(address(this)), "Not enough TENDIES in contract"); emit TendiesRecovered(payableAddr(), _amount); transferInternal(address(this), payableAddr(), _amount); } /** * Function: Allows the owner to withdraw the total balance of a specific CRC20 token * from the TENDIES contract. * * Justification: As above but for any token. The owner does not preclude the possibility of * taking some of this LP, breaking it, distributing the TENDIES back to the community via * the Growth wallet and keeping some CRO for personal use. This is hoped to be viewed as a * reasonable action due to the fact that 0% of the initial supply is held in reserve as an ROI. * * Risk statement: As above but for any token. Could be called to withdraw TENDIES awaiting * LP conversion but this is redundant with the function below. Owner could withdraw all LP * which would be of significant value once the market cap has matured and dump it. * Clearly this presents a centralization risk and requires an amount of trust. It also * exists for if there arises a need or desire to add liquidity to another DEX before the LP * from the initial liquidity has unlocked from the LP locker. * * Mitigation: Owner will regularly withdraw and lock or burn the accumulated LP * to build trust and prevent it from creating a large centralization risk. Any intentions * to withdraw LP from the contract will be clearly announced and the input of the FrenDAO * will be welcomed. */ function recoverCRC20(address _token) external onlyOwner() { emit CRC20Recovered(_token, payableAddr(), ICRC20(_token).balanceOf(address(this))); ICRC20(_token).safeTransfer(payableAddr(), ICRC20(_token).balanceOf(address(this))); } /** * Function: Allows the owner to withdraw all CRO from the TENDIES contract. * * Justification: The reason this is called a recover function is that its intended * use is to recover CRO sent accidentally to the TENDIES contract address. This is * a common and often costly mistake that usually results in tokens being lost forever. * Some CRO will build up in the contract over time as a byproduct of the autoLiquidity * function. This is because every time half the amount of the auto-liquidity threshold * in TENDIES is swapped for CRO and combined to form LP, the swap itself marginally reduces * the price of TENDIES. The autoLiquidity function does not account for this the next * time it is called. * * Risk statement: The amount of CRO that builds up due to auto-liquidity is likely to * become significant over time, and this presents a centralization risk. * * Mitigation: The CRO will most likely be locked or redistributed to the community, with a * reasonable amount that could be kept aside for the owner's personal use after consultation * with the FrenDAO. */ function recoverCRO() external onlyOwner() { emit CRORecovered(payableAddr(), balanceOf(address(this))); payableAddr().transfer(address(this).balance); } /** Gets the address to which tokens can be recovered from the TENDIES contract - the owner wallet. */ function payableAddr() private view returns (address payable) { address payable payableMsgSender = payable(owner()); return payableMsgSender; } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"AddressExcludedFromReflections","inputs":[{"type":"address","name":"excludedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressIncludedInMaxTx","inputs":[{"type":"address","name":"addressIncludedInMaxTx","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressIncludedInMaxWallet","inputs":[{"type":"address","name":"includedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressIncludedInReflections","inputs":[{"type":"address","name":"includedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressIncludedInTax","inputs":[{"type":"address","name":"includedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressWhitelistedFromMaxTx","inputs":[{"type":"address","name":"whitelistedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressWhitelistedFromMaxWallet","inputs":[{"type":"address","name":"whitelistedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"AddressWhitelistedFromTax","inputs":[{"type":"address","name":"whitelistedAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AutoLiquidity","inputs":[{"type":"uint256","name":"tokensSwapped","internalType":"uint256","indexed":false},{"type":"uint256","name":"croReceived","internalType":"uint256","indexed":false},{"type":"uint256","name":"tokensIntoLiquidity","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"AutoLiquidityEnabledUpdated","inputs":[{"type":"bool","name":"enabled","internalType":"bool","indexed":false}],"anonymous":false},{"type":"event","name":"AutoLiquidityThresholdChanged","inputs":[{"type":"uint256","name":"previousAutoLiquidityThreshold","internalType":"uint256","indexed":true},{"type":"uint256","name":"newAutoLiquidityThreshold","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"BurnFeePercentChanged","inputs":[{"type":"uint256","name":"previousBurnFeePercent","internalType":"uint256","indexed":true},{"type":"uint256","name":"newBurnFeePercent","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"CRC20Recovered","inputs":[{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"CRORecovered","inputs":[{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"CharityAddressChanged","inputs":[{"type":"address","name":"previousCharityAddress","internalType":"address","indexed":true},{"type":"address","name":"newCharityAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"CharityFeePercentChanged","inputs":[{"type":"uint256","name":"previousCharityFeePercent","internalType":"uint256","indexed":true},{"type":"uint256","name":"newCharityFeePercent","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"FunAddressChanged","inputs":[{"type":"address","name":"previousFunAddress","internalType":"address","indexed":true},{"type":"address","name":"newFunAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"FunFeePercentChanged","inputs":[{"type":"uint256","name":"previousFunFeePercent","internalType":"uint256","indexed":true},{"type":"uint256","name":"newFunFeePercent","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"GrowthAddressChanged","inputs":[{"type":"address","name":"previousGrowthAddress","internalType":"address","indexed":true},{"type":"address","name":"newGrowthAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"LiquidityFeePercentChanged","inputs":[{"type":"uint256","name":"previousLiquidityFeePercent","internalType":"uint256","indexed":true},{"type":"uint256","name":"newLiquidityFeePercent","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"MaxTxAmountChanged","inputs":[{"type":"uint256","name":"previousMaxTxAmount","internalType":"uint256","indexed":true},{"type":"uint256","name":"newMaxTxAmount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"MaxWalletChanged","inputs":[{"type":"uint256","name":"previousMaxWallet","internalType":"uint256","indexed":true},{"type":"uint256","name":"newMaxWallet","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"PairAddressChanged","inputs":[{"type":"address","name":"previousDEXPair","internalType":"address","indexed":true},{"type":"address","name":"newDEXPair","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ReflectFeePercentChanged","inputs":[{"type":"uint256","name":"previousReflectFeePercent","internalType":"uint256","indexed":true},{"type":"uint256","name":"newReflectFeePercent","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"RouterAddressChanged","inputs":[{"type":"address","name":"previousRouterAddress","internalType":"address","indexed":true},{"type":"address","name":"newRouterAddress","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"TendiesRecovered","inputs":[{"type":"address","name":"recipient","internalType":"address","indexed":true},{"type":"uint256","name":"amount","internalType":"uint256","indexed":true}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"fallback","stateMutability":"payable"},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"DEXPair","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IDEXRouter02"}],"name":"DEXRouter","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"DEXRouterAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"ownerAddr","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"autoLiquidityThreshold","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"burnFeePercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"charityAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"charityFeePercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"deadAddress","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"dexPadAirdropperAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"dexPadLPLockerAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"dexPadTokenLockerAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeFromMaxTxAmount","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeFromMaxWallet","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeFromReflections","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"excludeFromTax","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"funAddress","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"funFeePercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getCurrentSupplyTotals","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getNowBlockTime","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getOwner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"growthAddress","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"includeInMaxTxAmount","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"includeInMaxWallet","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"includeInReflections","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"includeInTax","inputs":[{"type":"address","name":"_address","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isAutoLiquidityEnabled","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromMaxTxAmount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromMaxWallet","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromReflections","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isExcludedFromTax","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"liquidityFeePercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxTxAmount","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"maxWallet","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverCRC20","inputs":[{"type":"address","name":"_token","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverCRO","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"recoverTendies","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reflectFeePercent","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"reflectionFromToken","inputs":[{"type":"uint256","name":"tAmount","internalType":"uint256"},{"type":"bool","name":"deductTransferFee","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"releaseUnixTimeDate","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAutoLiquidityEnabled","inputs":[{"type":"bool","name":"enableAutoLiquidity","internalType":"bool"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setAutoLiquidityThreshold","inputs":[{"type":"uint256","name":"_newValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setBurnFeePercent","inputs":[{"type":"uint256","name":"_newPercent","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setCharityFeePercent","inputs":[{"type":"uint256","name":"_newPercent","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFunFeePercent","inputs":[{"type":"uint256","name":"_newPercent","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setLiquidityFeePercent","inputs":[{"type":"uint256","name":"_newPercent","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxTxAmount","inputs":[{"type":"uint256","name":"_newValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMaxWallet","inputs":[{"type":"uint256","name":"_newValue","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setPairAddress","inputs":[{"type":"address","name":"_newAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setReflectFeePercent","inputs":[{"type":"uint256","name":"_newPercent","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setRouterAddress","inputs":[{"type":"address","name":"_newAddress","internalType":"address"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"tokenFromReflection","inputs":[{"type":"uint256","name":"rAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalFees","inputs":[]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"_newAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateCharityAddress","inputs":[{"type":"address","name":"_newAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateFunAddress","inputs":[{"type":"address","name":"_newFunAddress","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateGrowthAddress","inputs":[{"type":"address","name":"_newGrowthAddress","internalType":"address"}]},{"type":"receive","stateMutability":"payable"}]
Deployed ByteCode
0x6080604052600436106103f75760003560e01c806370a082311161020a578063b9d4400e11610119578063e17c4c74116100b2578063eefbbaab11610084578063f2fde38b1161006c578063f2fde38b14610cbe578063f67d22bf14610cde578063f8b45b0514610cfe57005b8063eefbbaab14610c8b578063f15c8b6514610cab57005b8063e17c4c7414610bf2578063e449aa8114610c12578063e6375d3e14610c32578063ec28438a14610c6b57005b8063ce5d47c6116100eb578063ce5d47c614610b33578063cea2695814610b53578063d3b64ecd14610b73578063dd62ed3e14610bac57005b8063b9d4400e14610aa4578063ba26b4a714610ac4578063cb4ca63114610ada578063ce5be4d214610b1357005b80638ee88c53116101a3578063a9059cbb11610175578063ae5a17a71161015d578063ae5a17a714610a44578063af41063b14610a64578063afcf2fc414610a8457005b8063a9059cbb14610a04578063ac22661c14610a2457005b80638ee88c531461095e57806395d89b411461097e578063a22d4832146109c4578063a457c2d7146109e457005b806384331512116101dc57806384331512146108ff578063893d20e8146109155780638c0b5e221461092a5780638da5cb5b1461094057005b806370a082311461087657806375c5f6e4146108965780637da4869f146108c95780637e3f5606146108df57005b8063313ce5671161030657806341cb87fc1161029f5780635c59523b1161027157806360d1259e1161025957806360d1259e146108075780636dd3d39f146108275780636e2310b21461086057005b80635c59523b146107c75780635d0044ca146107e757005b806341cb87fc146107515780634549b039146107715780634e0856a7146107915780635b700d91146107a757005b806339509351116102d857806339509351146106db5780633b540996146106fb5780633bb48ff7146107115780633f33e9091461073157005b8063313ce5671461065f5780633211a83d1461067b578063345a8b591461069b578063355326eb146106bb57005b806318160ddd1161039057806327c8f835116103625780632d8381191161034a5780632d838119146105ff5780632daa73f71461061f5780632f1191431461063f57005b806327c8f835146105bf578063285e801f146105d557005b806318160ddd1461054557806323b872dd1461055f57806325c5a5521461057f57806325f25f4d1461059f57005b806306fdde03116103c957806306fdde0314610479578063095ea7b3146104c857806313114a9d146104f8578063179795dd1461050d57005b8063044b5d4614610400578063056bd30a1461042057806305f5d3b31461044457806306ea73841461046457005b366103fe57005b005b34801561040c57600080fd5b506103fe61041b366004614591565b610d14565b34801561042c57600080fd5b506000545b6040519081526020015b60405180910390f35b34801561045057600080fd5b506103fe61045f3660046146ab565b610fa0565b34801561047057600080fd5b506103fe611099565b34801561048557600080fd5b5060408051808201909152600781527f54656e646965730000000000000000000000000000000000000000000000000060208201525b60405161043b919061474c565b3480156104d457600080fd5b506104e86104e3366004614645565b61117c565b604051901515815260200161043b565b34801561050457600080fd5b50600554610431565b34801561051957600080fd5b5060115461052d906001600160a01b031681565b6040516001600160a01b03909116815260200161043b565b34801561055157600080fd5b5066038d7ea4c68000610431565b34801561056b57600080fd5b506104e861057a366004614604565b611193565b34801561058b57600080fd5b50601f5461052d906001600160a01b031681565b3480156105ab57600080fd5b506103fe6105ba366004614591565b6111fd565b3480156105cb57600080fd5b5061052d61dead81565b3480156105e157600080fd5b506105ea611448565b6040805192835260208301919091520161043b565b34801561060b57600080fd5b5061043161061a3660046146ab565b6115dc565b34801561062b57600080fd5b506103fe61063a366004614591565b611646565b34801561064b57600080fd5b506103fe61065a366004614591565b611823565b34801561066b57600080fd5b506040516009815260200161043b565b34801561068757600080fd5b5060105461052d906001600160a01b031681565b3480156106a757600080fd5b5060245461052d906001600160a01b031681565b3480156106c757600080fd5b506103fe6106d6366004614591565b6118e4565b3480156106e757600080fd5b506104e86106f6366004614645565b611a74565b34801561070757600080fd5b5061043160085481565b34801561071d57600080fd5b506103fe61072c3660046146ab565b611aaa565b34801561073d57600080fd5b506103fe61074c366004614591565b611bed565b34801561075d57600080fd5b506103fe61076c366004614591565b611cae565b34801561077d57600080fd5b5061043161078c3660046146dd565b611fc9565b34801561079d57600080fd5b50610431600a5481565b3480156107b357600080fd5b506103fe6107c2366004614591565b61204b565b3480156107d357600080fd5b506103fe6107e2366004614591565b61210f565b3480156107f357600080fd5b506103fe6108023660046146ab565b61229f565b34801561081357600080fd5b506103fe610822366004614591565b6123da565b34801561083357600080fd5b506104e8610842366004614591565b6001600160a01b031660009081526029602052604090205460ff1690565b34801561086c57600080fd5b50610431600e5481565b34801561088257600080fd5b50610431610891366004614591565b61249e565b3480156108a257600080fd5b506014546104e8907501000000000000000000000000000000000000000000900460ff1681565b3480156108d557600080fd5b5061043160195481565b3480156108eb57600080fd5b506103fe6108fa366004614591565b6124fd565b34801561090b57600080fd5b50610431600c5481565b34801561092157600080fd5b5061052d6125c1565b34801561093657600080fd5b5061043160155481565b34801561094c57600080fd5b50601b546001600160a01b031661052d565b34801561096a57600080fd5b506103fe6109793660046146ab565b6125da565b34801561098a57600080fd5b5060408051808201909152600781527f54454e444945530000000000000000000000000000000000000000000000000060208201526104bb565b3480156109d057600080fd5b506103fe6109df366004614591565b612743565b3480156109f057600080fd5b506104e86109ff366004614645565b612875565b348015610a1057600080fd5b506104e8610a1f366004614645565b6128c4565b348015610a3057600080fd5b506103fe610a3f366004614671565b6128d1565b348015610a5057600080fd5b506103fe610a5f366004614591565b6129b0565b348015610a7057600080fd5b506103fe610a7f3660046146ab565b612b40565b348015610a9057600080fd5b5060215461052d906001600160a01b031681565b348015610ab057600080fd5b506103fe610abf3660046146ab565b612c76565b348015610ad057600080fd5b5061043160065481565b348015610ae657600080fd5b506104e8610af5366004614591565b6001600160a01b031660009081526028602052604090205460ff1690565b348015610b1f57600080fd5b506103fe610b2e3660046146ab565b612d78565b348015610b3f57600080fd5b5060255461052d906001600160a01b031681565b348015610b5f57600080fd5b506103fe610b6e3660046146ab565b612eae565b348015610b7f57600080fd5b506104e8610b8e366004614591565b6001600160a01b03166000908152602a602052604090205460ff1690565b348015610bb857600080fd5b50610431610bc73660046145cb565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b348015610bfe57600080fd5b506103fe610c0d366004614591565b612fe4565b348015610c1e57600080fd5b50601d5461052d906001600160a01b031681565b348015610c3e57600080fd5b506104e8610c4d366004614591565b6001600160a01b031660009081526026602052604090205460ff1690565b348015610c7757600080fd5b506103fe610c863660046146ab565b6130a5565b348015610c9757600080fd5b5060235461052d906001600160a01b031681565b348015610cb757600080fd5b5042610431565b348015610cca57600080fd5b506103fe610cd9366004614591565b6131df565b348015610cea57600080fd5b5060135461052d906001600160a01b031681565b348015610d0a57600080fd5b5061043160175481565b601b546001600160a01b03163314610d735760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e657200000000000000000000000000000000000060448201526064015b60405180910390fd5b6001600160a01b03811660009081526026602052604090205460ff16610ddb5760405162461bcd60e51b815260206004820152601b60248201527f4164647265737320697320616c726561647920696e636c7564656400000000006044820152606401610d6a565b6040516001600160a01b038216907fd687405d4d2679f959ddd9e06266152c7184c21950c54c2b8ec996407f7591f690600090a260005b602754811015610f9c57816001600160a01b031660278281548110610e3957610e3961497c565b6000918252602090912001546001600160a01b03161415610f8a5760278054610e649060019061489e565b81548110610e7457610e7461497c565b600091825260209091200154602780546001600160a01b039092169183908110610ea057610ea061497c565b600091825260208083209190910180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03948516179055918416815260038252604080822082905560269092522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556027805480610f2e57610f2e61494d565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555050565b80610f94816148e5565b915050610e12565b5050565b601b546001600160a01b03163314610ffa5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b640ba43b74008110158015611014575064746a5288008111155b6110605760405162461bcd60e51b815260206004820181905260248201527f5468726573686f6c64206d757374206265206265747765656e2035302d3530306044820152606401610d6a565b6019546040518291907fefcf7b0651690fde95da14220fbfe2424088cf3728e0d4f4dfd6dcfb03e04d6590600090a360198054601a5555565b601b546001600160a01b031633146110f35760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6110fc3061249e565b611104613311565b6001600160a01b03167f24e1bea80368f2a20bddbf4391a480ca73f2cf7a85142b0baebc24a0f212f8ea60405160405180910390a3611141613311565b6001600160a01b03166108fc479081150290604051600060405180830381858888f19350505050158015611179573d6000803e3d6000fd5b50565b6000611189338484613326565b5060015b92915050565b60006111a08484846133f3565b6111f284336111ed856040518060600160405280602181526020016149cf602191396001600160a01b038a16600090815260016020908152604080832033845290915290205491906135cc565b613326565b5060015b9392505050565b601b546001600160a01b031633146112575760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6013546001600160a01b03828116911614156112b55760405162461bcd60e51b815260206004820152601b60248201527f526f75746572206578636c7573696f6e20646973616c6c6f77656400000000006044820152606401610d6a565b6001600160a01b03811660009081526026602052604090205460ff161561131e5760405162461bcd60e51b815260206004820152601b60248201527f4164647265737320697320616c7265616479206578636c7564656400000000006044820152606401610d6a565b6040516001600160a01b038216907f51c333fec5f0c391a6c8887cb7828501ba94881666ca33105f3f669f38dbe2ac90600090a26001600160a01b038116600090815260026020526040902054156113ac576001600160a01b038116600090815260026020526040902054611392906115dc565b6001600160a01b0382166000908152600360205260409020555b6001600160a01b0316600081815260266020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660019081179091556027805491820181559091527f98a476f1687bc3d60a2da2adbcba2c46958e61fa2fb4042cd7bc5816a710195b0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b600454600090819066038d7ea4c68000825b6027548110156115a35782600260006027848154811061147c5761147c61497c565b60009182526020808320909101546001600160a01b0316835282019290925260400190205411806114e757508160036000602784815481106114c0576114c061497c565b60009182526020808320909101546001600160a01b03168352820192909252604001902054115b156115015750506004549366038d7ea4c680009350915050565b611547600260006027848154811061151b5761151b61497c565b60009182526020808320909101546001600160a01b0316835282019290925260400190205484906135f8565b925061158f60036000602784815481106115635761156361497c565b60009182526020808320909101546001600160a01b0316835282019290925260400190205483906135f8565b91508061159b816148e5565b91505061145a565b506004546115b89066038d7ea4c68000613604565b8210156115d35750506004549266038d7ea4c6800092509050565b90939092509050565b60006004548211156116305760405162461bcd60e51b815260206004820181905260248201527f416d6f756e74206578636565647320746f74616c207265666c656374696f6e736044820152606401610d6a565b600061163a613610565b90506111f68382613604565b601b546001600160a01b031633146116a05760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038216906370a082319060240160206040518083038186803b1580156116f857600080fd5b505afa15801561170c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061173091906146c4565b611738613311565b6001600160a01b0316826001600160a01b03167f97777e0d049e8c6ea21e08153c603fbd56f2276944e9fa416ae55f3e4997a36a60405160405180910390a4611179611782613311565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a082319060240160206040518083038186803b1580156117da57600080fd5b505afa1580156117ee573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061181291906146c4565b6001600160a01b0384169190613633565b601b546001600160a01b0316331461187d5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b0381166000818152602a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f1fd984041c31c7563135d9eb2665164a9e4de93558028c6a587e208386aec99c9190a250565b601b546001600160a01b0316331461193e5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b0381166119945760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b601f546001600160a01b03828116911614156119f25760405162461bcd60e51b815260206004820152601360248201527f4164647265737320616c726561647920736574000000000000000000000000006044820152606401610d6a565b601f546040516001600160a01b038084169216907f774cfaaa1d8772aa9fafd8157e93b89d7a445fe0036d38364bc16cb72969be0990600090a3601f8054602080546001600160a01b038084167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092559091169216919091179055565b3360008181526001602090815260408083206001600160a01b038716845290915281205490916111899185906111ed90866136b8565b601b546001600160a01b03163314611b045760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b60058110158015611b165750600a8111155b611b625760405162461bcd60e51b815260206004820181905260248201527f5265666c65637420666565206d757374206265206265747765656e20352d31306044820152606401610d6a565b600654811415611bb45760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b6006546040518291907fa5b3651733f3a2fb4a2b7238575ef825255db6aa5c70ef21b988189e5d96118490600090a36006805460075555565b601b546001600160a01b03163314611c475760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03811660008181526029602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f6d52ea90b53520ded80cbaff7471d8dc8fe1a0ec5bec867629926d04cfa6fa1b9190a250565b601b546001600160a01b03163314611d085760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b038116611d5e5760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b6013546040516001600160a01b038084169216907fba8909f452a8d4e389cf607ef89115b537d1aae7b3519cd1ee95100864b545e490600090a360138054601480546001600160a01b038084167fffffffffffffffffffffffff000000000000000000000000000000000000000092831617909255909116908316908117909155604080517fc45a01550000000000000000000000000000000000000000000000000000000081529051829163c45a0155916004808301926020929190829003018186803b158015611e2f57600080fd5b505afa158015611e43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e6791906145ae565b6001600160a01b031663c9c6539630836001600160a01b031663ad5c46486040518163ffffffff1660e01b815260040160206040518083038186803b158015611eaf57600080fd5b505afa158015611ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee791906145ae565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381600087803b158015611f4757600080fd5b505af1158015611f5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f7f91906145ae565b601180546001600160a01b039283167fffffffffffffffffffffffff0000000000000000000000000000000000000000918216179091556010805493909216921691909117905550565b600066038d7ea4c680008311156120225760405162461bcd60e51b815260206004820152601960248201527f416d6f756e742065786365656473206d617820737570706c79000000000000006044820152606401610d6a565b60008061202e856136c4565b505091509150831561204357915061118d9050565b50905061118d565b601b546001600160a01b031633146120a55760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03811660008181526029602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517fe5372373c5102b83bd2386a8de7611034806591422c8fe0c181f6126c03d6d0a9190a250565b601b546001600160a01b031633146121695760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b0381166121bf5760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b601d546001600160a01b038281169116141561221d5760405162461bcd60e51b815260206004820152601360248201527f4164647265737320616c726561647920736574000000000000000000000000006044820152606401610d6a565b601d546040516001600160a01b038084169216907ff1b735ce2abab56f4c686468c84ae4dd08008af9152a0b6611965342231079bd90600090a3601d8054601e80546001600160a01b038084167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092559091169216919091179055565b601b546001600160a01b031633146122f95760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6509184e72a00081101561234f5760405162461bcd60e51b815260206004820152601660248201527f4d696e206c696d697420313030303020746f6b656e73000000000000000000006044820152606401610d6a565b6017548114156123a15760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b6017546040518291907f44d543cdf368504a8e1363a6f41fe63122b6d67c8cdb004b74d8c976439e416b90600090a36017805460185555565b601b546001600160a01b031633146124345760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03811660008181526028602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f3c19df9711d1fdba3552022436b55d6e0339d170a371debb749841fa52ad7ede9190a250565b6001600160a01b03811660009081526026602052604081205460ff16156124db57506001600160a01b031660009081526003602052604090205490565b6001600160a01b03821660009081526002602052604090205461118d906115dc565b601b546001600160a01b031633146125575760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b0381166000818152602a602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055517f36ea1e97529f78154fb6f7657e5498c670ebbd8558ee1b0946c4d915b5f3c72a9190a250565b60006125d5601b546001600160a01b031690565b905090565b601b546001600160a01b031633146126345760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b60018110158015612646575060058111155b6126b85760405162461bcd60e51b815260206004820152602160248201527f4c697175696469747920666565206d757374206265206265747765656e20312d60448201527f35000000000000000000000000000000000000000000000000000000000000006064820152608401610d6a565b600e5481141561270a5760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b600e546040518291907fa58cc3215f31d542b7fddb4ee6ca53ef679609fb6de3d9e3b96f5deefa2873bf90600090a3600e8054600f5555565b601b546001600160a01b0316331461279d5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b0381166127f35760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b6011546040516001600160a01b038084169216907f1866e0728e6e89c2ebd286a744b7f1c174b4fd145c7fa20b446ef15988c43edd90600090a360118054601280546001600160a01b038084167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092559091169216919091179055565b600061118933846111ed856040518060600160405280602281526020016149f0602291393360009081526001602090815260408083206001600160a01b038d16845290915290205491906135cc565b60006111893384846133f3565b601b546001600160a01b0316331461292b5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b601480548215157501000000000000000000000000000000000000000000027fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff9091161790556040517f6ba383421aa078dca1d49e105174c3bd84af39712fb6736f168781cd709a0e0d906129a590831515815260200190565b60405180910390a150565b601b546001600160a01b03163314612a0a5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b038116612a605760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b6021546001600160a01b0382811691161415612abe5760405162461bcd60e51b815260206004820152601360248201527f4164647265737320616c726561647920736574000000000000000000000000006044820152606401610d6a565b6021546040516001600160a01b038084169216907f5ab9b88456c3123d329ac95fb71a7ca2038d5c7d0d9d36de82f749cdee59118590600090a360218054602280546001600160a01b038084167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092559091169216919091179055565b601b546001600160a01b03163314612b9a5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6003811115612beb5760405162461bcd60e51b815260206004820152601f60248201527f4368617269747920666565206d757374206265206265747765656e20302d33006044820152606401610d6a565b600854811415612c3d5760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b6008546040518291907f6152b0c8064ce64f7bc3efccccd98f4b15b3892d615ad7e81268e7e91b09e52690600090a36008805460095555565b601b546001600160a01b03163314612cd05760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b612cd93061249e565b811115612d285760405162461bcd60e51b815260206004820152601e60248201527f4e6f7420656e6f7567682054454e4449455320696e20636f6e747261637400006044820152606401610d6a565b80612d31613311565b6001600160a01b03167f184af76793da1243821c78b43dd8055354f3e3d370f6ee9a12c10fb3190a87f960405160405180910390a361117930612d72613311565b836133f3565b601b546001600160a01b03163314612dd25760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6003811115612e235760405162461bcd60e51b815260206004820152601b60248201527f46756e20666565206d757374206265206265747765656e20302d3300000000006044820152606401610d6a565b600c54811415612e755760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b600c546040518291907f1ce17d37a178820c0f12cca4ef6918cd34f34433ed66a79877b3b6223d3a612390600090a3600c8054600d5555565b601b546001600160a01b03163314612f085760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6005811115612f595760405162461bcd60e51b815260206004820152601c60248201527f4275726e20666565206d757374206265206265747765656e20302d35000000006044820152606401610d6a565b600a54811415612fab5760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b600a546040518291907fb1979b9f4b503526ad572434d093d9357dabe3e958522450a2bf1ed4af76bd0190600090a3600a8054600b5555565b601b546001600160a01b0316331461303e5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03811660008181526028602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f94be775e0fd8ba1bd40feda9d3306b6c400606850637b93189fe956f3557bb299190a250565b601b546001600160a01b031633146130ff5760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b64e8d4a510008110156131545760405162461bcd60e51b815260206004820152601560248201527f4d696e206c696d6974203130303020746f6b656e7300000000000000000000006044820152606401610d6a565b6015548114156131a65760405162461bcd60e51b815260206004820152601160248201527f56616c756520616c7265616479207365740000000000000000000000000000006044820152606401610d6a565b6015546040518291907fd6f586005531e7d32112f5389278497d656f7ed9029f31f85494a3f58ca1833390600090a36015805460165555565b601b546001600160a01b031633146132395760405162461bcd60e51b815260206004820152600e60248201527f5265717569726573206f776e65720000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03811661328f5760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b601b546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3601b8054601c80546001600160a01b038084167fffffffffffffffffffffffff0000000000000000000000000000000000000000928316179092559091169216919091179055565b60008061118d601b546001600160a01b031690565b6001600160a01b0383161580159061334657506001600160a01b03821615155b6133925760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b0383811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383161580159061341357506001600160a01b03821615155b61345f5760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b600081116134d55760405162461bcd60e51b815260206004820152602660248201527f5472616e7366657220616d6f756e74206d75737420626520677265617465722060448201527f7468616e203000000000000000000000000000000000000000000000000000006064820152608401610d6a565b60006134e03061249e565b9050600060195482106134f1575060015b808015613519575060145474010000000000000000000000000000000000000000900460ff16155b801561353357506011546001600160a01b03868116911614155b801561355a57506014547501000000000000000000000000000000000000000000900460ff165b1561356d57601954915061356d8261372e565b6001600160a01b03841660009081526028602052604090205460019060ff16806135af57506001600160a01b03861660009081526028602052604090205460ff165b156135b8575060005b6135c48686868461381c565b505050505050565b600081848411156135f05760405162461bcd60e51b8152600401610d6a919061474c565b505050900390565b60006111f6828461489e565b60006111f68284614826565b600080600061361d611448565b909250905061362c8282613604565b9250505090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526136b3908490613be0565b505050565b60006111f6828461480e565b60008060006136d1614573565b60006136dc86613cc5565b90506000808061371a89858360200201518660016020020151876002602002015188600360200201518960046020020151613715613610565b613d9c565b919950975095509293505050509193509193565b601480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674010000000000000000000000000000000000000000179055600061377a826002613604565b9050600061378883836135f8565b90504761379483613e30565b60006137a047836135f8565b90506137ac8382613fc3565b60408051858152602081018390529081018490527fda7f053cd23e95a08eb319388087a2806a629265db68cc2f2043a1e1ea852e619060600160405180910390a15050601480547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff169055505050565b8061385b5761385b6006805460075560088054600955600a8054600b55600c8054600d55600e8054600f55600094859055928490559083905582905555565b60008060008061386a866136c4565b6001600160a01b038c166000908152602660205260409020549397509195509350915060ff16156138d2576001600160a01b0388166000908152600360205260409020546138b890876135f8565b6001600160a01b0389166000908152600360205260409020555b6001600160a01b0388166000908152600260205260409020546138f590856135f8565b6001600160a01b03808a16600090815260026020908152604080832094909455918a1681526026909152205460ff161561396a5760a08101516001600160a01b038816600090815260036020526040902054613950916136b8565b6001600160a01b0388166000908152600360205260409020555b6001600160a01b03871660009081526002602052604090205461398d90846136b8565b6001600160a01b0388166000908152600260205260409020556139b6816001602002015161409c565b60408101516139c490614124565b60608101516139d2906141e3565b60808101516139e0906142f5565b80516139ed9083906143b4565b6001600160a01b038088169089167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360056020020151604051613a3391815260200190565b60405180910390a384613a6357613a63600754600655600954600855600b54600a55600d54600c55600f54600e55565b6001600160a01b0388166000908152602a602052604090205460ff16158015613a9a5750601b546001600160a01b03888116911614155b15613af157601554861115613af15760405162461bcd60e51b815260206004820152601060248201527f4d61782054782076696f6c6174696f6e000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03881615801590613b1157506001600160a01b03871615155b613b5d5760405162461bcd60e51b815260206004820152600c60248201527f5a65726f206164647265737300000000000000000000000000000000000000006044820152606401610d6a565b6001600160a01b03871660009081526029602052604090205460ff16613bd657601754613b898861249e565b10613bd65760405162461bcd60e51b815260206004820152601460248201527f4d61782077616c6c65742076696f6c6174696f6e0000000000000000000000006044820152606401610d6a565b5050505050505050565b6000613c35826040518060400160405280602081526020017f5361666543524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143d89092919063ffffffff16565b8051909150156136b35780806020019051810190613c53919061468e565b6136b35760405162461bcd60e51b815260206004820152602a60248201527f5361666543524332303a204352433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610d6a565b613ccd614573565b613cd5614573565b613cf56064613cef600654866143ef90919063ffffffff16565b90613604565b8152600e54613d0c90606490613cef9086906143ef565b6020820152600854613d2690606490613cef9086906143ef565b6040820152600a54613d4090606490613cef9086906143ef565b6060820152600c54613d5a90606490613cef9086906143ef565b608082018190526060820151604083015160208401518451613d919493613d8b939092849283919082908c906135f8565b906135f8565b60a082015292915050565b6000808080613dab8b866143ef565b90506000613db98b876143ef565b90506000613dc78b886143ef565b90506000613dd58b896143ef565b90506000613de38b8a6143ef565b90506000613df18b8b6143ef565b90506000613e0385613d8b89896135f8565b9050613e1582613d8b858185896135f8565b96995095975093955050505050509750975097945050505050565b6040805160028082526060820183526000926020830190803683370190505090503081600081518110613e6557613e6561497c565b6001600160a01b03928316602091820292909201810191909152601054604080517fad5c46480000000000000000000000000000000000000000000000000000000081529051919093169263ad5c4648926004808301939192829003018186803b158015613ed257600080fd5b505afa158015613ee6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f0a91906145ae565b81600181518110613f1d57613f1d61497c565b6001600160a01b039283166020918202929092010152601054613f439130911684613326565b6010546040517f791ac9470000000000000000000000000000000000000000000000000000000081526001600160a01b039091169063791ac94790613f9590859060009086903090429060040161479d565b600060405180830381600087803b158015613faf57600080fd5b505af11580156135c4573d6000803e3d6000fd5b601054613fdb9030906001600160a01b031684613326565b6010546040517ff305d719000000000000000000000000000000000000000000000000000000008152306004820181905260248201859052600060448301819052606483015260848201524260a48201526001600160a01b039091169063f305d71990839060c4016060604051808303818588803b15801561405c57600080fd5b505af1158015614070573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906140959190614702565b5050505050565b60006140a6613610565b905060006140b483836143ef565b306000908152600260205260409020549091506140d190826136b8565b3060009081526002602090815260408083209390935560269052205460ff16156136b3573060009081526003602052604090205461410f90846136b8565b30600090815260036020526040902055505050565b600061412e613610565b9050600061413c83836143ef565b6021546001600160a01b031660009081526002602052604090205490915061416490826136b8565b602180546001600160a01b03908116600090815260026020908152604080832095909555925490911681526026909152205460ff16156136b3576021546001600160a01b03166000908152600360205260409020546141c390846136b8565b6021546001600160a01b0316600090815260036020526040902055505050565b60006141ed613610565b905060006141fb83836143ef565b61dead60005260026020527f6a9609baa168169acaea398c4407efea4be641bb08e21e88806d9836fd9333cc5490915061423590826136b8565b61dead6000527f6a9609baa168169acaea398c4407efea4be641bb08e21e88806d9836fd9333cc5560266020527f436f594ac5248b7e44d6a4b4c35ba3e500f642e681dd33b10ee0fd4f06d15f3b5460ff16156136b35761dead60005260036020527f262bb27bbdd95c1cdc8e16957e36e38579ea44f7f6413dd7a9c75939def06b2c546142c390846136b8565b61dead60005260036020527f262bb27bbdd95c1cdc8e16957e36e38579ea44f7f6413dd7a9c75939def06b2c55505050565b60006142ff613610565b9050600061430d83836143ef565b601f546001600160a01b031660009081526002602052604090205490915061433590826136b8565b601f80546001600160a01b03908116600090815260026020908152604080832095909555925490911681526026909152205460ff16156136b357601f546001600160a01b031660009081526003602052604090205461439490846136b8565b601f546001600160a01b0316600090815260036020526040902055505050565b6004546143c190836135f8565b6004556005546143d190826136b8565b6005555050565b60606143e784846000856143fb565b949350505050565b60006111f68284614861565b6060824710156144735760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610d6a565b843b6144c15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610d6a565b600080866001600160a01b031685876040516144dd9190614730565b60006040518083038185875af1925050503d806000811461451a576040519150601f19603f3d011682016040523d82523d6000602084013e61451f565b606091505b509150915061452f82828661453a565b979650505050505050565b606083156145495750816111f6565b8251156145595782518084602001fd5b8160405162461bcd60e51b8152600401610d6a919061474c565b6040518060c001604052806006906020820280368337509192915050565b6000602082840312156145a357600080fd5b81356111f6816149ab565b6000602082840312156145c057600080fd5b81516111f6816149ab565b600080604083850312156145de57600080fd5b82356145e9816149ab565b915060208301356145f9816149ab565b809150509250929050565b60008060006060848603121561461957600080fd5b8335614624816149ab565b92506020840135614634816149ab565b929592945050506040919091013590565b6000806040838503121561465857600080fd5b8235614663816149ab565b946020939093013593505050565b60006020828403121561468357600080fd5b81356111f6816149c0565b6000602082840312156146a057600080fd5b81516111f6816149c0565b6000602082840312156146bd57600080fd5b5035919050565b6000602082840312156146d657600080fd5b5051919050565b600080604083850312156146f057600080fd5b8235915060208301356145f9816149c0565b60008060006060848603121561471757600080fd5b8351925060208401519150604084015190509250925092565b600082516147428184602087016148b5565b9190910192915050565b602081526000825180602084015261476b8160408501602087016148b5565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156147ed5784516001600160a01b0316835293830193918301916001016147c8565b50506001600160a01b03969096166060850152505050608001529392505050565b600082198211156148215761482161491e565b500190565b60008261485c577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156148995761489961491e565b500290565b6000828210156148b0576148b061491e565b500390565b60005b838110156148d05781810151838201526020016148b8565b838111156148df576000848401525b50505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8214156149175761491761491e565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6001600160a01b038116811461117957600080fd5b801515811461117957600080fdfe5472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636543616e6e6f7420646563726561736520616c6c6f77616e63652062656c6f7720302ea2646970667358221220f3a7c21d0c8d90ecfb501ee3d35f5ace43d8cbc7fb6998a4a6b4681dd180779664736f6c63430008060033