1. I created a contract named Pepito by calling new in web3:
   import Pepito from "./contracts_abi/Pepito.json";
   const instance = new web3.eth.Contract(
  1. Inside Pepito.sol there is a function that calls newin solidity
   import "./PepitoDisguise.sol";
   function createPepitoDisguise() public returns(PepitoDisguise) {
        PepitoDisguise pepitoDisguise = new PepitoDisguise(owner);
        return pepitoDisguise;
  1. I call createPepitoDisguise from web3 by calling the function inside Pepito
   const pepitoDisguise = await instance.methods.createPepitoDisguise();

My question is: how come that in case 1 a contract is returned and in case 2 a transaction object (https://web3js.readthedocs.io/en/v1.2.11/web3-eth-contract.html#id24) is returned?

The answer is important for me because when a contract Pepito is returned, I can call a function of Pepito but when a transaction object is returned after new PepitoDisguise, I cannot. I need to call a function also in PepitoDisguise. How can I get this new Contract?


Case 1:

Your wallet account sends a contract creation instruction using its local copy of the bytecode it got from somewhere. The msg.sender in the context of the constructor of the deployed contract is your wallet account.

The contract address is deterministic based on your wallet history and the address is knowable, assuming the transaction succeeds, so the address is returned.

Case 2:

Your contract uses bytecode that became part of it's bytecode at compile time so it would know what to do when someone calls the function. Your transaction didn't create a contract, directly. It sent a message to a function in a contract. As it happens, that function created a contract but this only knowable after parsing the function. You get a transaction receipt. You wait for it to mine.

If the function was called from another contract, that caller would be able to receive the returned address. But, since this is a normal transaction from your wallet, you cannot see the return values. If the deployer function recorded the value somewhere or emitted an event (both are good ideas) then an observer would be able to inspect the created contract address. As it is, it is difficult.

From the perspective of the deployed contract, the msg.sender is the contract with the function that asked it to be deployed.

Case 3:

You're using JS to invoke the contract function, so this the same as Case 2.

Hope it helps.

  • Thanks a lot Rob, you made my day. I'll try your solution (If the deployer function recorded the value somewhere or emitted an event (both are good ideas) then an observer would be able to inspect the created contract address). It happens that the deployer contract Pepito has a public mapping of addresses of PepitoDisguises. I've have my App.js call the getter function of this mapping Dec 26 '20 at 7:34
  • Question @Rob Hitchens: would my following plan using web3 make sense: (1) get the address of the child contract from the mapping, (2) deploy PepitoDisguise once more .at(address) to get a returned instance of this child contract (3) do pepitoDisguise.methods.setHatColor().call({ from: accounts[0] }); Dec 26 '20 at 7:47

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.