HoodTech

0x56cb1a3e464619393b08632c3aa3cf654235fb18

Verification
Verified
v0.8.25+commit.b61c2a91
Type
Contract
11,052 bytes
ABI entries
57
28 read · 20 write
License
none

Contract information

Address
0x56cb1a3e464619393b08632c3aa3cf654235fb18
Chain
Robinhood Chain (4663)
Compiler
v0.8.25+commit.b61c2a91
Optimization
Enabled
Creation tx
0xaf5bdae816…96c9149e46

Token

Name
HoodTech
Symbol
HOT
Decimals
18
Holders
62

Read contract (28)

FEE_DIVISOR()uint64
FINAL_TAX()uint256
START_TAX()uint256
TAX_DECAY_BLOCKS()uint256
WETH()address
allowance(address, address)uint256
antiMevEnabled()bool
balanceOf(address)uint256
buyTax()uint64, uint64
decimals()uint8
dexRouter()address
dynamicLiquidityTax()bool
dynamicTaxOn()bool
exemptFromFees(address)bool
feeReceiver1()address
feeReceiver2()address
isAMMPair(address)bool
launchBlock()uint256
lpPair()address
name()string
owner()address
sellTax()uint64, uint64
swapTokensAtAmt()uint256
symbol()string
tokensForFees()uint256
tokensForLiquidity()uint256
totalSupply()uint256
tradingAllowed()bool

Events (7)

ApprovalOwnershipTransferredSetExemptFromFeesTransferUpdatedBuyTaxUpdatedFeeReceiversUpdatedSellTax

ABI

[
  {
    "inputs": [],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "isExempt",
        "type": "bool"
      }
    ],
    "name": "SetExemptFromFees",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newTotal",
        "type": "uint256"
      }
    ],
    "name": "UpdatedBuyTax",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "r1",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "r2",
        "type": "address"
      }
    ],
    "name": "UpdatedFeeReceivers",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "newTotal",
        "type": "uint256"
      }
    ],
    "name": "UpdatedSellTax",
    "type": "event"
  },
  {
    "inputs": [],
    "name": "FEE_DIVISOR",
    "outputs": [
      {
        "internalType": "uint64",
        "name": "",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "FINAL_TAX",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "START_TAX",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "TAX_DECAY_BLOCKS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "WETH",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address[]",
        "name": "wallets",
        "type": "address[]"
      },
      {
        "internalType": "uint256[]",
        "name": "amountsInWei",
        "type": "uint256[]"
      }
    ],
    "name": "airdropToWallets",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      }
    ],
    "name": "allowance",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "antiMevEnabled",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "buyTax",
    "outputs": [
      {
        "internalType": "uint64",
        "name": "liquidityTax",
        "type": "uint64"
      },
      {
        "internalType": "uint64",
        "name": "totalTax",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "internalType": "uint8",
        "name": "",
        "type": "uint8"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "subtractedValue",
        "type": "uint256"
      }
    ],
    "name": "decreaseAllowance",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "dexRouter",
    "outputs": [
      {
        "internalType": "contract IDexRouter",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "dynamicLiquidityTax",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "dynamicTaxOn",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "enableTrading",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "exemptFromFees",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "feeReceiver1",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "feeReceiver2",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "addedValue",
        "type": "uint256"
      }
    ],
    "name": "increaseAllowance",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "isAMMPair",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "launchBlock",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "lpPair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "removeDynamicTax",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_token",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_to",
        "type": "address"
      }
    ],
    "name": "rescueTokens",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "sellTax",
    "outputs": [
      {
        "internalType": "uint64",
        "name": "liquidityTax",
        "type": "uint64"
      },
      {
        "internalType": "uint64",
        "name": "totalTax",
        "type": "uint64"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "pair",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "isPair",
        "type": "bool"
      }
    ],
    "name": "setAMMPair",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bool",
        "name": "_on",
        "type": "bool"
      }
    ],
    "name": "setDynamicLiquidityTax",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "isExempt",
        "type": "bool"
      }
    ],
    "name": "setExemptFromFee",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address[]",
        "name": "accounts",
        "type": "address[]"
      },
      {
        "internalType": "bool",
        "name": "isExempt",
        "type": "bool"
      }
    ],
    "name": "setExemptFromFees",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapTokensAtAmt",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tokensForFees",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tokensForLiquidity",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tradingAllowed",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "from",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint64",
        "name": "_totalTax",
        "type": "uint64"
      },
      {
        "internalType": "uint64",
        "name": "_liquidityTax",
        "type": "uint64"
      }
    ],
    "name": "updateBuyTax",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_r1",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_r2",
        "type": "address"
      }
    ],
    "name": "updateFeeReceivers",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bool",
        "name": "_enabled",
        "type": "bool"
      }
    ],
    "name": "updateMevBlockerEnabled",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint64",
        "name": "_totalTax",
        "type": "uint64"
      },
      {
        "internalType": "uint64",
        "name": "_liquidityTax",
        "type": "uint64"
      }
    ],
    "name": "updateSellTax",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "newAmount",
        "type": "uint256"
      }
    ],
    "name": "updateSwapTokensAmt",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

