-
Notifications
You must be signed in to change notification settings - Fork 585
Expand file tree
/
Copy pathCompetition.sol
More file actions
198 lines (150 loc) · 8.93 KB
/
Copy pathCompetition.sol
File metadata and controls
198 lines (150 loc) · 8.93 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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "../referrals/interfaces/IReferralStorage.sol";
import "../access/Governable.sol";
contract Competition is Governable {
struct Team {
address leader;
string name;
address[] members;
}
struct Competition {
uint start;
uint end;
uint maxTeamSize;
uint8 competitionType;
mapping(address => Team) teams;
mapping(string => bool) teamNames;
mapping(address => address) memberTeams;
mapping(address => address) joinRequests;
mapping(address => mapping(address => bytes32)) joinRequestsReferralCodes;
}
Competition[] public competitions;
IReferralStorage public referralStorage;
event TeamCreated(uint index, address leader, string name);
event JoinRequestCreated(uint index, address member, address leader, bytes32 referralCode);
event JoinRequestCanceled(uint index, address member);
event JoinRequestApproved(uint index, address member, address leader);
event MemberRemoved(uint index, address leader, address member);
event CompetitionCreated(uint index, uint start, uint end, uint maxTeamSize, uint8 competitionType);
event CompetitionUpdated(uint index, uint start, uint end, uint maxTeamSize, uint8 competitionType);
event CompetitionRemoved(uint index);
modifier registrationIsOpen(uint competitionIndex) {
require(competitions[competitionIndex].start > block.timestamp, "Competition: Registration is closed.");
_;
}
modifier isNotMember(uint competitionIndex) {
require(competitions[competitionIndex].memberTeams[msg.sender] == address(0), "Competition: Team members are not allowed.");
_;
}
modifier competitionExists(uint index) {
require(competitions.length > index && competitions[index].start > 0, "Competition: The competition does not exist.");
_;
}
modifier teamsAreAllowed(uint index) {
require(competitions[competitionIndex].competitionType !== 0, "Competition: Team are not allowed.");
_;
}
constructor(IReferralStorage _referralStorage) public {
referralStorage = _referralStorage;
}
function createCompetition(uint start, uint end, uint maxTeamSize, uint8 competitionType) external onlyGov {
_validateCompetitionParameters(start, end, maxTeamSize);
competitions.push(Competition(start, end, maxTeamSize, competitionType));
emit CompetitionCreated(competitions.length - 1, start, end, maxTeamSize);
}
function updateCompetition(uint index, uint start, uint end, uint maxTeamSize, uint8 competitionType) external onlyGov competitionExists(index) {
_validateCompetitionParameters(start, end, maxTeamSize);
competitions[index].start = start;
competitions[index].end = end;
competitions[index].maxTeamSize = maxTeamSize;
competitions[index].competitionType = competitionType;
emit CompetitionUpdated(index, start, end, maxTeamSize, competitionType);
}
function removeCompetition(uint index) external onlyGov competitionExists(index) {
require(competitions[index].start > block.timestamp, "Competition: Competition is active.");
delete competitions[index];
emit CompetitionRemoved(index);
}
function createTeam(uint competitionIndex, string calldata name) external registrationIsOpen(competitionIndex) isNotMember(competitionIndex) teamsAreAllowed(competitionIndex) {
Competition storage competition = competitions[competitionIndex];
require(!competition.teamNames[name], "Competition: Team name already registered.");
Team storage team = competition.teams[msg.sender];
team.leader = msg.sender;
team.name = name;
team.members.push(msg.sender);
competition.teamNames[name] = true;
competition.memberTeams[msg.sender] = msg.sender;
emit TeamCreated(competitionIndex, msg.sender, name);
}
function createJoinRequest(uint competitionIndex, address leaderAddress, bytes32 referralCode) external registrationIsOpen(competitionIndex) isNotMember(competitionIndex) teamsAreAllowed(competitionIndex) {
Competition storage competition = competitions[competitionIndex];
require(competition.memberTeams[msg.sender] == address(0), "Competition: You can't join multiple teams.");
require(competition.teams[leaderAddress].leader != address(0), "Competition: The team does not exist.");
if (referralCode != bytes32(0)) {
require(referralStorage.codeOwners(referralCode) != address(0), "Competition: The referral code does not exist.");
}
competition.joinRequests[msg.sender] = leaderAddress;
competition.joinRequestsReferralCodes[msg.sender][leaderAddress] = referralCode;
emit JoinRequestCreated(competitionIndex, msg.sender, leaderAddress, referralCode);
}
function approveJoinRequest(uint competitionIndex, address[] calldata memberAddresses) external registrationIsOpen(competitionIndex) teamsAreAllowed(competitionIndex) {
Competition storage competition = competitions[competitionIndex];
for (uint i = 0; i < memberAddresses.length; i++) {
address memberAddress = memberAddresses[i];
require(competition.joinRequests[memberAddress] == msg.sender, "Competition: Member did not apply.");
require(competition.memberTeams[memberAddress] == address(0), "Competition: Member already joined a team.");
require(competition.teams[msg.sender].members.length < competition.maxTeamSize, "Competition: Team is full.");
if (competition.joinRequestsReferralCodes[memberAddress][msg.sender] != bytes32(0)) {
referralStorage.setTraderReferralCode(memberAddress, competition.joinRequestsReferralCodes[memberAddress][msg.sender]);
}
competition.teams[msg.sender].members.push(memberAddress);
competition.memberTeams[memberAddress] = msg.sender;
competition.joinRequests[memberAddress] = address(0);
emit JoinRequestApproved(competitionIndex, memberAddress, msg.sender);
}
}
function cancelJoinRequest(uint competitionIndex) external registrationIsOpen(competitionIndex) teamsAreAllowed(competitionIndex) {
competitions[competitionIndex].joinRequests[msg.sender] = address(0);
emit JoinRequestCanceled(competitionIndex, msg.sender);
}
function removeMember(uint competitionIndex, address leaderAddress, address memberAddress) external registrationIsOpen(competitionIndex) teamsAreAllowed(competitionIndex) {
Competition storage competition = competitions[competitionIndex];
require(competition.memberTeams[memberAddress] == msg.sender || memberAddress == msg.sender, "Competition: You are not allowed to remove this member.");
address[] memory oldMembers = competition.teams[leaderAddress].members;
delete competition.teams[leaderAddress].members;
for (uint i = 0; i < oldMembers.length; i++) {
if (oldMembers[i] != memberAddress) {
competition.teams[leaderAddress].members.push(oldMembers[i]);
}
}
competition.memberTeams[memberAddress] = address(0);
emit MemberRemoved(competitionIndex, leaderAddress, memberAddress);
}
function getTeam(uint competitionIndex, address _leaderAddress) external view returns (address leaderAddress, string memory name) {
Team memory team = competitions[competitionIndex].teams[_leaderAddress];
return (team.leader, team.name);
}
function getTeamMembers(uint competitionIndex, address leaderAddress, uint start, uint offset) external view returns (address[] memory members) {
address[] memory members = competitions[competitionIndex].teams[leaderAddress].members;
address[] memory result = new address[](offset);
for (uint i = start; i < start + offset && i < members.length; i++) {
result[i] = members[i];
}
return result;
}
function getMemberTeam(uint competitionIndex, address memberAddress) external view returns (address leaderAddress) {
return competitions[competitionIndex].memberTeams[memberAddress];
}
function getJoinRequest(uint competitionIndex, address memberAddress) external view returns (address leaderAddress) {
return competitions[competitionIndex].joinRequests[memberAddress];
}
function validateName(uint competitionIndex, string calldata name) external view returns (bool isValid) {
return !competitions[competitionIndex].teamNames[name];
}
function _validateCompetitionParameters(uint start, uint end, uint maxTeamSize) internal {
require(start > block.timestamp, "Competition: Start time must be in the future.");
require(end > start, "Competition: End time must be greater than start time.");
require(maxTeamSize > 0, "Competition: Max team size must be greater than zero.");
}
}