7Block Labs
Blockchain Security

ByAUJay

“Safesetup” DAO‑Multisig and “DAO‑Multisig‑ETH‑Balance‑Change”: Forta Detection Engineering Essentials

A practical, deeply technical playbook to design, ship, and scale two high‑signal Forta detections for DAO treasuries: SafeSetup (Gnosis Safe initialization) and DAO‑Multisig‑ETH‑Balance‑Change (native ETH deltas), with concrete event signatures, chain quirks, and production hardening steps for 2026‑grade security operations. For decision‑makers, this post shows how to convert raw on‑chain signals into measurable risk reduction and faster incident response.

TL;DR (description)

  • Detecting Gnosis Safe “SafeSetup” events precisely and monitoring DAO multisig ETH balance changes across L1/L2s can catch misconfigurations early and surface anomalous treasury movements in time to act. This guide provides exact event topics, engineering patterns, alert schemas, and production scaling tactics to operationalize these detections in Forta.

Why these two detections matter in 2026

  • Safe has become the de‑facto smart account standard for DAO treasuries and institutions; even the Ethereum Foundation announced it moved its treasury to a Safe multisig in January 2026, after months of internal testing. That raises the bar for Safe telemetry and misconfiguration detection around new creations and treasury flows. (theblock.co)
  • Mature DAOs run Forta for continuous security and operational monitoring (Compound’s multisig and governance monitors are public precedent), so standardizing treasury‑grade detectors aligns with how leading teams already operate. (7blocklabs.com)
  • Forta’s ecosystem offers ready‑to‑compose building blocks (OpenZeppelin‑Gnosis Safe event bot, Attack Detector combiner, Time Series Analyzer) to turn low‑level signals into high‑precision alerts and runbooks. (docs.forta.network)

Detector 1: “SafeSetup” DAO‑Multisig

What exactly are we detecting?

The Safe contract emits a SafeSetup event when a newly created Safe is initialized:

  • Event signature:
    SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler)
  • Canonical topic (keccak256 of signature):
    0x141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8
  • Verified in‑the‑wild example (with owners array, threshold, fallbackHandler populated) from a Safe creation tx that also emitted ProxyCreation. (gnosisscan.io)

Strong correlation: new Safe proxies are deployed by SafeProxyFactory and emit

ProxyCreation(SafeProxy indexed proxy, address singleton)
; filter factories by canonical versions (e.g., Safe Proxy Factory 1.3.0 / 1.4.1) to reduce spoofing. (etherscan.io)

Why SafeSetup alerts are high value for DAOs

  • Catch misconfigurations at birth: thresholds of 1 for treasury safes, unknown fallback handlers, or suspicious initializers can be flagged before funds arrive. The fallback handler is powerful and has security foot‑guns if misused; watch for non‑standard handlers or handler=self patterns. (docs.safe.global)
  • Establish a canonical inventory of DAO safes across chains by joining SafeSetup with ProxyCreation and verified factory addresses. This inventory powers downstream owner‑change and funds‑movement monitoring with correct entity labeling. (docs.safe.global)

