3

please help me in this problem. I am successful to compile and deploy my smart contract using web3j on testrpc. But When I call the function that returns uint in this contract from web3j, I always receive 0. I present below my contract and my Java program. 1. My Smart Contracts:

pragma solidity ^0.4.6;
contract grandParentContract{

  address public myAddr = 0x1005...;

  modifier onlyFromMe() {
    if ((myAddr != address(0)) && (tx.origin != myAddr)) {
        Msg("Permission Error: this function is limited to the my address origin.");
        return;
    }
    _;
  }
}

pragma solidity ^0.4.6;
contract parentContract is grandParentContract {

/**************BEGIN: attributes or properties or dataobjectType**********/ 


 uint public maxIdValue=0;
 uint public minIdValue=0;

 event ElementAddition(uint _id);

 function parentContract() grandParentContract() {
   maxIdValue = 0;
   minIdValue = 0;
 }

}

contract MyContract is parentContract {
  struct MyElement {

    uint id; 
    string name;
    string description;
    uint[] currentForeignKeys;
  }
  mapping(uint => MyElement) public myElementMap; 


  function MyContract() parentContract() {

  }

  function addNewElement(string _name, string _description) public onlyFromMe() returns (uint) {
    uint _id = maxIdValue+1;


    myElementMap[_id].name = _name;
    myElementMap[_id].description = _description;

    maxIdValue = _id;
    ElementAddition(_id);
    return _id;
  }

}
  1. Compile and Deploy successfully I use testrpc

    Web3j web3 = Web3j.build(new HttpService("testrpcIp:testrpcPort"));

When I compile smart contracts, I obtains 3 *.bin files and 3 *.abi files MyContract.bin(abi), parentContract.bin(abi), grandParentContract.bin(abi) I deploy successfully the smart contract using the file MyContract.bin and web3j (Note that, when I deploy this smart contract, I only load the content of this MyContract.bin file, not add 0x before this content)

  1. Call addNewElement function from Java and receive always 0 (zero)

    List<String> results= callMyFunction(web3,aCredential,contractAddress, "addNewElement", Arrays.<Type>asList(new Utf8String("name1"),new Utf8String("description of name1")), Arrays.asList(new TypeReference<Uint>() {}));
    System.out.println("results = " + results);
    
    
    public static synchronized List<String> callMyFunction(Web3j web3, Credentials creds, String contractAddress, String functionName, List inputArgs, List outputs) throws Exception {
    
        List<String> results = new ArrayList();
        Function function = new Function(functionName, inputArgs, outputs);
        String encodedFunction = FunctionEncoder.encode(function);
        EthCall response = web3.ethCall(Transaction.createEthCallTransaction(creds.getEcKeyPair().getPrivateKey().toString(16), contractAddress, encodedFunction), DefaultBlockParameterName.LATEST).sendAsync().get();
        if(response.hasError()){
            System.out.println("functionCall: " + response.getError().getMessage());
        }
        convertMyResult((response != null) && (response.getValue() != null) ? FunctionReturnDecoder.decode(response.getValue(), function.getOutputParameters()) : new ArrayList(), results);
        return results;
    }
    
    public static void convertMyResult(List<Type> returns, List<String> results) throws Exception {
        if (returns.size() > 0) {
    
            for(int i=0; i<returns.size(); i++){
    
                    results.add(returns.get(i).getValue().toString());
    
            }
        }
    }
    

I always receive the results : [0]. I tried to put maxIdValue in the MyContract instead of in ParentContract, but the result is the same

2
  • I think you need to order your question Jul 14, 2017 at 13:54
  • Thanks for your answer. I only want to receive the exact result from my function call to addNewElement in the smart contract. But I always the zero result. I want to know Why and solve this prolem. I presented above my smart contracts and Java code
    – CD Tran
    Jul 14, 2017 at 18:14

1 Answer 1

3

Non-constant solidity functions can not return a value.

This is generally because you have to send the value out to the network to be processed for an indeterminate amount of time. This makes it kind of difficult to get any data back to you, the sender.

What you could do, is use events, or just follow up later with a constant function call.

3
  • Thanks very much for your answer. As you said, I have to declare the method in Solidity like below? function addNewElement(string _name, string _description) public onlyFromMe() constant returns (uint) {...} As you see, I have to modify the value of maxIdValue attribute of this smart contract in this function. I also have to create a new Struct element and insert it to a mapping attribute of this smart contract. A constant function allows me to do such modifications? I also use event ElementAddition in addNewElement, but I find nothing in Java after using Java functions above
    – CD Tran
    Jul 15, 2017 at 22:41
  • No, the function can either make changes to the blockchain or it can return a value. It can not do both. You can kind of get around it with events(see the link in my answer), or adding a function to return the value you want that you can run after the transaction goes through. Jul 16, 2017 at 0:14
  • Thanks for your answer. I use events to get the returned value
    – CD Tran
    Jul 17, 2017 at 21:20

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.