Crypto Training
ERC-7579 vs Safe Modules: Deep Architecture, Ecosystem, and Security Tradeoffs
A code-first deep dive into Safe modules, Zodiac, ERC-7579 architecture, and major module implementations (Safe7579, Kernel, Nexus, OpenZeppelin, Rhinestone Core). Focused on feature power versus security risk with concrete Solidity references and dense Mermaid diagrams.
Smart-account modularity has split into two major lineages:
- Safe-native module architecture (and the Zodiac ecosystem built around it).
- ERC-7579 modular account standardization (cross-vendor interfaces for validators/executors/fallback/hooks).
Both lineages solve the same product problem: ship account features without redeploying a new account implementation for every new capability.
Both also create the same security problem: every extension point can become a privilege-escalation point.
This post is a deep technical comparison of those systems, with Solidity-level references, practical ecosystem mapping, and a risk-first model for auditors and wallet engineers.
Scope and methodology#
I reviewed local source snapshots from cloned repositories and pinned references to exact commits.
Primary standards/docs#
- ERC-7579 spec: https://eips.ethereum.org/EIPS/eip-7579
- ERC-7579 hub: https://erc7579.com/
- Safe ERC-7579 docs overview: https://docs.safe.global/advanced/erc-7579/overview
- Safe + ERC-7579 architecture: https://docs.safe.global/advanced/erc-7579/7579-safe
- Safe 7579 tutorial: https://docs.safe.global/advanced/erc-7579/tutorials/7579-tutorial
- Safe module explainer: https://help.safe.global/en/articles/40827-what-is-a-module
- Safe UI constraints for modules/guards: https://help.safe.global/en/articles/40803-why-can-t-i-add-modules-and-transaction-guards-to-my-safe-via-the-ui
- Safe module add flow: https://help.safe.global/en/articles/40826-add-a-module
- Safe v1.5.0 module guards release: https://safe.global/blog/introducing-safe-v1-5-0-module-guards-enhanced-smart-account-features
Repositories and pinned commits#
safe-global/safe-smart-account@dc437e8fba8b4805d76bcbd1c668c9fd3d1e83berhinestonewtf/safe7579@f22a194148ff087f0c16125e530512e59794e188erc7579/erc7579-implementation@16138d1afd4e9711f6c1425133538837bd7787b5zerodevapp/kernel@6a098bc8f9a7001fe7ae801368e96a5ee635ddb1bcnmy/nexus@7db9b00b7288eaefbe0124abd9ed2daa3f4ae2ccOpenZeppelin/openzeppelin-community-contracts@a12b30ca7affe3320777378eddf2d0cebae8c5b2rhinestonewtf/core-modules@1f97c2920a17a43359413d8616a8228100c9f71agnosisguild/zodiac-modifier-roles@8c80d40b8b1354d1d3c5d2ee9d399a214fc4c790gnosisguild/zodiac-module-exit@2720c7fa990842b9ea58f5b85aeb8769aff21331
Evolution of ideas#
Why this evolution happened#
- Safe modules proved that account extension points are operationally powerful.
- But Safe-native modules are Safe-specific, so portability across account vendors was weak.
- ERC-7579 standardized only the minimal interoperability surfaces: execute/config/fallback/module interfaces and module types.
- The ecosystem then split cleanly:
- Account vendors compete on implementation and UX.
- Module vendors compete on reusable security and feature modules.
Mental model: same goal, different abstraction layer#
Safe modules deep dive#
Safe’s module architecture is still one of the cleanest production-grade modular account designs.
Core Safe module machinery#
- Module linked-list management:
enableModule,disableModule,isModuleEnabled- https://github.com/safe-global/safe-smart-account/blob/dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be/contracts/base/ModuleManager.sol
- Module execution lane:
execTransactionFromModule,execTransactionFromModuleReturnData- same file as above.
- Transaction guard (classic Safe tx path):
- Module guard (v1.5.0 extension):
setModuleGuard, pre/post checks around module execution- module manager file above.
- Fallback manager:
- stores fallback handler in dedicated slot
- appends caller to calldata in fallback forwarding
- explicitly blocks setting handler to
address(this)due selector-confusion footgun - https://github.com/safe-global/safe-smart-account/blob/dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be/contracts/base/FallbackManager.sol
Feature-value in Safe modules#
- Very direct execution path for trusted modules.
- Strong production hardening and battle-tested tooling.
- Explicit guard insertion points for policy enforcement.
- Simple mental model for signers, modules, and fallback.
Risk surface in Safe modules#
- Module trust is absolute: enabled modules can become de facto superusers.
- Linked-list management complexity: operational mistakes can leave stale or unexpected module state.
- Fallback abuse risk: handler mistakes can open privileged internal call reachability.
- Guard assumptions: if teams assume guard coverage where none exists, control gaps emerge.
Zodiac as Safe module specialization#
Zodiac shows what happens when Safe modules are treated as composable middleware.
Roles Modifier (zodiac-modifier-roles)#
- Core contract:
- Permission engine:
Key idea: scoped capability graphs, not just yes/no module rights.
Risk tradeoff:
- Feature: granular and expressive authorization.
- Risk: condition-tree complexity creates policy-audit burden and misconfiguration risk.
Exit Module (zodiac-module-exit)#
- Base:
- ERC20 flavor:
Key idea: controlled proportional exits from avatar-managed treasury.
Risk tradeoff:
- Feature: explicit ragequit-like mechanism.
- Risk: denominator/source-of-truth assumptions (circulating supply contracts, token ordering constraints, denylist governance).
ERC-7579: what was standardized (and what was intentionally not)#
ERC-7579 is intentionally minimal.
- Mandatory account interfaces for execution/config/module management.
- Module types with typed install/uninstall semantics.
- Optional hook extension.
- Explicit fallback behavior expectations with ERC-2771 sender append semantics.
Spec reference: https://eips.ethereum.org/EIPS/eip-7579
The key design choice#
ERC-7579 standardized interfaces and behavior envelopes, not specific storage layouts or nonce/signature encoding schemes.
That is why Kernel, Nexus, Safe7579, and reference implementations all look different internally while still being recognizably ERC-7579 systems.
Safe modules vs ERC-7579 modules: precise differences#
| Dimension | Safe-native modules | ERC-7579 modules |
|---|---|---|
| Interop target | Safe ecosystem | Cross-account vendor ecosystem |
| Module typing | Safe-specific semantics | Standardized type IDs (validator/executor/fallback/hook + extensions) |
| Entry abstraction | execTransactionFromModule* | execute, executeFromExecutor, typed config |
| Fallback expectations | Safe fallback handler pattern | Selector-routed fallback modules + ERC-2771 append requirement |
| Hook semantics | Guard model and optional patterns | Standardized hook extension (preCheck/postCheck) |
| Validation composition | Safe signature model + optional modules | Validator modules as first-class standardized type |
| Upgrade path | Safe account/version roadmap | Vendor-specific, often proxy/UUPS with module ecosystem portability |
Implementation deep dives#
1) Safe7579 (Safe adapter)#
Repository: https://github.com/rhinestonewtf/safe7579
Key contracts:
Safe7579.sol: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/Safe7579.solcore/ModuleManager.sol: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/core/ModuleManager.solSafe7579Launchpad.sol: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/Safe7579Launchpad.sol
Notable features#
- Safe-backed
executeandexecuteFromExecutorwith mode decoding. - Validator selection from nonce high bits during
validateUserOp. - Fallback signature route to Safe
checkSignatureswhen validator is unset/uninstalled. - Selector-routed fallback modules with ERC-2771 appended sender semantics.
- Global hook wrapping and dedicated prevalidation hooks for ERC-4337 and ERC-1271.
- Emergency hook uninstall timelock mechanism.
- Launchpad lifecycle for safe setup under 4337 flow (
preValidationSetup->validateUserOp->setupSafe).
Risk lens#
- Strong feature velocity through adapter abstraction.
- Risk shifts to composition correctness across Safe semantics + 7579 semantics.
- Prevalidation hooks and fallback handlers are powerful and can create DoS/authorization bugs if misused.
2) ERC-7579 reference implementation#
Repository: https://github.com/erc7579/erc7579-implementation
Key contracts:
MSAAdvanced.sol: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.solcore/ModuleManager.sol: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/core/ModuleManager.solcore/HookManager.sol: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/core/HookManager.solcore/PreValidationHookManager.sol: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/core/PreValidationHookManager.sol- Interface: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/interfaces/IERC7579Module.sol
Important caveat#
The repository explicitly says it is not audited and not recommended for production use as-is.
Why it matters anyway#
It is the clearest map of core mechanics:
- explicit module-type branching in install/uninstall
- linked-list validator/executor stores
- selector-based fallback routing with sender append
- single-hook model + split prevalidation hook model
- vendor-choice examples (validator-in-nonce encoding marked as implementation-specific)
3) Kernel (ZeroDev)#
Repository: https://github.com/zerodevapp/kernel
Key contracts:
Kernel.sol: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/Kernel.solcore/ValidationManager.sol: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/core/ValidationManager.solcore/SelectorManager.sol: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/core/SelectorManager.soltypes/Constants.sol: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/types/Constants.sol
Architecture character#
Kernel is a full policy engine, not just a module host.
- Validation mode/type/id encoding in nonce.
- Root validator + validator + permission + 7702 branches.
- Selector grants bound to validation identifiers.
- Permission mode with signer + policy chains.
- Replayable signature lane (
MAGIC_VALUE_SIG_REPLAYABLE). - Sentinel hook constants with distinct semantics (
address(0),address(1),HOOK_ONLY_ENTRYPOINT).
Risk lens#
- Extremely powerful composition model.
- Security complexity is high: policy graphs, selector mapping, nonce modes, and hook sentinels are easy to misconfigure.
- At this pinned commit,
Kernel.uninstallModulefallback branch appears to call_clearSelectorData(selector)without capturing the returnedtarget, then checks an unassigned localtarget. That pattern deserves immediate manual verification and regression testing in downstream forks.
4) Nexus (Biconomy)#
Repository: https://github.com/bcnmy/nexus
Key contracts:
Nexus.sol: https://github.com/bcnmy/nexus/blob/7db9b00b7288eaefbe0124abd9ed2daa3f4ae2cc/contracts/Nexus.solbase/ModuleManager.sol: https://github.com/bcnmy/nexus/blob/7db9b00b7288eaefbe0124abd9ed2daa3f4ae2cc/contracts/base/ModuleManager.solbase/BaseAccount.sol: https://github.com/bcnmy/nexus/blob/7db9b00b7288eaefbe0124abd9ed2daa3f4ae2cc/contracts/base/BaseAccount.sol
Architecture character#
- Supports validate mode, module-enable mode, and PREP mode inside validation flow.
- Default validator concept plus installed validators list.
- Hooked execution wrappers across account and executor flows.
- Multi-type module installation and emergency hook uninstall timelock.
- UUPS upgrade path with dual-slot compatibility logic for prior account versions.
- ERC-7702-aware initialization branch.
Risk lens#
- Excellent operational flexibility (especially onboarding flows).
- Increased control-plane complexity across nonce modes and init paths.
- Hook and prevalidation hook composition means attack/DoS surface expands with each extension.
5) OpenZeppelin Community ERC-7579 modules#
Repository: https://github.com/OpenZeppelin/openzeppelin-community-contracts
Key contracts:
ERC7579DelayedExecutor.sol: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579DelayedExecutor.solERC7579Multisig.sol: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579Multisig.solERC7579MultisigStorage.sol: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579MultisigStorage.solERC7579SelectorExecutor.sol: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579SelectorExecutor.sol
Architecture character#
- Delayed executor provides explicit schedule/ready/expire lifecycle.
- Multisig family provides signer sets, threshold checks, weighted/confirmation/storage flavors.
- Selector executor provides function-level execution allowlists.
Risk lens#
- This suite is great for explicit controls and composable policy.
- Documented unbounded set-clearing operations can become gas-scaling hazards for very large signer/selector sets.
6) Rhinestone Core Modules#
Repository: https://github.com/rhinestonewtf/core-modules
Representative contracts:
- Ownable Executor: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/OwnableExecutor/OwnableExecutor.sol
- Ownable Validator: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/OwnableValidator/OwnableValidator.sol
- Registry Hook: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/RegistryHook/RegistryHook.sol
- Hook MultiPlexer: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/HookMultiPlexer/HookMultiPlexer.sol
- Social Recovery: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/SocialRecovery/SocialRecovery.sol
- MultiFactor: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/MultiFactor/MultiFactor.sol
- DeadmanSwitch: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/DeadmanSwitch/DeadmanSwitch.sol
Architecture character#
- Practical security modules that map directly to consumer wallet needs.
- Registry attestation checks (ERC-7484 style) integrated into hook paths.
- Multi-validator composition and subhook multiplexing patterns.
Risk lens#
- Feature density is high and useful.
- Each additional validator/hook composition level multiplies review complexity.
- Timelock, nominee, and guardian semantics are only as strong as install/update governance and fallback escape paths.
7) Adjacent modular account ecosystems (important in practice)#
Even when not all of these are pure ERC-7579 module sets, they shape real deployments.
- Safe7579 article: https://blog.rhinestone.wtf/introducing-safe7579-cf390b630d28
- Rhinestone registry: https://github.com/rhinestonewtf/registry/
- Rhinestone address book/docs: https://docs.rhinestone.dev/home/resources/address-book
- Rhinestone module docs index: https://docs.rhinestone.dev/home/resources/modules
- Awesome modular accounts list: https://github.com/rhinestonewtf/awesome-modular-accounts
- Biconomy client SDK: https://github.com/bcnmy/biconomy-client-sdk
- ZeroDev docs: https://docs.zerodev.app/
- ZeroDev chain abstraction docs: https://docs.zerodev.app/sdk/advanced/chain-abstraction
- Pimlico ERC-7579 guide: https://docs.pimlico.io/guides/how-to/accounts/use-erc7579-account
- Thirdweb modular 7579 post: https://blog.thirdweb.com/thirdweb-modular-smart-accounts-powered-by-erc-7579/
- Etherspot modular SDK: https://etherspot.io/etherspot-modular-sdk/
Also relevant for delegation-style modularity and EIP-7702-adjacent account controls:
- MetaMask DelegationManager (deployed): https://etherscan.io/address/0xDb9B1e94B5b69Df7e401DDbedE43491141047dB3#code
- EIP-7702 glossary context: https://www.cyfrin.io/glossary/eip-7702
- Example 7702 delegator deployment: https://etherscan.io/address/0x63c0c19a282a1B52b07dD5a65b58948A07DAE32B
Feature vs risk matrix#
| Capability | Why teams want it | Risk introduced | Typical control |
|---|---|---|---|
| Validator modules | flexible auth (MFA, passkeys, guardians, policy signers) | validation confusion, parser bugs, replay mistakes | strict domain separation, nonce discipline, minimal parser surface |
| Executor modules | delegated execution and automation | module privilege escalation | strict install governance, selector allowlists, module guards/hooks |
| Fallback modules | extend interface without account upgrades | unauthorized fallback execution | selector routing + ERC-2771 sender checks + forbidden selector filters |
| Hooks | pre/post policy checks and telemetry | DoS via hook reverts, reentrancy complexity | isolation patterns, emergency uninstall, hook timeouts |
| Prevalidation hooks | custom auth pre-processing | signature/hash mutation mistakes | deterministic transforms, explicit test vectors |
| Multi-type modules | fewer installs and richer bundles | coupled failure domains | explicit install order, typed context encoding tests |
| Launchpad/bootstrap flows | seamless first userOp onboarding | init replay and setup confusion | init-hash commitments, singleton swaps, strict setup selectors |
| Upgradeability | patchability and velocity | governance key compromise, upgrade bugs | timelocks, codehash allowlists, staged rollouts |
Deep difference: trust boundaries#
The deepest distinction is not syntax, it is where trust sits.
Safe-native systems concentrate trust in a well-understood account core plus explicitly enabled modules.
ERC-7579 systems distribute trust across standardized extension points and a larger third-party module market.
That trade makes portability and ecosystem growth possible, but demands stronger module vetting and integration discipline.
Audit checklist for modular accounts#
Use this list when reviewing either Safe-module or ERC-7579-module systems.
- Module lifecycle safety
- Can malicious
onUninstallreverts brick removal? - Are there safe-mode escape hatches (timelock emergency uninstall, forced delete, isolation)?
- Authorization boundaries
- Are install/uninstall paths strictly
entryPoint/self/root-restricted? - Can internal self-calls bypass stricter controls unintentionally?
- Fallback safety
- Are forbidden selectors blocked (
onInstall/onUninstalland dangerous internal selectors)? - Is sender forwarding explicit and verified consistently?
- Nonce and replay semantics
- Is nonce encoding parse-safe and collision-resistant?
- Are replayable lanes intentionally scoped?
- Hook behavior
- Can hook reverts create permanent DoS?
- Are hook pre/post state assumptions formally tested?
- Upgrade safety
- Are upgrade call paths bound to robust authorization?
- Is new implementation code existence checked?
- Is storage layout compatibility proven?
- Registry/attestation assumptions
- Is registry downtime or compromise handled?
- Are attester thresholds and trust assumptions explicit?
- Gas-scaling hazards
- Any unbounded loops in uninstall/clear operations?
- Any arrays/sets likely to become practically uncallable?
Side-by-side execution mechanics#
At high level, all systems do the same thing: authorize then execute.
At audit depth, they differ in exactly where policy enters and where fallback logic can redirect control.
Why this matters#
- Safe-native paths are usually easier to reason about because they have fewer standardized layers.
- ERC-7579 paths are usually easier to extend across vendors because typed extension points are first-class.
- Security review effort tends to scale with the number of active extension points, not with the number of contracts alone.
Concrete failure modes (feature-to-exploit mapping)#
Below are practical failure classes that show up repeatedly in modular account reviews.
1) Fallback selector collisions#
If fallback selector routing is not strictly constrained, an attacker can route calls toward privileged paths or create ambiguous dispatch.
Defenses visible in production code:
- Safe fallback manager blocks self-handler setting: https://github.com/safe-global/safe-smart-account/blob/dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be/contracts/base/FallbackManager.sol
- Safe7579 and Nexus forbid dangerous selectors and differentiate call types: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/core/ModuleManager.sol https://github.com/bcnmy/nexus/blob/7db9b00b7288eaefbe0124abd9ed2daa3f4ae2cc/contracts/base/ModuleManager.sol
2) Malicious or broken onUninstall hooks#
Module deinit callbacks are an attack surface.
- If uninstall flow must call external module cleanup and that callback burns gas or reverts unexpectedly, removal may fail.
- Multiple implementations explicitly use
tryor safe-call wrappers to reduce permanent lock risk, but this can leave residual module state if not paired with full storage cleanup.
Examples:
- Safe7579 uses try-delegatecall patterns in uninstall paths.
- Nexus uses
excessivelySafeCallfor uninstall callbacks.
3) Hook-based denial of service#
Hooks can intentionally or accidentally revert in preCheck or postCheck, blocking all operations passing through that hook.
Spec-level concern is explicit in ERC-7579 security considerations: https://eips.ethereum.org/EIPS/eip-7579
4) Module-typing confusion#
If an account fails to differentiate validator/executor/fallback/hook types in storage and access checks, a lower-privilege type can be treated as higher privilege.
ERC-7579 explicitly calls out this risk and requires module-type differentiation in account storage/control: https://eips.ethereum.org/EIPS/eip-7579
5) Validation routing ambiguity#
Nonce-encoded or signature-encoded validator routing is powerful but fragile:
- parse mistakes
- short-signature corner cases
- fallback-to-default-validator surprises
Where this appears:
- Safe7579 validator-in-nonce + Safe fallback validation path
- Kernel validation mode/type/id in nonce
- Nexus mode branches including module-enable and PREP
6) Replay lanes that outgrow intent#
Replay-safe-by-default is hard once systems add “replayable” paths.
Kernel explicitly has replayable signature mechanics (MAGIC_VALUE_SIG_REPLAYABLE) and replayable hash derivation paths. These are useful for cross-domain flows, but they demand strict domain modeling and downstream UI clarity.
7) Governance over-upgrade risk#
Upgradeable account implementations plus module systems are a multiplicative trust surface:
- account upgrade control
- module install control
- registry/attester control
If these controls are not independent and observable, one compromised role may own the full stack.
8) Gas griefing in large module/signature sets#
Any unbounded clear/iterate operation can become a practical liveness bug at scale.
OZ module comments explicitly warn about this in clear and copy-heavy set operations: https://github.com/OpenZeppelin/openzeppelin-community-contracts/tree/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules
Implementation scorecard (security posture view)#
This is not a “best project” ranking. It is a map of where review effort should go first.
| Stack | Strength profile | Primary risk profile | First audit priority |
|---|---|---|---|
| Safe core modules | battle-tested base, clear guard model | privileged module misuse and fallback assumptions | module inventory + guard coverage validation |
| Zodiac roles/exit | expressive constrained execution and treasury workflows | policy complexity and config drift | role-condition invariant testing |
| Safe7579 | strong Safe bridge, mature module taxonomy support, emergency hook path | adapter complexity, dual semantic layers | validator fallback path + hook uninstall drills |
| ERC-7579 reference | clear educational baseline | explicitly non-production posture | use as reference only, not deployment template |
| Kernel | highly expressive permissions and validation modes | configuration complexity and mode errors | nonce/mode parser and selector authorization proofs |
| Nexus | practical production onboarding modes (module-enable, PREP), upgrade compatibility | flow complexity and extension interaction | init-mode hardening + uninstall and hook stress tests |
| OZ community modules | high-quality reusable building blocks | operational gas bounds and integration misuse | state-machine correctness + boundedness checks |
| Rhinestone core modules | rich consumer security modules (social recovery, MFA, deadman, registry hook) | composition and governance coupling | cross-module interaction and escalation analysis |
Implementation-specific audit heuristics#
This section is intentionally concrete. It is a checklist of where bugs usually hide in each architecture family.
Safe core and Zodiac#
- Verify module list integrity assumptions
- Linked-list based module storage means every removal requires a valid predecessor.
- Audit all code that supplies
prevModuleand all pagination clients that compute it offchain. - Regression test for stale pagination cursors and concurrent module mutations.
- Guard coverage mapping
- Map which paths are covered by transaction guard vs module guard.
- Confirm no critical path executes via module route without module guard where policy assumes one.
- Ensure guard contracts themselves do not have external dependency reentrancy surprises.
- Zodiac Roles policy depth
- Build execution trees for representative role configs.
- Prove that wildcard scopes cannot accidentally cover high-risk selectors.
- Verify allowance consumption commit/rollback semantics on failed inner tx.
- Zodiac Exit assumptions
- Verify designated token and circulating supply source can not be manipulated by unauthorized parties.
- Test proportional redemption for non-standard ERC20s and extreme decimal configurations.
- Verify denylist governance path under adversarial sequencing.
Safe7579 adapter family#
- Dual-semantics validation
- Safe7579 combines Safe-native signature semantics and ERC-7579 validator semantics.
- Test both branches intentionally:
- validator installed and selected
- validator missing or zero selector path
- Verify timestamp and validity-window handling remains coherent across both.
- Fallback routing and msg.sender forwarding
- For every fallback selector route, confirm handler logic uses forwarded sender semantics (not raw
msg.senderassumptions). - Confirm unsupported selectors return/revert according to expected token receiver compatibility behavior.
- Emergency uninstall survivability
- Validate the full timelock lifecycle:
- request
- waiting period
- reset window
- execute uninstall
- Confirm emergency signatures cannot be replayed due nonce mismanagement.
- Launchpad initialization integrity
- Prove
initHashcommitment cannot be bypassed. - Prove only valid setup selector flows are accepted in validation.
- Simulate malformed
callDataand partially initialized states.
ERC-7579 reference-style accounts#
- Treat as a design reference, not hardened product
- The reference repo explicitly warns it is not audited.
- Use it to reason about interfaces and extension points, not as default deployment.
- Hook + prevalidation interaction
- Test with and without hooks.
- Test hook mutation of hash/signature payloads and ensure deterministic behavior.
- Verify function ordering invariants (prevalidation first, then validator, then execution hooks).
- Fallback and selector safety
- Confirm reserved selectors cannot be rebound.
- Confirm handler calltype constraints are enforced (single/static where required).
Kernel-style permission-rich systems#
- Nonce decoding matrix tests
- Generate tests across all mode/type/id combinations.
- Include malformed nonce patterns and legacy-client nonce encodings.
- Prove type-specific parser cannot be confused into privileged mode.
- Selector authorization coherence
- For each validation ID, assert selector grants match policy/signer expectations.
- Test grant removal and permission revocation ordering.
- Ensure stale selector grants cannot survive disabled validation IDs.
- Replayable signature lane containment
- Validate replayable lane scope exactly equals intended domain.
- Ensure replayable hash derivation cannot be triggered accidentally by normal signatures.
- Test chain-ID/domain separation assumptions under L2 and forked environments.
- Hook sentinel semantics
- Kernel uses sentinel addresses to represent hook states.
- Explicitly test each sentinel branch in:
- fallback dispatch
- validation flow
- executor flow
- Sentinel confusion bugs are subtle and high impact.
Nexus-style onboarding-rich systems#
- Mode transition correctness
- Validate transitions across validate mode, module-enable mode, and PREP mode.
- Ensure PREP initialization cannot be replayed or reentered.
- Ensure module-enable signatures bind module type, module address, and intended init hash.
- Default validator fallback behavior
- Map all cases where
_DEFAULT_VALIDATORparticipates. - Ensure uninstalling optional validators cannot silently weaken expected auth policy.
- Confirm
isInitializedand validator initialization checks cannot be bypassed by partial state.
- Upgrade and compatibility logic
- Nexus supports compatibility with prior storage slot conventions.
- Verify both implementation-slot paths in tests and static checks.
- Confirm account-upgrade auth is identical across both slot-reading branches.
- Excessively-safe uninstall implications
- Safe-call wrappers reduce hard reverts but may hide partial cleanup.
- Verify post-uninstall invariants, not only call success status.
OZ module stack integrations#
- Delayed executor lifecycle invariants
- Scheduled operation can only move Unknown -> Scheduled -> Ready -> Executed/Expired/Canceled.
- No path should permit Scheduled -> Executed before delay.
- Expired should not be executable without rescheduling.
- Selector executor allowlist guarantees
- Ensure extracted inner selector is exactly the selector intended for authorization.
- Confirm no ABI encoding trick can shift the selector location.
- Validate behavior for empty calldata and malformed single-call payloads.
- Multisig signer set safety
- For signer add/remove/set-threshold, prove threshold reachability invariants always hold.
- For storage-presigned flows, verify presigned entries cannot be abused by unauthorized signer entries.
Core module ecosystem (Rhinestone and peers)#
- Module composability liveness
- Modules like
DeadmanSwitchandSocialRecoveryintentionally constrain execution patterns. - Ensure they cannot permanently lock critical maintenance paths.
- Test interactions when multiple validators and hooks are active simultaneously.
- Registry-hook assumptions
- Registry checks add supply-chain controls, but create external dependency.
- Test behavior under registry failure, stale attestation, and threshold changes.
- HookMultiPlexer complexity
- Ensure dedup and ordering logic cannot be manipulated to skip expected subhooks.
- Validate postCheck context association cannot be desynced across subhook calls.
Attack-path diagrams for reviewers#
Path A: Hook griefing to force emergency flow#
Review question: can the same malicious hook also block the signature path needed for emergency uninstall authorization?
Path B: Fallback misconfiguration to privilege escalation#
Review question: does fallback auth use forwarded sender semantics consistently in every code path?
Path C: Permission drift in policy-rich validators#
Review question: are selector grants and policy/signer changes always atomic from a security perspective?
Operational runbook (production teams)#
Designing a modular account securely is only half of the job. Operating it safely is the other half.
- Maintain a machine-readable module inventory per account implementation
- module address
- module type(s)
- install tx hash
- governance authority that approved installation
- expected uninstall fallback path
- Separate controls for:
- account upgrades
- module install/uninstall
- guard/hook updates
- registry and attester threshold changes
- Require canary rollout for new module versions
- first on low-value accounts
- then on medium-risk cohorts
- then broad rollout only after monitoring quiet period
- Continuously monitor UserOp behavior
- unknown validators appearing in nonce/signature routing
- unexpected fallback selector usage
- sudden spike in hook reverts
- repeated uninstall attempts
Observability starting points:
- JiffyScan for UserOp-level telemetry: https://jiffyscan.xyz/?network=mainnet
- Practice disaster drills
- emergency hook uninstall with real signer sets
- fallback handler rollback
- root validator rotation
- upgrade freeze mode
- Build hard invariants into tests and audits
- no untyped module can call executor-only paths
- no fallback selector can target install/uninstall selectors
- uninstall always progresses to a safe state even with malicious module callbacks
- configuration self-calls cannot silently bypass stronger auth checks
ERC-7579 ecosystem maturity model#
Teams often ask whether the ecosystem is “ready.” The better question is: ready for which trust model?
In short:
- ERC-7579 is mature enough for serious production use.
- But production safety is mostly determined by module governance, not by interface compliance alone.
Migration patterns: Safe modules to ERC-7579 world#
Practical advice:
- Keep Safe-native guard/module hygiene during migration.
- Treat adapter and first validator install as high-risk ceremony.
- Stage rollout with low-privilege executor modules first.
Closing perspective#
Safe modules and ERC-7579 are not competitors in a zero-sum sense.
- Safe modules proved that modular smart-account security can work in production.
- ERC-7579 turned that lesson into a portable interface economy.
- Safe7579 shows the bridge: a Safe account can keep its operational strengths while joining the ERC-7579 module ecosystem.
The strategic trade is clear:
- More modularity gives faster feature evolution and richer wallet UX.
- More modularity also gives larger authorization and composition attack surfaces.
Winning designs are not the ones with the most modules. Winning designs are the ones where module power, install governance, fallback behavior, and escape hatches are all deliberate, minimal, and test-proven.
Appendix: direct code links index#
Safe core#
- Module manager: https://github.com/safe-global/safe-smart-account/blob/dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be/contracts/base/ModuleManager.sol
- Guard manager: https://github.com/safe-global/safe-smart-account/blob/dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be/contracts/base/GuardManager.sol
- Fallback manager: https://github.com/safe-global/safe-smart-account/blob/dc437e8fba8b4805d76bcbd1c668c9fd3d1e83be/contracts/base/FallbackManager.sol
Safe7579#
- Safe7579 adapter: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/Safe7579.sol
- Safe7579 module manager: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/core/ModuleManager.sol
- Safe7579 launchpad: https://github.com/rhinestonewtf/safe7579/blob/f22a194148ff087f0c16125e530512e59794e188/src/Safe7579Launchpad.sol
ERC-7579 reference#
- MSAAdvanced: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/MSAAdvanced.sol
- ModuleManager: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/core/ModuleManager.sol
- IERC7579Module interface: https://github.com/erc7579/erc7579-implementation/blob/16138d1afd4e9711f6c1425133538837bd7787b5/src/interfaces/IERC7579Module.sol
Kernel#
- Kernel: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/Kernel.sol
- ValidationManager: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/core/ValidationManager.sol
- SelectorManager: https://github.com/zerodevapp/kernel/blob/6a098bc8f9a7001fe7ae801368e96a5ee635ddb1/src/core/SelectorManager.sol
Nexus#
- Nexus account: https://github.com/bcnmy/nexus/blob/7db9b00b7288eaefbe0124abd9ed2daa3f4ae2cc/contracts/Nexus.sol
- Nexus module manager: https://github.com/bcnmy/nexus/blob/7db9b00b7288eaefbe0124abd9ed2daa3f4ae2cc/contracts/base/ModuleManager.sol
OpenZeppelin community modules#
- Delayed executor: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579DelayedExecutor.sol
- Multisig: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579Multisig.sol
- Multisig storage extension: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579MultisigStorage.sol
- Selector executor: https://github.com/OpenZeppelin/openzeppelin-community-contracts/blob/a12b30ca7affe3320777378eddf2d0cebae8c5b2/contracts/account/modules/ERC7579SelectorExecutor.sol
Rhinestone core modules#
- OwnableExecutor: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/OwnableExecutor/OwnableExecutor.sol
- OwnableValidator: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/OwnableValidator/OwnableValidator.sol
- RegistryHook: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/RegistryHook/RegistryHook.sol
- HookMultiPlexer: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/HookMultiPlexer/HookMultiPlexer.sol
- SocialRecovery: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/SocialRecovery/SocialRecovery.sol
- MultiFactor: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/MultiFactor/MultiFactor.sol
- DeadmanSwitch: https://github.com/rhinestonewtf/core-modules/blob/1f97c2920a17a43359413d8616a8228100c9f71a/src/DeadmanSwitch/DeadmanSwitch.sol
Zodiac modules#
- Roles modifier: https://github.com/gnosisguild/zodiac-modifier-roles/blob/8c80d40b8b1354d1d3c5d2ee9d399a214fc4c790/packages/evm/contracts/Roles.sol
- Permission checker: https://github.com/gnosisguild/zodiac-modifier-roles/blob/8c80d40b8b1354d1d3c5d2ee9d399a214fc4c790/packages/evm/contracts/PermissionChecker.sol
- Exit base: https://github.com/gnosisguild/zodiac-module-exit/blob/2720c7fa990842b9ea58f5b85aeb8769aff21331/packages/contracts/contracts/ExitModule/ExitBase.sol
- Exit ERC20: https://github.com/gnosisguild/zodiac-module-exit/blob/2720c7fa990842b9ea58f5b85aeb8769aff21331/packages/contracts/contracts/ExitModule/ExitERC20Module.sol