與簡單合約互動時遇到問題
我是一個初學者,試圖通過 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"); }); });
相關:消息呼叫返回對像中的C、E和S屬性是什麼?
在第二種情況下,我稍微修改了您的測試:
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);