0

i trying something simple, store and retrieve a data in a smart contract, but when i want to retrieve the data, nothing is returned.

solc version is 0.4.24 web3 version is 1.2

Solidity code:

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;
    }

}

Node Js code:

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();

Right now and testing with ganache-cli, but the same result with geth.

ganache-cli -u 0 -l 1000000000

Example output:

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

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

As can be seen, the get is empty.

The contract works fine, can be tested here:

Ethfiddle

Thank for any tips.

2 Answers 2

2

This is all wrong:

    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);
                });
        });

The first var result that you have declared is not being used further down your code.

This is because the callback of function setTestData uses a variable of the exact same name (in the line .then(result => {).

Also note that function setTestData is not constant (neither pure nor view).

So while you can rely on its return-value when you call it on-chain (i.e., from this contract or from another contract), you cannot rely on its return-value when you call it off-chain (i.e., from a web3 script), where it will return the transaction hash instead.

Finally (and as also noted in the other answer), because this function is not constant, you should be using send instead of call.

Since you're using the async/await scheme anyway, you may as well do this:

    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);
1

You are making a call, which will treat the function as view and it will not generate a transaction.

contractDeployed.methods.setTestData('testing store data').call()

You have to use send (like in deploy)

contractDeployed.methods.setTestData('testing store data').send({
    from: address
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.