Questions
Table with columns: key, question| key | question |
|---|
block_wallets | Can the owner make transfers revert for specific chosen addresses? |
trading_switch | Can the owner stop trading for everyone who is not exempt? |
limit_tx | Can the owner set or change a max transaction, max wallet or cooldown after deployment? |
change_fees | Can the owner change the buy, sell or transfer fee after deployment? |
owner_mint_or_balance_edit | Can the owner mint new supply or edit other holders' balances? |
owner_withdraw | Can the owner withdraw ETH or tokens held by the contract? |
tx_origin_in_transfer | Does the transfer logic depend on tx.origin? |
sell_block | Can sells fail or be taxed at 50%+ for normal holders while buys still work (honeypot)? |
external_control | Can another contract decide whether transfers succeed (every transfer checks or calls an outside contract that can block it)? |
fake_events | Does the contract emit Transfer events that do not match real balance changes? |
lp_pulled_24h | Launched in a pool with this code, was the liquidity pulled within 24 hours? (code-only prior) |
Results
Robinhood Chain test split: 6,899 questions on code shapes never seen in training (newest period); v2 = the
previous release, scored on the same rows.
Table with columns: question, yes in test, v2 AUROC, v3 AUROC, v2 F1, v3 F1| question | yes in test | v2 AUROC | v3 AUROC | v2 F1 | v3 F1 |
|---|
| block_wallets | 54 | 0.963 | 0.962 | 0.58 | 0.74 |
| change_fees | 41 | 0.923 | 0.940 | 0.49 | 0.51 |
| external_control * | 216 |
* test labels for external control come mostly from a decompiled-code rule (precision 0.89 against the teacher).
fake_events has too few examples (16 in training, none in test) to evaluate yet.
Fresh contracts deployed after the training data (60, labelled blind by an LLM teacher, never trained on):
external control AUROC 0.987 / F1 0.90 (9 cases), owner mint or balance edit AUROC 0.997 / F1 0.80 (3 cases, v2: 0.33),
tx.origin 2/2. Ranking is strong; hard yes/no answers are less reliable, so treat P(yes) as a score. The dataset's
exact/shape lookup answered 74% of fresh tokens without the model.
Use
Input = the compact decompiled view from the dataset pipeline (heimdall-rs 0.9.2 output, selector names resolved,
bodies common to 1,000+ contracts folded, code capped at 3,000 tokens):
import torchfrom peft import PeftModelfrom transformers import AutoModelForCausalLM, AutoTokenizer tok = AutoTokenizer.from_pretrained("Qwen/Qwen3.5-0.8B")model = AutoModelForCausalLM.from_pretrained("Qwen/Qwen3.5-0.8B", dtype=torch.float32)model = PeftModel.from_pretrained(model, "ethduke/robinhood-contract-traps-qwen3.5-0.8b-lora").eval()SYSTEM = "You read decompiled EVM token contracts (heimdall output, names resolved where known) and answer with one letter."user = (f"Decompiled contract:\n```solidity\n{code}\n```\n\nQuestion: {question}\n" "A) yes\nB) no\nAnswer with one letter.")ids = tok.apply_chat_template([{"role": "system", "content": SYSTEM}, {"role": "user", "content": user}], add_generation_prompt=True, enable_thinking=False, return_tensors="pt", return_dict=True)logits = model(**ids, logits_to_keep=1).logits[0, -1]a, b = (tok.encode(x, add_special_tokens=False)[0] for x in "AB")p_yes = torch.softmax(logits[[a, b]].float(), dim=0)[0].item()
thresholds.json holds the per-question cut-off (chosen on the valid split) for a "high" flag. On Apple Silicon
use float32 (float16 produced NaNs) and one prompt per forward pass.
Rug risk: code only vs. with launch data
The model's code answers feed a small rug-risk model (gradient-boosted trees, v2_risk_models.py in the project
repo, trained from the dataset's launch tables) that predicts a rug within 24 h: liquidity pulled, or the price
dumped (−90% within minutes, no recovery — e.g. a wallet farm selling into a pool whose liquidity is burned).
triage.py --mode picks how much on-chain data to fetch:
Table with columns: mode, inputs, RPC, AUROC +1 / +10 / +60 min, recall @ 5% false alarms (+10 min)| mode | inputs | RPC | AUROC +1 / +10 / +60 min | recall @ 5% false alarms (+10 min) |
|---|
code | code answers + rug history of the same code shape | none beyond the bytecode | 0.891 / 0.910 / 0.892 | 66.5% |
light | + launchpad, DEX version, starting ETH, creation receipt, LP custody, developer share | ~70 calls | 0.971 / 0.985 / 0.976 | 91.3% |
full |
Time split over launches from 2026-09-01 to 2026-10-01 (train oldest 75%, test newest 25%; test rug rates 29% /
12% / 5% at +1 / +10 / +60 min). Code alone ranks well but misses most late rugs (average precision 0.40 at +60 min
vs 0.73 with full launch data); who holds the LP is the strongest single launch signal, and the buyers' history
explains dumps where the liquidity itself is safe.
Retraining with more teacher labels (evaluated, not adopted)
A retrain with 262 more teacher-labelled contracts (one-offs resembling harmful families and large unlabelled
shapes) was compared with v3 on the same 7,490 test questions (paired bootstrap, 95% CI): better on owner withdraw
(+0.041 AUROC), worse on change fees (−0.015) and the code-only LP question (−0.028), no significant difference on
the other questions. v3 stays the published model; the new labels are in the dataset.
Simulated honeypots (evaluated, not adopted)
A further retrain added a question answered by on-chain simulation (buy, then sell 5 minutes later through a
router-style path): from code alone it reached test AUROC 0.745 on 48 simulated honeypots, while the other questions
were slightly below v3, so v3 stays. In practice triage.py --mode light/full runs the simulation live on the token
itself, which is more reliable than predicting it from code.
Training
LoRA r=16 / alpha=32 on all linear layers, loss on the answer letter only, bf16 on one RTX 4090.
Stage A: 20k Ethereum mainnet warm-up questions (owner-power rules + Slither detectors). Stage B: 21.8k Robinhood
Chain questions (all trap positives, two negatives per positive, balanced LP-outcome sample). Labels come from
source-logic rules on verified code, free propagation through identical function bodies and code shapes, and
LLM-teacher labels on unverified contracts (see the dataset card).
Limitations
- Decompiled code is lossy; some answers rest on partial bodies.
- Weakest on trading switches, mint/balance edits and owner withdrawals; strongest on limits, blacklists, tx.origin
and external control.
fake_events is trained on very few examples.
- Trained on Robinhood Chain launches (2026-05 to 2026-10); other chains and token styles may differ.