Javascript

使用 Truffle 進行 JavaScript 和 Solidity 測試之間相同合約的不同行為

  • November 12, 2019

我有一個簡單的合約,它的作用是作為利率管理員——它是用容量和 time_frame(以塊為單位)參數構造的,並確保我們在任何給定的時間範圍內不會添加超過 $capacity 的付款。如果我們沒有超出容量,函式 addPayment() 會註冊支付的時間戳並將負載加一。否則它將返回 false 。

pragma solidity >=0.5.8 <0.6.0;

   contract RateKeeper {
       uint256 public capacity;
       uint256 public timeframe;

       uint256 public load; // Number of transactions in record so far

       constructor (uint256 _capacity, uint256 _timeframe) public {

           capacity = _capacity;
           timeframe = _timeframe;
           load = 0;
       }

       function addPayment() public onlyOwner returns (bool added) {
           // removeOldEntries();
           if (load >= capacity){
               return false;
           }
           load++;
           return true;
       }

當我在solidity 中測試該函式時,它的行為符合預期,但是在JavaScript 中,負載不會隨著函式呼叫而增加。這是為什麼?

在以下 JavaScript 測試中,最後兩個斷言失敗:

contract("JS RateKeeper test", async accounts => {
 it("Constructor, addPayment(). This test doesn't pass", async function () {

   let instance = await RateKeeper.new(1, 299);
   let inst_capacity = await instance.capacity.call();
   assert.equal(inst_capacity, 1);
   let load = await instance.load.call();
   assert.equal(load, 0, "load is 0 as no payments were initiated so far");
   let payment_success = await instance.addPayment.call();
   assert(payment_success, "Load is 0, capacity is 1 - payment should succeed");
   let load2 = await instance.load.call();
   assert.equal(load2, 1, "load should be 1 after a single call to addPayment()");
   payment_success = await instance.addPayment.call();
   assert(!payment_success, "We are at full capacity, payment should fail");

同時,堅固性測試進展順利

 function testAddPayment() public{
   RateKeeper keeper = new RateKeeper(2,299);
   Assert.equal(keeper.load(), 0, "We added no payments");
   Assert.isTrue(keeper.addPayment(), "Contract has (0/2) payments");
   Assert.equal(keeper.load(), 1, "We added 1 payment");
   Assert.isTrue(keeper.addPayment(), "Contract has (1/2) payments");
   Assert.equal(keeper.load(), 2, "We added 2 payment");
   Assert.isFalse(keeper.addPayment(), "Contract has (2/2) payments");
   Assert.equal(keeper.load(), 2, "We added 2 payment");
   Assert.isFalse(keeper.addPayment(), "Contract has (2/2) payments");
   Assert.equal(keeper.load(), 2, "We added 2 payment");
   keeper.destroy();

這是由於 的行為call()Call是只讀的,例如在函式中所做的任何狀態更改都不是持久的。如果您更改instance.addPayment.call()to的實例instance.addPayment(),它將保留更改。

當然,還有另一個複雜情況,即您使用的是 的返回值addPayment,這對於持久更改並不真正起作用。您將不得不恢復錯誤或添加日誌語句以查看外部發生的情況。

引用自:https://ethereum.stackexchange.com/questions/77431