Precision engineering checklist

  1. Event source authenticity

    • Filter to known SafeProxyFactory addresses per chain and check
      singleton
      matches known Safe master copies (or a vetted allowlist per DAO), per Safe’s verification guidance. (help.safe.global)
  2. Extract and normalize parameters

    • Owners: canonical checksum, dedupe, map to known signers if you maintain a signer registry.
    • Threshold: immediate policy checks (e.g., “treasury safes must be ≥ 3‑of‑5”).
    • Fallback handler: verify against known‑good addresses, watch for 0x0 or unknown contracts. Safe emits
      ChangedFallbackHandler(address)
      on later changes—subscribe to that event too. (docs.safe.global)
  3. Suspicion heuristics at setup time

    • Threshold < 2 for a DAO treasury Safe.
    • Owners include EOAs tagged as high‑risk or sanctioned by your intel feeds.
    • Non‑zero
      initializer
      that enables modules/guards immediately without review.
    • Fallback handler points to an unverified or self address (GS400 guard in code warns against handler=self). (gnosisscan.io)
  4. Correlate with ProxyCreation in the same tx

    • Require
      ProxyCreation(proxy, singleton)
      within N blocks of SafeSetup and
      proxy == log.address
      . This both reduces false positives and aids entity labeling. (docs.safe.global)
  5. Canonical Safe events to additionally watch post‑setup

    • OwnerManager:
      AddedOwner
      ,
      RemovedOwner
      ,
      ChangedThreshold
      .
    • ModuleManager:
      EnabledModule
      ,
      DisabledModule
      .
    • GuardManager:
      ChangedGuard
      .
    • FallbackManager:
      ChangedFallbackHandler
      . Track all as separate detections or enrich SafeSetup with a “subscribed signals” list. (gnosisscan.io)

Implementation sketch (TypeScript forta-agent)

import { Finding, FindingType, FindingSeverity, getEthersProvider } from "forta-agent";
import { Interface } from "ethers/lib/utils";

const SAFE_ABI = new Interface([
  "event SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler)"
]);
const SAFESETUP_TOPIC = SAFE_ABI.getEventTopic("SafeSetup");
// allowlisted factories per chain
const FACTORIES = new Set<string>([
  // mainnet
  "0xc22834581ebc8527d974f8a1c97e1bea4ef910bc".toLowerCase(), // Proxy Factory 1.3.x
  "0x4e1dcf7ad4e460cfd30791ccc4f9c8a4f820ec67".toLowerCase(), // Proxy Factory 1.4.1
]);

export async function handleTransaction(txEvent) {
  const findings: Finding[] = [];
  for (const log of txEvent.filterLog(SAFE_ABI, undefined)) {
    if (log.topics[0] !== SAFESETUP_TOPIC) continue;
    // cross-check tx also touched a known ProxyFactory emitting ProxyCreation
    const hasFactory = txEvent.logs.some(l =>
      FACTORIES.has(l.address.toLowerCase())
    );
    if (!hasFactory) continue;

    const { initiator, owners, threshold, initializer, fallbackHandler } = log.args;

    // basic policy checks
    const badThreshold = Number(threshold) < 2;
    const suspiciousHandler = (fallbackHandler === "0x0000000000000000000000000000000000000000");

    findings.push(Finding.fromObject({
      name: "SafeSetup",
      description: "New Safe initialized",
      alertId: "SAFE-SETUP",
      type: FindingType.Info,
      severity: (badThreshold || suspiciousHandler) ? FindingSeverity.High : FindingSeverity.Medium,
      protocol: "safe",
      metadata: {
        safe: log.address,
        initiator,
        owners: owners.join(","),
        ownersCount: String(owners.length),
        threshold: String(threshold),
        initializer,
        fallbackHandler
      }
    }));
  }
  return findings;
}

Notes:

  • Use the Safe docs’ factory/event references to maintain your factory allowlist and keep it fresh. (docs.safe.global)
  • For rapid prototyping or coverage, you can also subscribe to the OpenZeppelin‑Gnosis Safe Contract Events base bot and build a combiner, but bespoke parsing lets you enforce your DAO’s exact policies at setup time. (docs.forta.network)

Detector 2: “DAO‑Multisig‑ETH‑Balance‑Change”

What exactly are we detecting?

A normalized, chain‑portable alert whenever a labeled DAO multisig’s native ETH balance changes, including:

  • Direct ETH transfers
  • Internal value movements caused by execTransaction, module calls, refunds
  • L2 specifics (sequencer fees, base asset still ETH on major EVM L2s)

