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
- Creator
- 0x504Bd00109…0870D1cb71
- Creation tx
- 0xaf5bdae816…96c9149e46
Token
- Name
- HoodTech
- Symbol
- HOT
- Decimals
- 18
- Holders
- 62
- Market
- View token page →
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