Stox

0x5d7335ad46585fe87946040f024019deb5f2b6d7

Verification
Verified
v0.8.28+commit.7893614a
Type
Contract
7,992 bytes
ABI entries
77
31 read · 20 write
License
none

Contract information

Address
0x5d7335ad46585fe87946040f024019deb5f2b6d7
Chain
Robinhood Chain (4663)
Compiler
v0.8.28+commit.7893614a
Optimization
Enabled
Creation tx
0x1e442971d1…36b9c9b670

Token

Name
Stox
Symbol
STOX
Decimals
18
Holders
7,155

Read contract (31)

DENOM()uint256
MAX_TAX_BPS()uint256
MIN_MAX_TX()uint256
MIN_MAX_WALLET()uint256
allowance(address, address)uint256
automatedMarketMakerPairs(address)bool
balanceOf(address)uint256
buyTaxBps()uint256
decimals()uint8
distributor()address
distributorShareBps()uint256
isExcludedFromDividends(address)bool
isExcludedFromFee(address)bool
isExcludedFromLimits(address)bool
limitsInEffect()bool
liquidityShareBps()uint256
marketingShareBps()uint256
marketingWallet()address
maxTransaction()uint256
maxWallet()uint256
name()string
owner()address
pendingOwner()address
router()address
sellTaxBps()uint256
swapEnabled()bool
swapTokensAtAmount()uint256
symbol()string
totalSupply()uint256
tradingEnabled()bool
uniswapV2Pair()address

Events (9)

ApprovalLimitsRemovedOwnershipTransferStartedOwnershipTransferredSplitUpdatedSwapBackTaxesUpdatedTradingEnabledTransfer

ABI

