Add a fail-closed honeypot check to a Base trading bot
A successful quote or simulation does not establish that a token is safe to trade. Before signing, a bot should combine sellability, taxes, privileged controls, verified source, holder concentration, liquidity, and evidence availability—and block when critical evidence is missing.
1. Test a contract against current evidence
The public endpoint supports Base and Ethereum and returns JSON to API clients. The trial is limited to three checks per IP per hour.
curl --get 'https://solnodelabs.com/free/token-risk' \
--data-urlencode 'chain=base' \
--data-urlencode 'address=0x4200000000000000000000000000000000000006' \
-H 'Accept: application/json'
2. Add a deterministic Node.js gate
const BLOCKING_FLAGS = new Set([
"honeypot_simulation", "cannot_sell", "cannot_buy",
"owner_balance_control", "buy_tax_extreme", "sell_tax_extreme"
]);
export async function tokenPreflight(address) {
if (!/^0x[a-fA-F0-9]{40}$/.test(address)) {
return { execute: false, reason: "invalid_token_address" };
}
const url = new URL("https://solnodelabs.com/free/token-risk");
url.searchParams.set("chain", "base");
url.searchParams.set("address", address);
let response;
try {
response = await fetch(url, {
headers: { accept: "application/json" },
signal: AbortSignal.timeout(10_000)
});
} catch {
return { execute: false, reason: "risk_provider_unavailable" };
}
if (!response.ok) {
return { execute: false, reason: `risk_http_${response.status}` };
}
const evidence = await response.json();
const missingCriticalEvidence = [
"tokenMetadata", "contractMetadata", "marketData", "goPlusSecurity"
].some(key => evidence.dataCompleteness?.[key] !== true);
if (missingCriticalEvidence) {
return { execute: false, reason: "risk_evidence_incomplete", evidence };
}
const blocking = evidence.flags?.filter(flag =>
flag.severity === "critical" || BLOCKING_FLAGS.has(flag.code)
) ?? [];
if (blocking.length) {
return { execute: false, reason: "blocking_token_risk", blocking, evidence };
}
if (evidence.riskScore >= 40) {
return { execute: false, reason: "risk_threshold_exceeded", evidence };
}
return { execute: true, evidence };
}
3. Enforce the gate before signing
const preflight = await tokenPreflight(candidateToken);
if (!preflight.execute) {
auditLog.write({ token: candidateToken, ...preflight });
return { status: "blocked", reason: preflight.reason };
}
// Position limits, slippage checks, approval limits, and transaction
// simulation remain separate controls after this point.
return buildUnsignedSwap(candidateToken);
4. Preserve the decision evidence
Store the normalized chain and address, analysis time, policy version, completeness fields, flags, score, and final action. Do not cache a low-risk result indefinitely: ownership, taxes, liquidity, and market conditions can change.
5. Production considerations
- Fail closed on timeouts, malformed JSON, rate limits, and unavailable critical sources.
- Use a short cache keyed by chain and normalized address, with tighter freshness for newly launched assets.
- Keep signing keys outside the screening process.
- Apply independent limits for position size, slippage, approvals, and simulation.
- Treat automated output as evidence, not a safety guarantee or financial advice.
Need this fitted to an existing bot?
The $49 USDC pilot adds one fail-closed preflight, evidence logging, and focused failure-path tests to a supplied public repository or minimal reproduction. Scope is agreed before payment.
Create a private pilot ticket