impossible to get the return value of state changing calls.
If it is state-changing, it is not a call. It's a transaction.
Consider this example.sol:
It doesn't compile.
If I instantiate F
You can't do that, because it doesn't compile.
then call F.createChildContract()
We have to make some assumptions about you want to do so we're talking about something that works.
You could create a new C
and return the address:
address c = new Child();
return c;
Or, possibly return the address of child
if it is a C
that was properly instantiated previously/elsewhere, e.g. C child = C(addressC);
return address(child);
If you call
the function, you will indeed receive an address. These just won't be a contract there because it was a read-only activity. If you send it a transaction, you will get a receipt.
But is there not a way to wait on the transaction, then once it is mined get that child address that it returns?
Yes. There are several ways to do that. It is a client-side responsibility. The blockchain is concerned with processing or rejecting the transaction. It is not concerned with client-side interpretation.
Everywhere I look, I see people telling me it can't be done, and I should use Events
That is one of the ways a client can be informed about an on-chain state transition. You can also use the receipt and poll the blockchain until you see the transaction is mined. In either case and at every stage, you have the option of inspecting the contract state.
For emphasis, it's a client-side responsibility to decide how many confirmations are acceptable, etc.. This library may help: https://gist.github.com/xavierlepretre/88682e871f4ad07be4534ae560692ee6
A little more explanation: Optimal way of waiting for transactions to be mined in geth
So, basically:
return myContract.doSomething();})
.then(function(txnHash) {return getTransactionReceiptMined(txnHash);})
.then(function(receipt) { //... it's mined once
That can be improved for readability with async/await.
I would like to understand why this not possible
There is logical issue with relieving clients of their responsibility. Let me show you a conundrum.
Suppose we have a simple contract:
pragma solidity 0.5.1;
contract OrderMatters {
// the children's game of tag
address it;
constructor() public {
it = msg.sender;
}
function tagYoureIt(address _newIt) public returns(address newIt) {
require(msg.sender == it); // only "it" can tag someone else
it = _newIt;
return it;
}
}
Further suppose we have three transactions signed and sent simultaneously:
- A - Alice deploys the contract
- B - Alice tags Bob
- C - Bob tags Carol
Mining disambiguates the order.
Suppose it goes, A, B, C. B returns Bob and C returns Carol.
But wait! Suppose there is chain reorganization and the cannonical chain reverses the order, so now it goes, C, B, A. C and B are invalid because there is no contract. They return an error.
What if the order is shuffled again? Say, A, C, B? C returns an error cause Carol isn't "it". B returns Bob.
There will eventually be a stable cannonical transaction order but this is far from certain after only one or two confirmations and it can have an effect on outputs. A system that tries to address this has to deal not only with the callback
and result, but also with the possibility that it needs to recall a prevision emission and revise the result. It's not an easy thing to work out a catch-all solution that somehow balances speed and confidence for all dapps.
So, clients have all the primitives they need to work out something satisfactory. That's how it probably should be because it's not a one-approach-fits-all type of problem. And the node/EVM-level teams favor minimalism in any case. I believe those are the reasons why.
Hope it helps.
But is there not a way to wait on the transaction, then once it is mined get that child address that it returns?
- The "convention" is to wait at least 12 blocks (12*16 seconds on mainnet) after it is mined, which guarantees in a reasonably high probability that the transaction is there for good. – goodvibration Feb 7 '19 at 10:16why this not possible?
- as you said -the transaction will not have been mined yet
(so you've technically answered yourself). – goodvibration Feb 7 '19 at 10:17