-
Notifications
You must be signed in to change notification settings - Fork 0
/
Le.sol
244 lines (194 loc) · 8.97 KB
/
Le.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
pragma solidity ^0.8.0;
enum State { draft, active, terminated, violated }
struct Party {
string name;
address payable wallet;
bool signed;
}
contract Agreement {
Party public partyA;
Party public partyB;
uint256 public executionDate;
uint256 public endDate;
uint256 public renewalPeriod;
uint256 public terminationDate;
uint256 public terminationNoticePeriod;
uint256 public terminationNoticeDate;
uint256 public violatedDate;
bool public competingProductsRestriction;
bool public isRenewed;
bool public writtenApproval;
bool public auditRights;
uint256 public auditProvideDate;
uint256 public auditPeriod;
uint256 public seasonAdThreshold;
uint256 public addTotalFee;
uint256 public addTotalDemand;
uint256 public payPercentage; // Represented as basis points e.g., 1500 for 15%
uint256 public recommendFee;
uint256[] public incomes;
address[] public dataOwnership;
uint256 public nextAdFeeDate;
uint256 public nextIncomePayDate;
bool public transferStatus;
State public currentState;
event sign_agreement();
event renew_agreement();
event terminate_agreement();
event breach_advertisement();
event transfer_approval();
event transfer_contract();
event pay_on_success_candidate();
event pay_income();
event ad_fee_requirements();
event ad_fee_violate();
event audit_provide();
event StateTransition(State from, State to);
constructor(address payable _partyA, address payable _partyB) {
partyA = Party("VerticalNet", _partyA, false);
partyB = Party("LeadersOnline", _partyB, false);
endDate = timestampToDate("2001-06-15");
renewalPeriod = 365 days;
terminationNoticePeriod = 90 days;
competingProductsRestriction = true;
auditRights = true;
auditPeriod = 12 * 30 days;
seasonAdThreshold = 1000000;
addTotalDemand = 10000000;
payPercentage = 1500; // 15%
recommendFee = 1000;
currentState = State.draft;
}
function timestampToDate(string memory _date) internal pure returns (uint256 timestamp) {
// Implement date string to timestamp conversion (Simplified example - vulnerable to errors)
(uint16 year, uint8 month, uint8 day) = splitDate(_date);
timestamp = uint256((year - 1970) * 31536000 + month * 2592000 + day * 86400); // Approx. conversion
}
function splitDate(string memory _date) internal pure returns (uint16 year, uint8 month, uint8 day) {
bytes memory dateBytes = bytes(_date);
year = uint16(parseUint(dateBytes, 0, 4));
month = uint8(parseUint(dateBytes, 5, 2));
day = uint8(parseUint(dateBytes, 8, 2));
}
function parseUint(bytes memory _bytes, uint256 _start, uint256 _len) internal pure returns (uint256 res) {
for(uint256 i = _start; i < _start + _len; i++) {
res = res * 10 + uint8(_bytes[i]) - 48;
}
}
function safeTransfer(address payable _to, uint256 _amount) internal {
(bool success, ) = _to.call{value: _amount}("");
require(success, "Transfer failed.");
}
function signAgreement() public {
require(currentState == State.draft, "Invalid state transition.");
bool bothSigned = false;
if (msg.sender == partyA.wallet) {
partyA.signed = true;
} else if (msg.sender == partyB.wallet) {
partyB.signed = true;
} else {
revert("Unauthorized party.");
}
if (partyA.signed && partyB.signed) {
executionDate = block.timestamp;
nextIncomePayDate = executionDate + 30 days;
nextAdFeeDate = executionDate + 120 days;
currentState = State.active;
emit StateTransition(State.draft, State.active);
}
emit sign_agreement();
}
function renewAgreement(bool renew_approval) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyA.wallet, "Unauthorized party.");
require(block.timestamp < endDate, "Agreement already ended.");
require(renew_approval, "Renewal not approved.");
isRenewed = true;
endDate = endDate + renewalPeriod;
emit renew_agreement();
}
function terminateAgreement() public {
require(currentState == State.active, "Invalid state transition.");
require(terminationNoticeDate != 0, "Termination notice date not set."); // Guard: terminationNoticeDate is not null
terminationDate = block.timestamp;
dataOwnership.push(partyA.wallet);
dataOwnership.push(partyB.wallet);
currentState = State.terminated;
emit terminate_agreement();
emit StateTransition(State.active, State.terminated);
}
function breachAdvertisement(bool competitorAdvertisement) public {
require(currentState == State.active, "Invalid state transition.");
require(competitorAdvertisement, "No competitor advertisement reported.");
violatedDate = block.timestamp;
currentState = State.violated;
emit breach_advertisement();
emit StateTransition(State.active, State.violated);
}
function transferApproval(bool _writtenApproval) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyB.wallet, "Unauthorized party.");
writtenApproval = _writtenApproval; // Assuming input is the intended new value
emit transfer_approval();
}
function transferContract(bool _writtenApproval, bool isCompetitor, address payable transferParty) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyA.wallet, "Unauthorized party.");
require(_writtenApproval, "Written approval required.");
require(!isCompetitor, "Transfer to competitor not allowed.");
transferStatus = true;
partyA.wallet = transferParty; // Updating the partyA
emit transfer_contract();
}
function payOnSuccessCandidate(bool recommendCheck) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyB.wallet, "Unauthorized party.");
require(recommendCheck, "Recommendation check failed.");
safeTransfer(partyA.wallet, recommendFee);
// recommendCheck = false; Not allowed - it's an input parameter.
emit pay_on_success_candidate();
}
function payIncome(uint256 income) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyB.wallet, "Unauthorized party.");
require(block.timestamp > nextIncomePayDate, "Next income payment date not reached.");
uint256 amountToPay = (income * payPercentage) / 10000; // Correct percentage calculation
safeTransfer(partyA.wallet, amountToPay);
incomes.push(income);
nextIncomePayDate = nextIncomePayDate + 30 days;
emit pay_income();
}
function adFeeRequirements(uint256 adFee) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyB.wallet, "Unauthorized party.");
require(block.timestamp > nextAdFeeDate, "Next ad fee payment not due yet.");
require(adFee > seasonAdThreshold, "Ad fee below threshold.");
safeTransfer(partyA.wallet, adFee); // Transfer the adFee, not income
addTotalFee += adFee;
nextAdFeeDate = nextAdFeeDate + 120 days;
emit ad_fee_requirements();
}
function adFeeViolate() public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyB.wallet, "Unauthorized party.");
require(block.timestamp > endDate, "Agreement not ended yet.");
require(addTotalFee < addTotalDemand, "Ad fee demand met.");
violatedDate = block.timestamp;
currentState = State.terminated; // Transition to terminated
emit ad_fee_violate();
emit StateTransition(State.active, State.terminated);
}
function auditProvide(bool auditCheck) public {
require(currentState == State.active, "Invalid state transition.");
require(msg.sender == partyB.wallet, "Unauthorized party.");
require(auditCheck, "Audit check failed."); // Corrected check condition
require(block.timestamp <= nextIncomePayDate - 30 days + auditPeriod && block.timestamp >= nextIncomePayDate - 30 days,"Outside the allowed audit provide period.");
auditProvideDate = block.timestamp;
emit audit_provide();
}
// Helper function to set the termination notice date (can be called by authorized party to initiate termination process). This simplifies the terminateAgreement function.
function setTerminationNoticeDate() public {
require(currentState == State.active, "Invalid State");
terminationNoticeDate = block.timestamp;
}
}