Created
March 14, 2026 06:59
-
-
Save doncesarts/1e169ad530f6225db3f52eb388c8b851 to your computer and use it in GitHub Desktop.
Gnosis Safe Module minimal Example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // SPDX-License-Identifier: MIT | |
| pragma solidity ^0.8.24; | |
| import { Enum } from "@safe-global/safe-smart-account/contracts/interfaces/Enum.sol"; | |
| import { | |
| IModuleManager | |
| } from "@safe-global/safe-smart-account/contracts/interfaces/IModuleManager.sol"; | |
| /** | |
| * @title StipendModule | |
| * @notice Minimal example module for periodic token transfers via Safe wallet. | |
| * @dev WARNING: This contract is NOT production ready. It lacks security checks, upgradeability, and robust error handling. | |
| * Use only for demonstration or testing purposes. | |
| */ | |
| contract StipendModule { | |
| address public immutable safeWallet; | |
| address public immutable token; | |
| address public immutable recipient; | |
| uint256 public lastExecuted; | |
| uint256 public immutable amount; | |
| uint256 public constant interval = 4 weeks; | |
| error MultiSendNotConfigured(); | |
| error ZeroAddress(); | |
| error ZeroAmount(); | |
| error PrematureExecution(uint256 currentTime, uint256 nextAllowedTime); | |
| constructor(address _safeWallet, address _token, address _recipient, uint256 _amount) { | |
| if (_safeWallet == address(0)) revert ZeroAddress(); | |
| if (_token == address(0)) revert ZeroAddress(); | |
| if (_recipient == address(0)) revert ZeroAddress(); | |
| if (_amount == 0) revert ZeroAmount(); | |
| safeWallet = _safeWallet; | |
| token = _token; | |
| recipient = _recipient; | |
| amount = _amount; | |
| lastExecuted = block.timestamp; | |
| } | |
| /** | |
| * @notice Execute a call via the Safe contract | |
| * @param to Destination address to call | |
| * @param data Data payload of the transaction | |
| * @return success bool for success | |
| */ | |
| function _execCallFromModule(address to, bytes memory data) | |
| internal | |
| virtual | |
| returns (bool success) | |
| { | |
| IModuleManager safe = IModuleManager(safeWallet); | |
| success = safe.execTransactionFromModule({ | |
| to: to, value: 0, data: data, operation: Enum.Operation.Call | |
| }); | |
| require(success, "!success"); | |
| return success; | |
| } | |
| function stipend() external { | |
| if (block.timestamp < lastExecuted + interval) { | |
| revert PrematureExecution(block.timestamp, lastExecuted + interval); | |
| } | |
| bytes memory data = abi.encodeWithSignature("transfer(address,uint256)", recipient, amount); | |
| lastExecuted = block.timestamp; | |
| _execCallFromModule(token, data); | |
| } | |
| /*////////////////////////////////////////////////////////////////////////// | |
| METADATA | |
| //////////////////////////////////////////////////////////////////////////*/ | |
| /** | |
| * Returns the name of the module | |
| * | |
| * @return name of the module | |
| */ | |
| function name() external pure virtual returns (string memory) { | |
| return "StipendModule"; | |
| } | |
| /** | |
| * Returns the version of the module | |
| * | |
| * @return version of the module | |
| */ | |
| function version() external pure virtual returns (string memory) { | |
| return "0.0.0"; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment