-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfreelanceProject.sol
125 lines (96 loc) · 3.79 KB
/
freelanceProject.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
pragma solidity 0.8.3;
pragma experimental ABIEncoderV2;
contract Project{
enum Status {COMPLETED, PENDING, CANCELED}
address payable public employer;
address payable public freelancer;
uint public deadline;
uint public price;
uint public remainingPayment;
uint public createdAt;
Status public status;
bool locked = false;
struct Request{
string description;
uint amount;
bool locked;
bool paid;
}
Request[] public requests;
modifier onlyEmployer(){
require(msg.sender == employer, "Only employer!");
_;
}
modifier onlyFreelancer(){
require(msg.sender == freelancer, "Only freelancer!");
_;
}
modifier onlyPendingProject(){
require(status == Status.PENDING, "Only pending!");
_;
}
event RequestCreated(string description, uint amount, bool locked, bool paid);
event RequestUnlocked(bool locked);
event RequestPaid(address receiver, uint amount);
event ProjectCompleted(address employer, address freelancer, uint amount, Status status);
event ProjectCanceled(uint remainingPayment, Status status);
constructor(address payable _freelancer, uint _deadline) payable {
employer = payable(msg.sender);
freelancer = _freelancer;
deadline = block.timestamp + _deadline * 1 days;
createdAt = block.timestamp;
price = msg.value;
remainingPayment = msg.value;
status = Status.PENDING;
}
receive() external payable{
price += msg.value;
}
function createRequest(string memory _description, uint _amount) public onlyFreelancer onlyPendingProject{
require(_amount <= remainingPayment, "High request price!");
Request memory request = Request({
description: _description,
amount: _amount,
locked: true,
paid: false
});
requests.push(request);
emit RequestCreated(request.description, request.amount, request.locked, request.paid);
}
function unlockRequest(uint _index) public onlyEmployer onlyPendingProject{
Request storage request = requests[_index];
require(request.locked, "Already unlocked!");
request.locked = false;
emit RequestUnlocked(request.locked);
}
function payRequest(uint _index) public onlyFreelancer{
require(!locked, "Reenterant detected!");
Request storage request = requests[_index];
require(!request.locked, "Request is locked!");
require(!request.paid, "Already paid!");
locked = true;
(bool success, bytes memory transaction) = freelancer.call{value: request.amount}("");
require(success, "Transaction failed!");
remainingPayment -= request.amount;
request.paid = true;
locked = false;
emit RequestPaid(msg.sender, request.amount);
}
function completeProject() public onlyEmployer onlyPendingProject{
require(!locked, "Reenterant detected!");
locked = true;
(bool success, bytes memory transaction) = freelancer.call{value: remainingPayment}("");
require(success, "Transaction failed!");
status = Status.COMPLETED;
locked = false;
emit ProjectCompleted(employer, freelancer, remainingPayment, status);
}
function cancelProject() public onlyEmployer onlyPendingProject{
require(block.timestamp > deadline, "Deadline passed!");
status = Status.CANCELED;
emit ProjectCanceled(remainingPayment, status);
}
function increaseDeadline(uint _deadline) public onlyEmployer onlyPendingProject{
deadline += _deadline;
}
}