0

I am trying to get a return value from the payable function, the idea is a user must pay the fees and in return, he will get his special code. My JS test code is as follow

it('get special code which was stored by the admin',async()=> {

        const user = accounts[4];

        // get the deployed contract instance
        contractInstance = await MyContract.deployed()

        const expectedCode = "Wolvorine";

        const fees = "1";  

        let result1 = await contractInstance.getCode(user,{from:user,value:fees}) ;

    assert.equal(result1,expectedCode, " Code which was stored by the admin must be equal to the expected value")

My contract which returns the value is as below

 function getCode(address _identityaddress) payable
public returns (string memory)
{
    require((identity_details[_identityaddress].identityaddress==msg.sender));

    require(msg.value >= attestationFee);

    Transaction memory p = identity_details[_identityaddress];

    return (p.code);
}

Here Transaction is a structure data type that has code as a string variable inside. If I make this function without payable and don't take any money from the caller then return value accurately returns me the code. But since I am using payable and receiving ethers, therefore, it is returning me a big transaction object instead of my returned value.

What is the best way to tackle this issue since I want the user to use MetaMask only one time where he will just pay and then get this value in one shot?

1 Answer 1

1

If I make this function without payable and don't take any money from the caller then return value accurately returns me the code.

You are on the right track but misinterpreting what you see. I'll break it down.

accurately returns me the code

I think you mean returns(string memory).

without payable

Payable has nothing to do with it. You have to add either view or constant to make it a read-only function as the compiler will suggest you do if you remove payable because without value transfer, this function doesn't change anything. So, I think that's what happened, or something very similar.

This issue relates to Ethereum's treatment of state-changing (write) and read-only operations. In the case of a state-changing function the sender never gets the expected return value, but another contract does. The reason for this is the sent transactions have not been mined, so the return value is unknown.

The receipt you get is an identifier your node produced to let you know how to track the transaction. This callback confirms that your node is aware of your desire to submit something to the network. It's not the same concept as "result".

It's a confusing topic and it implies front-end design patterns that deal with waiting for mining. Have a look over here for an explainer: https://blog.b9lab.com/calls-vs-transactions-in-ethereum-smart-contracts-62d6b17d0bc2

Hope it helps.

3
  • As the blog you shared says to get the return value you might need to see logs or other functions. Though I have a choice of taking fees in one function and returning the data in second by making it a "view" only function. But I am still confused about what is the best practise to get return value in the above situation. Right now I am using the log and a log is returning me user's code as a returned value. Do you think this is a good way? Oct 17, 2019 at 7:23
  • First, in case the "user's code" is meant to be confidential, it isn't. As a starting point, avoid over-fitting to the use-case you have in mind. Contracts have to support every use-case that will ever possibly be needed. If the contract function generates data, then return it and emit an event. If the generated data persists, then make a way to discover it. Consumption by clients/servers/other contracts is a separate concern. You will have given them all the tools. Depart from that default pattern only when there is a clear reason and after deep introspection. Oct 17, 2019 at 17:58
  • The code text is a user code (Let say a kind of a digital fingerprint) that does persist inside the blockchain. Anyhow so I have limited choices here either I can retrieve it through emitting an event or as you said make a way to discover it. I will go with the event. Oct 18, 2019 at 12:38

Your Answer

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

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