-
Notifications
You must be signed in to change notification settings - Fork 5
/
Payroll.sol
280 lines (249 loc) · 8.17 KB
/
Payroll.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
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
pragma solidity ^0.4.21;
/// @title Payroll contract - Manage employees and token payments
/// @author Nicolas frega - <frega.nicolas@gmail.com>
import "./InterfacePayroll.sol";
import "./EmployeeStorage.sol";
import "./EmployeeToken.sol";
contract Payroll is InterfacePayroll, Ownable {
using SafeMath for uint256;
/*
* Events
*/
event Deposit(address indexed sender, uint value);
event NewEmployee(address indexed newEmployee);
event EmployeeAddressChange(address indexed newAddress);
event EmployeePaydayChange(address indexed employeeAddress, uint indexed newPayday);
event EmployeeSalaryChange(address indexed employeeAddress, uint indexed newSalary);
event EmployeeRemoved(address indexed employeeAddress, uint indexed_id);
event EmployeePayed(address indexed employeeAddress, uint payPeriod);
/*
* Storage
*/
InterfaceEmployeeStorage public employeeStorage;
EmployeeToken public employeeToken;
/*
* Modifiers
*/
modifier validAddress(address _address) {
require (_address != 0x0);
_;
}
modifier higherThanZero(uint256 _uint) {
require(_uint > 0);
_;
}
modifier employeePayPeriodExists(uint256 _payPeriod) {
require(_payPeriod == employeeStorage.getLatestPayday(msg.sender));
_;
}
modifier enoughTokensLeft() {
uint256 tokensLeft = employeeToken.balanceOf(employeeToken.owner());
require(employeeStorage.getMonthlySalary(msg.sender) < tokensLeft);
_;
}
/// @dev Fallback function allows to deposit ether.
function()
public
payable
{
if (msg.value > 0) {
emit Deposit(msg.sender, msg.value);
}
}
/*
* Public functions
*/
/// @dev Contract constructor sets employee storage and employee token.
constructor()
public
{
setEmployeeStorage(new EmployeeStorage());
setEmployeeToken(new EmployeeToken());
}
/// @dev adds a new employee.
/// @param _address Address of new employee.
/// @param _monthlySalary uint of salary.
/// @param _startDate uint of starting date.
function addEmployee(address _address, uint256 _monthlySalary, uint256 _startDate)
public
onlyOwner
validAddress(_address)
higherThanZero(_monthlySalary)
{
employeeStorage.add(_address, _monthlySalary, _startDate);
emit NewEmployee(_address);
}
/// @dev changes the address of an existing employee.
/// @param _id uint of existing employee id.
/// @param _address Address of employee.
function setEmployeeAddress(uint256 _id, address _address)
public
onlyOwner
validAddress(_address)
{
address employeeAddress = employeeStorage.getAddress(_id);
employeeStorage.setAddress(employeeAddress, _address);
emit EmployeeAddressChange(employeeAddress);
}
/// @dev changes the payday of an existing employee.
/// @param _address Address of employee.
/// @param _date uint of new pay day.
function setEmployeePayday(address _address, uint256 _date)
public
onlyOwner
validAddress(_address)
{
employeeStorage.setlatestPayday(_address, _date);
emit EmployeePaydayChange(_address, _date);
}
/// @dev changes the salary of an existing employee.
/// @param _id uint of existing employee id.
/// @param _monthlySalary uint of new pay day.
function setEmployeeSalary(uint256 _id, uint256 _monthlySalary)
public
onlyOwner
higherThanZero(_monthlySalary)
{
address employeeAddress = employeeStorage.getAddress(_id);
employeeStorage.setMonthlySalary(employeeAddress, _monthlySalary);
emit EmployeeSalaryChange(employeeAddress, _monthlySalary);
}
/// @dev gets the total employee count.
/// @return Returns employee count.
function getEmployeeCount()
public
onlyOwner
view
returns (uint256)
{
return employeeStorage.getCount();
}
/// @dev gets the employee ID.
/// @param _address Address of existing employee.
/// @return Returns employee ID.
function getEmployeeID(address _address)
public
onlyOwner
validAddress(_address)
view
returns (uint256)
{
return employeeStorage.getId(_address);
}
/// @dev gets the total employee address from ID.
/// @param _id ID of existing employee.
/// @return Returns employee address.
function getEmployeeAddress(uint256 _id)
public
onlyOwner
view
returns (address)
{
return employeeStorage.getAddress(_id);
}
/// @dev gets the latest employee pay day.
/// @param _address Address of existing employee.
/// @return Returns employee pay day.
function getEmployeePayday(address _address)
public
onlyOwner
validAddress(_address)
view
returns (uint256)
{
return employeeStorage.getLatestPayday(_address);
}
/// @dev gets the employee salary.
/// @param _address Address of existing employee.
/// @return Returns employee salary.
function getEmployeeSalary(address _address)
public
onlyOwner
validAddress(_address)
view
returns (uint256)
{
return employeeStorage.getMonthlySalary(_address);
}
/// @dev gets the total employee info.
/// @param _id ID of existing employee.
/// @return Returns all existing employee info.
function getEmployee(uint256 _id)
public
onlyOwner
view
returns (address _address, uint256 _payday, uint256 _salary, uint256 _payed)
{
_address = employeeStorage.getAddress(_id);
_payday = employeeStorage.getLatestPayday(employeeStorage.getAddress(_id));
_salary = employeeStorage.getMonthlySalary(employeeStorage.getAddress(_id));
_payed = employeeToken.balanceOf(_address);
}
/// @dev gets the balance of employee.
/// @param _id ID of existing employee.
/// @return Returns employee balance.
function getEmployeeBalance(uint256 _id)
public
onlyOwner
view
returns (uint256)
{
address employeeAddress = employeeStorage.getAddress(_id);
return employeeToken.balanceOf(employeeAddress);
}
/// @dev gets the balance left of employee tokens.
/// @return Returns the token balance.
function getTotalSupply()
public
onlyOwner
view
returns (uint256)
{
return employeeToken.totalSupply();
}
/// @dev removes and employee.
/// @param _id ID of existing employee.
function removeEmployee(uint256 _id)
public
onlyOwner
{
address employeeAddress = employeeStorage.getAddress(_id);
employeeStorage.remove(employeeAddress);
emit EmployeeRemoved(employeeAddress, _id);
}
/// @dev allows employee to get payed.
/// @param _payPeriod of requested payment.
function getPay (uint256 _payPeriod)
public
employeePayPeriodExists(_payPeriod)
enoughTokensLeft()
{
uint256 employeeSalary = employeeStorage.getMonthlySalary(msg.sender);
employeeToken.transfer(msg.sender, employeeSalary);
uint256 newPayday = employeeStorage.getLatestPayday(msg.sender);
newPayday++;
employeeStorage.setlatestPayday(msg.sender, newPayday);
emit EmployeePayed(msg.sender, newPayday--);
}
/*
* Internal functions
*/
/// @dev sets the employee storage contract.
/// @param _newEmployeeStorage Address of new employee storage.
function setEmployeeStorage(address _newEmployeeStorage)
internal
onlyOwner
validAddress(_newEmployeeStorage)
{
employeeStorage = InterfaceEmployeeStorage(_newEmployeeStorage);
}
/// @dev sets the employee token contract.
/// @param _newEmployeetoken Address of new employee token.
function setEmployeeToken(address _newEmployeetoken)
internal
onlyOwner
validAddress(_newEmployeetoken)
{
employeeToken = EmployeeToken(_newEmployeetoken);
}
}