Smart Wallets
By @friedger
Contract Summary
There's many different implementations of a smart contract wallet available for developers to build with depending on their user's needs. The specific implementation showcased here is the Smart Wallet with Rules contract, which is a sophisticated wallet abstraction that enables programmable spending rules and multi-admin governance. Built by @friedger, this contract demonstrates advanced patterns for creating customizable wallet logic with security levels, activity monitoring, and extension capabilities.
Key Features:
Rule-Based Access Control - Configurable security levels (no rules, standard rules, emergency rules) that govern STX transfers and extension calls
Multi-Admin Support - Multiple principals can be designated as admins with the ability to manage other admins and security settings
Activity Monitoring - Tracks last transaction time to detect wallet inactivity (10 weeks on mainnet, 1 second on testnet)
Extension System - Modular architecture allowing custom extension contracts to add new functionality
Token Support - Built-in support for SIP-010 fungible tokens and SIP-009 NFT transfers
What Developers Can Learn:
How to implement customizable access control with rule-set traits
Multi-admin patterns with self-protection (admins cannot disable themselves)
Activity tracking using block timestamps for inactivity detection
Extension pattern for modular smart contract functionality
Dynamic trait selection based on security levels
Function-by-Function Breakdown
STX Transfer Functions
stx-transfer (amount uint) (recipient principal) (memo (optional (buff 34)))
Transfers STX from the smart wallet to a recipient, first checking with the current rule-set if the transfer is allowed. Updates the last transaction time for activity tracking and uses as-contract to transfer from the wallet's balance.
Extension System Functions
extension-call (extension <extension-trait>) (payload (buff 2048))
Calls an external extension contract with arbitrary payload data, after checking with the current rule-set if the extension call is allowed. Enables modular functionality to be added to the wallet.
SIP-010 Token Functions
sip010-transfer (amount uint) (recipient principal) (memo (optional (buff 34))) (sip010 <sip-010-trait>)
Transfers SIP-010 fungible tokens from the smart wallet to a recipient. Currently has placeholder validation logic that always allows transfers.
SIP-009 NFT Functions
sip009-transfer (nft-id uint) (recipient principal) (sip009 <sip-009-trait>)
Transfers SIP-009 NFTs from the smart wallet to a recipient. Currently has placeholder validation logic that always allows transfers.
Admin Management Functions
enable-admin (admin principal) (enabled bool)
Adds or removes admin privileges for a principal. Only callable by existing admins, and includes self-protection to prevent admins from disabling themselves.
set-security-level (new-level uint)
Changes the wallet's security level (0 = no rules, 1 = standard rules, 2+ = emergency rules). Only callable by admins, this determines which rule-set governs wallet operations.
Rule Validation Functions (Private)
is-allowed-stx (rules <rule-set-trait>) (amount uint) (recipient principal) (memo (optional (buff 34)))
Private function that delegates STX transfer validation to the current rule-set contract.
is-allowed-extension (rules <rule-set-trait>) (extension <extension-trait>) (payload (buff 2048))
Private function that delegates extension call validation to the current rule-set contract.
is-allowed-sip010 (sip010 <sip-010-trait>) (amount uint) (recipient principal) (memo (optional (buff 34)))
Private function for SIP-010 transfer validation. Currently always returns true.
is-allowed-sip009 (sip009 <sip-009-trait>) (amount uint) (recipient principal)
Private function for SIP-009 transfer validation. Currently always returns true.
Access Control & Utility Functions
is-admin-calling
Read-only function that verifies if the contract caller is an authorized admin. Returns an error if not authorized.
current-rules
Read-only function that returns the appropriate rule-set trait based on the current security level (0 = no-rules, 1 = standard-rules, 2+ = emergency-rules).
to-trait (trait <rule-set-trait>)
Helper function that converts a rule-set contract to a trait for use in validation functions.
Activity Tracking Functions
get-time
Read-only function that retrieves the timestamp of the previous Stacks block.
is-inactive
Read-only function that checks if the wallet has been inactive for longer than the activity period (10 weeks on mainnet, 1 second on testnet).
Traits Used
extension-trait
Custom trait that defines the interface for wallet extension contracts that can add modular functionality.
rule-set-trait
Custom trait that defines the interface for rule-set contracts that govern wallet operations.
sip-010-trait
Standard SIP-010 fungible token trait for token transfers.
sip-009-trait
Standard SIP-009 NFT trait for NFT transfers.
Key Concepts
Programmable Security Levels
The wallet implements a three-tier security system through the security-level variable. Level 0 applies no restrictions, level 1 uses standard rules, and level 2+ activates emergency rules. This allows the wallet to dynamically adjust security posture based on threat conditions.
Rule-Set Trait Pattern
The contract uses a trait-based architecture for validation logic, allowing different rule contracts to be swapped based on security level. The current-rules function dynamically selects which rule-set to use, enabling flexible and upgradeable access control without modifying the core wallet contract.
Multi-Admin Governance
The contract supports multiple administrators through a admins map. The enable-admin function includes a self-protection mechanism ((asserts! (not (is-eq admin contract-caller)) err-forbidden)) preventing admins from accidentally or maliciously removing their own access.
Activity-Based Inactivity Detection
The contract tracks the timestamp of the last transaction in last-tx-time and compares it against an activity period (10 weeks on mainnet). The is-inactive function can be used by external contracts (like the inactive-observer admin) to detect dormant wallets and potentially trigger recovery mechanisms.
Extension Modularity
The extension system allows new functionality to be added without modifying the core wallet. Extensions receive a 2048-byte payload and can execute arbitrary logic while being subject to rule-set validation. This enables features like scheduled payments, multi-sig requirements, or DeFi integrations.
Last updated
Was this helpful?