- Overview
- Design Choices
- Status
- Technical Stack
- Getting Started
- Diagrams & Visuals
- Links And References
- License
This project demonstrates a smart contract wallet that implements ERC-4337 (Account Abstraction) with social recovery. The contract is controlled by an owner, but if the owner loses access, the owner can initiate a recovery request from another account. A guardian or set of guardians can approve a recovery request proposed by the owner (or anyone). After a 2‑day timelock and sufficient approvals, anyone can execute the recovery. The accompanying frontend dashboard offers a tabbed interface to separate the four main functionalities. First, the 'Info' tab allows users to see basic information about the account, including ownership and balance. Second, the 'Guardians' tab enables the owner to modify the guardian list and the recovery threshold (minimum number of guardian approvals). Third, the 'Recovery' tab displays a conditional interface (based on pending recovery existence) for recovery status, initiation, approval, execution, and cancellation. Lastly, the 'Wallet' tab shows an interface allowing the owner to send transactions (contract calls or plain ETH transfers) as well as EIP-1271 signature verification.
This project extends the Cyfrin Updraft's Minimal Account Abstraction project. The RecoverableAccount contract design builds on the EIP-4337 standard for account abstraction and adds social recovery as its main feature. The contract requires at least one guardian as a safeguard mechanism. In the event that the owner loses access, anyone can initiate a recovery request by specifying a new owner.
Guardians can then approve the proposal (either directly on‑chain or by signing an off‑chain EIP‑712 message). After the two-day timelock period has passed and after acquiring the minimum number of approvals (the recovery threshold), anyone can execute the recovery—and thus transfer ownership to the new owner. If a recovery request was maliciously or accidentally initiated, the guardians or the owner can cancel it at any time.
The contract also implements EIP‑1271 for smart contract signature verification and EIP‑712 for structured off‑chain approvals, enabling gas‑less guardian approvals.
For the account recovery dashboard demo, I used a single deployed contract for UI simplicity. However, the architecture is modular: all components read the contract address and ABI from a single configuration file. To support multiple accounts, I could inject a different address via a prop, React Context, or URL parameter without fundamentally changing the component logic. This is a potential UI extension that would support a user switching between their own accounts or viewing another user's account.
This project is an educational demonstration of a smart contract wallet with social recovery, built on ERC‑4337. It is not intended for production use without further security review and testing. The code is a demo of a potential use case for real-world applications and showcases account abstraction patterns.
- Support for multiple accounts via dynamic address selection
- Factory contract to deploy new recoverable accounts
- Integration with a relayer for gas‑less approvals
- More comprehensive test coverage and formal verification
- Languages: Solidity ^0.8.24, TypeScript
- Framework: Foundry
- EIPs: EIP-4337, EIP-712, EIP-1271
- Frontend: Vite, React, Wagmi, Viem, RainbowKit, TailwindCSS, TanStack Query
To only view the Recoverable Account Abstraction frontend without cloning the repository, visit this link: https://recoverable-aa.vercel.app.
To view the Recoverable Account Abstraction frontend locally (and optionally deploy the smart contract yourself), follow the directions below.
- Node.js (v18+) and npm
- A WalletConnect project ID (see WalletConnect)
- A
.envfile forrecoverable-aa-frontend/
- Foundry
- A keystore account created with
cast wallet import(see Foundry Documentation) - An RPC URL for Sepolia (e.g., from Alchemy or Infura)
- An Etherscan API key for contract verification (see Etherscan)
- A
.envfile forrecoverable-aa-backend/
git clone https://github.com/vridhib/recoverable-aa
cd recoverable-aaCopy the variable in recoverable-aa-frontend/.env.example to recoverable-aa-frontend/.env and fill in your WalletConnect project ID. This WalletConnect project ID is required for the frontend to function.
VITE_WALLET_CONNECT_PROJECT_ID=your_wallet_connect_idThen, run the following commands:
cd recoverable-aa-frontend
npm install
npm run devNow, open http://localhost:5173/ to view the dashboard.
Connect your wallet (e.g., MetaMask) to view the dashboard. Visit the 'Info', 'Guardians', 'Recovery', and 'Wallet' to view the different functions. To see the recovery flow process in the UI, click on the 'Recovery' tab and initiate a recovery proposal.
To deploy the contract yourself, follow the directions below.
Copy the variables in recoverable-aa-backend/.env.example to recoverable-aa-backend/.env and fill in your values. Ensure that the burner wallet address is funded with SepoliaETH.
SEPOLIA_RPC_URL=your_rpc_url
ETHERSCAN_API_KEY=your_etherscan_key
BURNER_WALLET_ADDRESS=burner_wallet_address_associated_with_your_keystore_account
Modify recoverable-aa-backend/Makefile and replace sepolia-deployer with the name of your keystore account (e.g., my-account):
deploy-recoverable-account :; forge script script/DeployRecoverable.s.sol --rpc-url $(SEPOLIA_RPC_URL) --account sepolia-deployer --broadcast --verify --etherscan-api-key $(ETHERSCAN_API_KEY) -vvvvVerify that the contracts compile properly and pass all tests:
cd recoverable-aa-backend
forge build
forge testDeploy the RecoverableAccount contract:
make deploy-recoverable-accountModify recoverable-aa-frontend/src/config/contract.ts and update recoverableAccountAddress to use your deployed contract address:
export const recoverableAccountAddress = "0xC968B487f31Ad5632C675248aF5E9e4a00A6F61B"sequenceDiagram
actor User as Anyone
participant Contract
participant Owner
participant Guardian
User->>Contract: initiateRecovery(proposedOwner)
Note over Contract: timelock starts
Guardian->>Contract: approveRecovery() / approveRecoveryBySig()
loop Until threshold reached
Guardian->>Contract: approveRecovery()
end
Note over Contract: timelock passes
User->>Contract: executeRecovery()
Contract-->>Owner: ownership transferred
- RecoverableAccount on Sepolia Etherscan
- Cyfrin Updraft Course
- Original Cyfrin Project
- Vercel Deployment Link
This project is licensed under the MIT License. See the full license text for details.
