'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 |