-
Notifications
You must be signed in to change notification settings - Fork 1
/
Gurukul.sol
152 lines (120 loc) · 5.29 KB
/
Gurukul.sol
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
// contracts/Gurukul.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract Gurukul {
address owner;
using Counters for Counters.Counter;
Counters.Counter private courseIds;
//Creating constant parameters for now - ONLY FOR HACKATHON
//Will change based on the length of course and other parameters
uint256 public constant CREATOR_STAKE = 100;
//Will change based on the type of course and other parameters
uint256 public constant STUDENT_STAKE = 50;
ERC20 guruToken;
struct Course {
address creator;
uint256 courseId;
string name;
}
Course[] courses;
mapping(address => uint256[]) creatorCourseMap;
mapping(uint256 => Course) courseMap;
mapping(address => uint256[]) studentCourseMap;
mapping(address => mapping(uint256 => bool)) courseCompletion;
mapping(address => uint256[]) completedCoursesByStudent;
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}
constructor(address guruTokenAddress) {
guruToken = ERC20(guruTokenAddress);
owner = msg.sender;
}
//Internal function to transfer the GURU tokens
function depositToken(address tokenOwner, uint256 amount) internal {
uint256 amountToDeposit = amount * (1 ether);
uint256 balance = guruToken.balanceOf(tokenOwner);
require(balance >= amountToDeposit,"Balance is low");
guruToken.transferFrom(tokenOwner, address(this),amountToDeposit);
}
//Creator calls this function to create the course
function createCourse(string memory name) public {
courseIds.increment();
uint256 courseId = courseIds.current();
//Step1: Deposit the creator stake
depositToken(msg.sender, CREATOR_STAKE);
Course memory course = Course(msg.sender, courseId , name);
creatorCourseMap[msg.sender].push(courseId);
courseMap[courseId] = course;
courses.push(course);
}
//Call this function when the student enrolls in a course - Called by student
function joinCourse(uint256 courseId) public {
//Step1: Deposit the student stake
depositToken(msg.sender, STUDENT_STAKE);
studentCourseMap[msg.sender].push(courseId);
courseCompletion[msg.sender][courseId] = false;
}
//Call this function when the course is completed - Called by student
function completeCourse(uint256 courseId) public {
require(courseCompletion[msg.sender][courseId] == false, "Student has already completed this course");
bool hasEnrolled = false;
//Checking if the student enrolled in this course
for(uint i = 0; i < studentCourseMap[msg.sender].length; i++) {
if(studentCourseMap[msg.sender][i] == courseId) {
hasEnrolled = true;
}
}
require(hasEnrolled, "Student has not enrolled in this course");
courseCompletion[msg.sender][courseId] = true;
address courseCreator = courseMap[courseId].creator;
//Distributing staked money - 80% to student, 10% to creator and 10% to platform
//Platform amount remains in the contract
uint256 studentAmount = 40 * 1 ether;
uint256 creatorAmount = 5 * 1 ether;
completedCoursesByStudent[msg.sender].push(courseId);
uint256 guruBalance = guruToken.balanceOf(owner);
require(guruBalance > (STUDENT_STAKE * 1 ether), "Not enough balance in the pool");
guruToken.transferFrom(owner, msg.sender, studentAmount);
guruToken.transferFrom(owner, payable(courseCreator), creatorAmount);
}
//Get all the courses created on the platform
function getAllCourses() public view returns(Course[] memory) {
return courses;
}
//Get all the courses enrolled by a particular student
function getStudentCourse(address studentAddress) public view returns(uint256[] memory) {
return studentCourseMap[studentAddress];
}
//Get all the courses completed by a particular student
function getStudentCompletedCourses(address studentAddress) public view returns(uint256[] memory) {
return completedCoursesByStudent[studentAddress];
}
//Withdraw the funds from the contract
function withDrawFunds(uint256 amount) public onlyOwner {
uint256 amountToDeposit = amount * (1 ether);
uint256 balance = guruToken.balanceOf(address(this));
require(balance >= amountToDeposit,"Balance is low");
guruToken.transferFrom(address(this), msg.sender, amountToDeposit);
}
}
/**
* @title Guru
* @dev Very simple ERC20 Token example, where all tokens are pre-assigned to the creator.
* Note they can later distribute these tokens as they wish using `transfer` and other
* `ERC20` functions.
* Based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v2.5.1/contracts/examples/SimpleToken.sol
*/
contract Guru is ERC20 {
/**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
constructor(
) ERC20("Gurukul", "GURU") {
//Minting 10 million GURU tokens
uint256 totalSupply = 10000000 * 1 ether;
_mint(msg.sender, totalSupply);
}
}