Solidity

與簡單合約互動時遇到問題

  • October 25, 2018

我是一個初學者,試圖通過 web3 與一個簡單的合約進行互動,我遇到了一些我無法弄清楚的問題。

我已經編寫了一個帶有結構和兩個函式的基本契約。這基本上是從這裡複製的:Returning a struct and reading via Web3

contract MyContract {
   struct MyStruct {
       address a;
       uint b;
   }

   MyStruct[] public MyStructs;

   function getStruct(uint index) public constant returns (address, uint) {
       return (MyStructs[index].a, MyStructs[index].b);
   }

   function addStruct(address _a, uint _b) public returns (uint){
       MyStruct memory a = MyStruct(_a, _b);
       MyStructs.length++;
       MyStructs.push(a);
       return MyStructs.length;
   }
}

我使用 truffle 的測試功能呼叫了兩個測試函式。這些基本上是從http://truffleframework.com/docs/getting_started/javascript-tests複製的

var MyContract = artifacts.require("MyContract");


contract('MyContract', function() {
 it("should create a stuct", function() {
   return MyContract.deployed().then(function(instance) {
     return instance.addStruct.call(0xf17f52151EbEF6C7334FAD080c5704D77216b732, 1000);
   }).then(function(length) {
      console.log(length);
      assert.equal(length, 1, "length is not 1");

   });
 });

 it("get the struct that was previously created", function() {
   return MyContract.deployed().then(function(instance) {
     return instance.getStruct.call(0);
   }).then(function(values) {
     console.log(values);
     assert.equal(values, (0xf17f52151EbEF6C7334FAD080c5704D77216b732, 1000));
   });
 });
});

當我執行它時,我得到以下資訊:

 Contract: MyContract { [String: '2'] s: 1, e: 0, c: [ 2 ] }
   1) should create a stuct
   > No events were emitted
   2) get the struct that was previously created
   > No events were emitted


 0 passing (190ms)   2 failing

 1) Contract: MyContract should create a stuct:
    AssertionError: length is not 1: expected { Object (s, e, ...) } to equal 1
     at test/mycontract.js:10:15
     at process._tickCallback (internal/process/next_tick.js:103:7)

 2) Contract: MyContract get the struct that was previously created:
    Error: Invalid JSON RPC response: {"id":21,"jsonrpc":"2.0"}
     at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:41483:16)
     at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:330353:36
     at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:326008:9
     at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:329052:7)
     at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176427:18)
     at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176717:12)
     at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176872:12)
     at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176832:24)

換句話說,當它到達 console.log(length) 時,它應該是 addStruct 函式的響應,而不是 get { [String: '2'] s: 1, e: 0, c: [ 2 ] },然後 getStruct 錯誤輸出Error: Invalid JSON RPC response: {"id":21,"jsonrpc":"2.0"}

知道為什麼會這樣嗎?這兩件事對我來說都毫無意義,所以我什至不知道Google是什麼。我查看了 Truffle 和 Solidity 文件,據我所知,我做的一切都是正確的。

也許不相關,但我包括在內以防萬一 - 以前,我已成功將其部署到 Ganache 並在瀏覽器控制台中播放。我能夠呼叫 web3.eth.contract(abi) 並得到似乎正確的響應,但是當我添加地址作為參數時,它拒絕給我任何東西,除了“無效地址”。我在 web3 和 ganache 文件中確認我做對了大約 10 次,所以我認為可能還有其他問題。或者也許不是——請隨意忽略這部分。

在第一種情況下,您的結果是BigNumber,因此您只需.toNumber()添加length

 it("should create a stuct", function() {
   return MyContract.deployed().then(function(instance) {
     return instance.addStruct.call(0xf17f52151EbEF6C7334FAD080c5704D77216b732, 1000);
   }).then(function(length) {
      console.log(length.toNumber());
      assert.equal(length.toNumber(), 1, "length is not 1");
   });
 });

相關:消息呼叫返回對像中的CES屬性是什麼?


在第二種情況下,我稍微修改了您的測試:

it("get the struct that was previously created", function() {
   return MyContract.deployed().then(function(instance) {
     instance.addStruct.sendTransaction("0xf17f52151ebef6c7334fad080c5704d77216b732", 1000);
     return instance.getStruct.call(1);
   }).then(function(values) {
     console.log(values[0].toString(), values[1].toNumber());
     assert.equal(values[0].toString(), "0xf17f52151ebef6c7334fad080c5704d77216b732", 'blah-blah');
     assert.equal(values[1].toNumber(), 1000, 'blah-blah');
   });
 });

我們將執行sendTransaction實際將新結構添加到數組。然後我們將call它和返回的數組將被讀取.toString().toNumber()標準化輸出。


還需要注意的是,如果我們call getStruct使用 0 它會返回0x0000000000000000000000000000000000000000 0

解決方法是:

function addStruct(address _a, uint _b) public returns (uint){
   MyStruct memory a = MyStruct(_a, _b);
   MyStructs.push(a);
   // delete this line (MyStructs.length++;)
   return MyStructs.length;
}

在此編輯後,您可以call在此處將值從 0 更改回 1:

return instance.getStruct.call(0);

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