ETH Price: $2,262.20 (-0.58%)

Transaction Decoder

Block:
20810386 at Sep-23-2024 02:45:35 AM +UTC
Transaction Fee:
0.001244417652643938 ETH $2.82
Gas Used:
112,566 Gas / 11.055004643 Gwei

Emitted Events:

190 NodeStaking.RewardPaid( user=[Sender] 0x2ff2b2b034a7e31f5f325271d54d72bb2ff74ed7, reward=559906316948603 )
191 NODEAI.Transfer( from=[Receiver] NodeStaking, to=[Sender] 0x2ff2b2b034a7e31f5f325271d54d72bb2ff74ed7, value=200000000000000000000 )
192 NodeStaking.Unstaked( user=[Sender] 0x2ff2b2b034a7e31f5f325271d54d72bb2ff74ed7, amount=200000000000000000000, index=0 )

Account State Difference:

  Address   Before After State Difference Code
0x1258D60B...FCFb7e870
0x2Ff2b2B0...b2Ff74ED7
0.064467725274860746 Eth
Nonce: 82
0.063783213939165411 Eth
Nonce: 83
0.000684511335695335
(Titan Builder)
13.937128564360648373 Eth13.937340391059448373 Eth0.0002118266988
0xF4dA8857...e2eeA6C85 26.745175952829077287 Eth26.744616046512128684 Eth0.000559906316948603

Execution Trace

