TaskBounty is a decentralized task and reward management system built on Ethereum. It provides a trustless platform for posting tasks, submitting work, and managing payments through smart contracts.
- Trustless Execution: All funds are escrowed in smart contracts
- Transparency: All actions are recorded on-chain with events
- Modularity: Separate concerns into distinct contracts
- Security: Reentrancy protection, access control, input validation
- Gas Efficiency: Optimized storage patterns and minimal operations
┌─────────────────────────────────────────────────────────────┐
│ TaskBountyFactory │
│ - Deploys new TaskBounty instances │
│ - Tracks all deployments │
└─────────────────────────────────────────────────────────────┘
│
│ creates
▼
┌─────────────────────────────────────────────────────────────┐
│ TaskBountyCore │
│ - Task creation and management │
│ - Work submission handling │
│ - Approval/rejection logic │
│ - Payment automation │
└─────────────────────────────────────────────────────────────┘
│
│ uses
▼
┌─────────────────────────────────────────────────────────────┐
│ DisputeResolver │
│ - Dispute creation and tracking │
│ - Arbitrator management │
│ - Resolution mechanism │
└─────────────────────────────────────────────────────────────┘
Responsibilities:
- Task lifecycle management (create, cancel, complete)
- Work submission handling
- Approval and rejection of submissions
- Automatic payment distribution
- Integration with dispute resolution
Key Features:
- Escrows rewards when tasks are created
- Enforces deadline constraints
- Supports multiple submissions per task
- Prevents duplicate submissions from same contributor
- Emits events for off-chain indexing
State Management:
Task States:
Open → InProgress → Completed
↓ ↓
Cancelled Disputed
Submission States:
Pending → Approved
↓
RejectedResponsibilities:
- Create and track disputes
- Manage arbitrator permissions
- Resolve disputes with binding outcomes
Key Features:
- One dispute per submission
- Multiple arbitrators supported
- Owner can add/remove arbitrators
- Disputes linked to specific submissions
Access Control:
- Only TaskBounty contract can create disputes
- Only arbitrators can resolve disputes
- Only owner can manage arbitrators
Responsibilities:
- Deploy new TaskBounty instances
- Track all deployments
- Associate deployments with creators
Use Cases:
- Organizations creating private bounty boards
- Different communities with custom arbitrators
- Testing and development environments
struct Task {
uint256 id; // Unique identifier
address poster; // Task creator
string title; // Short title
string description; // Detailed requirements
uint256 reward; // Escrowed payment
uint256 deadline; // Submission deadline
uint256 maxSubmissions; // Max allowed submissions
uint256 submissionCount; // Current submission count
TaskStatus status; // Current state
uint256 createdAt; // Creation timestamp
}struct Submission {
uint256 id; // Unique identifier
uint256 taskId; // Associated task
address contributor; // Submitter address
string workUrl; // Link to work (GitHub, IPFS, etc.)
string description; // Work description
uint256 submittedAt; // Submission timestamp
SubmissionStatus status; // Current state
}struct Dispute {
uint256 id; // Unique identifier
uint256 taskId; // Associated task
uint256 submissionId; // Associated submission
address raiser; // Who raised the dispute
string reason; // Dispute reason
uint256 createdAt; // Creation timestamp
DisputeStatus status; // Current state
bool favorContributor; // Resolution outcome
address resolver; // Arbitrator who resolved
}- All external calls use
nonReentrantmodifier - State changes before external calls (CEI pattern)
- Uses OpenZeppelin-style reentrancy guard
- Task posters can only modify their own tasks
- Contributors can only submit once per task
- Arbitrators have limited, specific permissions
- Owner has administrative control over arbitrators
- Minimum reward requirements
- Deadline bounds checking
- Max submissions validation
- Status transition validation
- Rewards escrowed at task creation
- Payments only released on approval
- Refunds only on cancellation
- No partial withdrawals
// Packed struct (saves gas)
struct Task {
uint256 id; // slot 0
address poster; // slot 1 (20 bytes)
// ... strings in separate slots
uint256 reward; // slot N
uint256 deadline; // slot N+1
uint256 maxSubmissions; // slot N+2 (could pack with smaller types)
uint256 submissionCount; // slot N+3
TaskStatus status; // slot N+4 (1 byte, could pack)
uint256 createdAt; // slot N+5
}- Minimal Storage Reads: Cache storage variables in memory
- Batch Operations: Process multiple items in single transaction
- Event Emission: Use events for off-chain data instead of storage
- Short-Circuit Logic: Early returns to save gas
- Immutable Variables: Use
immutablefor deployment-time constants
All state changes emit events for off-chain indexing:
// Task events
event TaskCreated(uint256 indexed taskId, address indexed poster, ...);
event TaskCancelled(uint256 indexed taskId, address indexed poster);
// Submission events
event WorkSubmitted(uint256 indexed taskId, uint256 indexed submissionId, ...);
event SubmissionApproved(uint256 indexed taskId, uint256 indexed submissionId, ...);
event SubmissionRejected(uint256 indexed taskId, uint256 indexed submissionId, ...);
// Dispute events
event DisputeRaised(uint256 indexed taskId, uint256 indexed submissionId, ...);
event DisputeCreated(uint256 indexed disputeId, ...);
event DisputeResolved(uint256 indexed disputeId, ...);Track contributor and poster reputation based on completed tasks and quality.
mapping(address => uint256) public reputation;
mapping(address => uint256) public completedTasks;Break large tasks into smaller milestones with partial payments.
struct Milestone {
string description;
uint256 reward;
bool completed;
}Accept ERC20 tokens as rewards instead of just ETH.
struct Task {
// ... existing fields
address rewardToken; // address(0) for ETH
}Require contributors to stake tokens to submit work.
mapping(uint256 => mapping(address => uint256)) public stakes;Replace single arbitrator with DAO voting for disputes.
interface IGovernance {
function vote(uint256 disputeId, bool favorContributor) external;
function executeResolution(uint256 disputeId) external;
}Stream rewards over time instead of lump sum payments.
import {Drips} from "drips-protocol/Drips.sol";
function streamReward(address contributor, uint256 amount, uint256 duration) internal {
// Configure streaming payment
}- Test individual contract functions
- Test error conditions and edge cases
- Test access control
- Test state transitions
- Test complete workflows
- Test contract interactions
- Test dispute resolution flow
- Test factory deployments
- Measure gas costs for common operations
- Optimize hot paths
- Compare against alternatives
- Reentrancy attack scenarios
- Access control bypass attempts
- Integer overflow/underflow
- Front-running scenarios
anvil # Start local node
forge script script/Deploy.s.sol --rpc-url http://localhost:8545 --broadcastforge script script/Deploy.s.sol \
--rpc-url $SEPOLIA_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify- Audit contracts thoroughly
- Deploy to testnet first
- Test all functionality
- Deploy with multisig owner
- Verify on Etherscan
- Transfer ownership to DAO/multisig
- NFT Certificates: Issue NFTs for completed tasks
- Skill Tags: Categorize tasks by required skills
- Escrow Extensions: Allow deadline extensions with mutual consent
- Partial Payments: Split rewards among multiple contributors
- Automated Arbitration: Use Kleros or similar for disputes
- Cross-Chain: Deploy on multiple chains with bridge support
- Privacy: Use zero-knowledge proofs for private tasks
- Social Features: Profiles, ratings, portfolios