SpotBlock Labs Zurich LogoSpotBlock Labs Zurich
App
← Back to docs

Contributor Manual

Discord validation, the contribution form, the validator API (including agents), and how rewards work.

SpotBlock grows when people ship verifiable threat intelligence. You can participate in three complementary ways: help clear the Discord validation queue, file structured reports through the contribution form, or—once registered—use the validator API to review staging tickets at scale (including with agents). When your work is accepted, you earn SPOT plus a USD-stable leg; see Rewards & claims. Technical details for the API start at Validator API.

Ways to contribute

Pick the path that fits how you like to work. All three feed the same detection pipeline; payouts differ by channel and by how much verified value you deliver.

Discord validation

Review scam-scanner items flagged for human judgment alongside other validators. Conversation, quick questions, and shared context live in the channel—good if you like a social rhythm and learning from the group.

Why use it

  • Low setup: no scripts required.
  • Baseline reward per accepted validation (see rewards).
  • Stay aligned with SpotBlock on process and edge cases.
Join Discord

Contribution form

Submit suspicious wallets or contracts with evidence on your own time. The form is the main on-ramp if you are not in Discord or you prefer a single structured submission instead of a live workflow.

Why use it

  • No chat commitment—submit when you are ready.
  • Room for rich evidence and multiple addresses.
  • Rewards scale with substance and verification (see rewards).
Open contribution form

Validator API

The same review action Discord validators take, exposed to code. Fetch the staging queue, run your own analysis stack, then post a verdict and an auditable comment—including optional toolName for agent attribution.

Why use it

  • Automate or semi-automate reviews without bypassing accountability.
  • Highest practical throughput when quality stays high.
  • Build repeatable pipelines (rules, ML, LLM assist) you own.
API reference

Rewards & claims

Rewards are based on accepted work quality, not only volume. The same quality bar applies across Discord, the contribution form, and the Validator API.

How rewards work

  • Routine validation tickets: first valid resolver earns contributor points (SPOT-linked reference value).
  • Requested queue tickets: higher per-ticket reference when that queue is enabled.
  • Contribution form submissions: variable reward based on confirmed impact and evidence quality.
  • Profile multiplier: consistent high-signal contributors can receive up to 5x.

Claims (simple)

  • Claim SPOT once the minimum threshold is met.
  • Claims are reviewed by SpotBlock admins before payout.
  • SPOT and USD-stable payout legs can be processed separately.
  • Pending claims lock claimable points until approved or rejected.

Validator API

Registered validators use the endpoints below to pull pending items from contracts_staging and submit signed reviews. Authentication ties requests to a wallet linked in SpotBlock’s contributor database.

What you can do

  • Fetch the current queue of pending scam-scanner detections waiting for validator review (from contracts_staging).
  • Run your own analysis locally (rules, scripts, LLMs, checklists).
  • Submit a verdict (safe/threat) and a comment (your full reasoning + tool output), and optionally set severity (low|medium|high|critical) if you need to amend scanner severity.

Use your own models, tools, and agents

You can train your own models and run custom agent/tool pipelines to perform deeper analysis before submitting. The API flow stays exactly the same (signed requests + verdict + comment + optional severity), but stronger accepted analysis can improve your reward outcomes over time through profile quality and multiplier effects.

Suggested references: AI reference and contributor leaderboard.

Note: the validator submission stores your comment on the contract entry once it is in the public malicious explorer database. If you provide severity, the review also updates contract severity for that decision.

Authentication model

The API uses short-lived wallet signatures with a server-issued nonce. Your wallet must be linked to your human analyst identity in SpotBlock’s contributor database.

  • Get a nonce from GET /api/validator/nonce.
  • Sign a message containing your wallet, nonce, and issued timestamp.
  • Use the signature in the request to fetch pending tickets or submit a review.

Endpoints

1) Get nonce

GET /api/validator/nonce

2) Fetch pending review tickets

GET /api/validator/pending (authenticated)

  • Returns items from contracts_staging where status is pending or needs_review.
  • Supports limit (default 50, max 200).

3) Submit a validator review (comment)

POST /api/validator/review (authenticated)

  • Required: verdict (safe or threat) and comment.
  • Optional: severity (low|medium|high|critical) to amend scanner-assigned severity when your analysis indicates a better level.
  • Optional: toolName (slug) so UI can display you as reviewer-tool (example: hug656-agent).

Example: fetch pending tickets (Node)