NodeStaking.unstake( _index=0, _amount=200000000000000000000 )
  • ETH 0.000559906316948603 0x2ff2b2b034a7e31f5f325271d54d72bb2ff74ed7.CALL( )
  • NODEAI.transfer( recipient=0x2Ff2b2B034A7e31F5F325271d54D72Bb2Ff74ED7, amount=200000000000000000000 ) => ( True )
    File 1 of 2: NodeStaking
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
    pragma solidity ^0.8.20;
    import {Context} from "../utils/Context.sol";
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * The initial owner is set to the address provided by the deployer. This can
     * later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    abstract contract Ownable is Context {
        address private _owner;
        /**
         * @dev The caller account is not authorized to perform an operation.
         */
        error OwnableUnauthorizedAccount(address account);
        /**
         * @dev The owner is not a valid owner account. (eg. `address(0)`)
         */
        error OwnableInvalidOwner(address owner);
        event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
        /**
         * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
         */
        constructor(address initialOwner) {
            if (initialOwner == address(0)) {
                revert OwnableInvalidOwner(address(0));
            }
            _transferOwnership(initialOwner);
        }
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            _checkOwner();
            _;
        }
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view virtual returns (address) {
            return _owner;
        }
        /**
         * @dev Throws if the sender is not the owner.
         */
        function _checkOwner() internal view virtual {
            if (owner() != _msgSender()) {
                revert OwnableUnauthorizedAccount(_msgSender());
            }
        }
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions. Can only be called by the current owner.
         *
         * NOTE: Renouncing ownership will leave the contract without an owner,
         * thereby disabling any functionality that is only available to the owner.
         */
        function renounceOwnership() public virtual onlyOwner {
            _transferOwnership(address(0));
        }
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Can only be called by the current owner.
         */
        function transferOwnership(address newOwner) public virtual onlyOwner {
            if (newOwner == address(0)) {
                revert OwnableInvalidOwner(address(0));
            }
            _transferOwnership(newOwner);
        }
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`).
         * Internal function without access restriction.
         */
        function _transferOwnership(address newOwner) internal virtual {
            address oldOwner = _owner;
            _owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
    pragma solidity ^0.8.20;
    /**
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
        function _contextSuffixLength() internal view virtual returns (uint256) {
            return 0;
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)
    pragma solidity ^0.8.20;
    import {Context} from "../utils/Context.sol";
    /**
     * @dev Contract module which allows children to implement an emergency stop
     * mechanism that can be triggered by an authorized account.
     *
     * This module is used through inheritance. It will make available the
     * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
     * the functions of your contract. Note that they will not be pausable by
     * simply including this module, only once the modifiers are put in place.
     */
    abstract contract Pausable is Context {
        bool private _paused;
        /**
         * @dev Emitted when the pause is triggered by `account`.
         */
        event Paused(address account);
        /**
         * @dev Emitted when the pause is lifted by `account`.
         */
        event Unpaused(address account);
        /**
         * @dev The operation failed because the contract is paused.
         */
        error EnforcedPause();
        /**
         * @dev The operation failed because the contract is not paused.
         */
        error ExpectedPause();
        /**
         * @dev Initializes the contract in unpaused state.
         */
        constructor() {
            _paused = false;
        }
        /**
         * @dev Modifier to make a function callable only when the contract is not paused.
         *
         * Requirements:
         *
         * - The contract must not be paused.
         */
        modifier whenNotPaused() {
            _requireNotPaused();
            _;
        }
        /**
         * @dev Modifier to make a function callable only when the contract is paused.
         *
         * Requirements:
         *
         * - The contract must be paused.
         */
        modifier whenPaused() {
            _requirePaused();
            _;
        }
        /**
         * @dev Returns true if the contract is paused, and false otherwise.
         */
        function paused() public view virtual returns (bool) {
            return _paused;
        }
        /**
         * @dev Throws if the contract is paused.
         */
        function _requireNotPaused() internal view virtual {
            if (paused()) {
                revert EnforcedPause();
            }
        }
        /**
         * @dev Throws if the contract is not paused.
         */
        function _requirePaused() internal view virtual {
            if (!paused()) {
                revert ExpectedPause();
            }
        }
        /**
         * @dev Triggers stopped state.
         *
         * Requirements:
         *
         * - The contract must not be paused.
         */
        function _pause() internal virtual whenNotPaused {
            _paused = true;
            emit Paused(_msgSender());
        }
        /**
         * @dev Returns to normal state.
         *
         * Requirements:
         *
         * - The contract must be paused.
         */
        function _unpause() internal virtual whenPaused {
            _paused = false;
            emit Unpaused(_msgSender());
        }
    }
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
    pragma solidity ^0.8.20;
    /**
     * @dev Contract module that helps prevent reentrant calls to a function.
     *
     * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
     * available, which can be applied to functions to make sure there are no nested
     * (reentrant) calls to them.
     *
     * Note that because there is a single `nonReentrant` guard, functions marked as
     * `nonReentrant` may not call one another. This can be worked around by making
     * those functions `private`, and then adding `external` `nonReentrant` entry
     * points to them.
     *
     * TIP: If you would like to learn more about reentrancy and alternative ways
     * to protect against it, check out our blog post
     * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
     */
    abstract contract ReentrancyGuard {
        // Booleans are more expensive than uint256 or any type that takes up a full
        // word because each write operation emits an extra SLOAD to first read the
        // slot's contents, replace the bits taken up by the boolean, and then write
        // back. This is the compiler's defense against contract upgrades and
        // pointer aliasing, and it cannot be disabled.
        // The values being non-zero value makes deployment a bit more expensive,
        // but in exchange the refund on every call to nonReentrant will be lower in
        // amount. Since refunds are capped to a percentage of the total
        // transaction's gas, it is best to keep them low in cases like this one, to
        // increase the likelihood of the full refund coming into effect.
        uint256 private constant NOT_ENTERED = 1;
        uint256 private constant ENTERED = 2;
        uint256 private _status;
        /**
         * @dev Unauthorized reentrant call.
         */
        error ReentrancyGuardReentrantCall();
        constructor() {
            _status = NOT_ENTERED;
        }
        /**
         * @dev Prevents a contract from calling itself, directly or indirectly.
         * Calling a `nonReentrant` function from another `nonReentrant`
         * function is not supported. It is possible to prevent this from happening
         * by making the `nonReentrant` function external, and making it call a
         * `private` function that does the actual work.
         */
        modifier nonReentrant() {
            _nonReentrantBefore();
            _;
            _nonReentrantAfter();
        }
        function _nonReentrantBefore() private {
            // On the first call to nonReentrant, _status will be NOT_ENTERED
            if (_status == ENTERED) {
                revert ReentrancyGuardReentrantCall();
            }
            // Any calls to nonReentrant after this point will fail
            _status = ENTERED;
        }
        function _nonReentrantAfter() private {
            // By storing the original value once again, a refund is triggered (see
            // https://eips.ethereum.org/EIPS/eip-2200)
            _status = NOT_ENTERED;
        }
        /**
         * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
         * `nonReentrant` function in the call stack.
         */
        function _reentrancyGuardEntered() internal view returns (bool) {
            return _status == ENTERED;
        }
    }
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.24;
    import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';
    import '@openzeppelin/contracts/access/Ownable.sol';
    import '@openzeppelin/contracts/utils/Pausable.sol';
    interface IERC20 {
      function transfer(address recipient, uint256 amount) external returns (bool);
      function transferFrom(
        address sender,
        address recipient,
        uint256 amount
      ) external returns (bool);
      function balanceOf(address account) external view returns (uint256);
      function approve(address spender, uint256 value) external returns (bool);
    }
    contract NodeStaking is ReentrancyGuard, Ownable, Pausable {
      IERC20 public stakingToken;
      struct Stake {
        uint256 amount;
        uint256 startTime;
        uint256 rewardPaid;
      }
      mapping(address => Stake[]) public stakes;
      mapping(address => uint256) public totalUserRewards;
      address[] public stakers;
      mapping(address => bool) public isStaker;
      uint256 public totalRewards = 0;
      uint256 public totalStaked;
      uint256 public earlyUnstakePenality = 30;
      uint256 public maxTotalStaked = 10_000_000 * (10 ** 18); // Example: 10 million tokens
      uint256 public maxPerWallet = 1_000 * (10 ** 18); // Example: 1,000 tokens per wallet
      uint256 public constant stakingPeriod = 30 days;
      address public constant deadWallet =
        0x000000000000000000000000000000000000dEaD;
      event Staked(address indexed user, uint256 amount, uint256 index);
      event Unstaked(address indexed user, uint256 amount, uint256 index);
      event RewardPaid(address indexed user, uint256 reward);
      event Migrated(
        address indexed newStakingContract,
        uint256 tokenAmount,
        uint256 ethAmount
      );
      /* Initializes the constructure with the staking token set and owner */
      constructor(address _stakingToken) Ownable(_msgSender()) {
        stakingToken = IERC20(_stakingToken);
      }
      /* Sets the staking token */
      function setStakingToken(address _stakingToken) external onlyOwner {
        require(_stakingToken != address(0), 'Invalid address');
        stakingToken = IERC20(_stakingToken);
      }
      /* Sets the maximum total staked amount */
      function setMaxTotalStaked(uint256 _maxTotalStaked) external onlyOwner {
        maxTotalStaked = _maxTotalStaked;
      }
      /* Sets the maximum staked amount per wallet */
      function setMaxPerWallet(uint256 _maxPerWallet) external onlyOwner {
        maxPerWallet = _maxPerWallet;
      }
      /* Sets the pause state of the contract */
      function setPaused(bool _paused) external onlyOwner {
        require(_paused != paused(), 'Already in the requested state');
        if (_paused) {
          _pause();
        } else {
          _unpause();
        }
      }
      /* Migrates the staking contract to a new contract */
      function migrate(address _newStakingContract) external onlyOwner {
        require(_newStakingContract != address(0), 'Invalid address');
        uint256 contractTokenBalance = stakingToken.balanceOf(address(this));
        require(
          stakingToken.transfer(_newStakingContract, contractTokenBalance),
          'Failed to transfer tokens to owner'
        );
        uint256 contractETHBalance = address(this).balance;
        (bool sent, ) = _newStakingContract.call{value: contractETHBalance}('');
        require(sent, 'Failed to transfer ETH');
        emit Migrated(
          _newStakingContract,
          contractTokenBalance,
          contractETHBalance
        );
      }
      function stake(uint256 _amount) external nonReentrant whenNotPaused {
        require(_amount > 0, 'Amount must be greater than 0');
        require(totalStaked + _amount <= maxTotalStaked, 'Staking limit exceeded');
        uint256 walletStaked = getWalletStaked(msg.sender);
        require(walletStaked + _amount <= maxPerWallet, 'Staking limit exceeded');
        if(!isStaker[msg.sender]) {
          stakers.push(msg.sender);
          isStaker[msg.sender] = true;
        }
        bool success = stakingToken.transferFrom(msg.sender, address(this), _amount);
        require(success, 'Failed to transfer tokens');
        stakes[msg.sender].push(Stake(_amount, block.timestamp, 0));
        totalStaked += _amount;
        emit Staked(msg.sender, _amount, stakes[msg.sender].length - 1);
      }
      function unstake(uint256 _index, uint256 _amount) external nonReentrant {
        require(_index < stakes[msg.sender].length, 'Invalid stake index');
        Stake storage userStake = stakes[msg.sender][_index];
        require(
          block.timestamp >= userStake.startTime + stakingPeriod,
          'Stake is still locked'
        );
        require(userStake.amount >= _amount, 'Insufficient staked amount');
        uint256 reward = _claimRewards(msg.sender, _index);
        if(reward > 0) {
          (bool sent, ) = payable(msg.sender).call{value: reward}('');
          require(sent, 'Failed to send Ether');
          emit RewardPaid(msg.sender, reward);
        }
        userStake.amount -= _amount;
        totalStaked -= _amount;
        if (userStake.amount == 0) {
          removeStake(msg.sender, _index);
        }
        bool success = stakingToken.transfer(msg.sender, _amount);
        require(success, 'Failed to transfer tokens');
        emit Unstaked(msg.sender, _amount, _index);
      }
      function earlyUnstake(uint256 _index, uint256 _amount) external nonReentrant {
        require(_index < stakes[msg.sender].length, 'Invalid stake index');
        Stake storage userStake = stakes[msg.sender][_index];
        require(userStake.amount >= _amount, 'Insufficient staked amount');
        uint256 timeElapsed = block.timestamp - userStake.startTime;
        require(
          timeElapsed < stakingPeriod,
          'Stake is not in early unstake period'
        );
        uint256 reward = _claimRewards(msg.sender, _index);
        if(reward > 0) {
          (bool sent, ) = payable(msg.sender).call{value: reward}('');
          require(sent, 'Failed to send Ether');
          emit RewardPaid(msg.sender, reward);
        }
        // Calculate the penalty fee, which linearly decreases from 50% to 0% over the lock-up period
        uint256 penaltyPercentage = earlyUnstakePenality -
          ((timeElapsed * earlyUnstakePenality) / stakingPeriod);
        uint256 penaltyAmount = (_amount * penaltyPercentage) / 100;
        // Apply the penalty
        uint256 returnAmount = _amount - penaltyAmount;
        // Update the stake and total staked amount
        userStake.amount -= _amount;
        totalStaked -= _amount;
        // Burn the penalty amount
        bool successBurn = stakingToken.transfer(deadWallet, penaltyAmount);
        require(successBurn, 'Failed to burn tokens');
        // Return the remaining tokens to the user
        bool sucessUnstake = stakingToken.transfer(msg.sender, returnAmount);
        require(sucessUnstake, 'Failed to transfer tokens');
        // Remove the stake if it's fully unstaked
        if (userStake.amount == 0) {
          removeStake(msg.sender, _index);
        }
        emit Unstaked(msg.sender, returnAmount, _index);
      }
      function _claimRewards(
        address user,
        uint256 index
      ) private returns (uint256) {
        require(index < stakes[user].length, 'Invalid stake index');
        Stake storage userStake = stakes[user][index];
        uint256 reward = calculateReward(user, index);
        if (reward > 0) {
          userStake.rewardPaid += reward;
          totalUserRewards[user] += reward;
          totalRewards += reward;
        }
        return reward;
      }
      function claimRewards() external nonReentrant {
        uint256 stakeCount = stakes[msg.sender].length;
        require(stakeCount > 0, 'No stakes available');
        uint256 totalReward = 0;
        for (uint256 i = 0; i < stakeCount; i++) {
          totalReward += _claimRewards(msg.sender, i); // Aggregate rewards
        }
        if(totalReward <= 0) {
          return;
        }
        (bool sent, ) = payable(msg.sender).call{value: totalReward}('');
        require(sent, 'Failed to send Ether');
        emit RewardPaid(msg.sender, totalReward);
      }
      function getWalletStaked(address _user) public view returns (uint256) {
        uint256 walletStaked = 0;
        for (uint256 i = 0; i < stakes[_user].length; i++) {
          walletStaked += stakes[_user][i].amount;
        }
        return walletStaked;
      }
      function getWalletReward(address _user) public view returns (uint256) {
        uint256 walletReward = 0;
        for (uint256 i = 0; i < stakes[_user].length; i++) {
          walletReward += stakes[_user][i].rewardPaid;
        }
        return walletReward;
      }
      function getWalletStakes(address _user) public view returns (Stake[] memory) {
        return stakes[_user];
      }
      function getWalletClaimableRewards(
        address _user
      ) public view returns (uint256 totalClaimable) {
        totalClaimable = 0;
        for (uint256 i = 0; i < stakes[_user].length; i++) {
          uint256 reward = calculateReward(_user, i);
          totalClaimable += reward;
        }
      }
      function calculateAllPendingRewards() public view returns (uint256 totalClaimable) {
        totalClaimable = 0;
        for (uint256 i = 0; i < stakers.length; i++) {
          address staker = stakers[i];
          totalClaimable += getWalletClaimableRewards(staker);
        }
      }
      function calculateReward(
        address _user,
        uint256 _index
      ) public view returns (uint256) {
        Stake storage userStake = stakes[_user][_index];
        uint256 stakeDuration = block.timestamp - userStake.startTime;
        if (stakeDuration > stakingPeriod) {
          stakeDuration = stakingPeriod; // Cap the stake duration to the lock-up period for reward calculation
        }
        // Scale the numerator before dividing
        uint256 scaledReward = (address(this).balance *
          userStake.amount *
          stakeDuration) / stakingPeriod;
        uint256 reward = scaledReward / totalStaked;
        if(userStake.rewardPaid > reward) {
          return 0;
        }
        return reward - userStake.rewardPaid; // Assuming rewardPaid is correctly managed elsewhere
      }
      function getUserStakingDetails(
        address _user
      )
        public
        view
        returns (
          uint256 _totalStaked,
          uint256 totalRewardsInEth,
          uint256[] memory timeElapsedPerStake
        )
      {
        _totalStaked = 0;
        totalRewardsInEth = 0;
        timeElapsedPerStake = new uint256[](stakes[_user].length);
        for (uint256 i = 0; i < stakes[_user].length; i++) {
          _totalStaked += stakes[_user][i].amount;
          totalRewardsInEth += calculateReward(_user, i); // This should return ETH rewards
          timeElapsedPerStake[i] = block.timestamp - stakes[_user][i].startTime;
        }
      }
      function removeStake(address _user, uint256 _index) private {
        require(_index < stakes[_user].length, 'Invalid stake index');
        stakes[_user][_index] = stakes[_user][stakes[_user].length - 1];
        stakes[_user].pop();
      }
      receive() external payable {}
    }
    

    File 2 of 2: NODEAI
    // SPDX-License-Identifier: UNLICENSED
    pragma solidity 0.8.19;
    
    /*
    
        /$$$$$$  /$$$$$$$  /$$   /$$
        /$$__  $$| $$__  $$| $$  | $$
        | $$  \__/| $$  \ $$| $$  | $$
        | $$ /$$$$| $$$$$$$/| $$  | $$
        | $$|_  $$| $$____/ | $$  | $$
        | $$  \ $$| $$      | $$  | $$
        |  $$$$$$/| $$      |  $$$$$$/
        \______/ |__/       \______/ 
                                                             
                            
        Website:    https://nodeai.app
        Twitter:    https://twitter.com/NodeAIETH
        Telegram:   https://t.me/nodeaieth
    
        Rent or lend GPU power, and earn rewards with $GPU.
    
        We generate revenue by powering AI with GPUs.
    */
    
    abstract contract Context {
        function _msgSender() internal view virtual returns (address) {
            return msg.sender;
        }
    
        function _msgData() internal view virtual returns (bytes calldata) {
            return msg.data;
        }
    }
    
    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
        );
    }
    
    /**
     * @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
         * ====
         *
         * [IMPORTANT]
         * ====
         * You shouldn't rely on `isContract` to protect against flash loan attacks!
         *
         * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
         * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
         * constructor.
         * ====
         */
        function isContract(address account) internal view returns (bool) {
            // This method relies on extcodesize/address.code.length, which returns 0
            // for contracts in construction, since the code is only stored at the end
            // of the constructor execution.
    
            return account.code.length > 0;
        }
    
        /**
         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
         * `recipient`, forwarding all available gas and reverting on errors.
         *
         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
         * of certain opcodes, possibly making contracts go over the 2300 gas limit
         * imposed by `transfer`, making them unable to receive funds via
         * `transfer`. {sendValue} removes this limitation.
         *
         * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
         *
         * IMPORTANT: because control is transferred to `recipient`, care must be
         * taken to not create reentrancy vulnerabilities. Consider using
         * {ReentrancyGuard} or the
         * https://solidity.readthedocs.io/en/v0.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);
            }
        }
    }
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * By default, the owner account will be the one that deploys the contract. This
     * can later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    abstract contract Ownable is Context {
        address private _owner;
    
        event OwnershipTransferred(
            address indexed previousOwner,
            address indexed newOwner
        );
    
        /**
         * @dev Initializes the contract setting the deployer as the initial owner.
         */
        constructor() {
            _transferOwnership(_msgSender());
        }
    
        /**
         * @dev Throws if called by any account other than the owner.
         */
        modifier onlyOwner() {
            _checkOwner();
            _;
        }
    
        /**
         * @dev Returns the address of the current owner.
         */
        function owner() public view virtual returns (address) {
            return _owner;
        }
    
        /**
         * @dev Throws if the sender is not the owner.
         */
        function _checkOwner() internal view virtual {
            require(owner() == _msgSender(), "Ownable: caller is not the owner");
        }
    
        /**
         * @dev Leaves the contract without owner. It will not be possible to call
         * `onlyOwner` functions 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);
        }
    }
    
    interface IUniswapV2Factory {
        event PairCreated(
            address indexed token0,
            address indexed token1,
            address pair,
            uint256
        );
    
        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(uint256) external view returns (address pair);
    
        function allPairsLength() external view returns (uint256);
    
        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,
            uint256 value
        );
        event Transfer(address indexed from, address indexed to, uint256 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 (uint256);
    
        function balanceOf(address owner) external view returns (uint256);
    
        function allowance(
            address owner,
            address spender
        ) external view returns (uint256);
    
        function approve(address spender, uint256 value) external returns (bool);
    
        function transfer(address to, uint256 value) external returns (bool);
    
        function transferFrom(
            address from,
            address to,
            uint256 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 (uint256);
    
        function permit(
            address owner,
            address spender,
            uint256 value,
            uint256 deadline,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external;
    
        event Burn(
            address indexed sender,
            uint256 amount0,
            uint256 amount1,
            address indexed to
        );
        event Swap(
            address indexed sender,
            uint256 amount0In,
            uint256 amount1In,
            uint256 amount0Out,
            uint256 amount1Out,
            address indexed to
        );
        event Sync(uint112 reserve0, uint112 reserve1);
    
        function MINIMUM_LIQUIDITY() external pure returns (uint256);
    
        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 (uint256);
    
        function price1CumulativeLast() external view returns (uint256);
    
        function kLast() external view returns (uint256);
    
        function burn(
            address to
        ) external returns (uint256 amount0, uint256 amount1);
    
        function swap(
            uint256 amount0Out,
            uint256 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,
            uint256 amountADesired,
            uint256 amountBDesired,
            uint256 amountAMin,
            uint256 amountBMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountA, uint256 amountB, uint256 liquidity);
    
        function addLiquidityETH(
            address token,
            uint256 amountTokenDesired,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline
        )
            external
            payable
            returns (uint256 amountToken, uint256 amountETH, uint256 liquidity);
    
        function removeLiquidity(
            address tokenA,
            address tokenB,
            uint256 liquidity,
            uint256 amountAMin,
            uint256 amountBMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountA, uint256 amountB);
    
        function removeLiquidityETH(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountToken, uint256 amountETH);
    
        function removeLiquidityWithPermit(
            address tokenA,
            address tokenB,
            uint256 liquidity,
            uint256 amountAMin,
            uint256 amountBMin,
            address to,
            uint256 deadline,
            bool approveMax,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external returns (uint256 amountA, uint256 amountB);
    
        function removeLiquidityETHWithPermit(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline,
            bool approveMax,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external returns (uint256 amountToken, uint256 amountETH);
    
        function swapExactTokensForTokens(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
    
        function swapTokensForExactTokens(
            uint256 amountOut,
            uint256 amountInMax,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
    
        function swapExactETHForTokens(
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external payable returns (uint256[] memory amounts);
    
        function swapTokensForExactETH(
            uint256 amountOut,
            uint256 amountInMax,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
    
        function swapExactTokensForETH(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external returns (uint256[] memory amounts);
    
        function swapETHForExactTokens(
            uint256 amountOut,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external payable returns (uint256[] memory amounts);
    
        function quote(
            uint256 amountA,
            uint256 reserveA,
            uint256 reserveB
        ) external pure returns (uint256 amountB);
    
        function getAmountOut(
            uint256 amountIn,
            uint256 reserveIn,
            uint256 reserveOut
        ) external pure returns (uint256 amountOut);
    
        function getAmountIn(
            uint256 amountOut,
            uint256 reserveIn,
            uint256 reserveOut
        ) external pure returns (uint256 amountIn);
    
        function getAmountsOut(
            uint256 amountIn,
            address[] calldata path
        ) external view returns (uint256[] memory amounts);
    
        function getAmountsIn(
            uint256 amountOut,
            address[] calldata path
        ) external view returns (uint256[] memory amounts);
    }
    
    interface IUniswapV2Router02 is IUniswapV2Router01 {
        function removeLiquidityETHSupportingFeeOnTransferTokens(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline
        ) external returns (uint256 amountETH);
    
        function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
            address token,
            uint256 liquidity,
            uint256 amountTokenMin,
            uint256 amountETHMin,
            address to,
            uint256 deadline,
            bool approveMax,
            uint8 v,
            bytes32 r,
            bytes32 s
        ) external returns (uint256 amountETH);
    
        function swapExactTokensForTokensSupportingFeeOnTransferTokens(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external;
    
        function swapExactETHForTokensSupportingFeeOnTransferTokens(
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external payable;
    
        function swapExactTokensForETHSupportingFeeOnTransferTokens(
            uint256 amountIn,
            uint256 amountOutMin,
            address[] calldata path,
            address to,
            uint256 deadline
        ) external;
    }
    
    contract NODEAI is Context, IERC20, Ownable {
        using Address for address;
        //Mapping section for better tracking.
        mapping(address => uint256) private _tOwned;
        mapping(address => mapping(address => uint256)) private _allowances;
        mapping(address => bool) private _isExcludedFromFee;
    
        //Loging and Event Information for better troubleshooting.
        event Log(string, uint256);
        event AuditLog(string, address);
        event RewardLiquidityProviders(uint256 tokenAmount);
        event SwapAndLiquifyEnabledUpdated(bool enabled);
        event SwapAndLiquify(
            uint256 tokensSwapped,
            uint256 ethReceived,
            uint256 tokensIntoLiqudity
        );
        event SwapTokensForETH(uint256 amountIn, address[] path);
        //Supply Definition.
        uint256 private _tTotal = 100_000_000 ether;
        uint256 private _tFeeTotal;
        //Token Definition.
        string public constant name = "NodeAI";
        string public constant symbol = "GPU";
        uint8 public constant decimals = 18;
        //Definition of Wallets for Marketing or team.
        address payable public marketingWallet =
            payable(0xD335c5E36F1B19AECE98b78e9827a9DF76eE29E6);
        address payable public revenueWallet =
            payable(0xE4eEc0C7e825f988aEEe7d05BE579519532E94E5);
        //Dead Wallet for SAFU Contract
        address public constant deadWallet =
            0x000000000000000000000000000000000000dEaD;
    
        //Taxes Definition.
        uint public buyFee = 4;
    
        uint256 public sellFee = 4;
        uint public revenueFee = 1;
        uint public marketingFee = 3;
    
        uint256 public marketingTokensCollected = 0;
    
        uint256 public totalMarketingTokensCollected = 0;
    
        uint256 public minimumTokensBeforeSwap = 10_000 ether;
    
        //Oracle Price Update, Manual Process.
        uint256 public swapOutput = 0;
        //Router and Pair Configuration.
        IUniswapV2Router02 public immutable uniswapV2Router;
        address public immutable uniswapV2Pair;
        address private immutable WETH;
        //Tracking of Automatic Swap vs Manual Swap.
        bool public inSwapAndLiquify;
        bool public swapAndLiquifyEnabled = true;
    
        modifier lockTheSwap() {
            inSwapAndLiquify = true;
            _;
            inSwapAndLiquify = false;
        }
    
        constructor() {
            _tOwned[_msgSender()] = _tTotal;
            address currentRouter;
            //Adding Variables for all the routers for easier deployment for our customers.
            if (block.chainid == 56) {
                currentRouter = 0x10ED43C718714eb63d5aA57B78B54704E256024E; // PCS Router
            } else if (block.chainid == 97) {
                currentRouter = 0xD99D1c33F9fC3444f8101754aBC46c52416550D1; // PCS Testnet
            } else if (block.chainid == 43114) {
                currentRouter = 0x60aE616a2155Ee3d9A68541Ba4544862310933d4; //Avax Mainnet
            } else if (block.chainid == 137) {
                currentRouter = 0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff; //Polygon Ropsten
            } else if (block.chainid == 6066) {
                currentRouter = 0x4169Db906fcBFB8b12DbD20d98850Aee05B7D889; //Tres Leches Chain
            } else if (block.chainid == 250) {
                currentRouter = 0xF491e7B69E4244ad4002BC14e878a34207E38c29; //SpookySwap FTM
            } else if (block.chainid == 42161) {
                currentRouter = 0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506; //Arbitrum Sushi
            } else if (
                block.chainid == 1 || block.chainid == 4 || block.chainid == 5
            ) {
                currentRouter = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D; //Mainnet
            } else {
                revert("You're not Blade");
            }
    
            //End of Router Variables.
            //Create Pair in the contructor, this may fail on some blockchains and can be done in a separate line if needed.
            IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(currentRouter);
            WETH = _uniswapV2Router.WETH();
            uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
                .createPair(address(this), WETH);
            uniswapV2Router = _uniswapV2Router;
            _isExcludedFromFee[owner()] = true;
            _isExcludedFromFee[address(this)] = true;
    
            emit Transfer(address(0), _msgSender(), _tTotal);
        }
    
        //Readable Functions.
        function totalSupply() public view override returns (uint256) {
            return _tTotal;
        }
    
        function balanceOf(address account) public view override returns (uint256) {
            return _tOwned[account];
        }
    
        //ERC 20 Standard Transfer Functions
        function transfer(
            address recipient,
            uint256 amount
        ) public override returns (bool) {
            _transfer(_msgSender(), recipient, amount);
            return true;
        }
    
        //ERC 20 Standard Allowance Function
        function allowance(
            address _owner,
            address spender
        ) public view override returns (uint256) {
            return _allowances[_owner][spender];
        }
    
        //ERC 20 Standard Approve Function
        function approve(
            address spender,
            uint256 amount
        ) public override returns (bool) {
            _approve(_msgSender(), spender, amount);
            return true;
        }
    
        //ERC 20 Standard Transfer From
        function transferFrom(
            address sender,
            address recipient,
            uint256 amount
        ) public override returns (bool) {
            uint currentAllowance = _allowances[sender][_msgSender()];
            require(
                currentAllowance >= amount,
                "ERC20: transfer amount exceeds allowance"
            );
            _transfer(sender, recipient, amount);
            _approve(sender, _msgSender(), currentAllowance - amount);
            return true;
        }
    
        //ERC 20 Standard increase Allowance
        function increaseAllowance(
            address spender,
            uint256 addedValue
        ) public virtual returns (bool) {
            _approve(
                _msgSender(),
                spender,
                _allowances[_msgSender()][spender] + addedValue
            );
            return true;
        }
    
        //ERC 20 Standard decrease Allowance
        function decreaseAllowance(
            address spender,
            uint256 subtractedValue
        ) public virtual returns (bool) {
            _approve(
                _msgSender(),
                spender,
                _allowances[_msgSender()][spender] - subtractedValue
            );
            return true;
        }
    
        //Approve Function
        function _approve(address _owner, address spender, uint256 amount) private {
            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);
        }
    
        //Transfer function, validate correct wallet structure, take fees, and other custom taxes are done during the transfer.
        function _transfer(address from, address to, uint256 amount) private {
            require(from != address(0), "ERC20: transfer from the zero address");
            require(to != address(0), "ERC20: transfer to the zero address");
            require(amount > 0, "Transfer amount must be greater than zero");
            require(
                _tOwned[from] >= amount,
                "ERC20: transfer amount exceeds balance"
            );
    
            //Adding logic for automatic swap.
            uint256 contractTokenBalance = balanceOf(address(this));
            bool overMinimumTokenBalance = contractTokenBalance >=
                minimumTokensBeforeSwap;
            uint fee = 0;
            //if any account belongs to _isExcludedFromFee account then remove the fee
            if (
                !inSwapAndLiquify &&
                from != uniswapV2Pair &&
                overMinimumTokenBalance &&
                swapAndLiquifyEnabled
            ) {
                swapAndLiquify();
            }
            if (to == uniswapV2Pair && !_isExcludedFromFee[from]) {
                fee = (sellFee * amount) / 100;
            }
            if (from == uniswapV2Pair && !_isExcludedFromFee[to]) {
                fee = (buyFee * amount) / 100;
            }
            amount -= fee;
            if (fee > 0) {
                _tokenTransfer(from, address(this), fee);
                marketingTokensCollected += fee;
                totalMarketingTokensCollected += fee;
            }
            _tokenTransfer(from, to, amount);
        }
    
        //Swap Tokens for BNB or to add liquidity either automatically or manual, by default this is set to manual.
        //Corrected newBalance bug, it sending bnb to wallet and any remaining is on contract and can be recoverred.
        function swapAndLiquify() public lockTheSwap {
            uint256 totalTokens = balanceOf(address(this));
            swapTokensForEth(totalTokens);
            uint ethBalance = address(this).balance;
            uint totalFees = revenueFee + marketingFee;
            if (totalFees == 0) totalFees = 1;
            uint revenueAmount = (ethBalance * revenueFee) / totalFees;
            ethBalance -= revenueAmount;
            transferToAddressETH(revenueWallet, revenueAmount);
            transferToAddressETH(marketingWallet, ethBalance);
    
            marketingTokensCollected = 0;
        }
    
        //swap for eth is to support the converstion of tokens to weth during swapandliquify this is a supporting function
        function swapTokensForEth(uint256 tokenAmount) private {
            // generate the uniswap pair path of token -> weth
            address[] memory path = new address[](2);
            path[0] = address(this);
            path[1] = WETH;
            _approve(address(this), address(uniswapV2Router), tokenAmount);
    
            // make the swap
            uniswapV2Router.swapExactTokensForETHSupportingFeeOnTransferTokens(
                tokenAmount,
                0, // accept any amount of ETH
                path,
                address(this), // The contract
                block.timestamp
            );
    
            emit SwapTokensForETH(tokenAmount, path);
        }
    
        //ERC 20 standard transfer, only added if taking fees to countup the amount of fees for better tracking and split purpose.
        function _tokenTransfer(
            address sender,
            address recipient,
            uint256 amount
        ) private {
            _tOwned[sender] -= amount;
            _tOwned[recipient] += amount;
    
            emit Transfer(sender, recipient, amount);
        }
    
        function isExcludedFromFee(address account) external view returns (bool) {
            return _isExcludedFromFee[account];
        }
    
        //exclude wallets from fees, this is needed for launch or other contracts.
        function excludeFromFee(address account) external onlyOwner {
            _isExcludedFromFee[account] = true;
            emit AuditLog(
                "We have excluded the following walled in fees:",
                account
            );
        }
    
        //include wallet back in fees.
        function includeInFee(address account) external onlyOwner {
            _isExcludedFromFee[account] = false;
            emit AuditLog(
                "We have including the following walled in fees:",
                account
            );
        }
    
        //Automatic Swap Configuration.
        function setTokensToSwap(
            uint256 _minimumTokensBeforeSwap
        ) external onlyOwner {
            require(
                _minimumTokensBeforeSwap >= 100 ether,
                "You need to enter more than 100 tokens."
            );
            minimumTokensBeforeSwap = _minimumTokensBeforeSwap;
            emit Log(
                "We have updated minimunTokensBeforeSwap to:",
                minimumTokensBeforeSwap
            );
        }
    
        function setSwapAndLiquifyEnabled(bool _enabled) external onlyOwner {
            require(swapAndLiquifyEnabled != _enabled, "Value already set");
            swapAndLiquifyEnabled = _enabled;
            emit SwapAndLiquifyEnabledUpdated(_enabled);
        }
    
        //set a new marketing wallet.
        function setMarketingWallet(address _marketingWallet) external onlyOwner {
            require(_marketingWallet != address(0), "setMarketingWallet: ZERO");
            marketingWallet = payable(_marketingWallet);
            emit AuditLog("We have Updated the MarketingWallet:", marketingWallet);
        }
    
        //set a new team wallet.
        function setRevenueWallet(address _revenueWallet) external onlyOwner {
            require(_revenueWallet != address(0), "setRevenueWallet: ZERO");
            revenueWallet = payable(_revenueWallet);
            emit AuditLog("We have Updated the RarketingWallet:", revenueWallet);
        }
    
    
    
        function transferToAddressETH(
            address payable recipient,
            uint256 amount
        ) private {
            if (amount == 0) return;
            (bool succ, ) = recipient.call{value: amount}("");
            require(succ, "Transfer failed.");
        }
    
        //to recieve ETH from uniswapV2Router when swaping
        receive() external payable {}
    
        /////---fallback--////
        //This cannot be removed as is a fallback to the swapAndLiquify
        event SwapETHForTokens(uint256 amountIn, address[] path);
    
        function swapETHForTokens(uint256 amount) private {
            // generate the uniswap pair path of token -> weth
            address[] memory path = new address[](2);
            path[0] = WETH;
            path[1] = address(this);
            // make the swap
            uniswapV2Router.swapExactETHForTokensSupportingFeeOnTransferTokens{
                value: amount
            }(
                swapOutput, // accept any amount of Tokens
                path,
                deadWallet, // Burn address
                block.timestamp + 300
            );
            emit SwapETHForTokens(amount, path);
        }
    
        // Withdraw ETH that's potentially stuck in the Contract
        function recoverETHfromContract() external onlyOwner {
            uint ethBalance = address(this).balance;
            (bool succ, ) = payable(marketingWallet).call{value: ethBalance}("");
            require(succ, "Transfer failed");
            emit AuditLog(
                "We have recover the stock eth from contract.",
                marketingWallet
            );
        }
    
        // Withdraw ERC20 tokens that are potentially stuck in Contract
        function recoverTokensFromContract(
            address _tokenAddress,
            uint256 _amount
        ) external onlyOwner {
            require(
                _tokenAddress != address(this),
                "Owner can't claim contract's balance of its own tokens"
            );
            bool succ = IERC20(_tokenAddress).transfer(marketingWallet, _amount);
            require(succ, "Transfer failed");
            emit Log("We have recovered tokens from contract:", _amount);
        }
    
        //Final Dev notes, this code has been tested and audited, last update to code was done to re-add swapandliquify function to the transfer as option, is recommended to be used manually instead of automatic.
    }