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);
});
  • Thanks @AchalaDissanayake do you mean on the client? The problem is it is not even going inside the function for .then – AntiNatalist Sep 23 '17 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: – AntiNatalist Sep 23 '17 at 17:49
  • yeah, inside that can you replace console.log('value: ' + value); with console.log('value: ' +Buffer.toString(value)); and check? – Achala Dissanayake Sep 23 '17 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. – AntiNatalist Sep 23 '17 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. – AntiNatalist Sep 23 '17 at 21:30
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>**"});.

  • 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 '17 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. – ethereum_alex Dec 14 '17 at 19:12
0

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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