'Can smart contracts deploy other smart contracts?

If a smart contract has the compiled bytecode for a contract can the first deploy a subsequent contract?

According to Ethereum.org: "To deploy a smart contract, you merely send an Ethereum transaction containing the compiled code of the smart contract without specifying any recipient."

I looked for how to send a transaction via smart contracts and the closest I could find were examples for transferring ETH...

    _to.transfer(msg.value);
  
    bool sent = _to.send(msg.value);
   
    (bool sent, bytes memory data) = _to.call{value: msg.value}("");
   


Solution 1:[1]

to make a smart contract deploy another smart contract you can do it with the use of the new keyword

contract UserMessage {
  string message;
  constructor(string memory message){
     message = _message;
  }
}

contract DeployUserMessage {
  mapping(address => address) userToContract;
  
  function Deploy(string memory message) public {
    address contractAddress = new UserMessage(message);
    userToContract[msg.sender] = contractAddress;
  }
}

I think this example make it clear, but if you want, check the docs https://docs.soliditylang.org/en/v0.8.9/contracts.html#creating-contracts

Solution 2:[2]

Yes It can, and it's called Factory Pattern contracts

contract Child {
    string public name;
    string public gender;

    constructor(string memory _name, string memory _gender) {
        name = _name;
        gender = _gender;
    }
}

contract Parent {

    Child public childContract; 

    function createChild(string memory _name, string memory _gender) public returns(Child) {
       childContract = new Child(_name, _gender); // creating new contract inside another parent contract
       return childContract;
    }
}

New Keyword is used to create contract in another contract function.

If it is a payable contract then :

contract Child {
    string public name;
    string public gender;

    constructor(string memory _name, string memory _gender) payable {
        name = _name;
        gender = _gender;
    }
}

contract Parent{

    Child public childContract; 

    function createChild(string memory _name, string memory _gender) public payable returns(Child) {
require(msg.value == 0.005 ether)
       childContract = new Child{value: msg.value}(_name, _gender); // creating new contract inside another parent contract
       return childContract;
    }
}

Solution 3:[3]

Let's say you have an application that when a user enters info can create a smart contract. Now to make the user pay for the cost of the creation of a new contract, we make a factory contract and store it in our application. Then when the user wants to create a new contract, it interacts with our factory contract via metamask, so the user sends a transaction via metamask and user pays for the creation of a new contract. So we securely create a new contract on our server and user pays for it. This is the main reason of having a factory contract.

contract Factory{
   address[] public deployedContracts;
   uint public contractsCount;

    // args will be the args that Campaign conract's constructor need.
    // message variable will be Factory campaig. but we want the user to be sender of Campaign
    // person who calls this should be marked as manager
    function createContract(uint minimumCost)public{
        // msg.sender is the user who tries to create the campaign
        ContractType newContract=new Contract(minimumCost,msg.sender);
        deployedContracts.push(address(newContract));
        contractssCount++;

    }
    function getDeployedContract(uint index) public view returns(address ){
        return deployedContracts[index];
    }
    
  }

Now after you properly deploy Factory contract and set up your provider with web3, you can call this method

await factory.methods
          .createContract(minCostPrice)
          // whenever we send transactions in the browser, metamask will automatically calculate the amount of gas we need to run this function. so we dont need to specify
          .send({
            from: connected_account[0],
          });

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jhonny
Solution 2 MFaiqKhan
Solution 3