4

Can someone please help me. While trying to invoke a constant function which returns string, I am getting

"Promise RejectedError: ERROR: The returned value is not a convertible string:"

Contract Code:

pragma solidity ^0.4.0;
contract LandTitles {

    struct Title {
        string latitude;
        string longitude;
        string geoAddress;
        string ownerName;
    }
mapping(address => Title) titles;

function first(){

}

function register(string latitudeOfLand, 
                    string longitudeOfLand, 
                    string geoAddressOfLand, 
                    string ownerNameOfLand){
    titles[msg.sender].latitude = latitudeOfLand;
    titles[msg.sender].longitude = longitudeOfLand;
    titles[msg.sender].geoAddress = geoAddressOfLand;
    titles[msg.sender].ownerName = ownerNameOfLand;
}

function getTitle() constant returns(string, string, string, string){
    return (titles[msg.sender].latitude, titles[msg.sender].longitude, titles[msg.sender].geoAddress, titles[msg.sender].ownerName);    

}

function getLatitude() constant returns(string){
    return (titles[msg.sender].latitude);    
}

function getMyAddress() constant returns(string){
    return strConcat(titles[msg.sender].latitude,
            titles[msg.sender].longitude,titles[msg.sender].ownerName);
}


function strConcat(string _a, string _b, string _c, string _d, string _e) constant returns (string){
    bytes memory _ba = bytes(_a);
    bytes memory _bb = bytes(_b);
    bytes memory _bc = bytes(_c);
    bytes memory _bd = bytes(_d);
    bytes memory _be = bytes(_e);
    string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length);
    bytes memory babcde = bytes(abcde);
    uint k = 0;
    for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i];
    for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i];
    for (i = 0; i < _bc.length; i++) babcde[k++] = _bc[i];
    for (i = 0; i < _bd.length; i++) babcde[k++] = _bd[i];
    for (i = 0; i < _be.length; i++) babcde[k++] = _be[i];
    return string(babcde);
}

function strConcat(string _a, string _b, string _c, string _d)  constant returns (string) {
    return strConcat(_a, _b, _c, _d, "");
}

function strConcat(string _a, string _b, string _c) constant returns (string) {
    return strConcat(_a, _b, _c, "", "");
}

function strConcat(string _a, string _b) constant returns (string) {
    return strConcat(_a, _b, "", "", "");
}
}

Client code:

var myContractAbi = [{"constant":false,"inputs":[{"name":"latitudeOfLand","type":"string"},{"name":"longitudeOfLand","type":"string"},{"name":"geoAddressOfLand","type":"string"},{"name":"ownerNameOfLand","type":"string"}],"name":"register","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"first","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_a","type":"string"},{"name":"_b","type":"string"},{"name":"_c","type":"string"}],"name":"strConcat","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_a","type":"string"},{"name":"_b","type":"string"},{"name":"_c","type":"string"},{"name":"_d","type":"string"}],"name":"strConcat","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_a","type":"string"},{"name":"_b","type":"string"},{"name":"_c","type":"string"},{"name":"_d","type":"string"},{"name":"_e","type":"string"}],"name":"strConcat","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getMyAddress","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getLatitude","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getTitle","outputs":[{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"},{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_a","type":"string"},{"name":"_b","type":"string"}],"name":"strConcat","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}];

var MyContract = new web3.eth.Contract(myContractAbi);

var myContractInstance = new web3.eth.Contract(myContractAbi,"0xD2010925d2C5b3ac3Cbde585d79C32af417946Ee");

// call constant function
var myresult = myContractInstance.methods.getLatitude().call();

console.log("contract result-:");

Promise.resolve(myresult).then(function(value) {
  console.log('value: ' + value);
}).catch(function (error) {
     console.log("Promise Rejected"+error);
});
11
  • Thanks @AchalaDissanayake do you mean on the client? The problem is it is not even going inside the function for .then Sep 23, 2017 at 17:45
  • In the following block - Promise.resolve(myresult).then(function(value) { console.log('value: ' + value); }).catch(function (error) { console.log("Promise Rejected"+error); }); ---- this block prints Promise RejectedError: ERROR: The returned value is not a convertible string: Sep 23, 2017 at 17:49
  • yeah, inside that can you replace console.log('value: ' + value); with console.log('value: ' +Buffer.toString(value)); and check? Sep 23, 2017 at 17:51
  • I tried that, it doesn't go in that function, a console.log("something") also doesn't get printed because it directly goes to catch function. Sep 23, 2017 at 17:56
  • 1
    @AchalaDissanayake thanks for your help. I have been able to resolve this issue and I'll document my findings in answer to this question. Sep 23, 2017 at 21:30

2 Answers 2

1

web3 cannot handle strings which will be returned from a solidity function. You have to return a bytes32 value. I recommend that you store your values (latitude, longitude etc) as bytes32 values and return them from your functions as bytes32 values.

0

After spending a whole day I have been able to get around the stupid confusion of contract address and account sender address. That was the reason for this error.

While instantiating a contract use contract address,

var myContractInstance = new web3.eth.Contract(myContractAbi,"**<contract address>**");.

While calling even a static method use account address,

var myresult = myContractInstance.methods.getTitle().call({"from": "**<account address>**"});.

2
  • IMHO a better interface is declaring function getTitle(address user) view returns (string..) { return (titles[user].latitude..); }. As a bonus you can call it from another contract.
    – Ismael
    Sep 26, 2017 at 3:48
  • 2
    I don't think this is the right answer. This error appeared for me and setting from did not fix it. Furthermore, I have other instances where I'm doing calls without specifying a sender. Dec 14, 2017 at 19:12

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.