1個函式 reclaimLeaseDeposit() 公開 {
2 租賃儲存租賃= tenantLease [msg.sender];
3 要求(lease.leaseFullyPaid, “必須全額支付租賃費用才能收回租賃押金”);
4 require(lease.leaseDepositUsd> 0, “租賃押金已被刪除”);
5
6 tenantAddress = msg.sender;
7 workingState = State.reclaimingLeaseDeposit;
8 fetchUsdRate();
9 }
10
11 函式 _reclaimLeaseDeposit() 內部 {
12 workingState = State.idle;
13 租賃儲存租賃= tenantLease [tenantAddress];
14 uint leaseDeposit = lease.leaseDepositUsd;
15 lease.leaseDepositUsd = 0 ;
16 tenantAddress.transfer(leaseDeposit.div(ETHUSD).mul(1E18));
17
18 發出leaseDepositReclaimed(
19 tenantAddress,
20 leaseDeposit
21 );
22 }
第1行例示了我們的public函式,用於替換租賃押金。租戶已全額付清租金,這函式由租戶呼叫。
第2-4行是重複邏輯。
第6-8行是重複邏輯。
第11行開始內部函式,以繼續重置租賃押金的過程。此函式的其餘部分是collectLeaseDeposit的重複邏輯。
1個函式 withdrawFunds()僅 公共 房東 {
2 要求(leaseBalanceWei> 0, “租賃餘額必須大於0”));
3 uint transferAmount = leaseBalanceWei;
4 leaseBalanceWei = 0 ;
5 房東地址.transfer(transferAmount);
6
7 發出資金提取(
8 轉移 金額,
9租賃餘額魏
10 );
11 }
12
13 函式 getLease(地址租戶) 公共 檢視 返回 (
14 UINT8,
15 UINT8,
16 UINT16,
17 UINT16,
18 UINT32,
19 UINT64,
20 UINT64,
21 布林,
22 布林) {
23 租賃儲存器租賃= tenantLease [租戶];
24 return (
25 lease.numberOfMonths,
26 lease.monthsPaid,
27 lease.monthlyAmountUsd,
28 lease.leaseDepositUsd,
29 lease.leasePaymentWindowSeconds,
30 lease.leasePaymentWindowEnd,
31 lease.depositPaymentWindowEnd,
32 lease.leaseDepositPaid,
33 lease.leaseFullyPaid
34 );
35 }
36
37 函式 getRate() 公眾 視野 收益 (uint) {
38 return ETHUSD;
39 }
40
41 函式 getContractBalance() 公開 檢視 返回 (uint) {
42 return uint(address(this).balance);
43 }
44
45 功能() 外部 應付款項 {}
第1-11行是房東呼叫的用於提取租賃付款的函式。
第2行確保餘額大於0。
第3-5行顯示了與_collectLeaseDeposit和_reclaimLeaseDeposit相同的提款方式。智慧合約將餘額轉移給房東。
第7-10行發出了fundsWithdrawn事件。
第13–35行表示一個實用函式,用於在給定租戶地址的情況下檢索啟用租賃上的所有屬性。
第13-22行告訴函式它必須返回某些型別。
第23行提出了有問題的租約併為其分配給記憶體。不必預先為它準備儲存,只需要讀取它即可。
第24–34行告訴函式返回Lease物件上的所有屬性。
第37–39行是一個實用函式,用於檢索當前的ETHUSD匯率。
第41–43行宣告瞭另一個實用程式功能,以顯示智慧合約的當前餘額。為獲得餘額,我們必須將此(智慧合約例項)轉換為地址型別,然後從中讀取餘額。
最後,第45行是回退函式。中。
以下是完整的智慧合約程式碼:
1語用強度^ 0.5 .17 ;
2匯入 “ ./SafeMath.sol”;
3匯入 “ ./provableAPI.sol”;
4
5合同LeaseGenerator 正在 usingProvable {
6
7 使用 SafeMath 進行 uint ;
8
9 地址應付房東地址;
10個 地址的應付租戶地址;
11
12 UINT ETHUSD;
13 uint tenantPayment;
14 uint leaseBalanceWei;
15
16 列舉 狀態{
17個 付費租賃存款,
18個 付費租賃,
19個 集合租賃存款,
20個 回收租賃存款,
21個 空閒
22 }
23
24 國家工作狀態;
25
26 struct Lease {
27 uint8 numberOfMonths;
28 uint8個月有償;
29 uint16 monthAmountUsd;
30 uint16 leaseDepositUsd;
31 uint32 leasePaymentWindowSeconds;
32 uint64 leasePaymentWindowEnd;
33 uint64 depositPaymentWindowEnd;
34 bool leaseDepositPaid;
35 bool leaseFullyPaid;
36 }
37
38 對映(bytes32 => bool)validIds;
39 對映(address => Lease)tenantLease;
40
41 改性劑 onlyLandlord() {
42 require(msg.sender == landlordAddress, “必須是建立租賃的房東”));
43 _;
44 }
45
46 event leaseCreated(
47 uint8 numberOfMonths,
48 uint8 monthsPaid,
49 uint16 monthAmountUsd,
50 uint16 leaseDepositUsd,
51 uint32 leasePaymentWindowSeconds,
52 bool leaseDepositPaid,
53 bool leaseFullyPaid
54 );
55
56項 活動 leaseDepositPaid(
57 地址tenantAddress,
58 uint amountSentUsd
59 ) ;
60
61 event leasePaymentPaid(
62 地址tenantAddress,
63 uint amountSentUsd
64 ) ;
65
66 event leaseDepositCollected(
67 address tenantAddress,
68 uint amountCollected
69 ) ;
70
71 事件 leaseDepositReclaimed(
72 address tenantAddress,
73 uint amountReclaimed
74 ) ;
75
76 事件 leaseFullyPaid(
77個 地址tenantAddress,
78個 UINT NUMBEROFMONTHS,
79 UINT monthsPaid
80 ) ;
81
82 事件 fundsWithdrawn(
83 UINT transferAmount,
84 UINT leaseBalanceWei
85 ) ;
86
87 建設者() 公共 應付款{
88 landlordAddress = msg.sender;
89 provable_setCustomGasPrice(100000000000);
90 OAR = OracleAddrResolverI(0xB7D2d92e74447535088A32AD65d459E97f692222);
91 }
92
93 函式 fetchUsdRate() 內部 {
94 require(provable_getPrice (“ URL”)<address(this).balance,“合同中沒有足夠的以太幣 ,請新增更多”));
95 位元組32 queryId = provable_query(“ URL”, “ json(https://api.pro.coinbase.com/products/ETH-USD/ticker).price”);
96 validIds [queryId] = true ;
97 }
98
99 函式__callback(bytes32 myId, 字串 儲存結果) public {
100 require(validIds [myId], “可提供的查詢ID不匹配,未對provable_query()進行有效呼叫”);
101 require(msg.sender == provable_cbAddress(),“使用可提供的合同地址, 呼叫地址確實匹配”);
102 validIds [myId] = false ;
103 ETHUSD = parseInt(結果);
104
105 如果 (workingState == State.payingLeaseDeposit){
106 _payLeaseDeposit();
107 } else if (workingState == State.payingLease){
108 _payLease();
109 } else if (workingState == State.collectingLeaseDeposit){
110 _collectLeaseDeposit();
111 } else if (workingState == State.reclaimingLeaseDeposit){
112 _reclaimLeaseDeposit();
113 }
114 }
115
116 功能 createNewLease(
117個 UINT8 NUMBEROFMONTHS,
118 UINT16 monthlyAmountUsd,
119 UINT16 leaseDepositUsd,
120個 UINT32 leasePaymentWindowSeconds,
121個 UINT32 depositPaymentWindowSeconds,
122 地址應付tenantAddr
123 ) 公共 onlyLandlord {
124
125 UINT64 depositPaymentWindowEnd = UINT64(現。新增(depositPaymentWindowSeconds));
126
127 tenantLease [tenantAddr] =契(
128個 NUMBEROFMONTHS,
129 0,
130 monthlyAmountUsd,
131 leaseDepositUsd,
132個 leasePaymentWindowSeconds,
133 0,
134 depositPaymentWindowEnd,
135 假,
136 假,
137 錯誤
138 );
139
140 EMIT leaseCreated(
141 NUMBEROFMONTHS,
142 0,
143 monthlyAmountUsd,
144 leaseDepositUsd,
145個 leasePaymentWindowSeconds,
146 假,
147 假,
148 虛假
149 ) ;
150 }
151
152 功能 payLeaseDeposit() 公共 應付款 {
153 租賃儲存租賃= tenantLease [msg.sender];
154 require(!lease.leaseDepositPaid, “已支付租賃押金。”);
155 require(lease.depositPaymentWindowEnd> =現在, “租賃押金必須適合支付視窗”);
156
157 tenantAddress = msg.sender;
158 tenantPayment =訊息 價值 ;
第159 章
160 fetchUsdRate();
161 }
162
163 功能_payLeaseDeposit() 內部 {
164 workingState = State.idle;
165 租賃儲存租賃= tenantLease [tenantAddress];
166 UINT amountSentUsd = tenantPayment.mul(ETHUSD).div(1E18);
167
168 要求(
169 amountSentUsd> = lease.leaseDepositUsd - 5 &&
170 amountSentUsd <= lease.leaseDepositUsd + 5,
171 “存款支付必須等於到存款金額,最大的$ 5偏移量”);
172
173 lease.leaseDepositPaid = 真 ;
174 lease.depositPaymentWindowEnd = 0 ;
(175)第175 章
176
177 EMIT leaseDepositPaid(
178個 tenantAddress,
179 amountSentUsd
180 ) ;
181 }
182個
183 功能 payLease() 公共 應付款 {
184 租賃儲存租賃= tenantLease [msg.sender];
185 require(lease.leaseDepositPaid, “必須在支付租賃款項之前支付租賃押金”);
186 require(!lease.leaseFullyPaid, “租賃已經全額支付”);
187 require(lease.leasePaymentWindowEnd> =現在, “租賃付款必須適合付款視窗”);
188
189 tenantAddress = msg.sender;
190 tenantPayment =訊息 價值 ;
191 workingState = State.payingLease;
192 fetchUsdRate();
193 }
194
195 函式_payLease() 內部 {
196 workingState = State.idle;
197 租賃儲存租賃= tenantLease [tenantAddress];
198 UINT amountSentUsd = tenantPayment.mul(ETHUSD).div(1E18);
199
200 要求(
201 amountSentUsd> = lease.monthlyAmountUsd - 5,
202 “租賃付款必須大於或等於每月量與最大的$ 5偏移量”);
203
204 UINT monthsPaid = uint256(lease.monthsPaid)。新增(amountSentUsd。新增(10).div(uint256(lease.monthlyAmountUsd)));
205 lease.monthsPaid = uint8(monthsPaid);
206 leaseBalanceWei = leaseBalanceWei。新增(tenantPayment);
207
208 如果 (monthsPaid == lease.numberOfMonths){
209 lease.leaseFullyPaid = 真 ;
210 lease.leasePaymentWindowEnd = 0 ;
211
212 發出 leaseFullyPaid(
213 租戶地址
214 lease.numberOfMonths,
215個月 支付
216 ) ;
217 } else {
218 lease.leasePaymentWindowEnd = lease.leasePaymentWindowEnd + lease.leasePaymentWindowSeconds;
219
220 EMIT leasePaymentPaid(
221個 tenantAddress,
222 amountSentUsd
223 ) ;
224 }
225 }
226
227 函式 collectLeaseDeposit(應付地址tenantAddr) 公共 onlyLandlord {
228 租賃儲存租賃= tenantLease [tenantAddr];
229 require(!lease.leaseFullyPaid, “如果已經支付了租賃費用,則無法收取租賃保證金”);
230 require(lease.leasePaymentWindowEnd <=現在, “租賃付款必須在付款視窗之後過期才能收取租賃押金”);
231 require(lease.leaseDepositUsd> 0, “租賃押金已被刪除”);
232
233 tenantAddress = tenantAddr;
234 =狀態.State.collectingLeaseDeposit;
第235 章
236 }
237
238 功能_collectLeaseDeposit() 內部 {
239 workingState = State.idle;
240 租賃儲存租賃= tenantLease [tenantAddress];
241 uint leaseDeposit = lease.leaseDepositUsd;
242 lease.leaseDepositUsd = 0 ;
243 landlordAddress.transfer(leaseDeposit.div(ETHUSD).mul(1E18));
244
245 EMIT leaseDepositCollected(
246個 tenantAddress,
247 leaseDeposit
248 ) ;
249 }
250
251 功能 reclaimLeaseDeposit() 公共 {
252 租賃儲存租賃= tenantLease [msg.sender];
253 require(lease.leaseFullyPaid, “必須全額支付租賃押金才能收回租賃押金”);
254 require(lease.leaseDepositUsd> 0, “租賃押金已被刪除”);
255
256 tenantAddress = msg.sender;
257 ==== State.reclaimingLeaseDeposit;
258 fetchUsdRate();
259 }
260
261 功能_reclaimLeaseDeposit() 內部 {
262 workingState = State.idle;
263 租賃儲存租賃= tenantLease [tenantAddress];
264 uint leaseDeposit = lease.leaseDepositUsd;
265 lease.leaseDepositUsd = 0 ;
266 tenantAddress.transfer(leaseDeposit.div(ETHUSD).mul(1E18));
267
268 EMIT leaseDepositReclaimed(
269個 tenantAddress,
270 leaseDeposit
271 ) ;
272 }
273
274 函式 withdrawFunds()僅 公開 給房東 {
275 require(leaseBalanceWei> 0, “租賃餘額必須大於0”);
276 uint transferAmount = leaseBalanceWei;
277 leaseBalanceWei = 0 ;
278 landlordAddress.transfer(transferAmount);
279
280 EMIT fundsWithdrawn(
281 transferAmount,
282 leaseBalanceWei
283 ) ;
284 }
285
286 功能 getLease(地址租戶) 公共 檢視 返回 (
287 UINT8,
288 UINT8,
289 UINT16,
290 UINT16,
291 UINT32,
292 UINT64,
293 UINT64,
294 布林,
295 布林,
296 布林) {
297 租賃儲存器租賃= tenantLease [租戶];
298 返回 (
299 lease.NumberOfMonths,
300 lease.monthsPaid,
301 lease.monthlyAmountUsd,
302 lease.leaseDepositUsd,
303 lease.leasePaymentWindowSeconds,
304 lease.leasePaymentWindowEnd,
305 lease.depositPaymentWindowEnd,
306 lease.leaseDepositPaid,
307 lease.leaseFullyPaid,
308 }
309
310 函式 getRate() 公眾 意見 返回 (uint) {
311 return ETHUSD;
312 }
313
314 功能 getContractBalance() 公開 檢視 返回 (uint) {
315 return uint(address(this).balance);
316 }
317
318 function()外部應付款{}
319 }
現在我們已經完成了智慧合約程式碼編寫,我們可以實操看看它的實際效果。
在本教程的最後一部分中,我們將介紹如何執行測試並檢測它們是否透過。
最初是在終端中執行npm run chain。您會注意到我們將每個帳戶的初始餘額設定為10000 ETH。這是因為在測試中會花費了大量ETH的地址的場景中進行迭代。 cli執行後,執行npm run bridge。當bridge完成啟動後,可以顯示一條訊息。
1請將此行新增 到 您的合同 建構函式中:
2 OAR = OraclizeAddrResolverI(0 x6f485C8BF6fc43eA212E93BBF8ce046C7f1cb475);
複製顯示的地址替換其貼上到LeaseGenerator.sol的建構函式中。
在終端中,執行truffle進行測試。 ,,進入執行bridge的終端視窗。在這裡,我們可以看到所有請求都已傳送,並在測試執行時實時返回結果。ganache視窗還在處理過程中快速顯示交易。
我建議所有讀者檢視/tests/leaseGenerator.test.js中的內容,看看這些測試是如何實現的。它顯示了我們如何處理智慧合約互動中涉及的大量非同步活動。
該應用程式還不是很完美。可能存有很多不足,無法解決某些現實生活中的情況。但是如果區塊鏈技術成為主流的話,那麼將來如何處理房東與租戶的關係是很有趣。最後感謝大家的耐心閱讀,謝謝。