http://www.7klian.com

详解如安在以太坊智能合约中集成可证明的Oracle-part2

23    } else if (workingState == State.collectingLeaseDeposit) {
第16行使ID无效,因此其他查询不能再次利用它。
第19-22行发出了leaseDepositCollected事件。

第8行provable_getPrice(“ URL”)要求Provable计较并返回从Web URL检索外部资源所需的gas量。我们利用require来确保智能合约中有足够的余额来付出该用度。
 7function fetchUsdRate() internal {
第13至28行是我们对Provable的_callback()的实现。第一个参数是查询发生的ID。第二个是string的查询实际功效。要害字memory用于在函数运行期间将字符串存储在内存中,而不是将其写入存储区,这样更节减了gas。
它是果真的,因此可以从外部以太坊帐户和onlylandord执行,因此只有房东的地点可以挪用它。
63    );
22    uint monthsPaid = uint256(lease.monthsPaid).add(amountSentUsd.add(10).div(uint256(lease.monthlyAmountUsd)));
28}
15    require(msg.sender == provable_cbAddress(), “Calling address does match usingProvable contract address “);
1. numberOfMonths:租约的期限,以月为单元
54        “Deposit payment must equal to the deposit amount with a maximum offset of $5”);
第51–54行确保以美元发送的金额与租赁的leaseDepositUsd相匹配。我们通过添加5美元的抵消额来办理ETH价值的快速颠簸。譬喻假如leaseDepositUsd是$500,则amountSendUsd的可接管值范畴是$495–$505。
第47行将状态重置为idle状态。
第9行provable_query汇报Provable用给定的端点执行查询,在我们的例子中,这是Coinbase的ETH/USD价值报价器。这将返回一个新的查询ID,我们将其添加到第10行的validIds中。
33}
43}
26    if (monthsPaid == lease.numberOfMonths) {
22    );
        “Lease deposit payment must fit into payment window”);
50
24    leaseBalanceWei = leaseBalanceWei.add(tenantPayment);
15    Lease storage lease = tenantLease[tenantAddress];
61        tenantAddress,
 7    address payable tenantAddr
40    tenantAddress = msg.sender;
第19–27行是一系列依赖于workState值的条件语句,该值由名为fetchUsdRate()的给定函数配置。我们还没有实施这些法子。
11
12    tenantLease[tenantAddr] = Lease(
30    false,
第56行将租约的押金付出标志为已付出。
47    workingState = State.idle;
46function _payLeaseDeposit() internal {
第57行重置存款的付款窗口竣事,因为它已经付出。
27    monthlyAmountUsd,
          “Lease payment must fit into payment window”);
 5}
