3
contract Calculator{
    int result;
    function Calculator(int initialResult){
       result=initialResult;
    }
}

If above is the contract source code I have created then how to call Calculator function using ethereumj API. I have already used

contract.callFunction("Calculator", 10)

But this did not work. Also called

contract.callConstFunction("Calculator", 10)

But this too didn't not work.

And when saw the ABI it had the function type ="constructor" but couldn't find any method that represents calling constructor.

Please suggest if there is any way to call constructor functions?

3 Answers 3

3

I finally found a solution. As discussed in the other answer, you need to parse and append the init parameters to the contract code before sending the transaction. I did't found actually an elegant and generic way to parse arguments directly in Java (but it should not hard to do it) so I decoded the ABI syntax into byte[].

First of all copy the StandaloneBlockchain.java and add one method (sorry, I can't find an easy way to do it via extension):

public SolidityContract submitNewContract(String soliditySrc, String contractName, byte[] initParameters) {
    SolidityContractImpl contract = createContract(soliditySrc, contractName);
    submitNewTx(new PendingTx(new byte[0], BigInteger.ZERO, ByteUtil.merge(Hex.decode(contract.getBinary()), initParameters), contract, null));
    return contract;
}

Then in the StandaloneBlockchainSample.java, refer the modified class, modify the sample contract to have 2 parameters in the constructor (I didn't have time to check all types, but it should work without problems) and assign the parameters init values:

// Pretty simple (and probably the most expensive) Calculator
private static final String contractSrc =
        "contract Calculator {" +
        "  int public result;" +  // public field can be accessed by calling 'result' function
        "  string testString;" +
        "  bool testBool;"+
        "  function add(int num) {" +
        "    result = result + num;" +
        "  }" +
        "  function sub(int num) {" +
        "    result = result - num;" +
        "  }" +
        "  function mul(int num) {" +
        "    result = result * num;" +
        "  }" +
        "  function div(int num) {" +
        "    result = result / num;" +
        "  }" +
        "  function clear() {" +
        "    result = 0;" +
        "  }" +
        "  function getString() constant returns (string) { return testString; }" +
        "  function getBool() constant returns (bool) { return testBool; }" +
        "  function Calculator(string _testString, bool _testBool){" +
        "    testString = _testString;" +
        "    testBool = _testBool;" +
        "  }" +
        "}";

[...]

String parameters = "{ 'inputs': [ { 'name': '_test', 'type': 'string' }, { 'name': '_test2', 'type': 'bool' } ] }".replaceAll("'", "\"");
byte[] initParameters = CallTransaction.Function.fromJsonInterface(parameters).encodeArguments("Test", true);
SolidityContract calc = bc.submitNewContract(contractSrc, null, initParameters);
System.out.println("Calculating...");

After that, check the correct value of the parameters with:

assertEqual("Test", (String) calc.callConstFunction("getString")[0]);
assertEqual(true, (boolean) calc.callConstFunction("getBool")[0]);

Note that you need to modify the private assertEqual method inside the class to assert other types aside from the already defined BigInteger. I tested this solution with EthereumJ 1.2.0: maybe next releases will include a better way to pass init values to the constructor, so update the answer if you will be aware of that.

2

You don't need to call the constructor, you need to submit the contract and you will automatically have a pointer to the contract, this way:

StandaloneBlockchain bc = new StandaloneBlockchain().withAutoblock(true);
bc.createBlock();
SolidityContract contract = bc.submitNewContract(contractSrc);
System.out.println(contract.callConstFunction("result")[0]);

You can see a simple but full working example at github

5
  • I have used that example and I know that example works without constructor. But there is a need to use a solidity contract with constructor, checkout the example of Crowdsale or Create your own crypto currency at at ethereum.org. If you checkout Mist wallet it provides you to create contracts with constructor, So your answer doesn't solve my issue. Still need someone to tell how to call constructor of the contract I have created. Thanks for taking time to answer. Commented May 29, 2016 at 6:28
  • Maybe I misunderstood your question. In your example, Calculator is a constructor because it has the same name of the contract. As far as I know, you cannot call constructors from outside the EVM (i.e from client in Java, Web3, etc.) but from the inside with instructions like "Calculator calc = new Calculator()" within a contract method. The constructor is called during the creation phase when you deploy a contract. You can refer a deployed contract to call methods on. All those method calls are then translated by the client (Java in your case) into transactions to be sent to the network. Commented May 29, 2016 at 16:01
  • Yep. You maybe correct. But then there should be some way to pass the arguments while submitting the constructor. This should have been there but this is surprising that its not there and the very first examples at the ethereum.org explain the use of constructors. And as you have suggested the "Calculator calc = new Calculator()", it doesn't seem right , because then you have to hardcode the arguments,which itself isn't a good practice.One more thing is that when you check for the ABI,it contains the argument and type of function as constructor, but not the name of constructor. Thanks Commented May 29, 2016 at 18:22
  • Now I see. The problem is how to pass init values during contract deploy phase. In Web3 this is really simple (i.e. MyContract.new(param1, param2, ...)) but in EthereumJ I don't see an easy way to do that. Under the hood, to pass init value to a constructor you need to "ABI encode" those parameters and append bytes to the contract bytes, so that the data bytes of the transacion contains code+parameters. In particular all should be put inside org.ethereum.core.Transaction.data bytes array before submitting. I'll dig further, it seems a very useful addendum to have an easy way to pass parameters Commented May 29, 2016 at 19:44
  • Thanks. I will also look into it. Will also try to suggest more changes. Commented May 30, 2016 at 3:37
0

Added to 1.3.0-RC4:

SolidityContract a = sb.submitNewContract(
  "contract A {" +
  "  uint public a;" +
  "  uint public b;" +
  "  function A(uint a_, uint b_) {a = a_; b = b_; }" +
  "}", 555, 777);
3
  • What was added? Could you explain what your answer is about?
    – q9f
    Commented Jul 8, 2016 at 14:19
  • @5chdn a ticket in ethereumj development stream was raised regarding having a facility to directly call constructor with initial arguments, so fix for that is added to the stream, I haven't tested it yet, Anton has mentioned about the changes for the same, so I guess he deserves upvotes instead of a downvote. :) Commented Jul 10, 2016 at 10:35
  • Just thought a code snippet would be self explanatory. @AjayBhojak thanks for advocating ;) Commented Jul 10, 2016 at 18:15

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.