Why it’s tricky:

  • ETH transfers don’t emit ERC‑20 logs; you must aggregate traces and/or snapshot balances by block.
  • Forta scan nodes provide trace data for Ethereum mainnet; for other chains, traces may be empty—fallback to
    eth_getBalance
    diffing. (docs.forta.network)

Labeling scope: what counts as “DAO multisig”?

Use a labeler that tags an address as DAO‑SAFE if:

  • It emitted SafeSetup and ProxyCreation from a canonical factory, and
  • Threshold ≥ your DAO policy (e.g., ≥ 2), and
  • It’s referenced in your DAO registry (optional, for strictness). This labeler feeds the balance‑change detector so you only track relevant safes. (gnosisscan.io)

Computing ETH deltas robustly

  • Ethereum mainnet path (preferred): sum trace
    action.value
    where
    to == safe
    minus where
    from == safe
    for all Call‑type traces in the tx/block window. Forta’s TransactionEvent.traces exposes OpenEthereum trace payloads. (docs.forta.network)
  • Cross‑chain fallback: snapshot
    getBalance(safe, blockTag)
    at N and N‑1; delta = bal(N)−bal(N‑1). Do this per block in a handleBlock or per transaction that touches the safe.
  • Hygiene:
    • Collapse multiple txs per block into a single delta to avoid alert spam.
    • Attribute source: if a single tx triggered net outflows > X (policy), include tx hash.
    • On L2s, treat fee‑related minuscule dust deltas as noise; maintain a floor (e.g., 1e14 wei) configurable per chain.

Severity and anomaly

  • Fixed thresholds for operational paging (e.g., high severity if outflow > 1% of treasury or > Y ETH).
  • Anomaly scoring via Forta’s Time Series Analyzer template on rolling windows per safe; trigger if z‑score > K for absolute or directionally consistent deltas. (docs.forta.network)

Example: alert schema

{
  "name": "DAO-Multisig-ETH-Balance-Change",
  "alertId": "DAO-ETH-DELTA",
  "type": "Info|Suspicious",
  "severity": "Medium|High|Critical",
  "protocol": "safe",
  "metadata": {
    "safe": "0x...",
    "chainId": "1",
    "blockNumber": "20123456",
    "deltaWei": "-345000000000000000",    // negative == outflow
    "balanceBeforeWei": "123450000000000000000",
    "balanceAfterWei": "123105000000000000000",
    "txCountInBlock": "3",
    "largestTxHash": "0x...",
    "largestTxDeltaWei": "-300000000000000000",
    "methodHints": "execTransaction|transfer",
    "labelSource": "SafeSetup+ProxyCreation"
  }
}

Implementation sketch (hybrid traces + balance snapshots)

import { Finding, FindingSeverity, FindingType, ethers } from "forta-agent";

const DAOSafes = new Set<string>(); // populated by your labeler
const provider = getEthersProvider();

export async function handleBlock(blockEvent) {
  const chainId = blockEvent.network.chainId;
  const findings: Finding[] = [];

  for (const safe of DAOSafes) {
    const [before, after] = await Promise.all([
      provider.getBalance(safe, blockEvent.blockNumber - 1),
      provider.getBalance(safe, blockEvent.blockNumber)
    ]);
    const delta = after.sub(before);
    if (delta.abs().gte(ethers.BigNumber.from("100000000000000000"))) { // >= 0.1 ETH
      findings.push(Finding.fromObject({
        name: "DAO-Multisig-ETH-Balance-Change",
        alertId: "DAO-ETH-DELTA",
        type: FindingType.Info,
        severity: delta.isNegative() ? FindingSeverity.Medium : FindingSeverity.Low,
        protocol: "safe",
        metadata: {
          safe, chainId: String(chainId),
          blockNumber: String(blockEvent.blockNumber),
          deltaWei: delta.toString(),
          balanceBeforeWei: before.toString(),
          balanceAfterWei: after.toString()
        }
      }));
    }
  }
  return findings;
}