Run this from any machine with Node.js 18+ where you can install ethers (for example, a fresh local folder or a small private validator tool repo).

mkdir spotblock-validator-tool && cd spotblock-validator-tool
npm init -y
npm i ethers

export API_BASE_URL="https://spotblock.org"
export VALIDATOR_PRIVATE_KEY="0xYOUR_PRIVATE_KEY"

node -e '
const { Wallet } = require("ethers");
(async () => {
  const base = (process.env.API_BASE_URL || "").replace(/\/$/, "");
  const pk = process.env.VALIDATOR_PRIVATE_KEY;
  const w = new Wallet(pk);
  const wallet = w.address;

  const n = await fetch(`${base}/api/validator/nonce`);
  const { nonce, issuedAt } = await n.json();

  const msg = [
    "SpotBlock validator pending review request",
    `Wallet: ${wallet}`,
    `Nonce: ${nonce}`,
    `IssuedAt: ${issuedAt}`,
  ].join("\n");

  const signature = await w.signMessage(msg);
  const url = new URL(`${base}/api/validator/pending`);
  url.searchParams.set("wallet", wallet);
  url.searchParams.set("nonce", nonce);
  url.searchParams.set("issuedAt", issuedAt);
  url.searchParams.set("signature", signature);
  url.searchParams.set("limit", "20");

  const r = await fetch(url);
  console.log(await r.json());
})().catch(console.error);
'

Security note: don’t use a high-value wallet private key for tooling automation. Prefer a dedicated hot wallet with minimal assets.

Example: submit a review comment (Node)

This signs a short-lived message, then submits a verdict + freeform comment (+ optional severity override). Use toolName to display as reviewer-tool in the UI.

export API_BASE_URL="https://spotblock.org"
export VALIDATOR_PRIVATE_KEY="0xYOUR_PRIVATE_KEY"

# Target address can be pulled from /api/validator/pending (contracts_staging queue)
export TARGET_ADDRESS="0x0000000000000000000000000000000000000000"
export VERDICT="threat"     # safe | threat
export SEVERITY="high"      # optional: low | medium | high | critical
export TOOL_NAME="agent"    # [a-z0-9-_]{1,32}

node -e '
const { Wallet, ethers } = require("ethers");
(async () => {
  const base = (process.env.API_BASE_URL || "").replace(/\/$/, "");
  const pk = process.env.VALIDATOR_PRIVATE_KEY;
  const target = process.env.TARGET_ADDRESS;
  const verdict = String(process.env.VERDICT || "").toLowerCase();
  const severity = String(process.env.SEVERITY || "").toLowerCase();
  const toolName = String(process.env.TOOL_NAME || "agent").toLowerCase();

  if (!base || !pk) throw new Error("Set API_BASE_URL and VALIDATOR_PRIVATE_KEY");
  if (!ethers.isAddress(target)) throw new Error("Invalid TARGET_ADDRESS");
  if (verdict !== "safe" && verdict !== "threat") throw new Error("VERDICT must be safe|threat");
  if (severity && !["low","medium","high","critical"].includes(severity)) {
    throw new Error("SEVERITY must be low|medium|high|critical");
  }

  const w = new Wallet(pk);
  const wallet = w.address;

  const n = await fetch(base + "/api/validator/nonce");
  const { nonce, issuedAt } = await n.json();

  const msg = [
    "SpotBlock validator review submission",
    "Wallet: " + wallet,
    "Address: " + ethers.getAddress(target),
    "ChainId: 1",
    "Verdict: " + verdict,
    ...(severity ? ["Severity: " + severity] : []),
    "Nonce: " + nonce,
    "IssuedAt: " + issuedAt,
  ].join("\n");

  const signature = await w.signMessage(msg);

  const comment = [
    "Validator review (external tooling)",
    "Verdict: " + verdict,
    "",
    "Reasoning:",
    "- paste your full analysis here (can include AI agent output, links, etc.)",
  ].join("\n");

  const r = await fetch(base + "/api/validator/review", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      address: ethers.getAddress(target),
      chainId: 1,
      verdict,
      ...(severity ? { severity } : {}),
      comment,
      toolName,
      wallet,
      nonce,
      issuedAt,
      signature,
    }),
  });

  console.log("status", r.status);
  console.log(await r.json());
})().catch(console.error);
'

Target address can be a staging ticket (from /api/validator/pending). If verdict is threat, the submission auto-promotes it into the malicious explorer database.