第58行划定了实际每月租赁付款的付款期限,该期限当即生效。同样,留意uint64范例转换,这样我们就可以获取附加值并将其正确地存储在Lease工具中。
14    workingState = State.idle;
45
25    numberOfMonths,
第2-5行反复了前面的逻辑。
34
39
第15行声明白leaseDeposit并将其分派给lease.leaseDepositUsd。目标是在下一行(16)将其重置为0之前捕捉该值。然后,在第17行,我们将捕捉的leaseDeposit除以ETHUSD汇率乘以1e18以从wei转换为房东。在将原始存储位置配置为0之前捕捉值的这种模式是为了防备众所周知的智能合约裂痕(称为重入进攻)。
24        _collectLeaseDeposit();
 1constructor () public payable {
第35-42行简朴地重置下一次租赁付款的截至日期,并发出一个leasePaid事件。
20    false,
51    require(
26        _reclaimLeaseDeposit();
24    emit leaseCreated(
52        amountSentUsd >= lease.leaseDepositUsd – 5 &&
第2行将房东的地点配置为msg.sender,这是陈设智能合约的地点。
16    leaseDepositUsd,
18
第12–33行正在建设一个新的Lease实例,利用一些数据对其举办初始化,并将其分派给tenantLease映射存储中的要害tenantAddr的值。请参考前面有关“Lease”工具的说明以增强领略。
第17行阐明字符串result,将其转换为uint范例,并将其分派给我们的全局变量ETHUSD。
19    emit leaseDepositCollected(
64}
41        );
55
我们利用uint8,uint16,uint32和uint64是因为有一个称为“布局打包”的观念。一旦我们从Lease布局建设了租赁实例,利用较小的uint范例就可以稍微淘汰gas本钱。
42    workingState = State.payingLeaseDeposit;
第60–63行发出了leaseDepositPaid事件。
21    } else if (workingState == State.payingLease) {
第38行确认租赁担保金的付款期限尚未高出。
         collect lease deposit”);
第1至5行配置告终构函数,该结构函数是在陈设智能合约时执行的函数。它被标志为payable,以便可以吸收以太币。我们但愿在初始化时发送一些以,以付出可证明的查询的用度。
27    }
49    uint amountSentUsd = tenantPayment.mul(ETHUSD).div(1e18);
23    lease.monthsPaid = uint8(monthsPaid);
 5    require(lease.leasePaymentWindowEnd >= now, 
20        tenantAddress,
第1-10行声明白我们收集(收回)租赁押金的public函数。它接管有关租户的地点作为独一参数,并标志为“onlyLandlord”,以确保没有其他人可以窃取租赁押金。
 6
第7-11行是认真奉告Provable提取ETH的美元汇率的函数。
15    uint leaseDeposit = lease.leaseDepositUsd;
38    require(lease.depositPaymentWindowEnd >= now, 
13    numberOfMonths,
35    } else {
36    Lease storage lease = tenantLease[msg.sender];
第18–20行确保以美元发送的金额至少为所需的每月金额,并带有负的$5抵销。假如lease.monthlyAmountUsd为$500,则最低amountSentUsd必需为$495。没有上限,因为发送的金额抉择了付出的月数。租户可以一次付出多个月的用度。
5. depositPaymentWindowSeconds:租户必需付出的时间(以秒为单元)。建设租约后当即生效
第3行为Provable的__callback()函数配置了自界说gas价值。我们配置了一个很高的金额,以确保我们可以包围——_callback()中的操纵本钱。
 4    OAR = OracleAddrResolverI(0xB7D2d92e74447535088A32AD65d459E97f692222);
         “Lease payment must be overdue past payment window to 
37
 3    require(!lease.leaseFullyPaid, 
 1function payLease() public payable {
38        emit leasePaymentPaid(
57    lease.depositPaymentWindowEnd = 0;
 4    require(lease.leasePaymentWindowEnd <= now, 
60    emit leaseDepositPaid(
第35至44行认真付出租赁押金。它应该由租户挪用。
第23行将上述操纵的功效值转换为uint8,以便可以将其存储在lease.monthsPaid中。
 8    tenantPayment = msg.value;
40            amountSentUsd
14    Lease storage lease = tenantLease[tenantAddress];
18    0,
39            tenantAddress,
 2    Lease storage lease = tenantLease[tenantAddr];
第40行将全局变量tenant address配置为租户的地点。
27        lease.leaseFullyPaid = true;
20        _payLeaseDeposit();
25    } else if (workingState == State.reclaimingLeaseDeposit) {
22        _payLease();
第1行是我们付出租金的果真函数。
第7-9行反复了前面的逻辑。
 3    require(lease.leaseDepositPaid, 

为了建设更短的代码段,剩下的代码将继承显示为从第1行开始的新GitHub gist。
2. monthAmountUsd:每月要付出的总金额(美元)
31            tenantAddress,
31    false
36        lease.leasePaymentWindowEnd = lease.leasePaymentWindowEnd + lease.leasePaymentWindowSeconds;
第24行将全局变量leaseBalanceWei配置为leaseBalanceWei的原始值加上也以wei暗示的tenantPayment的值。假如房东但愿提取租赁付款,则此值为将要发送的金额。
3. leaseDepositUsd:应付出的租赁押金的总额
11}
第14-16行与payLeaseDeposit()沟通。
42    }
 9    workingState = State.payingLease;
21        leaseDeposit
 3    provable_setCustomGasPrice(100000000000);
21    false
33            monthsPaid
17    leasePaymentWindowSeconds,
10    fetchUsdRate();
48    Lease storage lease = tenantLease[tenantAddress];
10    validIds[queryId] = true;
第48行通过挪用payLeaseDeposit()来按照tenantAddress配置检索Lease。
37    require(!lease.leaseDepositPaid, 
20        “Lease payment must be greater than or equal to the monthly amount with a maximum offset of $5”);
 9
第12-23行界说了我们完成收取租赁押金进程的internal成果
19        amountSentUsd >= lease.monthlyAmountUsd – 5,
第2-5行应该是不问可知的。我们像往常一样获取Lease工具并执行一些查抄。
17    landlordAddress.transfer(leaseDeposit.div(ETHUSD).mul(1e18));
 9    fetchUsdRate();
19    if (workingState == State.payingLeaseDeposit) {
         “Lease has already been fully paid”);
10    uint64 depositPaymentWindowEnd = uint64(now.add(
32            lease.numberOfMonths,
29    leasePaymentWindowSeconds,
第14行查抄该ID是否已被查询利用。假如它还没有被利用,将抛出一个错误,执行将失败。
第24-33行发出带有一些信息的事件leaseCreated。
 7    tenantAddress = msg.sender;
53        amountSentUsd <= lease.leaseDepositUsd + 5,
 2    Lease storage lease = tenantLease[msg.sender];
 4    uint16 leaseDepositUsd,
第37行确认尚未付出租赁押金。
29
 3    uint16 monthlyAmountUsd,
41    tenantPayment = msg.value;
43    fetchUsdRate();
第13-43行声明白付出租约的internal函数。
 5    require(lease.leaseDepositUsd > 0, 
19    depositPaymentWindowEnd,
 8    ) public onlyLandlord {
34        );
6. tenantAddr:租户的以太坊地点,通过外部通信提供应房东
56    lease.leaseDepositPaid = true;
第13-14行反复了前面的逻辑。
第26-35行指出,假如因当前举办中的付款而付出的月数已到达租约中商定的月数,则将租约声明为已全额付出并发出leaseFullyPaid事件。租户已全额付出了租金。
 2    uint8 numberOfMonths,
 6
第10行将实际的unix时间戳配置为now的值,即now的当前值加上depositPaymentWindowSeconds。我们利用uint64()对附加功效举办“范例转换”(留意.add),,并将其从uint256转换为uint64,因为Safemath仅合用于uint256。
25
16    uint amountSentUsd = tenantPayment.mul(ETHUSD).div(1e18);
23
17
11}
17    ETHUSD = parseInt(result);
28    leaseDepositUsd,
44}
62        amountSentUsd
21
12function _collectLeaseDeposit() internal {
12
第7-10行与payLeaseDeposit()沟通,除了我们将状态配置为payingLease。
 2    landlordAddress = msg.sender;
 6    uint32 depositPaymentWindowSeconds,
       “Lease deposit is already paid.”);
14    require(validIds[myId], “Provable query IDs do not match, no valid call was made to provable_query()”);
28        lease.leasePaymentWindowEnd = 0;
第4行是可证明的地点理会器。当我们启动ethereum-bridge时,它会陈设一个智能合约,以利便我们的智能合约与互联网外部世界的通信。该智能合约的地点已经果真出来,因此我们可以将其包括在本智能合约中。此刻Provable可以利用此智能合约执行其操纵。筹备将地点修改为最终运行的npm run bridge的输出。
 8    workingState = State.collectingLeaseDeposit;
10}
第42行将workingState配置为payingLeaseDeposit。这样一来,挪用fetchUsdRate()给出功效后触发的回调(第45行)领略为挪用_payLeaseDeposit()继承执行流程。
第49行通过挪用payLeaseDeposit()来获取tenantPayment配置,将其乘以ETHUSD汇率,最后将其除以1e18。该除法是将乘法的wei值转换为以太坊暗示。这时租户发送的金额为美元。
第41行将全局变量tenantPayment配置为租户发送的wei中ETH的数量msg.value。
13function _payLease() internal {
26    0,
4. leasePaymentWindowSeconds:租户每月付出的时间(以秒为单元),在租户付出了租赁押金后生效
 1function createNewLease(
15    monthlyAmountUsd,
第22行的lease.monthsPaid和lease.monthlyAmountUsd都强制转换为uint256,以确保利用正确的范例来生成安详的.add。在这里,我们将付出的现有月数和当前付出的月数相乘,这是通过将每月租赁本钱除以10 +美元数得出的。配置这10美元的脱期期是为了确保在amountSentUsd的值略低于lease.monthlyAmountUsd的环境下记录正确的月份数。
22    );
12
 8    require(provable_getPrice(“URL”) < address(this).balance, “Not enough Ether in contract, please add more”);
16    lease.leaseDepositUsd = 0;
 7    tenantAddress = tenantAddr;
23}
58    lease.leasePaymentWindowEnd = uint64(now + lease.leasePaymentWindowSeconds);
13    workingState = State.idle;
30        emit leaseFullyPaid(
18    require(
 6
 4    require(!lease.leaseFullyPaid, 
第36行按照租户的地点(msg.sender)从存储器中获取租约。
59
        “Cannot collect lease deposit if lease is already paid”);
18
14    0,
第15行确保_callback()的挪用方是已陈设可证明智能合约的地点,作为附加的安详成果。任何随机参加者都不能执行_callback()。
35function payLeaseDeposit() public payable {
第1–33行是认真建设新租约的成果。它具有六个参数:
 5    uint32 leasePaymentWindowSeconds,
 1function collectLeaseDeposit(address payable tenantAddr) 
       public onlyLandlord {
32    );
16    validIds[myId] = false;
第46-64行代表internal函数,认真在收到USD/ETH汇率后继承付出租赁押金。它是internal的,因此只有_callback()才气在吸收速率后执行它。
13function __callback(bytes32 myId, string memory result) public {
         “Lease deposit must be paid before making lease payments”);
         “Lease deposit has already been removed”);
depositPaymentWindowSeconds));
11
 9    bytes32 queryId = provable_query(“URL”, “json(https://api.pro.coinbase.com/products/ETH-USD/ticker).price”);

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读