export async function handleTransaction(txEvent) {
  // Optional mainnet trace-enhanced path: sum call values to attribute largest tx in block
  // Requires txEvent.traces (only mainnet provided by scan nodes)
  // Aggregate per safe per block in a cache to enrich the block-level alert.
  return [];
}

Reference: Forta SDK surface for TransactionEvent/BlockEvent, traces availability, and testing guidance. (docs.forta.network)


Production hardening for Forta detections

  • Execution ceilings: Forta enforces ~30s per handler; move heavy I/O to async tasks and cache findings between blocks. (docs.forta.network)
  • Throughput and coverage: sharding via CLI when monitoring thousands of Safes across chains; split by block ranges or address partitions and avoid duplicate coverage. (docs.forta.network)
  • Staking and slashing: bots must remain reliable; follow Forta’s slashing policy (resource abuse, malformed findings, malicious behavior can be penalized). (docs.forta.network)
  • Compose with existing bots: subscribe to the OpenZeppelin‑Gnosis Safe events bot for broader coverage, then feed your base alerts into the Attack Detector combiner to raise precision during multi‑stage attacks. (docs.forta.network)
  • Delivery to ops: wire Forta alerts to OpenZeppelin Defender or your SIEM; Compound’s public precedent shows multisig monitors feeding Discord/Defender pipelines. (github.com)

Practical heuristics that reduce false positives

  • Factory/singleton allowlists per chain: Validate
    ProxyCreation
    against known SafeProxyFactory addresses and vetted singleton versions (e.g., 1.3.x, 1.4.1). (etherscan.io)
  • Fallback handler sanity: alert on handler=0x0, handler=self, or unknown unverified contracts; Safe docs detail handler change events. (docs.safe.global)
  • Classification of ETH deltas:
    • Deposit vs. withdrawal vs. refund: on mainnet, attribute using traces; else, tag deltas > threshold without attribution.
    • Filter repetitive dust deltas (gas refunds) via per‑chain floors.
    • Batch suppression: one alert per block per safe with the largest tx hash recorded.
  • DAO policy alignment: severity escalations for trespass beyond treasury policy (e.g., outflow > 1% AUM or > X ETH in a single block) and for misconfig at setup.

Best emerging practices we recommend (2026)

  • Inventory first: use Safe’s “Verify Safe creation” guidance to auto‑build your DAO multisig catalog per chain, then enforce SafeSetup policies across that catalog. (help.safe.global)
  • Treat SafeSetup with the same rigor as prod deploys: require change review when initializer enables modules/guards at creation; many attacks ride on mis‑set modules or permissive guards.
  • Enrich balance‑change alerts with governance context: if a multisig executes within a few blocks of a passed on‑chain proposal (e.g., ENS working group budget transfers), downgrade severity; otherwise escalate as unexpected. (docs.ens.domains)
  • Adopt anomaly detection in addition to fixed thresholds: Forta Time Series Analyzer templates let you baseline per‑safe behavior and catch unusual liquidity moves even when they’re small in absolute terms. (docs.forta.network)
  • Learn from established users: Balancer and Compound illustrate how DAOs mix operational and security monitoring via Forta; reuse their pattern—bot suites, dashboards, and community‑visible alert channels. (forta.org)

Concrete runbook examples

  1. Immediate misconfig on SafeSetup

    • Trigger: threshold=1 or unknown fallbackHandler
    • Action: pause fund ingress (ops policy), open an incident, require a corrective owner/threshold change transaction.
    • Signal sources: SafeSetup log + ChangedFallbackHandler event (if applicable). (gnosisscan.io)
  2. Unscheduled outflow

    • Trigger: ETH outflow > 500 ETH from treasury Safe in a single block, not tied to an approved proposal or streaming payment
    • Action: page on‑call, post to community “alerts” channel, and—if your protocol supports it—engage pause/guardian or timelock veto process. Compound’s community multisig monitor shows this operational model in practice. (7blocklabs.com)
  3. Multi‑stage threat correlation

    • Combine: received Tornado‑funded EOA interacts with treasury Safe module + large ETH outflow within 30 minutes → High‑precision Attack Detector alert mapped to Preparation → Exploitation phases. (docs.forta.network)

