hentol
HENTOL DOCS · RISK ENGINE V1.4.2

Build with Hentol.

Hentol is a security layer for onchain execution. It reads a contract's runtime bytecode, forks current chain state and runs thousands of simulated transactions against it — then returns a single risk score and a list of concrete findings before anyone signs.

These docs cover everything you need to put that verdict inside your product: the REST API, the TypeScript and Python SDKs, drop-in React components, webhooks for live monitoring, and step-by-step guides for DEXes, launchpads and wallets.

PRIVATE BETA

The public API is in private beta. Keys are issued manually while we scale capacity — request access at access@hentol.systems. Endpoints and payloads documented here are stable for Hentol-Version: 2026-09-01.

GETTING STARTED

How it works

Every scan goes through the same deterministic pipeline. Nothing depends on the token's website, socials or self-reported audit — Hentol only trusts what the bytecode actually does on a fork of the live chain.

01resolving chain rpc
02fetching runtime bytecode
03recovering function selectors
04resolving proxy / EIP-1967 slots
05building control-flow graph
06mapping privileged SSTORE
07forking state @ latest block
08simulating buy/sell paths
09adversarial execution
10scoring

What each stage does

  • Bytecode & selectors. We pull runtime code at the requested block and recover every 4-byte function selector — including ones that are not in the verified source, which is where hidden mint and blacklist functions usually live.
  • Proxy resolution. EIP-1967, EIP-1822 and legacy admin slots are read so the scan follows the implementation, not just the proxy shell. Upgrade rights are reported separately.
  • Control-flow graph & privileged writes. We map which storage slots can be written and by whom. A write to totalSupply or a fee slot behind an onlyOwner guard is flagged with its exact selector.
  • Fork simulation. State is forked at the latest block and we run hundreds of buy and sell sequences from fresh wallets. If sells revert, the token is a honeypot — no matter what the source says.
  • Adversarial execution. An executor tries to trap exits: tax mutation mid-sequence, blacklist on first sell, liquidity pull. Each attempt that succeeds becomes a finding.
  • Scoring. Findings roll up into seven surface scores and one 0–100 risk score. Same bytecode + same state = same score, every time.
TIP

Reports are cached by codeHash. A second scan of identical bytecode on the same block returns in a few milliseconds and does not count toward your quota.

GETTING STARTED

Quickstart

From zero to your first verdict in about two minutes.

Get an API key

Keys are issued from the dashboard once your beta access is approved. You get two: sk_live_… (secret, server only) and pk_live_… (publishable, safe in the browser).

.env.local
1# Server-side secret key — never ship this to the browser
2HENTOL_KEY=sk_live_••••••••••••••••••••••••
3
4# Publishable key — safe for client bundles, read-only scans
5NEXT_PUBLIC_HENTOL_PK=pk_live_••••••••••••••••
Install the SDK

Node 18+, Bun and Deno are supported. Python 3.9+ for the Python client.

terminal
1$ npm install @hentol/sdk
Run your first scan

Pass a chain and an address. The call resolves when the full pipeline has finished — typically 30–60 ms for a cached contract and under 2 s for a cold one.

scan.ts
1import { Hentol } from "@hentol/sdk";
2
3const hentol = new Hentol({ apiKey: process.env.HENTOL_KEY });
4
5const report = await hentol.scan({
6 chain: "base",
7 address: "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2",
8});
9
10console.log(report.riskScore); // 92
11console.log(report.severity); // "low"
12
13for (const check of report.checks) {
14 if (check.status !== "pass") console.log(check.id, check.value, check.detail);
15}
Act on the verdict

Use severity for a simple allow / warn / block decision, or read individual checks to show users exactly what was found. See Risk score for recommended thresholds.

GETTING STARTED

Authentication

All requests are authenticated with a bearer token in the Authorization header. Requests without a valid key return 401 unauthorized.

request
1POST /v1/scan HTTP/1.1
2Host: api.hentol.systems
3Authorization: Bearer sk_live_••••••••••••
4Content-Type: application/json
5Hentol-Version: 2026-09-01
6Idempotency-Key: 6f1c2a7e-31b4-4d0f-9a8e-0c5b7d2e1f44
KEYWHERECAN DO
sk_live_…Server onlyEverything: scan, simulate, monitors, webhooks, report history.
pk_live_…Browser / mobileRead-only scans and cached reports. Origin-restricted in the dashboard.
whsec_…Your webhook handlerVerifies the signature on incoming webhook events. Not an API key.

