Safe{Wallet} Modules Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Safe{Wallet} Modules Development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1218
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    853
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1047
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Safe{Wallet} Module Development

Safe (formerly Gnosis Safe) is the Web3 multisig standard. Over $100B in DAO assets, protocols, and corporate treasuries are held on it. Safe's architecture is intentionally minimal at the core but extends through modules — contracts that Safe owners delegate to execute transactions without the standard signature threshold.

How Modules Work in Safe

Safe{Wallet} follows the modular proxy pattern. The core (GnosisSafe.sol) contains basic multisig logic and maintains a list of active modules in linked list storage. A module is activated via enableModule(address module) — a standard multisig transaction requiring the signature threshold.

Once activated, a module can call execTransactionFromModule() directly on Safe, bypassing the standard signature process:

interface IGnosisSafe {
    function execTransactionFromModule(
        address to,
        uint256 value,
        bytes calldata data,
        Enum.Operation operation
    ) external returns (bool success);
}

operation is 0 for CALL, 1 for DELEGATECALL. DELEGATECALL executes the target contract's code in Safe's storage context — a powerful tool and potential attack vector if the module isn't carefully audited.

Common Use Cases for Custom Modules

Spending limits. A DAO allows its operations team to spend up to $10K per day without multisig. The module stores the limit, spending counter, and approved callers. The standard Safe Allowance Module implements this, but custom versions are needed when the limit must work across multiple tokens simultaneously or reset on an event rather than by time.

Automated payouts. Integration with Chainlink Automation or Gelato: the module gains the right to execute monthly transfers from Safe to team addresses. No multisig required, but with strict constraints: only pre-approved addresses, specific tokens only, within budget.

Recovery module. Safe configured with 3/5 signers, but what if 3 keys are lost? A recovery module lets you designate guardian addresses (other Safes, cold wallets) that can replace the signer list via timelock. Guardians can't withdraw funds — only change Safe configuration after a waiting period.

Governance-controlled execution. The module accepts decisions from on-chain governance (Snapshot X with on-chain execution, OpenZeppelin Governor). Voting happens, results execute via the module without additional multisig signatures.

Safe Module Security Architecture

Authorization Checks

The module's primary responsibility is correct authorization. If execTransactionFromModule can be called by anyone, it's a disaster. Pattern:

contract SpendingLimitModule {
    mapping(address safe => mapping(address delegate => SpendingLimit)) public limits;

    modifier onlyDelegate(address safe) {
        require(limits[safe][msg.sender].amount > 0, "Not a delegate");
        _;
    }

    function executeTransfer(
        address safe,
        address token,
        address recipient,
        uint256 amount
    ) external onlyDelegate(safe) {
        SpendingLimit storage limit = limits[safe][msg.sender];
        require(amount <= limit.remaining, "Exceeds limit");

        // Update state first
        limit.remaining -= amount;

        // Then execute transaction
        bytes memory data = abi.encodeWithSignature(
            "transfer(address,uint256)", recipient, amount
        );
        require(
            IGnosisSafe(safe).execTransactionFromModule(token, 0, data, Enum.Operation.Call),
            "Module tx failed"
        );
    }
}

Order: checks → state changes → external calls. Classic checks-effects-interactions pattern.

Guard — Additional Protection Layer

Safe 1.3+ supports Guard — a contract called before and after each Safe transaction. A guard can block transactions based on any criteria: prohibit interaction with certain addresses, require cooldown between large transactions, log everything on-chain.

Guard and Module are different mechanisms. Guard doesn't execute transactions, only filters them. Module executes transactions, bypassing the standard threshold.

Timelock in Modules

For critical actions, modules should include timelock. Operations are queued with a timestamp and executed only after a delay period passes. This gives observers (community, other signers) time to react to unwanted actions.

mapping(bytes32 => uint256) public queue;
uint256 public constant DELAY = 2 days;

function propose(address target, uint256 value, bytes calldata data)
    external onlyAuthorized returns (bytes32 txHash) {
    txHash = keccak256(abi.encode(target, value, data, block.timestamp));
    queue[txHash] = block.timestamp + DELAY;
    emit Proposed(txHash, target, value, data);
}

function execute(address target, uint256 value, bytes calldata data, uint256 timestamp)
    external onlyAuthorized {
    bytes32 txHash = keccak256(abi.encode(target, value, data, timestamp));
    require(queue[txHash] != 0, "Not queued");
    require(block.timestamp >= queue[txHash], "Timelock active");
    delete queue[txHash];
    // execute via Safe module
}

Testing and Audit

Test on Foundry with a real Safe instance. Forge lets you deploy the Safe factory and create Safe instances in tests — no mocks needed.

import {GnosisSafeProxyFactory} from "safe-contracts/proxies/GnosisSafeProxyFactory.sol";
import {GnosisSafe} from "safe-contracts/GnosisSafe.sol";

function setUp() public {
    factory = new GnosisSafeProxyFactory();
    singleton = new GnosisSafe();
    // deploy Safe with our module already enabled via setup
}

Verify: the module can't call execTransactionFromModule from an arbitrary address, timelock can't be bypassed, reentrancy in callbacks is impossible, the module works correctly after Safe upgrade.

Module audits for Safe with significant assets are mandatory. The DELEGATECALL attack vector is especially dangerous: a malicious module can rewrite Safe's storage via delegatecall, including the signer list.

Timelines

Basic Spending Limit module: 3-5 days. Recovery module with timelock and guardian system: 5-8 days. Complex governance module with Snapshot X or OpenZeppelin Governor integration: 2-3 weeks. Audit: additional 1-2 weeks.

Cost is calculated after clarifying management requirements and the number of integrated systems.