Testing, scale, and operations

  • Local dev: use forta‑agent CLI with unit tests and mock events; enable traces locally via a provider that supports OpenEthereum trace module. (docs.forta.network)
  • Performance: shard large safe sets; partition by address hash mod N; ensure idempotency across shards. (docs.forta.network)
  • Long‑running tasks: paginate large owner lists or historical backfills asynchronously; cache findings and flush in subsequent blocks. (docs.forta.network)

Bonus: high‑signal enrichments to add on day one

  • Owner churn alerts:
    AddedOwner/RemovedOwner/ChangedThreshold
    with diffs and signer reputation scores. (gnosisscan.io)
  • Module guardrail:
    EnabledModule/DisabledModule
    deltas with allow/deny lists of modules (e.g., Zodiac Reality/Delay vs. unknown modules).
  • Reconciliation hints: if your treasury accounting knows scheduled disbursements, auto‑tag alerts as “expected vs. unexpected” to reduce pager fatigue.
  • Public transparency: Like Balancer and Compound, publish a public alerts feed; it builds stakeholder trust and crowdsources review. (forta.org)

Putting it all together: minimal rollout plan (2 weeks)

  • Day 1–2: Build/enable labeler from ProxyCreation+SafeSetup and create DAO multisig inventory per chain. (docs.safe.global)
  • Day 3–5: Ship SafeSetup detector with policy checks (threshold, handler, initializer).
  • Day 6–9: Ship ETH balance change detector with trace attribution on mainnet and snapshot fallback elsewhere; set absolute thresholds + baseline anomaly.
  • Day 10–12: Integrate with Attack Detector combiner and wire to Defender/Slack/PagerDuty; add dashboards. (docs.forta.network)
  • Day 13–14: Shard for throughput; tune severities; publish community‑visible alert channels with clear runbooks. (docs.forta.network)

Key references and signatures at a glance

  • SafeSetup event definition and real logs showing topic and params; Safe contract sources list other governance‑critical events to subscribe to. (gnosisscan.io)
  • ProxyCreation event on SafeProxyFactory (1.3.x, 1.4.1) and Safe’s “verify creation” guidance. (etherscan.io)
  • Forta SDK handlers, traces availability per chain, testing, sharding, and long‑running tasks patterns. (docs.forta.network)
  • OpenZeppelin‑Gnosis Safe events bot, Time Series Analyzer template, Attack Detector combiner. (docs.forta.network)
  • Case studies: Balancer and Compound using Forta; operational alignment for DAO monitoring. (forta.org)
  • Governance context example (ENS working group budgets) for downgrading “expected” outflows. (docs.ens.domains)

Final word for decision‑makers

If your organization runs on a Safe treasury, you want three things the moment a multisig comes online: confidence that it was set up correctly, continuous awareness of ETH moving in/out, and correlation to governance/intel so you page only when it matters. SafeSetup and DAO‑Multisig‑ETH‑Balance‑Change are the fastest, most leverage‑yielding Forta detectors to deploy toward that outcome—and, done right, they’re cheap to operate, resistant to false positives, and easy to scale across every chain where you keep capital.

Like what you're reading? Let's build together.

Get a free 30‑minute consultation with our engineering team.

Related Posts

7BlockLabs

Full-stack blockchain product studio: DeFi, dApps, audits, integrations.

7Block Labs is a trading name of JAYANTH TECHNOLOGIES LIMITED.

Registered in England and Wales (Company No. 16589283).

Registered Office address: Office 13536, 182-184 High Street North, East Ham, London, E6 2JA.

© 2025 7BlockLabs. All rights reserved.