Headers

HEADERREQUIREDDESCRIPTION
AuthorizationyesBearer token: Bearer sk_live_…
Hentol-VersionrecommendedPins the response format. Defaults to the version on your key.
Idempotency-KeyoptionalAny UUID. Retrying a POST with the same key returns the original result.
KEEP SECRET KEYS SECRET

Never put an sk_ key in frontend code, a mobile app or a public repo. If one leaks, roll it in the dashboard — the old key stops working immediately.

CONCEPTS

Risk score

Every report has a riskScore from 0 to 100. Higher is safer. The score maps to a fixed level and severity, so you can branch on a string instead of hard-coding numbers.

SCORELEVELSEVERITYRECOMMENDED UI
80 – 100LOW_RISKlowAllow. Show a green badge.
50 – 79ELEVATED_RISKelevatedAllow with a visible warning and the top findings.
25 – 49HIGH_RISKhighRequire explicit confirmation before signing.
0 – 24CRITICALcriticalBlock. Do not offer a sign button.

A high score is not an endorsement. It means Hentol found no exploitable path in the code and state it can see. Issuer-controlled assets such as regulated stablecoins can score well while still having pause or blacklist roles — those show up as warn or info checks so users can see them.

CONCEPTS

Checks

A report contains nine checks. Each has a status (pass, info, warn or crit), a short value for display and a detail string that points to the exact selector, slot or simulation result behind it.

IDWHAT IT CHECKSWHY IT MATTERS
hidden_mintAny reachable write to total supply after deployment.Owner can print tokens and dump them on holders.
sell_simulationHundreds of sells from fresh wallets on a fork.If sells revert, holders cannot exit.
blacklistAddress-keyed guards on transfer paths.Specific wallets can be frozen at will.
owner_tax_controlWritable fee slots and whether they are capped.Sell tax can be raised to 99% after you buy.
proxyUpgradeable implementation and who holds the admin key.Logic can be replaced with anything later.
liquidityWho holds the LP tokens and for how long they are locked.Unlocked LP can be pulled in one transaction.
transfer_restrictionAsymmetric buy/sell paths, pausing, cooldowns.Trading can be halted or limited per wallet.
bytecode_verifiedRuntime bytecode matches the verified source.Unverified code can hide anything.
honeypot_pathAdversarial executor tries to trap an exit.Confirms a working trap, not just a capability.

Reading a check

check.json
1{
2 "id": "owner_tax_control",
3 "status": "warn",
4 "value": "CAPPED 10%",
5 "detail": "setTax(uint256) 0x2e5bb6ff · require(value <= 1000)",
6 "selector": "0x2e5bb6ff"
7}

Here the owner can change the tax, but the contract enforces a 10% ceiling (1000 basis points), so the check is a warning rather than critical. Without that require, the same check would be crit with the value MUTABLE · NO CAP.

CONCEPTS

Surface breakdown

Besides the single score, each report includes seven surface scores (0–100, higher is safer). They are useful for charts and for explaining why a token scored the way it did.

FIELDCOVERS
bytecodeVerification status, unknown selectors, self-destruct, delegatecall to user input.
ownershipOwner type (EOA, multisig, timelock, renounced) and how much power it has.
transferLogicSymmetry of buy and sell paths, hooks inside transfer.
liquidityLP ownership, lock duration, depth relative to supply.
mintAuthorityWho can mint, whether it is capped or allowance-based.
taxControlCurrent fees, mutability and caps.
proxyRiskUpgradeability, admin key type, recent implementation swaps.
API REFERENCE

Overview

The API is REST over HTTPS. Request and response bodies are JSON, timestamps are ISO-8601 UTC, token amounts are strings in base units (wei) to avoid precision loss.

BASEhttps://api.hentol.systems/v1base URL
METHODPATHDESCRIPTION
POST/v1/scanAnalyze a contract and return a full report.
POST/v1/simulateSimulate a pending transaction and get allow / warn / block.
GET/v1/reports/:idFetch a stored report by id.
GET/v1/reportsList reports, filtered by address and chain.
POST/v1/monitorsWatch a contract and receive webhooks on changes.
DELETE/v1/monitors/:idStop a monitor.
GET/v1/chainsSupported chains and their status.
API REFERENCE

