ByAUJay
“Safesetup” DAO‑Multisig and “DAO‑Multisig‑ETH‑Balance‑Change”: Forta Detection Engineering Essentials
A Hands-On, Technical Guide to Building and Scaling Key Forta Detections for DAO Treasuries
Let's dive into how to design, launch, and scale two super valuable Forta detections for DAO treasuries: SafeSetup (which deals with Gnosis Safe initialization) and DAO-Multisig-ETH-Balance-Change (tracking native ETH changes). We'll break it down with clear event signatures, unique chain quirks, and solid production hardening steps to ensure you're set up for top-notch security in 2026.
For anyone in a decision-making role, this post will help you understand how to transform raw on-chain signals into effective risk reduction and quicker responses to incidents.
TL;DR (description)
- Keeping an eye on Gnosis Safe “SafeSetup” events and tracking DAO multisig ETH balance shifts across both L1 and L2 can help you spot misconfigurations early and catch any odd treasury movements before they become a bigger issue. This guide lays out the specific event topics, engineering patterns, alert schemas, and production scaling strategies needed to put these detections into action using Forta.
Why these two detections matter in 2026
- Safe has really become the go-to smart account for DAO treasuries and institutions. Even the Ethereum Foundation got on board, moving its entire $650 million treasury to a Safe multisig back in January 2026, following months of testing. This definitely raises the stakes for Safe in terms of telemetry and catching misconfigurations with new creations and treasury flows. (theblock.co)
- More established DAOs are using Forta for ongoing security and operational checks (like Compound’s multisig and governance monitors, which are pretty well-known), so it makes sense to standardize treasury-grade detectors that fit right into how these top teams are already working. (7blocklabs.com)
- The Forta ecosystem is packed with ready-to-use building blocks, like the OpenZeppelin-Gnosis Safe event bot, Attack Detector combiner, and Time Series Analyzer. These tools help transform low-level signals into precise alerts and actionable runbooks. (docs.forta.network)
Detector 1: “SafeSetup” DAO‑Multisig
What exactly are we detecting?
The Safe contract gives a shoutout with a SafeSetup event whenever a new Safe is set up:
- Event signature:
SafeSetup(address indexed initiator, address[] owners, uint256 threshold, address initializer, address fallbackHandler) - Canonical topic (keccak256 of signature):
0x141df868a6331af528e38c83b7aa03edc19be66e37ae67f9285bf4f8e3c6a1a8 - Here’s a verified example from a Safe creation transaction that shows off the owners array, threshold, and fallbackHandler all in action, plus it also triggered a ProxyCreation event. Check it out on gnosisscan.io.
Strong correlation: the new Safe proxies are deployed by SafeProxyFactory and they emit ProxyCreation(SafeProxy indexed proxy, address singleton). To minimize spoofing, make sure to filter factories by their canonical versions, like Safe Proxy Factory 1.3.0 or 1.4.1. You can check out more details on this etherscan.io.
Why SafeSetup alerts are high value for DAOs
- Catch misconfigurations early: Set thresholds of 1 for treasury safes, keep an eye on unknown fallback handlers, and watch out for any suspicious initializers before any funds start flowing in. The fallback handler can be super powerful, but it can also be a security risk if mishandled. So, be on the lookout for non-standard handlers or if you see patterns like
handler=self. Check out more info here. - Create a solid inventory of DAO safes across different chains: You can do this by linking SafeSetup with ProxyCreation and verified factory addresses. This inventory is key for monitoring any changes in ownership and tracking fund movements, all while making sure everything is labeled correctly. For more details, take a look here.
Precision engineering checklist
- Event Source Authenticity
- Make sure to filter for the known SafeProxyFactory addresses for each chain. Then, check that the
singletonmatches with recognized Safe master copies (or stick to a trusted allowlist for each DAO), following Safe's verification tips. (help.safe.global)
- Make sure to filter for the known SafeProxyFactory addresses for each chain. Then, check that the
2. Extract and Normalize Parameters
- Owners: Start with the canonical checksum and deduplicate the data. If you're keeping a signer registry, make sure to map those to known signers.
- Threshold: Set up some immediate policy checks. For example, “treasury safes must have at least a 3-of-5 setup.”
- Fallback Handler: You'll want to verify against trusted addresses and keep an eye out for any 0x0 or unknown contracts. Remember, the Safe will emit
ChangedFallbackHandler(address)when there are changes down the line--so make sure to subscribe to that event as well. Check out the details here: docs.safe.global.
3. Suspicion Heuristics at Setup Time
- Keep that threshold under 2 for a DAO treasury Safe.
- Owners should definitely include EOAs that are marked as high-risk or flagged by your intel feeds.
- Watch out for a non-zero
initializer--this one lets modules or guards kick in right away without a review. - If the fallback handler is pointing to an unverified address or even to itself, that’s a red flag (the GS400 guard in the code highlights the issue of handler=self). (gnosisscan.io)
4. Correlate with ProxyCreation in the Same Transaction
- You need to check for
ProxyCreation(proxy, singleton)happening within N blocks of the SafeSetup, ensuring thatproxy == log.address. This approach helps to minimize false positives and makes it easier to label entities. (docs.safe.global)
5. Canonical Safe Events to Keep an Eye On After Setup
Here are some key events you should watch for:
- OwnerManager: Look out for
AddedOwner,RemovedOwner, andChangedThreshold. - ModuleManager: Watch for
EnabledModuleandDisabledModule. - GuardManager: Keep track of
ChangedGuard. - FallbackManager: Don’t miss
ChangedFallbackHandler.
You can either track all these as separate detections or spice up SafeSetup by adding a “subscribed signals” list. Check out more details at 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:
- Make sure to use the Safe docs' factory and event references to keep your factory allowlist up to date. You can check them out here.
- If you're looking to move quickly with prototyping or just need some coverage, you can also subscribe to the OpenZeppelin‑Gnosis Safe Contract Events base bot and whip up a combiner. But if you really want to tailor things to fit your DAO's specific policies, custom parsing is the way to go when setting it all up. You can find more details here.
Detector 2: “DAO‑Multisig‑ETH‑Balance‑Change”
What exactly are we detecting?
A streamlined, chain-friendly alert that pings you whenever there's a change in a labeled DAO multisig's native ETH balance. This includes:
- Direct ETH transfers
- Internal value shifts from execTransaction, module calls, and refunds
- L2 details (like sequencer fees and the fact that the base asset remains ETH on major EVM L2s)
Why it’s tricky:
- ETH transfers don’t generate ERC‑20 logs, so you’ll need to pull together traces and/or snapshot balances by block.
- Forta scan nodes give you trace data for the Ethereum mainnet, but for other chains, you might find the traces are empty--so you’ll have to revert to using
eth_getBalancefor diffing. (docs.forta.network)
Labeling scope: what counts as “DAO multisig”?
Use a labeler to tag an address as DAO‑SAFE when:
- It emits SafeSetup and ProxyCreation from a canonical factory, and
- The Threshold is greater than or equal to your DAO policy (like, say, ≥ 2), and
- It’s included in your DAO registry (this one’s optional, but it adds a layer of strictness).
This labeler is pretty handy since it feeds into the balance‑change detector, helping you keep an eye on just the safes that matter. Check it out here: (gnosisscan.io).
Computing ETH deltas robustly
- Ethereum Mainnet Path (Preferred): To calculate the net value for a safe, take the sum of
action.valuewhereto == safe, and subtract the sum wherefrom == safefor all Call-type traces within the transaction or block window. You can find the OpenEthereum trace payloads using Forta’s TransactionEvent.traces. Check out the details here. - Cross-Chain Fallback: For each block, snapshot
getBalance(safe, blockTag)at the current block (N) and the previous one (N-1). The delta would be calculated as bal(N)−bal(N-1). You can do this in a handleBlock process or per transaction that interacts with the safe. - Hygiene:
- To keep things tidy, combine multiple transactions per block into a single delta. This helps cut down on alert spam.
- For attribution, if a single transaction causes net outflows greater than X (based on your policy), make sure to include the transaction hash.
- On Layer 2s, consider those tiny fee-related dust deltas as background noise. It’s a good idea to set a floor (like 1e14 wei) that you can configure according to each chain.
Severity and anomaly
- Set up fixed thresholds for operational alerts, like marking it as high severity if outflow is greater than 1% of the treasury or exceeds Y ETH.
- Use Forta’s Time Series Analyzer template for scoring anomalies by analyzing rolling windows per safe. Trigger an alert when the z-score is greater than K for either absolute changes or consistent directional deltas. Check it out here: (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 [];
}
Check out the Forta SDK resources for TransactionEvent/BlockEvent, availability of traces, and some helpful testing tips. You can find everything you need right here: (docs.forta.network)
Production hardening for Forta detections
- Execution ceilings: Forta keeps things efficient with a ~30s limit per handler. If you’ve got heavy I/O, consider moving those tasks to async and caching your findings between blocks. Check it out here.
- Throughput and coverage: When you're monitoring thousands of Safes across different chains, sharding via CLI is the way to go! You can split by block ranges or address partitions to avoid any duplicate coverage. More details here.
- Staking and slashing: Keeping your bots reliable is super important! Make sure you follow Forta's slashing policy since resource abuse, malformed findings, or any malicious behavior could land you in hot water. Find the policy details here.
- Compose with existing bots: Want broader coverage? Subscribe to the OpenZeppelin-Gnosis Safe events bot, then integrate your alerts into the Attack Detector combiner. This combo can seriously boost your precision during those tricky multi-stage attacks. Dive into the specifics here.
- Delivery to ops: Make sure to wire Forta alerts to OpenZeppelin Defender or your SIEM. A great example to look at is Compound's public setup, which shows how multisig monitors can feed alerts into Discord/Defender pipelines. Take a peek at their approach here.
Practical heuristics that reduce false positives
- Factory/Singleton Allowlists per Chain: Make sure to validate
ProxyCreationagainst known SafeProxyFactory addresses and only approved singleton versions, like 1.3.x or 1.4.1. You can check it out here. - Fallback Handler Sanity: Keep an eye on any handlers set to 0x0, point to self, or are from unknown unverified contracts. The Safe documentation has some detailed info on handler change events, which you can find here.
- Classification of ETH Deltas:
- When it comes to deposits, withdrawals, and refunds on the mainnet, use traces to attribute them. If you're not on mainnet, just tag any deltas over a certain threshold without specifics.
- Don’t forget to filter out those repetitive dust deltas (you know, the gas refunds) using per-chain floors.
- For batch suppression, let’s stick to one alert per block for each safe, making sure to record the largest transaction hash.
- DAO Policy Alignment: We need to escalate the severity for any actions that breach the treasury policy, like if there's an outflow greater than 1% of AUM or more than X ETH in a single block. Also, keep an eye out for any misconfigurations during setup.
Best emerging practices we recommend (2026)
- First things first: check out Safe's "Verify Safe creation" guide to automatically create your DAO multisig catalog for each chain. After that, make sure to apply SafeSetup policies throughout that catalog. You can find the guide here.
- Treat SafeSetup like you would a production deployment. Make it a rule to review changes whenever an initializer enables modules or guards during creation. A lot of attacks happen due to poorly set modules or overly permissive guards, so staying vigilant is key.
- When you get balance-change alerts, add some governance context! If a multisig action happens shortly after a passed on-chain proposal (like budget transfers for the ENS working group), consider it lower priority. But if not, treat it as something unexpected and escalate it. Check out more on this here.
- Don't just stick to fixed thresholds--embrace anomaly detection too! The Forta Time Series Analyzer templates are great for understanding typical behavior for each safe and can help you spot unusual liquidity movements, even if they seem small at first. More info can be found here.
- Take a page from the playbook of some experienced users: Balancer and Compound show how DAOs can blend operational and security monitoring using Forta. Try to adopt their approach by implementing bot suites, dashboards, and alert channels that the community can see. Dive into their insights here.
Concrete runbook examples
- Quick Misconfig on SafeSetup
- Trigger: If the threshold is set to 1 or there's an unknown fallbackHandler.
- Action: Pause fund ingress according to ops policy, open an incident, and require a corrective owner or adjust the threshold change transaction.
- Signal Sources: Check the SafeSetup log and the ChangedFallbackHandler event (if it applies). You can find more details on Gnosis Scan.
2. Unscheduled Outflow
- Trigger: If you see more than 500 ETH flowing out of the treasury Safe in a single block, and it’s not linked to an approved proposal or a regular payment, that’s a red flag.
- Action: First up, alert the on-call team, then share the news in the community “alerts” channel. If your protocol allows it, you should also kick off the pause/guardian or timelock veto process. For a real-world example of how this all works, check out Compound’s community multisig monitor. (7blocklabs.com)
3. Multi-stage threat correlation
- Here’s the scoop: when the Tornado-funded EOA comes into play and starts interacting with the treasury Safe module, plus we spot a big ETH outflow happening within half an hour, it triggers a high-precision Attack Detector alert. This alert gets linked right to the Preparation and Exploitation phases. Check out the details over at (docs.forta.network).
Testing, scale, and operations
- Local dev: Kick things off with the forta‑agent CLI, and don't forget to run those unit tests with mock events. To enable traces locally, you’ll want to use a provider that supports the OpenEthereum trace module. Check out the full details here.
- Performance: For optimal performance, split those big safe sets into smaller shards. You can do this by partitioning them according to address hash mod N. Just remember to keep things idempotent across those shards. More info can be found here.
- Long‑running tasks: When dealing with large owner lists or doing historical backfills, make sure to paginate them asynchronously. It's also a good idea to cache your findings and flush them in the next blocks. You can learn more about this here.
Bonus: high‑signal enrichments to add on day one
- Owner churn alerts: You’ll get notifications for
AddedOwner/RemovedOwner/ChangedThresholdalong with diffs and signer reputation scores. Check it out: (gnosisscan.io). - Module guardrail: We’re tracking
EnabledModule/DisabledModulechanges, complete with allow/deny lists of modules (like Zodiac Reality/Delay versus those unknown modules). - Reconciliation hints: If your treasury accounting has a handle on scheduled disbursements, set alerts to auto-tag as “expected vs. unexpected.” This should help cut down on pager fatigue.
- Public transparency: Just like Balancer and Compound, consider launching a public alerts feed. It’s a great way to build trust with stakeholders and encourages community review. More info here: (forta.org).
Putting it all together: minimal rollout plan (2 weeks)
- Day 1-2: Kick things off by getting the labeler up and running through ProxyCreation and SafeSetup. Also, don’t forget to set up the DAO multisig inventory for each chain. You can check out the details here.
- Day 3-5: Time to roll out the SafeSetup detector! Make sure it has those essential policy checks for threshold, handler, and initializer.
- Day 6-9: Let's get the ETH balance change detector up on mainnet, complete with trace attribution and a snapshot fallback for other networks. We’ll set some absolute thresholds and baseline anomalies too.
- Day 10-12: Integrate everything with the Attack Detector combiner and link it all up to Defender, Slack, and PagerDuty. Don’t forget to throw in some dashboards for good measure. More info can be found here.
- Day 13-14: We need to shard for better throughput and fine-tune those severities. Finally, let’s publish some community-facing alert channels with clear runbooks so everyone knows what’s up. Check out the details here.
Key references and signatures at a glance
- Check out the SafeSetup event definition along with real logs that show the topic and parameters. You can also find a list of other governance-critical events to subscribe to in the Safe contract sources. Take a look here: (gnosisscan.io)
- Don’t miss the ProxyCreation event on the SafeProxyFactory (1.3.x, 1.4.1) and some handy “verify creation” guidance from Safe. Find out more at: (etherscan.io)
- If you're interested in Forta SDK, you'll want to look into handlers, how traces are available per chain, and patterns for testing, sharding, and long-running tasks. Check it out here: (docs.forta.network)
- There's also the OpenZeppelin-Gnosis Safe events bot, along with the Time Series Analyzer template and the Attack Detector combiner that you should explore. You can dive into the details here: (docs.forta.network)
- For some real-world insights, check out the case studies on Balancer and Compound using Forta, plus how they align operations for DAO monitoring. More info is available here: (forta.org)
- Finally, there's an example of governance context with the ENS working group budgets, which focuses on downgrading those “expected” outflows. You can read about it here: (docs.ens.domains)
Final word for decision‑makers
If your organization is using a Safe treasury, there are three key things you need as soon as your multisig is up and running: first, you want to be sure it was set up properly; second, you need to keep an eye on ETH as it moves in and out; and third, you want it connected to governance and intel so you’re only alerted when it really matters.
For that, SafeSetup and DAO‑Multisig‑ETH‑Balance‑Change are your go-to Forta detectors. They’ll help you achieve your goals quickly and efficiently, and when implemented correctly, they're inexpensive to run, minimize false alarms, and can easily be scaled across all the chains where you hold your assets.
Get a free security quick-scan of your smart contracts
Submit your contracts and our engineer will review them for vulnerabilities, gas issues and architecture risks.
Related Posts
ByAUJay
Building 'Bio-Authenticated' Infrastructure for Secure Apps When it comes to keeping our applications safe, using bio-authentication is a game changer. This method relies on unique biological traits, like fingerprints or facial recognition, which adds a whole new layer of security. By integrating bio-authentication into our infrastructure, we can ensure that only the right people have access to sensitive information. So, what exactly does bio-authentication look like in action? Think about it: instead of juggling passwords or worrying about someone guessing your security questions, you’re simply using your own unique features to log in. It’s not only convenient but also super secure. The road to creating this bio-authenticated infrastructure isn’t just about implementing tech; it's also about making sure it’s user-friendly. We want people to feel comfortable and confident using these systems. With advancements in technology, the future is looking bright for secure applications. By focusing on bio-authentication, we’re paving the way for safer digital experiences.
Hey everyone, exciting news! Bio-authenticated infrastructure is finally making its debut! Back in January 2026, WebAuthn Level 3 reached the W3C Candidate Recommendation stage, and NIST has put the finishing touches on SP 800-63-4. And with passkeys coming into the mix, we can look forward to smoother logins and a big drop in support calls. Just a heads up--don’t forget to roll those out!
ByAUJay
Protecting High-Value Transactions from Front-Running
Front-running protection for high-value on-chain transactions is a must-have for enterprise treasuries these days. Our strategy brings together private order flow, encrypted mempools, batch auctions, and Solidity hardening to completely seal off any potential leak paths while keeping everything secure.
ByAUJay
Making Sure Your Upgradable Proxy Pattern is Free of Storage Issues
Quick rundown: When it comes to upgradeable proxies, storage collisions can cause all sorts of sneaky headaches--think data corruption, dodging access controls, and throwing audits into chaos. This playbook is your essential buddy for identifying these tricky issues, steering clear of them, and safely migrating with tools like EIP-1967, UUPS, and ERC-721.

