Web3js

使用節點儲存/檢索數據不起作用

  • August 1, 2019

我嘗試了一些簡單的方法,在智能合約中儲存和檢索數據,但是當我想檢索數據時,什麼都沒有返回。

solc 版本是 0.4.24 web3 版本是 1.2

堅固性程式碼:

pragma solidity ^0.4.24;

contract tbdocs {

   address owner;

   string testData;

   constructor() public {
       owner = msg.sender;
   }

   function getOwner() public view returns (address) {
       return owner;
   }

   function setTestData(string data) public returns (string) {
       testData = data;
       return testData;
   }

   function getTestData() public view returns (string) {
       return testData;
   }

}

節點JS程式碼:

const path = require('path');
const fs = require('fs');
const Web3 = require('web3');     // Version 1.2
const solc = require('solc');     // Version 0.4.24


async function compileAndDeplot() {

   const simplePath = path.resolve(__dirname, 'contracts', 'simpleStore.sol');
   const sourceSolidity = fs.readFileSync(simplePath, 'utf8');

   const contract = solc.compile(sourceSolidity, 1).contracts[':tbdocs']

   const byteCode = contract.bytecode;
   const abi = JSON.parse(contract.interface);

   console.log('Compiled.');


   const web3 = new Web3('http://localhost:8545');

   const accounts = await web3.eth.getAccounts();
   const address = accounts[0];
   console.log('Using account: ' + address);

   var myContract = new web3.eth.Contract(abi)

   var contractDeployed = await myContract.deploy({
       data: byteCode
   }).send({
       from: address,
       gas: '2900000'
   }, function (error, transactionHash) {
       console.log('Transaction hash: ' + transactionHash);
   });

   const contractAddress = contractDeployed.options.address;

   console.log('Contract deployed at: ' + contractAddress);

   console.log('\nCalling methods: ')

   var result = await contractDeployed.methods.getOwner().call();
   console.log('\tgetOwner: ' + result);       // Works


   contractDeployed.methods.setTestData('testing store data').call()
       .then(result => {
           console.log('\tSet: ' + result);

           contractDeployed.methods.getTestData().call()
               .then(data => {
                   console.log('\tGet: ' + data);
               });
       })
}

compileAndDeplot();

現在並使用 ganache-cli 進行測試,但使用 geth 的結果相同。

ganache-cli -u 0 -l 1000000000

範例輸出:

Compiled.
Using account: 0xdf6c7a3c1d19DfEF9bae7fC1328f182D781f6631
Transaction hash: 0xad8d9f164d7ec16522eab2a17c8d2c4253f52d0b648a7921b63c6b8bb863f9de
Contract deployed at: 0x0Aa3916BD95B5C02E8ee44c4E9ccf5FAaa328a0a

Calling methods:
   getOwner: 0xdf6c7a3c1d19DfEF9bae7fC1328f182D781f6631
   Set: testing store data
   Get:

可以看出,get 是空的。

契約工作正常,可以在這裡測試:

Ethfiddle

感謝任何提示。

這都是錯誤的:

   var result = await contractDeployed.methods.getOwner().call();
   console.log('\tgetOwner: ' + result);       // Works

   contractDeployed.methods.setTestData('testing store data').call()
       .then(result => {
           console.log('\tSet: ' + result);
           contractDeployed.methods.getTestData().call()
               .then(data => {
                   console.log('\tGet: ' + data);
               });
       });

var result您聲明的第一個不會在您的程式碼中進一步使用。

這是因為函式的回調setTestData使用了完全相同名稱的變數(在行中.then(result => {)。

另請注意,函式setTestData不是恆定的(也不pureview)。

因此,當你在鏈上呼叫它時(即從這個合約或從另一個合約)你可以依賴它的返回值,當你在鏈下呼叫它時你不能依賴它的返回值(即從 web3腳本),它將返回交易雜湊。

最後(並且在另一個答案中也指出),因為這個函式不是恆定的,你應該使用send而不是call.

由於您無論如何都在使用async/await方案,因此您也可以這樣做:

   var result = await contractDeployed.methods.getOwner().call();
   console.log('\tgetOwner: ' + result);

   var options = {from: address, gas: ...};
   await contractDeployed.methods.setTestData('testing store data').send(options);

   var data = await contractDeployed.methods.getTestData().call();
   console.log('\tGet: ' + data);

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