Scan a contract

POST/v1/scan

Runs the full pipeline against one contract and returns a report. If an identical report exists for this codeHash at the same block it is returned from cache.

Body parameters

PARAMTYPEDESCRIPTION
address *stringContract address, 0x-prefixed, 40 hex chars. Checksum not required.
chain *stringOne of the ids from /v1/chains.
depthstringquick (selectors + static, ~10 ms) or full (default, includes simulation).
simulate.sellsnumberSell sequences to run. 64–2048, default 512.
simulate.adversarialbooleanRun the adversarial executor. Default true.
blocknumber | stringBlock to fork. Default latest.

Request

scan.sh
1curl -X POST https://api.hentol.systems/v1/scan \
2 -H "Authorization: Bearer $HENTOL_KEY" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "chain": "base",
6 "address": "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2",
7 "depth": "full",
8 "simulate": { "sells": 512, "adversarial": true },
9 "block": "latest"
10 }'

Response

response.json
1{
2 "id": "scn_4f1a9c02be71",
3 "object": "report",
4 "address": "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2",
5 "chain": "base",
6 "block": 28401907,
7 "codeHash": "0x9c4e1b07f2a8d35e61c0b9a47d2e8f13a5c6b70e94d1f28a3b5c7e60d9f1a2b4",
8 "riskScore": 92,
9 "level": "LOW_RISK",
10 "severity": "low",
11 "summary": "No exploitable privilege path. One mutable fee control, hard-capped.",
12 "checks": [
13 {
14 "id": "hidden_mint",
15 "status": "pass",
16 "value": "NONE",
17 "detail": "No reachable SSTORE to totalSupply outside constructor"
18 },
19 {
20 "id": "owner_tax_control",
21 "status": "warn",
22 "value": "CAPPED 10%",
23 "detail": "setTax(uint256) 0x2e5bb6ff · require(value <= 1000)",
24 "selector": "0x2e5bb6ff"
25 },
26 {
27 "id": "sell_simulation",
28 "status": "pass",
29 "value": "PASS",
30 "detail": "512 sell sequences · 0 reverts"
31 }
32 ],
33 "breakdown": {
34 "bytecode": 100,
35 "ownership": 86,
36 "transferLogic": 100,
37 "liquidity": 88,
38 "mintAuthority": 100,
39 "taxControl": 74,
40 "proxyRisk": 100
41 },
42 "stats": {
43 "executionPaths": 28481,
44 "simulatedTxs": 7291,
45 "stateMutations": 892,
46 "analysisMs": 43.7
47 },
48 "createdAt": "2026-10-11T09:14:02Z"
49}
NOTE

The response above is trimmed to three checks for readability. Real responses always include all nine.

API REFERENCE

Simulate a transaction

POST/v1/simulate

Executes an unsigned transaction on a fork of the latest block and tells you what would happen: balance changes, new approvals, reverts — plus a verdict. This is what powers wallet pre-sign warnings.

