-
Notifications
You must be signed in to change notification settings - Fork 139
Expand file tree
/
Copy pathTaskRewardSystem.sol
More file actions
158 lines (135 loc) · 6.21 KB
/
TaskRewardSystem.sol
File metadata and controls
158 lines (135 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract TaskRewardSystem is AccessControl, ReentrancyGuard {
enum TaskStatus { Pending, Claimed, Completed, Validated, Inactive}
struct Task {
uint id;
string description;
uint rewardPoints;
address assignee;
address validator;
TaskStatus status;
}
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant ASSIGNEE_ROLE = keccak256("ASSIGNEE_ROLE");
address public deployer;
uint public nextTaskId;
uint public taskCount;
mapping(uint => Task) public tasks;
mapping(address => uint) public balances;
Task[] public allTasks;
event TaskCreated(uint taskId, string description, uint rewardPoints);
event TaskClaimed(uint taskId, address assignee);
event TaskCompleted(uint taskId);
event TaskValidated(uint taskId, address assignee, uint rewardPoints);
event TaskAssigned(uint taskId, address assignee);
event TaskRewardTransferred(uint taskId, address assignee, uint rewardPoints);
event AdminAssigned(address newAdmin);
event AssigneeAssigned(uint taskId, address assignee);
event TaskUpdated(uint taskId, string newDescription, uint newRewardPoints);
event TaskDeleted(uint taskId);
modifier onlyAdmin() {
require(hasRole(ADMIN_ROLE, msg.sender), "Only admin can perform this action");
_;
}
modifier onlyAssignee(uint taskId) {
require(tasks[taskId].assignee == msg.sender || hasRole(ASSIGNEE_ROLE, msg.sender), "Not authorized");
_;
}
modifier taskNotCompleted(uint taskId) {
require(tasks[taskId].status != TaskStatus.Completed, "Task is already completed");
_;
}
modifier taskNotValidated(uint taskId) {
require(tasks[taskId].status != TaskStatus.Validated, "Task is already validated");
_;
}
modifier taskCanBeClaimed(uint taskId) {
require(tasks[taskId].status != TaskStatus.Claimed, "Task already claimed");
require(tasks[taskId].status != TaskStatus.Validated, "Task already validated");
require(tasks[taskId].status != TaskStatus.Completed, "Task already completed");
require(tasks[taskId].status != TaskStatus.Inactive, "Task already deleted");
_;
}
constructor() {
deployer = msg.sender;
_grantRole(ADMIN_ROLE, msg.sender);
_setRoleAdmin(ASSIGNEE_ROLE, ADMIN_ROLE);
nextTaskId = 1;
taskCount = 0;
}
// Create task
function createTask(string memory description, uint rewardPoints) public onlyAdmin {
tasks[nextTaskId] = Task(nextTaskId, description, rewardPoints, address(0), address(0), TaskStatus.Pending);
taskCount++;
allTasks.push(tasks[nextTaskId]);
emit TaskCreated(nextTaskId, description, rewardPoints);
nextTaskId++;
}
// Assign assignee to a task (only admin can assign an assignee)
function assignAssignee(uint taskId, address assignee) public onlyAdmin {
require(tasks[taskId].assignee == address(0), "Task already has an assignee");
tasks[taskId].assignee = assignee;
_grantRole(ASSIGNEE_ROLE, assignee); // Grant ASSIGNEE_ROLE to the assignee
allTasks[taskId - 1] = tasks[taskId];
emit AssigneeAssigned(taskId, assignee);
}
// Claim task automatically
function claimTask(uint taskId) public taskNotCompleted(taskId) taskCanBeClaimed(taskId) {
tasks[taskId].assignee = msg.sender;
tasks[taskId].status = TaskStatus.Claimed;
allTasks[taskId - 1] = tasks[taskId];
emit TaskClaimed(taskId, msg.sender);
emit TaskAssigned(taskId, msg.sender); // Emit task assigned event
}
// Mark task as complete
function completeTask(uint taskId) public onlyAssignee(taskId) taskNotCompleted(taskId) {
tasks[taskId].status = TaskStatus.Completed;
allTasks[taskId - 1] = tasks[taskId];
emit TaskCompleted(taskId);
}
// Validate task and reward
function validateTask(uint taskId) public onlyAdmin taskNotValidated(taskId) nonReentrant {
require(tasks[taskId].status == TaskStatus.Completed, "Task not completed yet");
tasks[taskId].status = TaskStatus.Validated;
tasks[taskId].validator = msg.sender;
balances[tasks[taskId].assignee] += tasks[taskId].rewardPoints;
allTasks[taskId - 1] = tasks[taskId];
emit TaskValidated(taskId, tasks[taskId].assignee, tasks[taskId].rewardPoints);
emit TaskRewardTransferred(taskId, tasks[taskId].assignee, tasks[taskId].rewardPoints); // Emit reward transfer event
}
// View task status
function viewTaskStatus(uint taskId) public view returns (TaskStatus) {
return tasks[taskId].status;
}
// Assign new admin (Deployer assigns a new admin by passing their address)
function assignAdmin(address newAdmin) public {
require(msg.sender == deployer, "Only the deployer can assign a new admin");
require(newAdmin != address(0), "New admin address cannot be zero address");
_grantRole(ADMIN_ROLE, newAdmin);
emit AdminAssigned(newAdmin);
}
// Get global overview of all tasks
function getAllTasks() public view returns (Task[] memory) {
return allTasks;
}
// Get reward points for a given task
function getRewardPoints(uint taskId) public view returns (uint) {
return tasks[taskId].rewardPoints;
}
// Mark a task as inactive (instead of deleting it)
function deleteTask(uint taskId) public onlyAdmin {
tasks[taskId].status = TaskStatus.Inactive;
allTasks[taskId - 1] = tasks[taskId]; // Mark as inactive in the array
emit TaskDeleted(taskId);
}
// Update task description or reward points (only admin can use this function)
function updateTask(uint taskId, string memory newDescription, uint newRewardPoints) public onlyAdmin {
tasks[taskId].description = newDescription;
tasks[taskId].rewardPoints = newRewardPoints;
allTasks[taskId - 1] = tasks[taskId];
emit TaskUpdated(taskId, newDescription, newRewardPoints);
}
}