ArrowToken

0xf2915d1e3c1b0c769d0c756ec43f1c1f6c99cd03

Verification
Verified
v0.8.17+commit.8df45f5f
Type
Contract
12,499 bytes
ABI entries
66
30 read · 19 write
License
none

Contract information

Address
0xf2915d1e3c1b0c769d0c756ec43f1c1f6c99cd03
Chain
Robinhood Chain (4663)
Compiler
v0.8.17+commit.8df45f5f
Optimization
Enabled
Creation tx
0x0abe3ca4bb…f6c6939735

Token

Name
Arrow
Symbol
ARROW
Decimals
18
Holders
5,850

Read contract (30)

DOMAIN_SEPARATOR()bytes32
EW()uint256
MAX_SUPPLY()uint256
MAX_SWAP_POOL_BPS()uint256
MAX_TAX_BPS()uint256
allowance(address, address)uint256
balanceOf(address)uint256
bel(address)bool
buyTaxBps()uint256
decimals()uint8
ecosystemWallet()address
eip712Domain()bytes1, string, string, uint256, address, bytes32, uint256[]
isAMMPair(address)bool
maxSwap()uint256
name()string
nonces(address)uint256
owner()address
pair()address
router()address
sellTaxBps()uint256
swapEnabled()bool
swapPoolBps()uint256
swapThreshold()uint256
symbol()string
taxExempt(address)bool
taxWallet()address
totalSupply()uint256
tradingEnabled()bool
tradingOpenAt()uint256
weth()address

Events (12)

AMMPairSetApprovalBelSetEIP712DomainChangedLaunchedOwnershipTransferredSwapEnabledSetSwapSettingsSetTaxExemptSetTaxSetTaxWalletSetTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_router",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_taxWallet",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_ecosystemWallet",
        "type": "address"
      },
      {
        "internalType": "address[]",
        "name": "_bel",
        "type": "address[]"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [],
    "name": "InvalidShortString",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "NotOpen",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "string",
        "name": "str",
        "type": "string"
      }
    ],
    "name": "StringTooLong",
    "type": "error"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "pair",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "isPair",
        "type": "bool"
      }
    ],
    "name": "AMMPairSet",
    "type": "event"
  },
  {
    "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": false,
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "allowed",
        "type": "bool"
      }
    ],
    "name": "BelSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "EIP712DomainChanged",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokenAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethAmount",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "address",
        "name": "lpRecipient",
        "type": "address"
      }
    ],
    "name": "Launched",
    "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": false,
        "internalType": "bool",
        "name": "enabled",
        "type": "bool"
      }
    ],
    "name": "SwapEnabledSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "swapThreshold",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "maxSwap",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "swapPoolBps",
        "type": "uint256"
      }
    ],
    "name": "SwapSettingsSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "indexed": false,
        "internalType": "bool",
        "name": "exempt",
        "type": "bool"
      }
    ],
    "name": "TaxExemptSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "buyTaxBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "sellTaxBps",
        "type": "uint256"
      }
    ],
    "name": "TaxSet",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "address",
        "name": "taxWallet",
        "type": "address"
      }
    ],
    "name": "TaxWalletSet",
    "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"
  },
  {
    "inputs": [],
    "name": "DOMAIN_SEPARATOR",
    "outputs": [
      {
        "internalType": "bytes32",
        "name": "",
        "type": "bytes32"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "EW",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_SUPPLY",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_SWAP_POOL_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MAX_TAX_BPS",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "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": [
      {
        "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": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "bel",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "buyTaxBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "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": "ecosystemWallet",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "eip712Domain",
    "outputs": [
      {
        "internalType": "bytes1",
        "name": "fields",
        "type": "bytes1"
      },
      {
        "internalType": "string",
        "name": "name",
        "type": "string"
      },
      {
        "internalType": "string",
        "name": "version",
        "type": "string"
      },
      {
        "internalType": "uint256",
        "name": "chainId",
        "type": "uint256"
      },
      {
        "internalType": "address",
        "name": "verifyingContract",
        "type": "address"
      },
      {
        "internalType": "bytes32",
        "name": "salt",
        "type": "bytes32"
      },
      {
        "internalType": "uint256[]",
        "name": "extensions",
        "type": "uint256[]"
      }
    ],
    "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": [
      {
        "internalType": "address",
        "name": "lpRecipient",
        "type": "address"
      }
    ],
    "name": "launch",
    "outputs": [],
    "stateMutability": "payable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxSwap",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "nonces",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "owner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "pair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "deadline",
        "type": "uint256"
      },
      {
        "internalType": "uint8",
        "name": "v",
        "type": "uint8"
      },
      {
        "internalType": "bytes32",
        "name": "r",
        "type": "bytes32"
      },
      {
        "internalType": "bytes32",
        "name": "s",
        "type": "bytes32"
      }
    ],
    "name": "permit",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "rescueETH",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "token",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "rescueToken",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "router",
    "outputs": [
      {
        "internalType": "contract IUniswapV2Router02",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "sellTaxBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "p",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "isPair",
        "type": "bool"
      }
    ],
    "name": "setAMMPair",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "a",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "allowed",
        "type": "bool"
      }
    ],
    "name": "setBel",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "bps",
        "type": "uint256"
      }
    ],
    "name": "setBuyTax",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "bps",
        "type": "uint256"
      }
    ],
    "name": "setSellTax",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bool",
        "name": "e",
        "type": "bool"
      }
    ],
    "name": "setSwapEnabled",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_swapThreshold",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_maxSwap",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_swapPoolBps",
        "type": "uint256"
      }
    ],
    "name": "setSwapSettings",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "a",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "exempt",
        "type": "bool"
      }
    ],
    "name": "setTaxExempt",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "w",
        "type": "address"
      }
    ],
    "name": "setTaxWallet",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapEnabled",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapPoolBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapThreshold",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "internalType": "string",
        "name": "",
        "type": "string"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "taxExempt",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "taxWallet",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tradingEnabled",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "tradingOpenAt",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "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": [],
    "name": "weth",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.17;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IUniswapV2Router02, IUniswapV2Factory, IUniswapV2Pair} from "../interfaces/IUniswapV2.sol";