PARAMTYPEDESCRIPTION
chain *stringChain id.
from *stringSender address (the user's wallet).
to *stringTarget contract.
datastringCalldata, 0x-prefixed. Omit for a plain transfer.
valuestringNative value in wei. Default "0".
simulate.ts
1const sim = await hentol.simulate({
2 chain: "base",
3 from: "0x91e4c3A2...b03", // the user's wallet
4 to: "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2",
5 data: "0xa9059cbb000000000000000000000000...", // transfer(address,uint256)
6 value: "0",
7});
8
9if (sim.verdict === "block") {
10 throw new Error(sim.reasons.join(", "));
11}
response.json
1{
2 "id": "sim_b27e90c4d1aa",
3 "verdict": "allow",
4 "riskScore": 92,
5 "reasons": [],
6 "balanceChanges": [
7 { "token": "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2", "delta": "-250000000000000000000" },
8 { "token": "ETH", "delta": "-0.000041" }
9 ],
10 "approvals": [],
11 "gasUsed": 51284,
12 "reverted": false
13}
VERDICTMEANING
allowTarget scores LOW_RISK and the simulation shows no unexpected outflows.
warnElevated risk, unlimited approval, or an outflow larger than the user likely expects.
blockHoneypot, drainer pattern, or a target scored CRITICAL.
API REFERENCE

Retrieve reports

GET/v1/reports/:id

Every scan is stored and addressable by its id (scn_…). Reports are immutable — a new scan of the same contract produces a new id, so you can diff how a contract changed over time.

report.sh
1curl https://api.hentol.systems/v1/reports/scn_4f1a9c02be71 \
2 -H "Authorization: Bearer $HENTOL_KEY"
QUERY (LIST)TYPEDESCRIPTION
addressstringFilter by contract.
chainstringFilter by chain.
limitnumber1–100, default 20.
cursorstringValue of nextCursor from the previous page.
API REFERENCE

Monitors

POST/v1/monitors

A monitor watches one contract block by block and POSTs to your URL when something security-relevant changes. Use it to pause a listing the moment a tax is raised or an implementation is swapped.

monitor.ts
1const monitor = await hentol.monitors.create({
2 chain: "base",
3 address: "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2",
4 events: ["tax.mutated", "owner.changed", "proxy.upgraded", "liquidity.removed"],
5 url: "https://api.your-app.com/hooks/hentol",
6});
7
8console.log(monitor.id); // "mon_7c21e0f9ab34"
9console.log(monitor.secret); // "whsec_…" — store it, shown once

Events are listed in Events & payloads. To stop a monitor, call DELETE /v1/monitors/:id.

API REFERENCE

Supported chains

GET/v1/chains
IDNAMECHAIN IDSHORT
ethereumEthereum1ETH
baseBase8453BASE
arbitrumArbitrum42161ARB
optimismOptimism10OP
polygonPolygon137POL
bnbBNB Chain56BSC
response.json
1{
2 "data": [
3 { "id": "ethereum", "chainId": 1, "status": "online" },
4 { "id": "base", "chainId": 8453, "status": "online" },
5 { "id": "arbitrum", "chainId": 42161, "status": "online" },
6 { "id": "optimism", "chainId": 10, "status": "online" },
7 { "id": "polygon", "chainId": 137, "status": "online" },
8 { "id": "bnb", "chainId": 56, "status": "online" }
9 ]
10}
SDK

Installation & client

@hentol/sdk is a thin, fully typed wrapper around the REST API. It handles auth, retries with backoff, response caching and typed errors. It ships ESM + CJS and works in Node, Bun, Deno, edge runtimes and the browser (with a publishable key).

terminal
1$ npm install @hentol/sdk

Creating a client

hentol.ts
1import { Hentol } from "@hentol/sdk";
2
3export const hentol = new Hentol({
4 apiKey: process.env.HENTOL_KEY, // required
5 defaultChain: "base", // used when a call omits chain
6 timeoutMs: 10_000, // per request
7 retries: 2, // on 429 / 5xx, exponential backoff
8 cache: { ttlMs: 60_000 }, // reuse reports for the same codeHash
9});
OPTIONDEFAULTDESCRIPTION
apiKey—Secret or publishable key.
defaultChain"ethereum"Chain used when a call omits it.
timeoutMs10000Abort a request after this long.
retries2Automatic retries on 429 and 5xx.
cache.ttlMs60000In-memory report cache. Set 0 to disable.

Methods

METHODRETURNS
hentol.scan(params)Promise<Report>
hentol.simulate(params)Promise<Simulation>
hentol.reports.get(id)Promise<Report>
hentol.reports.list(params)Promise<Page<Report>>
hentol.monitors.create(params)Promise<Monitor>
hentol.monitors.delete(id)Promise<void>
hentol.chains()Promise<Chain[]>

Error handling

errors.ts
1import { HentolError, RateLimitError } from "@hentol/sdk";
2
3try {
4 await hentol.scan({ address });
5} catch (err) {
6 if (err instanceof RateLimitError) {
7 await sleep(err.retryAfterMs);
8 } else if (err instanceof HentolError) {
9 console.error(err.code, err.message, err.requestId);
10 } else {
11 throw err;
12 }
13}
SDK

React components

@hentol/sdk/react gives you a provider, a hook and two ready-made components. They use the publishable key, deduplicate requests for the same address and work with Next.js App Router (client components).

app/providers.tsx
1"use client";
2import { HentolProvider } from "@hentol/sdk/react";
3
4export function Providers({ children }: { children: React.ReactNode }) {
5 return (
6 <HentolProvider publishableKey={process.env.NEXT_PUBLIC_HENTOL_PK} chain="base">
7 {children}
8 </HentolProvider>
9 );
10}
EXPORTWHAT IT IS
<HentolProvider>Holds the client and cache. Wrap your app once.
useHentol(address)Returns { report, loading, error, refresh }.
<RiskBadge>Compact score pill coloured by severity.
<HentolOverlay>The full floating verdict card, as seen on DEX integrations.
GUIDES

DEX & launchpad overlay

The fastest integration: one script tag, no build step. The overlay finds every element marked with a token address and attaches a verdict card next to it. Your UI stays the same — Hentol renders on top.

index.html
1<script
2 src="https://cdn.hentol.systems/overlay@1.4.2/overlay.js"
3 data-key="pk_live_••••••••••••"
4 data-chain="base"
5 data-selector="[data-token-address]"
6 defer
7></script>
8
9<!-- any element with a token address gets a verdict -->
10<div data-token-address="0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2"></div>
  1. Add the script with your publishable key and default chain.
  2. Mark token elements with data-token-address (or point data-selector at your own attribute).
  3. Optionally listen for hentol:verdict DOM events to disable your buy button on critical.
TIP

Using React? Prefer <HentolOverlay> from the SDK — same card, but you control mounting and get typed callbacks.

GUIDES

Wallet pre-sign guard

Wrap your send function so every transaction is simulated before the wallet popup appears. Users see a warning — or a hard block — before they ever get the chance to sign something malicious.

guardedSend.ts
1import { createWalletClient, custom } from "viem";
2import { base } from "viem/chains";
3import { hentol } from "./hentol";
4
5const wallet = createWalletClient({ chain: base, transport: custom(window.ethereum) });
6
7export async function guardedSend(tx: { to: `0x${string}`; data: `0x${string}`; value?: bigint }) {
8 const [from] = await wallet.getAddresses();
9
10 // 1. simulate against a fork of the latest block
11 const sim = await hentol.simulate({ chain: "base", from, ...tx, value: String(tx.value ?? 0n) });
12
13 // 2. stop before the wallet popup if Hentol blocks
14 if (sim.verdict === "block") {
15 throw new Error("Hentol blocked this transaction: " + sim.reasons.join(", "));
16 }
17
18 // 3. warn, but let the user decide
19 if (sim.verdict === "warn" && !confirm(sim.reasons.join("\n") + "\n\nSign anyway?")) return;
20
21 return wallet.sendTransaction({ account: from, ...tx });
22}
  • Simulation adds roughly 40–120 ms. Run it while you are already showing a "preparing transaction" state and users will not notice.
  • Always show sim.reasons to the user. A block without an explanation feels like a bug.
  • Fail open or closed? If the API is unreachable, most wallets fail open with a visible "not checked" label. Pick what fits your users.
GUIDES

Browser extension

The Hentol extension brings the same verdict to any site, with no integration from the site owner. It detects contract addresses in the active tab and in pending wallet requests, then shows the card from the toolbar.

PERMISSIONWHY
activeTabRead the address on the page you are looking at — only when you open the popup.
storageRemember dismissed warnings and your chain preference locally.
wallet requestsIntercept eth_sendTransaction to run a simulation first.

The extension never sees your private keys and never signs anything. It only reads addresses and unsigned transaction data, sends them to the scan API and shows the result.

WEBHOOKS

Events & payloads

When a monitor fires, Hentol sends a POST with a JSON body to your URL. Respond with any 2xx within 10 seconds. Failed deliveries are retried with exponential backoff for 24 hours (8 attempts).

EVENTFIRES WHENTYPICAL SEVERITY
tax.mutatedA fee slot is written.warn → critical if > 25%
owner.changedOwnership is transferred or renounced.info
proxy.upgradedThe implementation address changes.critical
liquidity.removedLP tokens leave the lock or > 20% of liquidity is pulled.critical
blacklist.addedAn address is added to a transfer guard.warn
score.changedA rescan moves the score across a level boundary.depends
payload.json
1{
2 "id": "evt_1d8a0c37f2e9",
3 "type": "tax.mutated",
4 "monitor": "mon_7c21e0f9ab34",
5 "chain": "base",
6 "address": "0x7A1C92e3319b0FE2A8D48B90EA52C14E991C91c2",
7 "block": 28401907,
8 "tx": "0x8f81c27b49ea21e0c3d1f7a9b44e2d06c51f88a3b70e9d2c4a61f05e3d8b7c19",
9 "data": { "slot": "0x08", "before": 5, "after": 99 },
10 "severity": "critical",
11 "createdAt": "2026-10-11T09:16:44Z"
12}
WEBHOOKS

Verifying signatures

Every delivery carries a Hentol-Signature header: t=<unix seconds>,v1=<hex HMAC>. The HMAC is SHA-256 over `${t}.${rawBody}` using your monitor's whsec_ secret. Always verify it — anyone can POST to a public URL.

app/hooks/hentol/route.ts
1import crypto from "node:crypto";
2
3const SECRET = process.env.HENTOL_WEBHOOK_SECRET!; // whsec_…
4const TOLERANCE_S = 300;
5
6export async function POST(req: Request) {
7 const raw = await req.text(); // verify the RAW body, before JSON.parse
8 const header = req.headers.get("hentol-signature") ?? "";
9
10 // header format: t=1760174204,v1=5f2c…e1
11 const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")));
12 const t = Number(parts.t);
13 if (!t || Math.abs(Date.now() / 1000 - t) > TOLERANCE_S) {
14 return new Response("stale", { status: 400 });
15 }
16
17 const expected = crypto.createHmac("sha256", SECRET).update(`${t}.${raw}`).digest("hex");
18 const ok =
19 expected.length === parts.v1?.length &&
20 crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
21 if (!ok) return new Response("bad signature", { status: 401 });
22
23 const event = JSON.parse(raw);
24 if (event.severity === "critical") await pauseTrading(event.address);
25
26 return new Response(null, { status: 204 });
27}
IMPORTANT

Verify against the raw request body. Parsing JSON and re-serialising it changes whitespace and key order, and the signature will not match.

REFERENCE

Errors

Errors use standard HTTP status codes and a consistent JSON body. Always log requestId — support can trace any request from it.

error.json
1{
2 "error": {
3 "code": "contract_not_found",
4 "message": "No runtime bytecode at 0x7A1C…91c2 on base (block 28401907).",
5 "param": "address",
6 "requestId": "req_e04b9d17c2f8",
7 "docs": "https://hentol.systems/docs#errors"
8 }
9}
STATUSCODEMEANING
400invalid_requestMalformed JSON or a missing required parameter.
401unauthorizedMissing, invalid or rolled API key.
403forbiddenKey type cannot do this (such as a pk_ key creating a monitor).
404not_foundReport or monitor id does not exist.
422contract_not_foundNo bytecode at that address on that chain — often the wrong chain.
422unsupported_chainChain id is not in /v1/chains.
429rate_limitedToo many requests. Respect Retry-After.
500internal_errorSomething broke on our side. Safe to retry.
503chain_unavailableUpstream RPC for that chain is degraded.
REFERENCE

Rate limits

Limits are per key, over a rolling 60-second window. Cached reports (same codeHash and block) do not count.

PLANSCANS / MINSIMULATIONS / MINMONITORS
Beta6012010
Growth6001,200250
Enterprisecustomcustomunlimited
response headers
1HTTP/1.1 429 Too Many Requests
2X-RateLimit-Limit: 600
3X-RateLimit-Remaining: 0
4X-RateLimit-Reset: 1760174264
5Retry-After: 12
REFERENCE

Changelog

v1.4.2
2026-09-28
  • Issuer-role detection for regulated stablecoins (mint allowances, pauser, blacklister).
  • Faster cold scans on Base: p50 1.1 s → 0.7 s.
v1.4.0
2026-09-01
  • New API version 2026-09-01: checks gain a selector field.
  • score.changed webhook event.
  • Python SDK 1.0.
v1.3.0
2026-07-15
  • Adversarial executor enabled by default.
  • BNB Chain and Polygon support.
REFERENCE

FAQ

Does a high score mean a token is a good investment?+

No. Hentol measures contract and execution risk — whether the code can trap, drain or dilute you. It says nothing about price, team or market.

Can a contract change after it was scanned?+

Yes — through proxies, owner functions or liquidity moves. That is why reports are tied to a block, and why monitors exist.

Do you need the source code?+

No. Analysis runs on runtime bytecode. Verified source only adds the bytecode_verified check and nicer function names.

Which chains are supported?+

Ethereum, Base, Arbitrum, Optimism, Polygon, BNB Chain. More EVM chains are added based on demand.

How do I get access?+

Email access@hentol.systems with your project and expected volume. Beta keys are free.