ETH Price: $2,539.55 (+1.75%)

Transaction Decoder

Block:
17727697 at Jul-19-2023 02:02:47 PM +UTC
Transaction Fee:
0.004505928924093947 ETH $11.44
Gas Used:
82,523 Gas / 54.602097889 Gwei

Emitted Events:

270 CHITCATStaking.EmergencyWithdrawFee( user=[Sender] 0x3b1c90d69123a7a80cf1fe8399cc708a810fb9d5, amount=3237362500000000000000 )
271 CHITCAT.Transfer( from=[Receiver] CHITCATStaking, to=[Sender] 0x3b1c90d69123a7a80cf1fe8399cc708a810fb9d5, value=64747250000000000000000 )
272 CHITCATStaking.EmergencyWithdraw( user=[Sender] 0x3b1c90d69123a7a80cf1fe8399cc708a810fb9d5, amount=64747250000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
2.872756221476759691 Eth2.872764473776759691 Eth0.0000082523
0x3b1c90D6...A810fb9D5
0.294764935229056499 Eth
Nonce: 144
0.290259006304962552 Eth
Nonce: 145
0.004505928924093947
0x7cF55125...245bF48c4
0xeb023bd0...d5066d076

Execution Trace

CHITCATStaking.emergencyWithdraw( _stakeId=0 )
  • CHITCAT.transfer( recipient=0x3b1c90D69123A7a80cF1FE8399cC708A810fb9D5, amount=64747250000000000000000 ) => ( True )
    File 1 of 2: CHITCATStaking
    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.16;
    
    interface IERC20 {
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `to`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address to, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `from` to `to` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(
            address from,
            address to,
            uint256 amount
        ) external returns (bool);
    }
    
    interface IERC20Permit {
        /**
         * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
         * given ``owner``'s signed approval.
         *
         * IMPORTANT: The same issues {IERC20-approve} has related to transaction
         * ordering also apply here.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `deadline` must be a timestamp in the future.
         * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
         * over the EIP712-formatted function arguments.
         * - the signature must use ``owner``'s current nonce (see {nonces}).
         *
         * For more information on the signature format, see the
         * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
         * section].
         */
        function permit(
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external;
    
        /**
         * @dev Returns the current nonce for `owner`. This value must be
         * included whenever a signature is generated for {permit}.
         *
         * Every successful call to {permit} increases ``owner``'s nonce by one. This
         * prevents a signature from being used multiple times.
         */
        function nonces(address owner) external view returns (uint256);
    
        /**
         * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
         */
        // solhint-disable-next-line func-name-mixedcase
        function DOMAIN_SEPARATOR() external view returns (bytes32);
    }
    
    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
         * ====
         *
         * [IMPORTANT]
         * ====
         * You shouldn't rely on `isContract` to protect against flash loan attacks!
         *
         * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
         * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
         * constructor.
         * ====
         */
        function isContract(address account) internal view returns (bool) {
            // This method relies on extcodesize/address.code.length, which returns 0
            // for contracts in construction, since the code is only stored at the end
            // of the constructor execution.
    
            return account.code.length > 0;
        }
    
        /**
         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
         * `recipient`, forwarding all available gas and reverting on errors.
         *
         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
         * of certain opcodes, possibly making contracts go over the 2300 gas limit
         * imposed by `transfer`, making them unable to receive funds via
         * `transfer`. {sendValue} removes this limitation.
         *
         * https://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");
    
            (bool success, ) = recipient.call{value: amount}("");
            require(success, "Address: unable to send value, recipient may have reverted");
        }
    
        /**
         * @dev Performs a Solidity function call using a low level `call`. A
         * plain `call` is an unsafe replacement for a function call: use this
         * function instead.
         *
         * If `target` reverts with a revert reason, it is bubbled up by this
         * function (like regular Solidity function calls).
         *
         * Returns the raw returned data. To convert to the expected return value,
         * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
         *
         * Requirements:
         *
         * - `target` must be a contract.
         * - calling `target` with `data` must not revert.
         *
         * _Available since v3.1._
         */
        function functionCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionCallWithValue(target, data, 0, "Address: low-level call failed");
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
         * `errorMessage` as a fallback revert reason when `target` reverts.
         *
         * _Available since v3.1._
         */
        function functionCall(
            address target,
            bytes memory data,
            string memory errorMessage
        ) internal returns (bytes memory) {
            return functionCallWithValue(target, data, 0, errorMessage);
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
         * but also transferring `value` wei to `target`.
         *
         * Requirements:
         *
         * - the calling contract must have an ETH balance of at least `value`.
         * - the called Solidity function must be `payable`.
         *
         * _Available since v3.1._
         */
        function functionCallWithValue(
            address target,
            bytes memory data,
            uint256 value
        ) internal returns (bytes memory) {
            return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
        }
    
        /**
         * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
         * with `errorMessage` as a fallback revert reason when `target` reverts.
         *
         * _Available since v3.1._
         */
        function functionCallWithValue(
            address target,
            bytes memory data,
            uint256 value,
            string memory errorMessage
        ) internal returns (bytes memory) {
            require(address(this).balance >= value, "Address: insufficient balance for call");
            (bool success, bytes memory returndata) = target.call{value: value}(data);
            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
         * but performing a static call.
         *
         * _Available since v3.3._
         */
        function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
            return functionStaticCall(target, data, "Address: low-level static call failed");
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
         * but performing a static call.
         *
         * _Available since v3.3._
         */
        function functionStaticCall(
            address target,
            bytes memory data,
            string memory errorMessage
        ) internal view returns (bytes memory) {
            (bool success, bytes memory returndata) = target.staticcall(data);
            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
         * but performing a delegate call.
         *
         * _Available since v3.4._
         */
        function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionDelegateCall(target, data, "Address: low-level delegate call failed");
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
         * but performing a delegate call.
         *
         * _Available since v3.4._
         */
        function functionDelegateCall(
            address target,
            bytes memory data,
            string memory errorMessage
        ) internal returns (bytes memory) {
            (bool success, bytes memory returndata) = target.delegatecall(data);
            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
        }
    
        /**
         * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
         * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
         *
         * _Available since v4.8._
         */
        function verifyCallResultFromTarget(
            address target,
            bool success,
            bytes memory returndata,
            string memory errorMessage
        ) internal view returns (bytes memory) {
            if (success) {
                if (returndata.length == 0) {
                    // only check isContract if the call was successful and the return data is empty
                    // otherwise we already know that it was a contract
                    require(isContract(target), "Address: call to non-contract");
                }
                return returndata;
            } else {
                _revert(returndata, errorMessage);
            }
        }
    
        /**
         * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
         * revert reason or using the provided one.
         *
         * _Available since v4.3._
         */
        function verifyCallResult(
            bool success,
            bytes memory returndata,
            string memory errorMessage
        ) internal pure returns (bytes memory) {
            if (success) {
                return returndata;
            } else {
                _revert(returndata, errorMessage);
            }
        }
    
        function _revert(bytes memory returndata, string memory errorMessage) private pure {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
    
    library SafeERC20 {
        using Address for address;
    
        function safeTransfer(
            IERC20 token,
            address to,
            uint256 value
        ) internal {
            _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
        }
    
        function safeTransferFrom(
            IERC20 token,
            address from,
            address to,
            uint256 value
        ) internal {
            _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
        }
    
        /**
         * @dev Deprecated. This function has issues similar to the ones found in
         * {IERC20-approve}, and its usage is discouraged.
         *
         * Whenever possible, use {safeIncreaseAllowance} and
         * {safeDecreaseAllowance} instead.
         */
        function safeApprove(
            IERC20 token,
            address spender,
            uint256 value
        ) internal {
            // safeApprove should only be called when setting an initial allowance,
            // or when resetting it to zero. To increase and decrease it, use
            // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
            require(
                (value == 0) || (token.allowance(address(this), spender) == 0),
                "SafeERC20: approve from non-zero to non-zero allowance"
            );
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
        }
    
        function safeIncreaseAllowance(
            IERC20 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(
            IERC20 token,
            address spender,
            uint256 value
        ) internal {
            unchecked {
                uint256 oldAllowance = token.allowance(address(this), spender);
                require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
                uint256 newAllowance = oldAllowance - value;
                _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
            }
        }
    
        function safePermit(
            IERC20Permit token,
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) internal {
            uint256 nonceBefore = token.nonces(owner);
            token.permit(owner, spender, value, deadline, v, r, s);
            uint256 nonceAfter = token.nonces(owner);
            require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
        }
    
        /**
         * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
         * on the return value: the return value is optional (but if data is returned, it must not be false).
         * @param token The token targeted by the call.
         * @param data The call data (encoded using abi.encode or one of its variants).
         */
        function _callOptionalReturn(IERC20 token, bytes memory data) private {
            // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
            // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
            // the target address contains contract code and also asserts for success in the low-level call.
    
            bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
            if (returndata.length > 0) {
                // Return data is optional
                require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
            }
        }
    }
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    
    abstract contract Ownable is Context {
        address private _owner;
        mapping (address => bool) private _authorized;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor() {
            _transferOwnership(_msgSender());
            _authorized[_msgSender()] = true;
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            _checkOwner();
            _;
        }
    
        modifier onlyAuthorized() {
            require(_authorized[_msgSender()], "Not authorized");
            _;
        }
    
        function setAuthorized(address _address, bool authorized) public onlyOwner {
            _authorized[_address] = authorized;
        }
    
        function isAuthorized(address _address) public view returns (bool) {
            return _authorized[_address];
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view virtual returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if the sender is not the owner.
         */
        function _checkOwner() internal view virtual {
            require(owner() == _msgSender(), "Ownable: caller is not the owner");
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions anymore. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby removing any functionality that is only available to the owner.
         */
        function renounceOwnership() public virtual onlyOwner {
            _transferOwnership(address(0));
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public virtual onlyOwner {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            _transferOwnership(newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Internal function without access restriction.
         */
        function _transferOwnership(address newOwner) internal virtual {
            address oldOwner = _owner;
            _owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    
    abstract contract ReentrancyGuard {
        // Booleans are more expensive than uint256 or any type that takes up a full
        // word because each write operation emits an extra SLOAD to first read the
        // slot's contents, replace the bits taken up by the boolean, and then write
        // back. This is the compiler's defense against contract upgrades and
        // pointer aliasing, and it cannot be disabled.
    
        // The values being non-zero value makes deployment a bit more expensive,
        // but in exchange the refund on every call to nonReentrant will be lower in
        // amount. Since refunds are capped to a percentage of the total
        // transaction's gas, it is best to keep them low in cases like this one, to
        // increase the likelihood of the full refund coming into effect.
        uint256 private constant _NOT_ENTERED = 1;
        uint256 private constant _ENTERED = 2;
    
        uint256 private _status;
    
        constructor() {
            _status = _NOT_ENTERED;
        }
    
        /**
         * @dev Prevents a contract from calling itself, directly or indirectly.
         * Calling a `nonReentrant` function from another `nonReentrant`
         * function is not supported. It is possible to prevent this from happening
         * by making the `nonReentrant` function external, and making it call a
         * `private` function that does the actual work.
         */
        modifier nonReentrant() {
            _nonReentrantBefore();
            _;
            _nonReentrantAfter();
        }
    
        function _nonReentrantBefore() private {
            // On the first call to nonReentrant, _notEntered will be true
            require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
    
            // Any calls to nonReentrant after this point will fail
            _status = _ENTERED;
        }
    
        function _nonReentrantAfter() private {
            // By storing the original value once again, a refund is triggered (see
            // https://eips.ethereum.org/EIPS/eip-2200)
            _status = _NOT_ENTERED;
        }
    }
    
    contract CHITCATStaking is Ownable, ReentrancyGuard {
        using SafeERC20 for IERC20;
        using Address for address;
    
        struct StakeInfo {
            uint256 amount;
            uint256 poolId;  
            uint256 depositTime;
        }
    
        struct PoolInfo{
            uint256 interest;
            uint256 apr;  
            uint256 startEpoch;
            uint256 poolLength;
            uint256 lockPeriod;
            uint256 liveStakedAmount;
            uint256 totalContributed;
            uint256 emergencyWithdrawFee;
            uint256 burnFee;
            bool isOpen;
        }
    
        struct DynamicPoolInfo {
            uint256 interest;  
            uint256 apr;  
            uint256 lockPeriod;
            bool isOpen;
            bool isLive;
            uint256 endDate;
            uint256 liveStakedAmount;
            uint256 rewardDept;
        }
    
        IERC20 public token;
    
        PoolInfo[] public poolInfo;
        mapping(address => StakeInfo[]) public stakeInfo;
    
        uint256 private totalRewardDistributed;
    
        event Deposit(address indexed user, uint256 amount);
        event Withdraw(address indexed user, uint256 amount);
        event EmergencyWithdraw(address indexed user, uint256 amount);
        event EmergencyWithdrawFee(address indexed user, uint256 amount);
    
        constructor() {
            token = IERC20(0x7cF551258d6871b72EE1bD1624588a6245bF48c4);
            poolInfo.push(PoolInfo(2000,  240, block.timestamp, 3653 days, 7 days, 0, 0, 1000, 0, true));
            poolInfo.push(PoolInfo(5000, 600, block.timestamp, 3653 days, 30 days, 0, 0, 500, 0, false));
            poolInfo.push(PoolInfo(10000, 1200, block.timestamp, 3653 days, 60 days, 0, 0, 500, 0, false));
            poolInfo.push(PoolInfo(15000, 1800, block.timestamp, 3653 days, 90 days, 0, 0, 500, 0, false));
        }
    
        function claimStuckTokens(address _token) external onlyOwner {
            if (_token == address(0x0)) {
                payable(msg.sender).transfer(address(this).balance);
                return;
            }
            IERC20 erc20Token = IERC20(_token);
            uint256 balance = erc20Token.balanceOf(address(this));
            erc20Token.transfer(msg.sender, balance);
        }
    
        function addPool(PoolInfo memory pool) external onlyOwner{
            poolInfo.push(pool);
        }
    
        function setFees(uint256 _poolId, uint emFee) external onlyOwner {
            PoolInfo storage pool = poolInfo[_poolId];
            require(emFee <= 3000, "EmergencyWithdrawFee should be <= 30");
            pool.emergencyWithdrawFee = emFee;
        }
    
        function changePoolStatus(uint256 _pid,bool _isOpen) external onlyAuthorized{
            PoolInfo storage pool = poolInfo[_pid];
            pool.isOpen = _isOpen;
        }
    
        function togglePool(uint256 _pid) external onlyAuthorized{
            PoolInfo storage pool = poolInfo[_pid];
            pool.isOpen = !pool.isOpen;
        }
    
        function updatePoolLength(uint256 _poolId, uint256 _poolLength) external onlyAuthorized{
            PoolInfo storage pool = poolInfo[_poolId];
            pool.poolLength = _poolLength;
        }
    
        function extendPoolLength(uint256 _poolId, uint256 _duration) external onlyAuthorized{
            PoolInfo storage pool = poolInfo[_poolId];
            pool.poolLength += (_duration * 1 days);
        }
    
        function getDynamicPoolInfo(uint256 _poolId) external view returns (DynamicPoolInfo memory) {
            PoolInfo storage pool = poolInfo[_poolId];
            DynamicPoolInfo memory dynamicPoolInfo;
    
            dynamicPoolInfo.interest = pool.interest;
            dynamicPoolInfo.apr = pool.apr;
            dynamicPoolInfo.lockPeriod = pool.lockPeriod;
            dynamicPoolInfo.isOpen = pool.isOpen;
            dynamicPoolInfo.isLive = isLivePool(_poolId);
    
            dynamicPoolInfo.endDate = pool.startEpoch + pool.poolLength;
            dynamicPoolInfo.liveStakedAmount = pool.liveStakedAmount;
            dynamicPoolInfo.rewardDept = (pool.liveStakedAmount * pool.interest) / 10000;
    
            return dynamicPoolInfo;
        }
    
        function pendingReward(uint256 _stakeId, address _user) public view returns (uint256) {
            StakeInfo memory stake = stakeInfo[_user][_stakeId];
            PoolInfo memory pool = poolInfo[stake.poolId];
            
            uint256 lockedTime = block.timestamp > stake.depositTime + pool.lockPeriod ? pool.lockPeriod : block.timestamp - stake.depositTime;
            uint256 reward = (((stake.amount * pool.interest)  * lockedTime) / pool.lockPeriod) / 10_000;
            return reward;
        }
    
    
        function canWithdraw(uint256 _stakeId, address _user) public view returns (bool) {
            return (withdrawCountdown(_stakeId,_user)==0 && stakeInfo[_user][_stakeId].amount > 0);
        }
    
        function withdrawCountdown(uint256 _stakeId, address _user) public view returns (uint256) {
            StakeInfo storage stake = stakeInfo[_user][_stakeId];
            PoolInfo  storage pool = poolInfo[stake.poolId];
            if ((block.timestamp < stake.depositTime + pool.lockPeriod)){
                return stake.depositTime + pool.lockPeriod -  block.timestamp;
            }else{
                return 0;
            }
        }
    
        function userInfo(uint256 stakeId, address _user) public view returns(uint256,uint256,uint256,uint256,uint256) {
            StakeInfo storage stake = stakeInfo[_user][stakeId];
            PoolInfo storage pool = poolInfo[stake.poolId];
            return (stake.amount, stake.depositTime, pool.interest, pool.startEpoch, pool.lockPeriod);
        }
    
        function getAllUserInfo(address _user) public view returns(uint256[] memory) {
            StakeInfo[] storage stake = stakeInfo[_user];
            PoolInfo[] storage pool = poolInfo;
            uint256 lenghtOfStake = 0;
             for(uint256 i = 0; i < stake.length; ++i)
                 if(stake[i].amount>0)
                    lenghtOfStake+=1;
                
            uint256[] memory information = new uint256[](lenghtOfStake*7);
            uint256 j=0;
            for(uint256 i = 0; i < stake.length; ++i){
                if(stake[i].amount>0){
                    information[j*7+0]=stake[i].amount;
                    information[j*7+1]=stake[i].depositTime;
                    information[j*7+2]=pool[stake[i].poolId].interest;
                    information[j*7+3]=pool[stake[i].poolId].lockPeriod;
                    information[j*7+4]=i;
                    information[j*7+5]=pendingReward(i,_user);
                    information[j*7+6]=canWithdraw(i,_user)? 1 : 0;
                    j+=1;
                }
            }
            return information;
        }
    
        function getUserTotalStakedAmount(address _user) public view returns(uint256) {
            StakeInfo[] storage stake = stakeInfo[_user];
    
            uint256 totalStakedAmount;
            for(uint256 i = 0; i < stake.length; ++i) {
                totalStakedAmount += stake[i].amount;
            }
            return totalStakedAmount;
        }
    
        function getTotalContributors() public view returns(uint256) {
            PoolInfo[] storage pool = poolInfo;
    
            uint256 totalContributors;
            for(uint256 i = 0; i < pool.length; ++i) {
                totalContributors += pool[i].totalContributed;
            }
            return totalContributors;
        }
    
        function getTotalLiveStakingAmount() public view returns(uint256) {
            PoolInfo[] storage pool = poolInfo;
    
            uint256 totalLiveStakeAmount;
            for(uint256 i = 0; i < pool.length; ++i) {
                totalLiveStakeAmount += pool[i].liveStakedAmount;
            }
            return totalLiveStakeAmount;
        }
    
        function getTotalRewardDepth() public view returns(uint256) {
            PoolInfo[] storage pool = poolInfo;
    
            uint256 pools = poolInfo.length;
            uint256 totalRewardDepth;
            for(uint256 i = 0; i < pools; ++i) {
                totalRewardDepth += (pool[i].liveStakedAmount * pool[i].interest) / 10_000;
            }
            return totalRewardDepth;
        }
    
        function getTotalRewardDistributed() public view returns(uint256) {
            return totalRewardDistributed;
        }
    
        function getTotals() external view returns(uint256[4] memory) {
            uint256[4] memory totals;
    
            totals[0] = getTotalContributors();
            totals[1] = getTotalLiveStakingAmount();
            totals[2] = getTotalRewardDepth();
            totals[3] = getTotalRewardDistributed();
    
            return totals;
        }
    
        function isLivePool(uint256 _poolId) public view returns(bool) {
            PoolInfo storage pool = poolInfo[_poolId];
            return (pool.isOpen && block.timestamp >= pool.startEpoch && block.timestamp <= pool.startEpoch + pool.poolLength);
        }
    
        function deposit(uint256 _poolId,uint256 _amount) public nonReentrant{
            require (_amount > 0, 'amount 0');
            PoolInfo storage pool = poolInfo[_poolId];
    
            require(isLivePool(_poolId),'Pool is not live');
            require(pool.startEpoch < block.timestamp,'pool has not started yet');
            
            token.safeTransferFrom(address(msg.sender), address(this), _amount);
    
            pool.liveStakedAmount += _amount;
            
            stakeInfo[msg.sender].push(StakeInfo({
                amount: _amount,
                poolId: _poolId,
                depositTime: block.timestamp
            }));
    
            if(stakeInfo[msg.sender].length==1){
                pool.totalContributed+=1;
            }
            emit Deposit(msg.sender, _amount);
        }
    
        function withdraw(uint256 _stakeId) public nonReentrant{
            require(canWithdraw(_stakeId,msg.sender),'cannot withdraw yet or already withdrawn');
            StakeInfo storage stake = stakeInfo[msg.sender][_stakeId];
            PoolInfo storage pool = poolInfo[stake.poolId];
            
            uint256 _amount = stake.amount;
            pool.liveStakedAmount -= _amount;
            
            uint256 _pendingReward = pendingReward(_stakeId, msg.sender);
    
            totalRewardDistributed += _pendingReward;
            _amount += _pendingReward;
            stake.amount=0;
    
            token.safeTransfer(address(msg.sender), _amount);
    
            emit Withdraw(msg.sender, _amount);
        }
    
        function emergencyWithdraw(uint256 _stakeId) public nonReentrant{
            require(!canWithdraw(_stakeId,msg.sender),'Use normal withdraw instead of emergency!');
            StakeInfo storage stake = stakeInfo[msg.sender][_stakeId];
            PoolInfo storage pool = poolInfo[stake.poolId];
            
            uint256 _amount = stake.amount ;
    
            pool.liveStakedAmount -= _amount;
            stake.amount = 0;
    
            if(pool.emergencyWithdrawFee>0){
                if(pool.burnFee > 0){
                uint256 burnFee = (_amount * pool.burnFee) / 10_000;
                token.safeTransfer(address(0xdead), burnFee);
                }
    
                _amount -= (_amount * pool.emergencyWithdrawFee) / 10_000; 
                emit EmergencyWithdrawFee(address(msg.sender), (_amount * pool.emergencyWithdrawFee) / 10_000); 
            }
    
            token.safeTransfer(address(msg.sender), _amount);
    
            emit EmergencyWithdraw(msg.sender, _amount);
        }
    }

    File 2 of 2: CHITCAT
    // SPDX-License-Identifier: MIT
    
    pragma solidity 0.8.17;
    
    interface IUniswapV2Factory {
        event PairCreated(address indexed token0, address indexed token1, address pair, uint);
    
        function feeTo() external view returns (address);
        function feeToSetter() external view returns (address);
        function getPair(address tokenA, address tokenB) external view returns (address pair);
        function allPairs(uint) external view returns (address pair);
        function allPairsLength() external view returns (uint);
        function createPair(address tokenA, address tokenB) external returns (address pair);
        function setFeeTo(address) external;
        function setFeeToSetter(address) external;
    }
    
    interface IUniswapV2Pair {
        event Approval(address indexed owner, address indexed spender, uint value);
        event Transfer(address indexed from, address indexed to, uint value);
    
        function name() external pure returns (string memory);
        function symbol() external pure returns (string memory);
        function decimals() external pure returns (uint8);
        function totalSupply() external view returns (uint);
        function balanceOf(address owner) external view returns (uint);
        function allowance(address owner, address spender) external view returns (uint);
    
        function approve(address spender, uint value) external returns (bool);
        function transfer(address to, uint value) external returns (bool);
        function transferFrom(address from, address to, uint value) external returns (bool);
    
        function DOMAIN_SEPARATOR() external view returns (bytes32);
        function PERMIT_TYPEHASH() external pure returns (bytes32);
        function nonces(address owner) external view returns (uint);
    
        function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
    
        event Mint(address indexed sender, uint amount0, uint amount1);
        event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
        event Swap(
            address indexed sender,
            uint amount0In,
            uint amount1In,
            uint amount0Out,
            uint amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
    
        function MINIMUM_LIQUIDITY() external pure returns (uint);
        function factory() external view returns (address);
        function token0() external view returns (address);
        function token1() external view returns (address);
        function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
        function price0CumulativeLast() external view returns (uint);
        function price1CumulativeLast() external view returns (uint);
        function kLast() external view returns (uint);
    
        function mint(address to) external returns (uint liquidity);
        function burn(address to) external returns (uint amount0, uint amount1);
        function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
        function skim(address to) external;
        function sync() external;
    
        function initialize(address, address) external;
    }
    
    interface IUniswapV2Router01 {
        function factory() external pure returns (address);
        function WETH() external pure returns (address);
    
        function addLiquidity(
            address tokenA,
            address tokenB,
            uint amountADesired,
            uint amountBDesired,
            uint amountAMin,
            uint amountBMin,
            address to,
            uint deadline
        ) external returns (uint amountA, uint amountB, uint liquidity);
        function addLiquidityETH(
            address token,
            uint amountTokenDesired,
            uint amountTokenMin,
            uint amountETHMin,
            address to,
            uint deadline
        ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
        function removeLiquidity(
            address tokenA,
            address tokenB,
            uint liquidity,
            uint amountAMin,
            uint amountBMin,
            address to,
            uint deadline
        ) external returns (uint amountA, uint amountB);
        function removeLiquidityETH(
            address token,
            uint liquidity,
            uint amountTokenMin,
            uint amountETHMin,
            address to,
            uint deadline
        ) external returns (uint amountToken, uint amountETH);
        function removeLiquidityWithPermit(
            address tokenA,
            address tokenB,
            uint liquidity,
            uint amountAMin,
            uint amountBMin,
            address to,
            uint deadline,
            bool approveMax, uint8 v, bytes32 r, bytes32 s
        ) external returns (uint amountA, uint amountB);
        function removeLiquidityETHWithPermit(
            address token,
            uint liquidity,
            uint amountTokenMin,
            uint amountETHMin,
            address to,
            uint deadline,
            bool approveMax, uint8 v, bytes32 r, bytes32 s
        ) external returns (uint amountToken, uint amountETH);
        function swapExactTokensForTokens(
            uint amountIn,
            uint amountOutMin,
            address[] calldata path,
            address to,
            uint deadline
        ) external returns (uint[] memory amounts);
        function swapTokensForExactTokens(
            uint amountOut,
            uint amountInMax,
            address[] calldata path,
            address to,
            uint deadline
        ) external returns (uint[] memory amounts);
        function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
            external
            payable
            returns (uint[] memory amounts);
        function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
            external
            returns (uint[] memory amounts);
        function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
            external
            returns (uint[] memory amounts);
        function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
            external
            payable
            returns (uint[] memory amounts);
    
        function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
        function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
        function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
        function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
        function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
    }
    
    interface IUniswapV2Router02 is IUniswapV2Router01 {
        function removeLiquidityETHSupportingFeeOnTransferTokens(
            address token,
            uint liquidity,
            uint amountTokenMin,
            uint amountETHMin,
            address to,
            uint deadline
        ) external returns (uint amountETH);
        function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
            address token,
            uint liquidity,
            uint amountTokenMin,
            uint amountETHMin,
            address to,
            uint deadline,
            bool approveMax, uint8 v, bytes32 r, bytes32 s
        ) external returns (uint amountETH);
    
        function swapExactTokensForTokensSupportingFeeOnTransferTokens(
            uint amountIn,
            uint amountOutMin,
            address[] calldata path,
            address to,
            uint deadline
        ) external;
        function swapExactETHForTokensSupportingFeeOnTransferTokens(
            uint amountOutMin,
            address[] calldata path,
            address to,
            uint deadline
        ) external payable;
        function swapExactTokensForETHSupportingFeeOnTransferTokens(
            uint amountIn,
            uint amountOutMin,
            address[] calldata path,
            address to,
            uint deadline
        ) external;
    }
    
    interface IERC20 {
        function totalSupply() external view returns (uint256);
        function balanceOf(address account) external view returns (uint256);
        function transfer(address recipient, uint256 amount) external returns (bool);
        function allowance(address owner, address spender) external view returns (uint256);
        function approve(address spender, uint256 amount) external returns (bool);
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) external returns (bool);
       
        event Transfer(address indexed from, address indexed to, uint256 value);
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    interface IERC20Metadata is IERC20 {
        function name() external view returns (string memory);
        function symbol() external view returns (string memory);
        function decimals() external view returns (uint8);
    }
    
    library Address {
        function isContract(address account) internal view returns (bool) {
            return account.code.length > 0;
        }
    
        function sendValue(address payable recipient, uint256 amount) internal returns(bool){
            require(address(this).balance >= amount, "Address: insufficient balance");
    
            (bool success, ) = recipient.call{value: amount}("");
            return success;
        }
    
        function functionCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionCallWithValue(target, data, 0, "Address: low-level call failed");
        }
    
        function functionCall(
            address target,
            bytes memory data,
            string memory errorMessage
        ) internal returns (bytes memory) {
            return functionCallWithValue(target, data, 0, errorMessage);
        }
    
        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");
        }
    
        function functionCallWithValue(
            address target,
            bytes memory data,
            uint256 value,
            string memory errorMessage
        ) internal returns (bytes memory) {
            require(address(this).balance >= value, "Address: insufficient balance for call");
            (bool success, bytes memory returndata) = target.call{value: value}(data);
            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
        }
    
        function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
            return functionStaticCall(target, data, "Address: low-level static call failed");
        }
    
        function functionStaticCall(
            address target,
            bytes memory data,
            string memory errorMessage
        ) internal view returns (bytes memory) {
            (bool success, bytes memory returndata) = target.staticcall(data);
            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
        }
    
        function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionDelegateCall(target, data, "Address: low-level delegate call failed");
        }
    
        function functionDelegateCall(
            address target,
            bytes memory data,
            string memory errorMessage
        ) internal returns (bytes memory) {
            (bool success, bytes memory returndata) = target.delegatecall(data);
            return verifyCallResultFromTarget(target, success, returndata, errorMessage);
        }
    
        function verifyCallResultFromTarget(
            address target,
            bool success,
            bytes memory returndata,
            string memory errorMessage
        ) internal view returns (bytes memory) {
            if (success) {
                if (returndata.length == 0) {
                    // only check isContract if the call was successful and the return data is empty
                    // otherwise we already know that it was a contract
                    require(isContract(target), "Address: call to non-contract");
                }
                return returndata;
            } else {
                _revert(returndata, errorMessage);
            }
        }
    
        function verifyCallResult(
            bool success,
            bytes memory returndata,
            string memory errorMessage
        ) internal pure returns (bytes memory) {
            if (success) {
                return returndata;
            } else {
                _revert(returndata, errorMessage);
            }
        }
    
        function _revert(bytes memory returndata, string memory errorMessage) private pure {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                /// @solidity memory-safe-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
            return msg.data;
        }
    }
    
    abstract contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
        constructor () {
            address msgSender = _msgSender();
            _owner = msgSender;
            emit OwnershipTransferred(address(0), msgSender);
        }
    
        function owner() public view returns (address) {
            return _owner;
        }
    
        modifier onlyOwner() {
            require(_owner == _msgSender(), "Ownable: caller is not the owner");
            _;
        }
    
        function renounceOwnership() public virtual onlyOwner {
            emit OwnershipTransferred(_owner, address(0));
            _owner = address(0);
        }
    
        function transferOwnership(address newOwner) public virtual onlyOwner {
            require(newOwner != address(0), "Ownable: new owner is the zero address");
            emit OwnershipTransferred(_owner, newOwner);
            _owner = newOwner;
        }
    }
    
    contract ERC20 is Context, IERC20, IERC20Metadata {
        mapping(address => uint256) private _balances;
    
        mapping(address => mapping(address => uint256)) private _allowances;
    
        uint256 private _totalSupply;
    
        string private _name;
        string private _symbol;
    
        constructor(string memory name_, string memory symbol_) {
            _name = name_;
            _symbol = symbol_;
        }
    
        function name() public view virtual override returns (string memory) {
            return _name;
        }
    
        function symbol() public view virtual override returns (string memory) {
            return _symbol;
        }
    
        function decimals() public view virtual override returns (uint8) {
            return 18;
        }
    
        function totalSupply() public view virtual override returns (uint256) {
            return _totalSupply;
        }
    
        function balanceOf(address account) public view virtual override returns (uint256) {
            return _balances[account];
        }
    
        function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
    
        function allowance(address owner, address spender) public view virtual override returns (uint256) {
            return _allowances[owner][spender];
        }
    
        function approve(address spender, uint256 amount) public virtual override returns (bool) {
            _approve(_msgSender(), spender, amount);
            return true;
        }
    
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) public virtual override returns (bool) {
            uint256 currentAllowance = _allowances[sender][_msgSender()];
            if (currentAllowance != type(uint256).max) {
                require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
                unchecked {
                    _approve(sender, _msgSender(), currentAllowance - amount);
                }
            }
    
            _transfer(sender, recipient, amount);
    
            return true;
        }
    
        function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
            _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
            return true;
        }
    
        function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
            uint256 currentAllowance = _allowances[_msgSender()][spender];
            require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
            unchecked {
                _approve(_msgSender(), spender, currentAllowance - subtractedValue);
            }
    
            return true;
        }
    
        function _transfer(
            address sender,
            address recipient,
            uint256 amount
        ) internal virtual {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _beforeTokenTransfer(sender, recipient, amount);
    
            uint256 senderBalance = _balances[sender];
            require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
            unchecked {
                _balances[sender] = senderBalance - amount;
            }
            _balances[recipient] += amount;
    
            emit Transfer(sender, recipient, amount);
    
            _afterTokenTransfer(sender, recipient, amount);
        }
    
        function _mint(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _beforeTokenTransfer(address(0), account, amount);
    
            _totalSupply += amount;
            _balances[account] += amount;
            emit Transfer(address(0), account, amount);
    
            _afterTokenTransfer(address(0), account, amount);
        }
    
        function _burn(address account, uint256 amount) internal virtual {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _beforeTokenTransfer(account, address(0), amount);
    
            uint256 accountBalance = _balances[account];
            require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
            unchecked {
                _balances[account] = accountBalance - amount;
            }
            _totalSupply -= amount;
    
            emit Transfer(account, address(0), amount);
    
            _afterTokenTransfer(account, address(0), amount);
        }
    
        function _approve(
            address owner,
            address spender,
            uint256 amount
        ) internal virtual {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
    
        function _beforeTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}
    
        function _afterTokenTransfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {}
    }
    
    contract CHITCAT is ERC20, Ownable {
        using Address for address payable;
    
        IUniswapV2Router02 public uniswapV2Router;
        address public  uniswapV2Pair;
    
        mapping (address => bool) private _isExcludedFromFees;
    
        address public  marketingWallet;
        address public  buyBackWallet;
    
        uint256 public  swapTokensAtAmount;
        bool    private swapping;
    
        event ExcludeFromFees(address indexed account, bool isExcluded);
        event SwapAndSendMarketing(uint256 tokensSwapped, uint256 bnbSend);
    
        constructor () ERC20("ChitCAT", "CHITCAT") 
        {   
            address router = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
    
            IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(router);
            address _uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
                .createPair(address(this), _uniswapV2Router.WETH());
    
            uniswapV2Router = _uniswapV2Router;
            uniswapV2Pair   = _uniswapV2Pair;
    
            _approve(address(this), address(uniswapV2Router), type(uint256).max);
    
            marketingWallet = 0x6CDC578a25D5f1eC5dB6C277bCdDa91e0e37e11B;
            buyBackWallet = 0x7Fe7077E6c42030d1397D592943b1f8eC9Aa67d2;
    
            _isExcludedFromFees[owner()] = true;
            _isExcludedFromFees[address(0xdead)] = true;
            _isExcludedFromFees[address(this)] = true;
            _isExcludedFromFees[marketingWallet] = true;
            _isExcludedFromFees[buyBackWallet] = true;
            _isExcludedFromFees[0x407993575c91ce7643a4d4cCACc9A98c36eE1BBE] = true; //pinklock
    
            _mint(owner(), 1e7 * (10 ** decimals()));
            swapTokensAtAmount = totalSupply() / 5_000;
        }
    
        receive() external payable {}
    
        function excludeFromFees(address account, bool excluded) external onlyOwner{
            require(_isExcludedFromFees[account] != excluded,"Account is already the value of 'excluded'");
            _isExcludedFromFees[account] = excluded;
    
            emit ExcludeFromFees(account, excluded);
        }
    
        function isExcludedFromFees(address account) public view returns(bool) {
            return _isExcludedFromFees[account];
        }
    
        bool public tradingEnabled;
    
        function enableTrading() external onlyOwner{
            require(!tradingEnabled, "Trading already enabled.");
            tradingEnabled = true;
        }
    
        function _transfer(address from,address to,uint256 amount) internal  override {
            require(from != address(0), "ERC20: transfer from the zero address");
            require(to != address(0), "ERC20: transfer to the zero address");
            require(tradingEnabled || _isExcludedFromFees[from] || _isExcludedFromFees[to], "Trading not yet enabled!");
           
            if (amount == 0) {
                super._transfer(from, to, 0);
                return;
            }
    
    		uint256 contractTokenBalance = balanceOf(address(this));
    
            bool canSwap = contractTokenBalance >= swapTokensAtAmount;
    
            if (canSwap &&
                !swapping &&
                to == uniswapV2Pair
            ) {
                swapping = true;
    
                swapAndSendMarketing(contractTokenBalance);     
    
                swapping = false;
            }
    
            uint256 _totalFees;
            if (_isExcludedFromFees[from] || _isExcludedFromFees[to] || swapping) {
                _totalFees = 0;
            } else if (from == uniswapV2Pair) {
                _totalFees = 0;
            } else if (to == uniswapV2Pair) {
                _totalFees = 3;
            } else {
                _totalFees = 0;
            }
    
            if (_totalFees > 0) {
                uint256 fees = (amount * _totalFees) / 100;
                amount = amount - fees;
                super._transfer(from, address(this), fees);
            }
    
            super._transfer(from, to, amount);
        }
    
        function swapAndSendMarketing(uint256 tokenAmount) private {
            uint256 initialBalance = address(this).balance;
    
            address[] memory path = new address[](2);
            path[0] = address(this);
            path[1] = uniswapV2Router.WETH();
    
            uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                tokenAmount,
                0,
                path,
                address(this),
                block.timestamp);
    
            uint256 newBalance = address(this).balance - initialBalance;
            uint256 buyBack = newBalance / 2;
    
            payable(buyBackWallet).sendValue(buyBack);
            payable(marketingWallet).sendValue(address(this).balance - initialBalance);
    
            emit SwapAndSendMarketing(tokenAmount, newBalance);
        }
    }