/**

   ██╗  ██╗ ██████╗  ██████╗ ██████╗    ████████╗███████╗ ██████╗██╗  ██╗
   ██║  ██║██╔═══██╗██╔═══██╗██╔══██╗   ╚══██╔══╝██╔════╝██╔════╝██║  ██║
   ███████║██║   ██║██║   ██║██║  ██║      ██║   █████╗  ██║     ███████║
   ██╔══██║██║   ██║██║   ██║██║  ██║      ██║   ██╔══╝  ██║     ██╔══██║
   ██║  ██║╚██████╔╝╚██████╔╝██████╔╝      ██║   ███████╗╚██████╗██║  ██║
   ╚═╝  ╚═╝ ╚═════╝  ╚═════╝ ╚═════╝       ╚═╝   ╚══════╝ ╚═════╝╚═╝  ╚═╝

   HoodTech — launch tokens on Robinhood Chain in one tap.

   🌐 Website:   https://hood.tech
   ✈️ Telegram:  https://t.me/HoodTech
   💬 Chat:      https://t.me/HoodTechRH
   ✖️ Twitter/X: https://x.com/HoodTech
   🤖 Bot:       https://t.me/HoodTechBot

   Deployed on Robinhood Chain (Uniswap V2). Presale/claim contracts can be whitelisted via the exclude-from-limits.

**/

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
        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);
}

interface IERC20Metadata is IERC20 {
    function name() external view returns (string memory);
    function symbol() external view returns (string memory);
    function decimals() external view returns (uint8);
}

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 to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, 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) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }
        return true;
    }

    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            _balances[to] += amount;
        }
        emit Transfer(from, to, amount);
    }

    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");
        _totalSupply += amount;
        unchecked {
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, 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 _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }
}

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() external 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;
    }
}

