On-Chain Accountability Escrow for Group Tasks
SmartDeadlines is a Solana-based decentralized application (dApp) that helps college students and teams stay accountable for group projects. By requiring members to stake SPL-USDC tokens, it creates financial incentives to complete tasks on time. If the task is completed successfully and the majority votes YES, everyone gets their money back. Otherwise, the funds go to charity.
- On-Chain Escrow: Secure SPL-USDC deposits managed by Solana smart contracts
- Democratic Voting: Members vote on task completion after the deadline
- Automatic Distribution: Funds are automatically refunded or donated based on vote outcome
- IPFS Integration: Task descriptions and proof of completion stored on IPFS
- Email Invitations: Seamless onboarding via email invite links -- Wallet Support: Built for Phantom and compatible Solana wallets
- Transparent: All actions recorded on-chain for full transparency
┌─────────────────────────────────────────────────────────────┐
│ SmartDeadlines System │
└─────────────────────────────────────────────────────────────┘
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ React Frontend │◄────►│ Node Backend │ │ Solana Program │
│ (Vite + TS) │ │ (Express API) │ │ (Anchor/Rust) │
└──────────────────┘ └──────────────────┘ └──────────────────┘
│ │ │
│ │ │
┌────▼────┐ ┌────▼────┐ ┌──────▼──────┐
│ Wallet │ │ SendGrid│ │ Solana RPC │
│ Adapter │ │ Email │ │ (Devnet) │
└─────────┘ └─────────┘ └─────────────┘
│ │
┌────▼────────────────────────────────────────────────────▼────┐
│ IPFS Network │
│ (Web3.Storage / NFT.Storage) │
└───────────────────────────────────────────────────────────────┘
-
Anchor Program (programs/smart-deadlines/src/lib.rs)
- Creates and manages tasks
- Handles SPL-USDC deposits via escrow PDAs
- Processes votes and distributes funds
- All logic executed on-chain
-
React Frontend (app/src/)
- User interface for all interactions
- Wallet connection (Phantom, etc.)
- IPFS file uploads
- Task dashboard and voting UI
-
Node Backend (backend/src/)
- Sends email invitations via SendGrid
- Generates and verifies invite tokens (JWT)
- Minimal state storage (production: use database)
-
IPFS Storage
- Stores task descriptions
- Stores proof of completion files
- Only CIDs stored on-chain
GroupProof/
├── programs/
│ └── smart-deadlines/
│ ├── src/
│ │ └── lib.rs # Anchor program (Rust)
│ ├── Cargo.toml
│ └── Xargo.toml
├── app/ # React frontend
│ ├── src/
│ │ ├── pages/ # All page components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── utils/ # Utility functions
│ │ ├── idl/ # Program IDL
│ │ ├── App.tsx
│ │ └── main.tsx
│ ├── package.json
│ ├── vite.config.ts
│ └── .env.example
├── backend/ # Node.js backend
│ ├── src/
│ │ ├── server.js
│ │ ├── routes/
│ │ │ └── invites.js
│ │ └── utils/
│ │ ├── email.js
│ │ └── storage.js
│ ├── package.json
│ └── .env.example
├── scripts/ # Deployment scripts
│ ├── deploy.sh
│ ├── create-usdc-mint.sh
│ ├── test-local.sh
│ └── setup-env.sh
├── tests/
│ └── smart-deadlines.ts # Anchor tests
├── Anchor.toml
├── Cargo.toml
└── README.md
- Node.js v18+ and npm/yarn
- Rust v1.70+
- Solana CLI v1.16+
- Anchor CLI v0.29+
- Git
git clone https://github.com/yourusername/GroupProof.git
cd GroupProof# Install all dependencies (root, frontend, backend)
npm run install:all
# Or manually:
npm install
cd app && npm install && cd ..
cd backend && npm install && cd ..# Creates .env files from examples
npm run setup
# Or manually:
cp backend/.env.example backend/.env
cp app/.env.example app/.envBackend (backend/.env):
PORT=3001
SENDGRID_API_KEY=your_sendgrid_api_key_here
FROM_EMAIL=noreply@smartdeadlines.com
FRONTEND_URL=http://localhost:5173
JWT_SECRET=change_this_to_a_random_secretFrontend (app/.env):
VITE_SOLANA_RPC_URL=https://api.devnet.solana.com
VITE_BACKEND_URL=http://localhost:3001
VITE_PROGRAM_ID=Fg6PaFpoGXkYsidMpWTK6W2BeZ7FEfcYkg476zPFsLnS
VITE_USDC_MINT=4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU
VITE_WEB3_STORAGE_TOKEN=your_web3_storage_tokenNote: Get a Web3.Storage API token at https://web3.storage
# Set Solana to devnet
solana config set --url devnet
# Get some SOL for deployment
solana airdrop 2
# Build the program
anchor build
# Deploy to devnet
npm run deploy:devnet
# Or use the script directly:
./scripts/deploy.sh devnetAfter deployment, update VITE_PROGRAM_ID in app/.env with the deployed program ID.
# Create a test USDC mint on devnet
npm run create-usdc
# Or:
./scripts/create-usdc-mint.sh devnetThis will output a mint address. Update VITE_USDC_MINT in app/.env.
Open three terminals:
Terminal 1 - Backend:
cd backend
npm start
# Runs on http://localhost:3001Terminal 2 - Frontend:
cd app
npm run dev
# Runs on http://localhost:5173Terminal 3 - Local Validator (Optional for local testing):
npm run deploy:local
# Starts local validator and deploys program- Connect your Phantom wallet (or compatible Solana wallet)
- Click "Create New Task"
- Fill in:
- Task title and description
- Stake amount (USDC per member)
- Member email addresses (comma-separated)
- Join window (how long members have to join)
- Deadline (when task must be completed)
- Charity wallet address (receives funds if task fails)
- Click "Create Task"
- Approve the transaction in your wallet
- Check your email for the invitation
- Click the invite link
- Connect your wallet
- Review task details
- Click "Join & Deposit Stake"
- Approve the USDC transfer
- Navigate to the task dashboard
- Click "Submit Proof of Completion"
- Upload your proof file (PDF, images, documents)
- File is uploaded to IPFS
- CID is stored on-chain
- After the deadline passes, go to the task page
- Click "Cast Your Vote"
- Review the submitted proof (view on IPFS)
- Vote YES if completed, NO if not
- Approve the transaction
If majority voted YES:
- Click "Finalize Task"
- Each member can then "Claim Refund" to get their USDC back
If majority voted NO (or tie):
- Click "Finalize Task"
- All USDC is sent to the charity address
- No refunds available
anchor test# Starts local validator, deploys program, runs tests
npm run deploy:local- Create a test USDC mint (see Step 6 above)
- Fund multiple wallets with test USDC:
spl-token transfer <MINT> <AMOUNT> <RECIPIENT_ADDRESS>
- Create a task from one wallet
- Join from other wallets
- Test the full flow
-
Prerequisites Installed: Ensure Node.js, Solana CLI, Anchor installed
-
Clone and Install:
git clone <repo-url> cd GroupProof npm run install:all npm run setup
-
Configure .env files (use provided test values or create new ones)
-
Deploy to Devnet:
npm run deploy:devnet npm run create-usdc
-
Start Services:
# Terminal 1 cd backend && npm start # Terminal 2 cd app && npm run dev
-
Open Browser: Navigate to
http://localhost:5173
- Connect Wallet - Use Phantom or any Solana wallet on devnet
- Create Task - Fill in task details with test emails
- Check Console - Backend logs email invites (if SendGrid not configured)
- Join as Members - Use invite links from console/emails
- Submit Proof - Upload a test file (gets stored on IPFS)
- Vote - Each member votes YES/NO
- Finalize - See automatic distribution based on votes
SmartDeadlines supports multiple Solana wallets for maximum flexibility:
Previously there were experimental references to Gemini Wallet in this repository. The project currently recommends using Phantom or any Solana Wallet Adapter-compatible wallet. If an official Gemini Solana adapter is released in the future, it can be added.
Phantom is the most popular Solana wallet with excellent security and UX.
- Status: ✅ Ready to use
- Features: Multi-chain support, hardware wallet integration, NFT support
- Download: https://phantom.app/
- Integration: Fully integrated and tested
- Solflare
- Any Solana Wallet Adapter compatible wallet
- First Time Users: Click the "Connect Wallet" button in the header and select Phantom or another compatible wallet
- Already Have a Wallet: Click the "Connect Wallet" button in the header
- Choose Your Wallet: Select from available wallets in the modal
- Approve Connection: Sign the connection request in your wallet
- Ready to Go: Your wallet address will be displayed
create_task- Creates a new task with escrow PDAjoin_and_deposit- Member joins and deposits SPL-USDC stakesubmit_proof- Task creator uploads IPFS CID of proofvote- Members vote YES/NO after deadlinefinalize- Sends all funds to charity if majority NO (or tie)claim_refund- Members claim refund if majority YES
- Task PDA:
["task", task_id] - Escrow PDA:
["escrow", task_pubkey] - Member PDA:
["member", task_pubkey, member_pubkey]
- Majority YES (strict majority): All members get refunds
- Majority NO or TIE: All funds go to charity
- Example: 2-2 vote = charity (not a strict majority for YES)
- Join window prevents late joins
- Deadline enforcement for voting
- Proof submission only by task creator
- One vote per member
- PDA-signed transfers for security
- All state transitions validated on-chain
"Transaction simulation failed"
- Check your wallet has enough SOL for fees
- Ensure USDC balance is sufficient
- Verify you're on the correct network (devnet/testnet)
"Program not found"
- Redeploy the program
- Update
VITE_PROGRAM_IDinapp/.env - Clear browser cache
"Email not sending"
- Check
SENDGRID_API_KEYinbackend/.env - Emails are logged to console if SendGrid not configured
- Verify
FROM_EMAILis verified in SendGrid
"IPFS upload failed"
- Check
VITE_WEB3_STORAGE_TOKENis set - Ensure file size is reasonable (<100MB)
- Try alternative IPFS services (Pinata, NFT.storage)
- Mobile-responsive design improvements
- Notification system for task updates
- Multi-signature approval for large stakes
- Task templates for common use cases
- Analytics dashboard for task creators
- Integration with project management tools
- Support for other SPL tokens besides USDC
- Dispute resolution mechanism
- Reputation system for members
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- Built with Anchor
- Wallet integration via Solana Wallet Adapter
- IPFS storage via Web3.Storage
- Email service via SendGrid
- UI framework: React + Vite
- Issues: https://github.com/yourusername/GroupProof/issues
- Documentation: See
/docsfolder (if available) - Discord: [Your Discord link]
- Twitter: [@YourHandle]
| Variable | Description | Required | Example |
|---|---|---|---|
PORT |
Backend server port | No | 3001 |
SENDGRID_API_KEY |
SendGrid API key for emails | Yes (for email) | SG.xxx... |
FROM_EMAIL |
Sender email address | Yes | noreply@smartdeadlines.com |
FRONTEND_URL |
Frontend URL for invite links | Yes | http://localhost:5173 |
JWT_SECRET |
Secret for signing invite tokens | Yes | random-secret-key |
| Variable | Description | Required | Example |
|---|---|---|---|
VITE_SOLANA_RPC_URL |
Solana RPC endpoint | Yes | https://api.devnet.solana.com |
VITE_BACKEND_URL |
Backend API URL | Yes | http://localhost:3001 |
VITE_PROGRAM_ID |
Deployed program address | Yes | Fg6PaFpo... |
VITE_USDC_MINT |
USDC mint address | Yes | 4zMMC9sr... |
VITE_WEB3_STORAGE_TOKEN |
Web3.Storage API token | Yes | eyJhbG... |
Built with ❤️ for hackathons, group projects, and accountability