[
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "_router",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_distributor",
        "type": "address"
      },
      {
        "internalType": "address",
        "name": "_marketingWallet",
        "type": "address"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "constructor"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "allowance",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "needed",
        "type": "uint256"
      }
    ],
    "name": "ERC20InsufficientAllowance",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "balance",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "needed",
        "type": "uint256"
      }
    ],
    "name": "ERC20InsufficientBalance",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "approver",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidApprover",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "receiver",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidReceiver",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "sender",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidSender",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      }
    ],
    "name": "ERC20InvalidSpender",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "InvalidSplit",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "LimitTooLow",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "MaxTxExceeded",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "MaxWalletExceeded",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "owner",
        "type": "address"
      }
    ],
    "name": "OwnableInvalidOwner",
    "type": "error"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "OwnableUnauthorizedAccount",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "TaxTooHigh",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "TradingNotEnabled",
    "type": "error"
  },
  {
    "inputs": [],
    "name": "ZeroAddress",
    "type": "error"
  },
  {
    "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": [],
    "name": "LimitsRemoved",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "internalType": "address",
        "name": "previousOwner",
        "type": "address"
      },
      {
        "indexed": true,
        "internalType": "address",
        "name": "newOwner",
        "type": "address"
      }
    ],
    "name": "OwnershipTransferStarted",
    "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": "uint256",
        "name": "distributorBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "liquidityBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "marketingBps",
        "type": "uint256"
      }
    ],
    "name": "SplitUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "tokensSwapped",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethToDistributor",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethToLiquidity",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "ethToMarketing",
        "type": "uint256"
      }
    ],
    "name": "SwapBack",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "buyBps",
        "type": "uint256"
      },
      {
        "indexed": false,
        "internalType": "uint256",
        "name": "sellBps",
        "type": "uint256"
      }
    ],
    "name": "TaxesUpdated",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [],
    "name": "TradingEnabled",
    "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": "DENOM",
    "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": [],
    "name": "MIN_MAX_TX",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "MIN_MAX_WALLET",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "acceptOwnership",
    "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": [
      {
        "internalType": "address",
        "name": "spender",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "automatedMarketMakerPairs",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "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": [],
    "name": "distributor",
    "outputs": [
      {
        "internalType": "contract StoxDistributor",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "distributorShareBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "enableTrading",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "isExcludedFromDividends",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "isExcludedFromFee",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "name": "isExcludedFromLimits",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "limitsInEffect",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "liquidityShareBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "manualSwapBack",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "marketingShareBps",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "marketingWallet",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxTransaction",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "maxWallet",
    "outputs": [
      {
        "internalType": "uint256",
        "name": "",
        "type": "uint256"
      }
    ],
    "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": "pendingOwner",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "removeLimits",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "rescueETH",
    "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": "pair",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "value",
        "type": "bool"
      }
    ],
    "name": "setAmmPair",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "setExcludedFromDividends",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "setExcludedFromFee",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "account",
        "type": "address"
      },
      {
        "internalType": "bool",
        "name": "excluded",
        "type": "bool"
      }
    ],
    "name": "setExcludedFromLimits",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_maxTransaction",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_maxWallet",
        "type": "uint256"
      }
    ],
    "name": "setLimits",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "address",
        "name": "wallet",
        "type": "address"
      }
    ],
    "name": "setMarketingWallet",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_distributorBps",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_liquidityBps",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_marketingBps",
        "type": "uint256"
      }
    ],
    "name": "setSplit",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "bool",
        "name": "enabled",
        "type": "bool"
      }
    ],
    "name": "setSwapEnabled",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "amount",
        "type": "uint256"
      }
    ],
    "name": "setSwapTokensAtAmount",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [
      {
        "internalType": "uint256",
        "name": "_buyBps",
        "type": "uint256"
      },
      {
        "internalType": "uint256",
        "name": "_sellBps",
        "type": "uint256"
      }
    ],
    "name": "setTaxes",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapEnabled",
    "outputs": [
      {
        "internalType": "bool",
        "name": "",
        "type": "bool"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "swapTokensAtAmount",
    "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": "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": [
      {
        "internalType": "address",
        "name": "to",
        "type": "address"
      },
      {
        "internalType": "uint256",
        "name": "value",
        "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": "value",
        "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": "uniswapV2Pair",
    "outputs": [
      {
        "internalType": "address",
        "name": "",
        "type": "address"
      }
    ],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "stateMutability": "payable",
    "type": "receive"
  }
]

Source code

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {IUniswapV2Factory, IUniswapV2Router02} from "./interfaces/IUniswapV2.sol";
import {StoxDistributor} from "./StoxDistributor.sol";

/**
 * @title Stox ($STOX)
 * @notice Hold it, get paid in stocks. An independent RWA index token for
 *         Robinhood Chain. A 4% trade tax is collected, swapped to ETH, and split:
 *         80% to the dividend distributor (buys the tokenized-stock basket for
 *         holders), 10% to auto-liquidity, 10% to the ops wallet.
 *
 * @dev Tokenomics are fully adjustable by the owner within safe caps
 *      (tax <= 5%), so the split can be revised as the model matures.
 *      OZ v5 ERC20; all transfer logic routes through `_update`.
 */
contract Stox is ERC20, Ownable2Step {
    uint256 public constant DENOM = 10_000;
    uint256 public constant MAX_TAX_BPS = 500; // hard cap 5% — cannot rug to a honeypot
    uint256 public constant MIN_MAX_TX = 1_000_000 * 1e18; // 0.1% — limits floor
    uint256 public constant MIN_MAX_WALLET = 5_000_000 * 1e18; // 0.5% — limits floor

    IUniswapV2Router02 public router;
    address public uniswapV2Pair;
    StoxDistributor public distributor;
    address public marketingWallet;

    // ── taxes (basis points) ──
    uint256 public buyTaxBps = 400; // 4%
    uint256 public sellTaxBps = 400; // 4%

    // ── split of collected tax (bps, sum = DENOM) ──
    uint256 public distributorShareBps = 8_000;
    uint256 public liquidityShareBps = 1_000;
    uint256 public marketingShareBps = 1_000;

    // ── swapback ──
    bool public swapEnabled = true;
    bool private inSwap;
    uint256 public swapTokensAtAmount;

    // ── trading / limits ──
    bool public tradingEnabled;
    bool public limitsInEffect = true;
    uint256 public maxTransaction;
    uint256 public maxWallet;

    mapping(address => bool) public isExcludedFromFee;
    mapping(address => bool) public isExcludedFromLimits;
    mapping(address => bool) public isExcludedFromDividends;
    mapping(address => bool) public automatedMarketMakerPairs;

    event TradingEnabled();
    event TaxesUpdated(uint256 buyBps, uint256 sellBps);
    event SplitUpdated(uint256 distributorBps, uint256 liquidityBps, uint256 marketingBps);
    event SwapBack(
        uint256 tokensSwapped, uint256 ethToDistributor, uint256 ethToLiquidity, uint256 ethToMarketing
    );
    event LimitsRemoved();

    error TradingNotEnabled();
    error TaxTooHigh();
    error InvalidSplit();
    error MaxTxExceeded();
    error MaxWalletExceeded();
    error LimitTooLow();
    error ZeroAddress();

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

    /**
     * @param _router     Uniswap V2 router on Robinhood Chain.
     * @param _distributor Pre-deployed StoxDistributor. After deploying this token,
     *        the distributor owner must call `distributor.setStox(token)` and
     *        `distributor.setBasket(...)` to finish wiring.
     * @param _marketingWallet Ops wallet.
     */
    constructor(address _router, address _distributor, address _marketingWallet)
        ERC20("Stox", "STOX")
        Ownable(msg.sender)
    {
        if (_router == address(0) || _distributor == address(0) || _marketingWallet == address(0)) {
            revert ZeroAddress();
        }
        uint256 supply = 1_000_000_000 * 1e18;

        router = IUniswapV2Router02(_router);
        marketingWallet = _marketingWallet;
        distributor = StoxDistributor(payable(_distributor));

        // Create the STOX/WETH pair.
        uniswapV2Pair = IUniswapV2Factory(router.factory()).createPair(address(this), router.WETH());
        _setAmmPair(uniswapV2Pair, true);

        // Defaults: 0.1% swap threshold, 1% max tx, 2% max wallet.
        swapTokensAtAmount = supply / 1_000;
        maxTransaction = supply / 100;
        maxWallet = supply / 50;

        // Exclusions.
        _excludeAll(owner());
        _excludeAll(address(this));
        _excludeAll(_marketingWallet);
        isExcludedFromFee[address(distributor)] = true;
        isExcludedFromLimits[address(router)] = true;
        // NB: the pair is intentionally NOT excluded from limits — the per-branch
        // logic in _update applies maxTx/maxWallet correctly to buys and sells.
        isExcludedFromDividends[address(this)] = true;
        isExcludedFromDividends[address(distributor)] = true;
        isExcludedFromDividends[uniswapV2Pair] = true;
        isExcludedFromDividends[address(0)] = true;
        isExcludedFromDividends[address(0xdead)] = true;

        _approve(address(this), _router, type(uint256).max);
        _mint(owner(), supply);
    }

    function _excludeAll(address a) internal {
        isExcludedFromFee[a] = true;
        isExcludedFromLimits[a] = true;
        isExcludedFromDividends[a] = true;
    }

    // ── core transfer hook ──
    function _update(address from, address to, uint256 amount) internal override {
        if (amount == 0 || inSwap) {
            super._update(from, to, amount);
            return;
        }

        if (!tradingEnabled && !(isExcludedFromFee[from] || isExcludedFromFee[to])) {
            revert TradingNotEnabled();
        }

        // Anti-whale limits (mint/burn skipped: from/to == 0 handled by exclusions).
        if (limitsInEffect && !isExcludedFromLimits[from] && !isExcludedFromLimits[to]) {
            if (automatedMarketMakerPairs[from]) {
                if (amount > maxTransaction) revert MaxTxExceeded();
                if (balanceOf(to) + amount > maxWallet) revert MaxWalletExceeded();
            } else if (automatedMarketMakerPairs[to]) {
                if (amount > maxTransaction) revert MaxTxExceeded();
            } else {
                if (balanceOf(to) + amount > maxWallet) revert MaxWalletExceeded();
            }
        }

        // Swap accumulated tax on sells.
        if (
            swapEnabled && !inSwap && automatedMarketMakerPairs[to] && !isExcludedFromFee[from]
                && balanceOf(address(this)) >= swapTokensAtAmount
        ) {
            _swapBack();
        }

        // Take fee on buys/sells (never on plain wallet-to-wallet).
        uint256 fee;
        bool takeFee = !isExcludedFromFee[from] && !isExcludedFromFee[to];
        if (takeFee) {
            if (automatedMarketMakerPairs[to]) {
                fee = (amount * sellTaxBps) / DENOM;
            } else if (automatedMarketMakerPairs[from]) {
                fee = (amount * buyTaxBps) / DENOM;
            }
        }
        if (fee > 0) {
            super._update(from, address(this), fee);
            amount -= fee;
        }
        super._update(from, to, amount);

        _syncDividends(from);
        _syncDividends(to);
    }

    function _syncDividends(address account) internal {
        if (isExcludedFromDividends[account]) return;
        try distributor.setBalance(account, balanceOf(account)) {} catch {}
    }

    // ── swapback / auto-liquidity ──
    function _swapBack() internal lockSwap {
        uint256 collected = balanceOf(address(this));
        uint256 cap = swapTokensAtAmount * 20;
        if (collected > cap) collected = cap;
        if (collected == 0) return;

        // Reserve half the liquidity share as tokens for the LP add.
        uint256 liqTokens = (collected * liquidityShareBps) / DENOM / 2;
        uint256 swapAmount = collected - liqTokens;

        uint256 ethBefore = address(this).balance;
        _swapTokensForEth(swapAmount);
        uint256 ethGained = address(this).balance - ethBefore;
        if (ethGained == 0) return;

        // swapAmount corresponds to (DENOM - liquidityShareBps/2) parts.
        uint256 denomParts = DENOM - liquidityShareBps / 2;
        uint256 ethForLiq = (ethGained * (liquidityShareBps / 2)) / denomParts;
        uint256 ethForMarketing = (ethGained * marketingShareBps) / denomParts;
        uint256 ethForDistributor = ethGained - ethForLiq - ethForMarketing;

        if (liqTokens > 0 && ethForLiq > 0) {
            try router.addLiquidityETH{value: ethForLiq}(
                address(this), liqTokens, 0, 0, owner(), block.timestamp
            ) {}
            catch {
                ethForDistributor += ethForLiq; // if LP add fails, redirect to holders
            }
        }
        if (ethForMarketing > 0) {
            (bool ok,) = payable(marketingWallet).call{value: ethForMarketing}("");
            if (!ok) ethForDistributor += ethForMarketing;
        }
        if (ethForDistributor > 0) {
            distributor.distribute{value: ethForDistributor}();
        }
        emit SwapBack(swapAmount, ethForDistributor, ethForLiq, ethForMarketing);
    }

    function _swapTokensForEth(uint256 tokenAmount) internal {
        address[] memory path = new address[](2);
        path[0] = address(this);
        path[1] = router.WETH();
        router.swapExactTokensForETHSupportingFeeOnTransferTokens(
            tokenAmount, 0, path, address(this), block.timestamp
        );
    }

    // ── admin ──
    function enableTrading() external onlyOwner {
        tradingEnabled = true;
        emit TradingEnabled();
    }

    function setTaxes(uint256 _buyBps, uint256 _sellBps) external onlyOwner {
        if (_buyBps > MAX_TAX_BPS || _sellBps > MAX_TAX_BPS) revert TaxTooHigh();
        buyTaxBps = _buyBps;
        sellTaxBps = _sellBps;
        emit TaxesUpdated(_buyBps, _sellBps);
    }

    function setSplit(uint256 _distributorBps, uint256 _liquidityBps, uint256 _marketingBps)
        external
        onlyOwner
    {
        if (_distributorBps + _liquidityBps + _marketingBps != DENOM) revert InvalidSplit();
        distributorShareBps = _distributorBps;
        liquidityShareBps = _liquidityBps;
        marketingShareBps = _marketingBps;
        emit SplitUpdated(_distributorBps, _liquidityBps, _marketingBps);
    }

    function setSwapTokensAtAmount(uint256 amount) external onlyOwner {
        swapTokensAtAmount = amount;
    }

    function setSwapEnabled(bool enabled) external onlyOwner {
        swapEnabled = enabled;
    }

    function setLimits(uint256 _maxTransaction, uint256 _maxWallet) external onlyOwner {
        // Floors so the owner can never freeze trading with near-zero limits.
        if (_maxTransaction < MIN_MAX_TX || _maxWallet < MIN_MAX_WALLET) revert LimitTooLow();
        maxTransaction = _maxTransaction;
        maxWallet = _maxWallet;
    }

    function removeLimits() external onlyOwner {
        limitsInEffect = false;
        emit LimitsRemoved();
    }

    /// @notice Owner can manually convert accumulated tax tokens (e.g. if auto
    /// swapback hasn't triggered). Cannot touch anything but the tax reserve.
    function manualSwapBack() external onlyOwner {
        if (balanceOf(address(this)) > 0) _swapBack();
    }

    function setMarketingWallet(address wallet) external onlyOwner {
        if (wallet == address(0)) revert ZeroAddress();
        marketingWallet = wallet;
        isExcludedFromFee[wallet] = true;
    }

    function setExcludedFromFee(address account, bool excluded) external onlyOwner {
        isExcludedFromFee[account] = excluded;
    }

    function setExcludedFromLimits(address account, bool excluded) external onlyOwner {
        isExcludedFromLimits[account] = excluded;
    }

    function setExcludedFromDividends(address account, bool excluded) external onlyOwner {
        isExcludedFromDividends[account] = excluded;
        if (excluded) {
            try distributor.setBalance(account, 0) {} catch {}
        } else {
            try distributor.setBalance(account, balanceOf(account)) {} catch {}
        }
    }

    function setAmmPair(address pair, bool value) external onlyOwner {
        require(pair != uniswapV2Pair, "cannot change primary pair");
        _setAmmPair(pair, value);
    }

    function _setAmmPair(address pair, bool value) internal {
        automatedMarketMakerPairs[pair] = value;
        isExcludedFromDividends[pair] = value;
    }

    /// @notice Recover non-STOX tokens or stuck ETH accidentally sent here.
    function rescueETH() external onlyOwner {
        (bool ok,) = payable(owner()).call{value: address(this).balance}("");
        require(ok, "rescue failed");
    }

    receive() external payable {}
}
Chain explorer1335msChain node82ms