library Address {
    function isContract(address account) internal view returns (bool) {
        return account.code.length > 0;
    }

    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,
        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 verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        if (returndata.length > 0) {
            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 _callOptionalReturn(IERC20 token, bytes memory data) private {
        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

interface ILpPair {
    function sync() external;
}

interface IDexRouter {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

contract HoodTech is ERC20, Ownable {

    // ─────────────────────────────────────────────────────────────────────────
    // Robinhood Chain (chain id 4663) — the ONLY router this token uses.
    // Uniswap V2 Router02 on Robinhood Chain. WETH + factory are read from it.
    // ─────────────────────────────────────────────────────────────────────────
    address private constant ROBINHOOD_V2_ROUTER = 0x89e5DB8B5aA49aA85AC63f691524311AEB649eba;

    // Fee revenue splits 50/50 between these two addresses (owner-updatable).
    address public feeReceiver1 = 0x0Add64bc1A22B5A23C3f59cFCf41143e4aA672Da;
    address public feeReceiver2 = 0x5dFe040B6d423c7a8302f3A755490Ba5427644d5;

    // Dynamic launch tax schedule: 20% -> 2%, linear over TAX_DECAY_BLOCKS blocks.
    // Robinhood Chain produces ~10 blocks/sec (~100ms/block, measured on-chain),
    // i.e. ~600 blocks/min. 18000 blocks ≈ 30 minutes.
    uint256 public constant START_TAX = 2000; // 20.00%
    uint256 public constant FINAL_TAX = 200;  //  2.00%
    uint256 public constant TAX_DECAY_BLOCKS = 18000; // ~30 min at ~100ms blocks

    uint64 public constant FEE_DIVISOR = 10000;

    mapping(address => bool) public exemptFromFees; // whitelist: presale/claim/team wallets pay no tax

    bool public tradingAllowed;
    mapping(address => bool) public isAMMPair;

    Taxes public buyTax;
    Taxes public sellTax;

    uint256 public tokensForLiquidity;
    uint256 public tokensForFees;

    mapping(address => uint256) private _holderLastTransferBlock; // MEV protection (1 block)
    bool public antiMevEnabled = true;

    uint256 public swapTokensAtAmt;

    // The pair + liquidity are created by the presale launchpad, NOT by this token.
    // lpPair is set in the constructor to the deterministic WETH pair address and that
    // pair is pre-flagged as an AMM, so tax + anti-MEV are live the instant the
    // launchpad creates it — no manual setAMMPair step is needed for the WETH pair.
    address public lpPair;
    IDexRouter public immutable dexRouter;
    address public immutable WETH;

    uint256 public launchBlock;
    bool public dynamicTaxOn;
    bool public dynamicLiquidityTax;

    struct Taxes {
        uint64 liquidityTax; // portion of totalTax routed to LP (bps of the trade)
        uint64 totalTax;     // total tax (bps of the trade)
    }

    // events
    event SetExemptFromFees(address indexed account, bool isExempt);
    event UpdatedBuyTax(uint256 newTotal);
    event UpdatedSellTax(uint256 newTotal);
    event UpdatedFeeReceivers(address r1, address r2);

    constructor() ERC20("HoodTech", "HOT") {
        _mint(msg.sender, 10_000_000 * 1e18);

        require(ROBINHOOD_V2_ROUTER != address(0), "Router unset");
        dexRouter = IDexRouter(ROBINHOOD_V2_ROUTER);

        dynamicTaxOn = true;
        dynamicLiquidityTax = false;

        swapTokensAtAmt = totalSupply() * 25 / 100000; // 0.025% of supply

        // start at 20% buy & sell; dynamic schedule decays it to 2%
        buyTax = Taxes({ liquidityTax: 0, totalTax: uint64(START_TAX) });
        sellTax = Taxes({ liquidityTax: 0, totalTax: uint64(START_TAX) });

        WETH = dexRouter.WETH();

        // ── Anti-snipe: pre-flag the canonical WETH pair (audit finding #2) ────────
        // The launchpad (GemPad) creates the real pair and seeds the initial
        // liquidity at finalize — this token does NOT create it. But the pair's
        // address is deterministic (Uniswap V2 CREATE2 of factory + sorted
        // [token, WETH] + the canonical init-code hash), so we compute it and flag
        // it as an AMM up front. The moment the pair exists and trading opens, buys
        // and sells are ALREADY taxed and anti-MEV is active — there is no ordering
        // gap where a sniper can trade a not-yet-flagged pair at 0% tax, regardless
        // of whether setAMMPair() or enableTrading() is called first (or by GemPad).
        // setAMMPair() below still allows flagging any additional pairs later.
        address _factory = dexRouter.factory();
        (address _t0, address _t1) = address(this) < WETH
            ? (address(this), WETH)
            : (WETH, address(this));
        address _wethPair = address(uint160(uint256(keccak256(abi.encodePacked(
            hex"ff",
            _factory,
            keccak256(abi.encodePacked(_t0, _t1)),
            hex"96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f"
        )))));
        isAMMPair[_wethPair] = true;
        lpPair = _wethPair;

        exemptFromFees[msg.sender] = true;
        exemptFromFees[address(this)] = true;
        exemptFromFees[address(dexRouter)] = true;

        _approve(address(this), address(dexRouter), type(uint256).max);
        _approve(address(msg.sender), address(dexRouter), totalSupply());
    }

    function _transfer(address from, address to, uint256 amount) internal virtual override {
        if (!exemptFromFees[from] && !exemptFromFees[to]) {
            require(tradingAllowed, "Trading not active");
            amount -= handleTax(from, to, amount);
            antiBotChecks(from, to);
        }
        super._transfer(from, to, amount);
    }

    // Same-block anti-MEV only (blocks buy+sell in the same block to stop sandwiches).
    // No transfer delay, no max-wallet / max-tx limits — buys are unrestricted.
    function antiBotChecks(address from, address to) internal {
        if (antiMevEnabled) {
            if (isAMMPair[to]) {
                require(_holderLastTransferBlock[from] < block.number, "Anti MEV");
            } else {
                _holderLastTransferBlock[to] = block.number;
                _holderLastTransferBlock[tx.origin] = block.number;
            }
        }
    }

    function handleTax(address from, address to, uint256 amount) internal returns (uint256) {
        if (balanceOf(address(this)) >= swapTokensAtAmt && !isAMMPair[from]) {
            convertTaxes();
        }
        if (dynamicTaxOn) {
            setInternalTaxes();
        }

        Taxes memory taxes;
        if (isAMMPair[to]) {
            taxes = sellTax;
        } else if (isAMMPair[from]) {
            taxes = buyTax;
        }

        uint256 tax = 0;
        if (taxes.totalTax > 0) {
            tax = amount * taxes.totalTax / FEE_DIVISOR;
            uint256 liqPortion = taxes.liquidityTax == 0 ? 0 : tax * taxes.liquidityTax / taxes.totalTax;
            tokensForLiquidity += liqPortion;
            tokensForFees += (tax - liqPortion);
            super._transfer(from, address(this), tax);
        }
        return tax;
    }

    function convertTaxes() private {
        uint256 contractBalance = balanceOf(address(this));
        if (contractBalance == 0) return; // balance is the source of truth, not the counters

        if (contractBalance > swapTokensAtAmt * 20) {
            contractBalance = swapTokensAtAmt * 20;
        }

        // Liquidity portion: donate tokens to the pair and sync (raises the floor).
        // Only when a primary pair has been set and the liquidity tax is actually used.
        uint256 totalToProcess = tokensForLiquidity + tokensForFees;
        if (lpPair != address(0) && tokensForLiquidity > 0 && totalToProcess > 0) {
            uint256 liquidityTokens = contractBalance * tokensForLiquidity / totalToProcess;
            if (liquidityTokens > 0) {
                super._transfer(address(this), lpPair, liquidityTokens);
                try ILpPair(lpPair).sync() {} catch {}
                contractBalance -= liquidityTokens;
            }
        }

        // Swap the rest to ETH and split 50/50. The swap is wrapped in try/catch so a
        // missing or mismatched route (e.g. liquidity finalized on a different router
        // or pair) can NEVER revert a sell — that would be a honeypot. If it fails,
        // the tax tokens simply stay in the contract and are retried on later trades.
        if (contractBalance > 0) {
            address[] memory path = new address[](2);
            path[0] = address(this);
            path[1] = WETH;
            try dexRouter.swapExactTokensForETHSupportingFeeOnTransferTokens(
                contractBalance, 0, path, address(this), block.timestamp
            ) {
                uint256 ethBalance = address(this).balance;
                if (ethBalance > 0) {
                    uint256 half = ethBalance / 2;
                    bool ok;
                    (ok, ) = feeReceiver1.call{value: half}("");
                    (ok, ) = feeReceiver2.call{value: ethBalance - half}("");
                }
            } catch {
                // swap route unavailable — do NOT revert the sell; retry next time
            }
        }

        tokensForLiquidity = 0;
        tokensForFees = 0;
    }

    function setInternalTaxes() internal {
        uint256 elapsed = block.number - launchBlock;
        uint64 newTotal;
        if (elapsed >= TAX_DECAY_BLOCKS) {
            newTotal = uint64(FINAL_TAX);
            dynamicTaxOn = false; // lock at 2% once fully decayed
        } else {
            newTotal = uint64(START_TAX - ((START_TAX - FINAL_TAX) * elapsed) / TAX_DECAY_BLOCKS);
        }
        if (buyTax.totalTax != newTotal) {
            buyTax = Taxes({ liquidityTax: dynamicLiquidityTax ? newTotal * 2 / 10 : 0, totalTax: newTotal });
        }
        if (sellTax.totalTax != newTotal) {
            sellTax = Taxes({ liquidityTax: dynamicLiquidityTax ? newTotal * 2 / 10 : 0, totalTax: newTotal });
        }
    }

    // ── owner / admin ────────────────────────────────────────────────────────

    function setExemptFromFee(address account, bool isExempt) external onlyOwner {
        require(account != address(0), "Zero Address");
        require(account != address(this), "Cannot unexempt contract");
        exemptFromFees[account] = isExempt;
        emit SetExemptFromFees(account, isExempt);
    }

    // Batch whitelist — e.g. presale, vesting, and claim contracts so distribution isn't taxed.
    function setExemptFromFees(address[] calldata accounts, bool isExempt) external onlyOwner {
        for (uint256 i = 0; i < accounts.length; i++) {
            if (accounts[i] == address(0) || accounts[i] == address(this)) continue;
            exemptFromFees[accounts[i]] = isExempt;
            emit SetExemptFromFees(accounts[i], isExempt);
        }
    }

    function updateSwapTokensAmt(uint256 newAmount) external onlyOwner {
        require(newAmount >= (totalSupply() * 1) / 100000, "min 0.001% supply");
        require(newAmount <= (totalSupply() * 5) / 1000, "max 0.5% supply");
        swapTokensAtAmt = newAmount;
    }

    function updateBuyTax(uint64 _totalTax, uint64 _liquidityTax) external onlyOwner {
        require(_liquidityTax <= _totalTax, "liq > total");
        require(_totalTax <= 1000, "Keep tax below 10%");
        buyTax = Taxes({ liquidityTax: _liquidityTax, totalTax: _totalTax });
        emit UpdatedBuyTax(_totalTax);
    }

    function updateSellTax(uint64 _totalTax, uint64 _liquidityTax) external onlyOwner {
        require(_liquidityTax <= _totalTax, "liq > total");
        require(_totalTax <= 1000, "Keep tax below 10%");
        sellTax = Taxes({ liquidityTax: _liquidityTax, totalTax: _totalTax });
        emit UpdatedSellTax(_totalTax);
    }

    function updateFeeReceivers(address _r1, address _r2) external onlyOwner {
        require(_r1 != address(0) && _r2 != address(0), "zero address");
        feeReceiver1 = _r1;
        feeReceiver2 = _r2;
        emit UpdatedFeeReceivers(_r1, _r2);
    }

    function enableTrading() external onlyOwner {
        require(!tradingAllowed, "Trading already enabled");
        tradingAllowed = true;
        launchBlock = block.number;
    }

    // Flag an ADDITIONAL Uniswap pair (e.g. a token/stablecoin pair) as an AMM so its
    // buys/sells are taxed. The canonical WETH pair is already pre-flagged in the
    // constructor, so this is only needed for extra pairs created later.
    function setAMMPair(address pair, bool isPair) external onlyOwner {
        require(pair != address(0), "zero pair");
        isAMMPair[pair] = isPair;
        if (isPair && lpPair == address(0)) {
            lpPair = pair;
        }
    }

    function updateMevBlockerEnabled(bool _enabled) external onlyOwner {
        antiMevEnabled = _enabled;
    }

    // Ending the dynamic schedule early ALWAYS snaps taxes to the final 2% — it can
    // never be used to freeze a higher launch tax (no honeypot lever).
    function removeDynamicTax() external onlyOwner {
        require(dynamicTaxOn, "Already off");
        dynamicTaxOn = false;
        uint64 liq = dynamicLiquidityTax ? uint64(FINAL_TAX) * 2 / 10 : 0;
        buyTax = Taxes({ liquidityTax: liq, totalTax: uint64(FINAL_TAX) });
        sellTax = Taxes({ liquidityTax: liq, totalTax: uint64(FINAL_TAX) });
    }

    function setDynamicLiquidityTax(bool _on) external onlyOwner {
        dynamicLiquidityTax = _on;
    }

    function airdropToWallets(address[] calldata wallets, uint256[] calldata amountsInWei) external onlyOwner {
        require(wallets.length == amountsInWei.length, "length mismatch");
        for (uint256 i = 0; i < wallets.length; i++) {
            super._transfer(msg.sender, wallets[i], amountsInWei[i]);
        }
    }

    // Rescue foreign tokens accidentally sent here. Cannot touch HOT itself, so the
    // owner can never pull accrued tax tokens out to dump them.
    function rescueTokens(address _token, address _to) external onlyOwner {
        require(_token != address(0), "zero token");
        require(_token != address(this), "cannot rescue own token");
        uint256 bal = IERC20(_token).balanceOf(address(this));
        SafeERC20.safeTransfer(IERC20(_token), _to, bal);
    }

    receive() external payable {}
}
Chain explorer5461msChain node80ms