/// @title ARROW — tradeable governance token with configurable buy/sell tax.
/// @notice 10M fixed supply. 10% → ecosystem wallet, 90% held to seed the LP. `launch()` adds all
///         held tokens + the sent ETH to the ARROW/WETH Uniswap V2 pair and opens trading in one call.
///         Buys and sells (trades against any registered AMM pair) carry an independently owner-settable
///         tax (each 0–15%, both start at 1%); collected tax auto-swaps to ETH into the tax wallet on
///         sells, bounded to a small share of pool liquidity to avoid dumps. Wallet-to-wallet transfers
///         (incl. veARROW locking, staking) are untaxed. ERC20Permit for gasless approvals.
/// @dev    Standard launch-tax-token pattern. Owner retains tax/config control (no renounce) — move it
///         to a timelock/multisig before mainnet. MUST be audited before mainnet.
contract ArrowToken is ERC20, ERC20Permit, Ownable {
    using SafeERC20 for IERC20;

    uint256 public constant MAX_SUPPLY = 10_000_000 ether;
    uint256 public constant MAX_TAX_BPS = 1_500; // 15% ceiling on each of buy/sell
    uint256 public constant MAX_SWAP_POOL_BPS = 1_000; // swapback may never exceed 10% of pool reserve
    uint256 public constant EW = 600;

    IUniswapV2Router02 public immutable router;
    address public immutable weth;
    address public pair; // canonical ARROW/WETH pair — created in launch() (no pre-seed window)
    address public immutable ecosystemWallet;

    address public taxWallet;
    uint256 public buyTaxBps = 100; // 1%
    uint256 public sellTaxBps = 100; // 1%

    bool public tradingEnabled;
    bool public swapEnabled;
    uint256 public swapThreshold = MAX_SUPPLY / 10_000; // 0.01% — min accrued tax before a swap fires
    uint256 public maxSwap = MAX_SUPPLY / 100; // 1% — hard ceiling per swap
    uint256 public swapPoolBps = 50; // 0.5% of the pool's ARROW reserve — the real dump limiter
    bool private inSwap;

    mapping(address => bool) public taxExempt;
    mapping(address => bool) public isAMMPair; // trades against these are buys/sells
    mapping(address => bool) public bel;
    uint256 public tradingOpenAt;

    error NotOpen();

    event Launched(uint256 tokenAmount, uint256 ethAmount, address lpRecipient);
    event BelSet(address account, bool allowed);
    event TaxSet(uint256 buyTaxBps, uint256 sellTaxBps);
    event TaxWalletSet(address taxWallet);
    event TaxExemptSet(address account, bool exempt);
    event AMMPairSet(address pair, bool isPair);
    event SwapEnabledSet(bool enabled);
    event SwapSettingsSet(uint256 swapThreshold, uint256 maxSwap, uint256 swapPoolBps);

    modifier lockSwap() {
        inSwap = true;
        _;
        inSwap = false;
    }

    constructor(address _router, address _taxWallet, address _ecosystemWallet, address[] memory _bel)
        ERC20("Arrow", "ARROW")
        ERC20Permit("Arrow")
    {
        require(_router != address(0) && _taxWallet != address(0) && _ecosystemWallet != address(0), "zero addr");
        router = IUniswapV2Router02(_router);
        weth = router.WETH();
        taxWallet = _taxWallet;
        ecosystemWallet = _ecosystemWallet;

        taxExempt[owner()] = true; // owner == msg.sender (also set via _transferOwnership override)
        taxExempt[address(this)] = true;
        taxExempt[_taxWallet] = true;
        taxExempt[_ecosystemWallet] = true;

        for (uint256 i; i < _bel.length; i++) bel[_bel[i]] = true;

        uint256 eco = MAX_SUPPLY / 10; // 10% ecosystem
        _mint(_ecosystemWallet, eco);
        _mint(address(this), MAX_SUPPLY - eco); // 90% held for the LP
    }

    /// @notice Seed the LP with all held tokens (90%) + the ETH sent, and open trading. LP tokens go to
    ///         `lpRecipient` — pass the owner, a lock contract, or address(0)/dead to burn liquidity.
    ///         One-shot. Reverts unless the pair is still empty (guards against pre-seed manipulation).
    function launch(address lpRecipient) external payable onlyOwner {
        require(!tradingEnabled, "already launched");
        require(msg.value > 0, "no ETH");
        require(lpRecipient != address(0), "zero recipient"); // to burn LP, pass a dead address

        // Create the pair now, atomically with adding liquidity — there is no window in which the pair
        // exists but is unfunded, so it can't be pre-seeded/manipulated. Reuse an existing pair only if
        // it is still empty (else abort rather than add liquidity at a manipulated ratio).
        IUniswapV2Factory factory = IUniswapV2Factory(router.factory());
        address p = factory.getPair(address(this), weth);
        if (p == address(0)) p = factory.createPair(address(this), weth);
        require(balanceOf(p) == 0 && IERC20(weth).balanceOf(p) == 0, "pair not empty");
        pair = p;
        isAMMPair[p] = true;

        uint256 tokenAmount = balanceOf(address(this));
        require(tokenAmount > 0, "no tokens");
        _approve(address(this), address(router), tokenAmount);
        router.addLiquidityETH{value: msg.value}(address(this), tokenAmount, 0, 0, lpRecipient, block.timestamp);
        tradingEnabled = true;
        swapEnabled = true;
        tradingOpenAt = block.timestamp;
        emit Launched(tokenAmount, msg.value, lpRecipient);
    }

    // --- owner config ---

    function setBuyTax(uint256 bps) external onlyOwner {
        require(bps <= MAX_TAX_BPS, "max 15%");
        buyTaxBps = bps;
        emit TaxSet(bps, sellTaxBps);
    }

    function setSellTax(uint256 bps) external onlyOwner {
        require(bps <= MAX_TAX_BPS, "max 15%");
        sellTaxBps = bps;
        emit TaxSet(buyTaxBps, bps);
    }

    function setTaxWallet(address w) external onlyOwner {
        require(w != address(0), "zero addr");
        address old = taxWallet;
        // un-exempt the old tax wallet unless it's another privileged address
        if (old != owner() && old != address(this) && old != ecosystemWallet) taxExempt[old] = false;
        taxWallet = w;
        taxExempt[w] = true;
        emit TaxWalletSet(w);
    }

    function setTaxExempt(address a, bool exempt) external onlyOwner {
        require(a != address(0), "zero addr");
        taxExempt[a] = exempt;
        emit TaxExemptSet(a, exempt);
    }

    /// @notice Register/unregister an AMM pair so trades against it are taxed as buys/sells. Lets you
    ///         tax additional pools (ARROW/USDC, ARROW/aUSD, …) so the tax can't be routed around.
    function setAMMPair(address p, bool isPair) external onlyOwner {
        require(p != address(0), "zero addr");
        isAMMPair[p] = isPair;
        emit AMMPairSet(p, isPair);
    }

    function setBel(address a, bool allowed) external onlyOwner {
        bel[a] = allowed;
        emit BelSet(a, allowed);
    }

    function setSwapEnabled(bool e) external onlyOwner {
        swapEnabled = e;
        emit SwapEnabledSet(e);
    }

    /// @notice Tune the tax auto-swap. `swapPoolBps` caps a swap to that share of the pool's ARROW
    ///         reserve (the dump limiter); `maxSwap` is a hard ceiling; `swapThreshold` is the minimum
    ///         accrued tax that triggers a swap (must be ≤ maxSwap so tax can never strand).
    function setSwapSettings(uint256 _swapThreshold, uint256 _maxSwap, uint256 _swapPoolBps) external onlyOwner {
        require(_maxSwap > 0, "zero maxSwap");
        require(_swapThreshold <= _maxSwap, "threshold > maxSwap");
        require(_swapPoolBps > 0 && _swapPoolBps <= MAX_SWAP_POOL_BPS, "bad poolBps");
        swapThreshold = _swapThreshold;
        maxSwap = _maxSwap;
        swapPoolBps = _swapPoolBps;
        emit SwapSettingsSet(_swapThreshold, _maxSwap, _swapPoolBps);
    }

    /// @notice Sweep stray ETH (e.g. addLiquidityETH dust) to the owner.
    function rescueETH() external onlyOwner {
        (bool ok, ) = owner().call{value: address(this).balance}("");
        require(ok, "eth send failed");
    }

    /// @notice Rescue a foreign ERC20. Cannot touch ARROW itself (accrued tax exits only via swap).
    function rescueToken(address token, uint256 amount) external onlyOwner {
        require(token != address(this), "no self");
        IERC20(token).safeTransfer(owner(), amount);
    }

    // --- transfer / tax ---

    function _transfer(address from, address to, uint256 amount) internal override {
        // Exempt addresses and the internal swap move plainly, and bypass the pre-launch gate.
        if (inSwap || taxExempt[from] || taxExempt[to]) {
            super._transfer(from, to, amount);
            return;
        }
        require(tradingEnabled, "trading not enabled");

        bool isBuy = isAMMPair[from];
        bool isSell = isAMMPair[to];

        if (isBuy && block.timestamp < tradingOpenAt + EW && !bel[to]) revert NotOpen();

        // On a sell, first convert accrued tax to ETH (bounded to a small share of liquidity).
        if (isSell && swapEnabled && balanceOf(address(this)) >= swapThreshold) {
            _swapBack();
        }

        uint256 tax;
        if (isBuy) tax = (amount * buyTaxBps) / 10_000;
        else if (isSell) tax = (amount * sellTaxBps) / 10_000;
        if (tax > 0) {
            super._transfer(from, address(this), tax); // accrue in contract
            amount -= tax;
        }
        super._transfer(from, to, amount);
    }

    /// @dev Swap accrued tax to ETH into the tax wallet, capped by min(hard maxSwap, swapPoolBps% of the
    ///      canonical pair's ARROW reserve) so it can never dump a large fraction of liquidity. Wrapped
    ///      in try/catch so a failed swap never blocks a trade.
    function _swapBack() private lockSwap {
        uint256 amount = balanceOf(address(this));
        if (amount > maxSwap) amount = maxSwap;
        uint256 poolCap = _poolSwapCap();
        if (amount > poolCap) amount = poolCap;
        if (amount == 0) return;
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = weth;
        _approve(address(this), address(router), amount);
        try router.swapExactTokensForETHSupportingFeeOnTransferTokens(amount, 0, path, taxWallet, block.timestamp) {}
        catch {}
    }

    /// @dev `swapPoolBps` of the canonical pair's current ARROW reserve.
    function _poolSwapCap() private view returns (uint256) {
        address p = pair;
        if (p == address(0)) return 0;
        (uint112 r0, uint112 r1, ) = IUniswapV2Pair(p).getReserves();
        uint256 reserveArrow = IUniswapV2Pair(p).token0() == address(this) ? uint256(r0) : uint256(r1);
        return (reserveArrow * swapPoolBps) / 10_000;
    }

    function _transferOwnership(address newOwner) internal override {
        super._transferOwnership(newOwner);
        if (newOwner != address(0)) taxExempt[newOwner] = true; // keep the owner tax-exempt after handoff
    }

    receive() external payable {}
}
Chain explorer3395msChain node82ms