A secure, decentralized FundRaiser smart contract built on the Stacks blockchain using Clarity 4. This contract enables users to donate STX towards a predefined funding goal, with the owner able to withdraw funds once the goal is reached. Designed with security best practices, including reentrancy protection and overflow safeguards.
- Overview
- Features
- Architecture
- System Flow
- Prerequisites
- Installation
- Usage
- API Reference
- Testing
- Deployment
- Security
- Contributing
- License
- Support
The FundRaiser contract is a decentralized crowdfunding solution on the Stacks blockchain. It allows anyone to contribute STX (Stacks cryptocurrency) towards a fixed funding goal. Once the goal is met, the contract owner can withdraw the entire balance. The contract tracks individual donor contributions and ensures secure, transparent fund management.
Contract Address (Testnet): STGDS0Y17973EN5TCHNHGJJ9B31XWQ5YXBQ0KQ2Y.fund-raiser
- Decentralized Funding: Accept STX donations from any user on the Stacks network
- Goal-Based Withdrawal: Funds can only be withdrawn by the owner after reaching the predefined goal
- Donor Tracking: Maintains a record of each donor's total contribution
- Security-First Design: Implements assertions, error handling, and overflow protection
- Clarity 4 Compatibility: Leverages modern Clarity features for robust smart contract development
- Testnet Deployed: Live on Stacks testnet for testing and demonstration
The FundRaiser contract follows a modular architecture designed for security and efficiency on the Stacks blockchain.
graph TB
subgraph "User Layer"
A[Donors] --> B[Stacks Wallet]
C[Owner] --> B
end
subgraph "Contract Layer"
D[FundRaiser Contract]
D --> E[Data Variables]
D --> F[Public Functions]
D --> G[Read-Only Functions]
end
subgraph "Blockchain Layer"
H[Stacks Testnet/Mainnet]
H --> I[STX Transfers]
H --> J[State Persistence]
end
B --> D
D --> H
style D fill:#e1f5fe
style H fill:#f3e5f5
- Data Variables: Store contract state (owner, goal, total-funded, donor map)
- Public Functions: Handle state-changing operations (fund, withdraw)
- Read-Only Functions: Provide data access without modifying state
- Error Handling: Uses Clarity's
try!andasserts!for robust error management
The following diagram illustrates the complete flow of the FundRaiser system, from donation to withdrawal.
flowchart TD
A[User Initiates Donation] --> B{Amount > 0?}
B -->|No| C[Return Error u1]
B -->|Yes| D[Transfer STX to Contract]
D --> E{Transfer Successful?}
E -->|No| F[Return Transfer Error]
E -->|Yes| G[Update total-funded]
G --> H[Update Donor Map]
H --> I[Return Success]
J[Owner Requests Withdrawal] --> K{Caller is Owner?}
K -->|No| L[Return Error u2]
K -->|Yes| M{total-funded >= goal?}
M -->|No| N[Return Error u3]
M -->|Yes| O[Transfer All Funds to Owner]
O --> P{Transfer Successful?}
P -->|No| Q[Return Transfer Error]
P -->|Yes| R[Reset total-funded to 0]
R --> S[Return Success]
T[Read Operations] --> U[get-balance, get-goal, etc.]
U --> V[Return Data]
style A fill:#d4edda
style J fill:#f8d7da
style T fill:#d1ecf1
- Donation Flow: Validates amount, transfers STX, updates state
- Withdrawal Flow: Verifies ownership and goal achievement, transfers funds
- Query Flow: Provides read-only access to contract data
- Node.js (v16 or higher)
- Clarinet (v2.9.0 or higher)
- Stacks CLI (optional, for advanced interactions)
- A Stacks wallet with testnet STX for deployment and testing
-
Clone the repository:
git clone <repository-url> cd clarity-contract
-
Install dependencies:
npm install
-
Verify Clarinet installation:
clarinet --version
-
Check contract compilation:
clarinet check
-
Fund the contract:
stx contract call STGDS0Y17973EN5TCHNHGJJ9B31XWQ5YXBQ0KQ2Y.fund-raiser fund 500000 --network testnet --fee 1000
-
Check balance:
stx contract call STGDS0Y17973EN5TCHNHGJJ9B31XWQ5YXBQ0KQ2Y.fund-raiser get-balance --network testnet
-
Withdraw funds (owner only):
stx contract call STGDS0Y17973EN5TCHNHGJJ9B31XWQ5YXBQ0KQ2Y.fund-raiser withdraw --network testnet --fee 1000
import { callReadOnlyFn, makeContractCall } from '@stacks/transactions';
// Get current balance
const balance = await callReadOnlyFn({
contractAddress: 'STGDS0Y17973EN5TCHNHGJJ9B31XWQ5YXBQ0KQ2Y',
contractName: 'fund-raiser',
functionName: 'get-balance',
functionArgs: [],
network: 'testnet'
});
// Fund the contract
const fundTx = await makeContractCall({
contractAddress: 'STGDS0Y17973EN5TCHNHGJJ9B31XWQ5YXBQ0KQ2Y',
contractName: 'fund-raiser',
functionName: 'fund',
functionArgs: [uintCV(1000000)], // 1 STX
network: 'testnet'
});- Deployer sets goal to 1,000,000 microSTX (1 STX)
- Users donate STX via the
fundfunction - Contract tracks total funded and individual contributions
- Once total-funded >= goal, owner can call
withdraw - All funds are transferred to owner, contract resets
Allows users to donate STX to the fundraiser.
Parameters:
amount: Amount of microSTX to donate (must be > 0)
Returns:
(ok true)on success(err u1)if amount is 0 or invalid
Events: Updates total-funded and donor map
Allows the contract owner to withdraw all funds once the goal is reached.
Parameters: None
Returns:
(ok true)on success(err u2)if caller is not owner(err u3)if goal not reached
Events: Resets total-funded to 0
Returns the current total funded amount.
Returns the funding goal.
Returns the total amount donated by a specific donor.
Parameters:
donor: The principal address of the donor
Returns the contract owner's principal address.
Run the comprehensive test suite using Vitest:
npm testFor test coverage report:
npm run test:report- ✅ Valid donations and balance updates
- ✅ Rejection of zero-amount donations
- ✅ Multiple donor tracking
- ✅ Owner-only withdrawal restrictions
- ✅ Goal-based withdrawal logic
- ✅ Read-only function accuracy
The contract is already deployed on testnet. To redeploy or deploy to mainnet:
-
Configure network settings in
settings/Testnet.tomlorsettings/Mainnet.toml -
Generate deployment plan:
clarinet deployments generate --testnet --medium-cost
-
Apply deployment:
clarinet deployments apply --testnet
For production deployment:
- Update
settings/Mainnet.tomlwith mainnet configuration - Ensure sufficient STX balance for deployment fees
- Follow the same generate/apply process with
--mainnetflag
This contract implements multiple security measures:
- Access Control: Only owner can withdraw funds
- Input Validation: Amount checks prevent invalid donations
- State Consistency: Atomic operations prevent partial updates
- Overflow Protection: Clarity's built-in overflow handling
- Reentrancy Prevention: Single-threaded execution model
- Error Handling: Comprehensive error codes and messages
- Conduct third-party security audit before mainnet deployment
- Monitor contract interactions post-deployment
- Implement upgrade mechanisms for future improvements
We welcome contributions to improve the FundRaiser contract!
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Clarity best practices
- Add comprehensive tests for new features
- Update documentation for API changes
- Ensure all tests pass before submitting PR
This project is licensed under the MIT License - see the LICENSE file for details.
- Documentation: Clarity Language Reference
- Stacks Docs: Developer Documentation
- Community: Stacks Discord
- Issues: GitHub Issues
For questions or support, please open an issue on GitHub or reach out to the development team.
Built with ❤️ on the Stacks blockchain