Skip to content

Latest commit

 

History

History
71 lines (65 loc) · 3.52 KB

factory.md

File metadata and controls

71 lines (65 loc) · 3.52 KB

Week 1 - Factory

Why do we need Factory contract?

  1. Ideally, a smart contract we deploy should serve a specific functionality, for example is like AMM. Ideally we should have a different contract for each money market (e.g. BUSD-BNB, CAKE-BNB, etc) so the state would not be too complicated and the contract can be more secured.
  2. The problem with that approach is we need to manually deploy the contract for each money market, which can cost us a lot, since deploying a contract requires gas fee
  3. Factory can solve the problems mentioned above

How Factory can benefit us

  1. We don't need to deploy many contract manually anymore, we can just call a function from our Factory contract to deploy another contract
  2. We spend less on gas fee from deploying many similar contracts

Types of Factory

1. Using new Keyword from Solidity

  • With this approach, we can first create our main contract. Let's call it Contract.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Contract {
    function add(uint256 a, uint256 b) external pure returns (uint256 c) {
        c = a + b;
        // return a + b
    }

    function sub(uint256 a, uint256 b) external pure returns (uint256 c) {
        c = a - b;
    }

    function mul(uint256 a, uint256 b) external pure returns (uint256 c) {
        c = a * b;
    }
}
  • We will not deploy Contract.sol to the blockchain
  • Next, we create another contract called Factory.sol
  • Import our main contract inside Factory.sol
import { Contract } from "./Contract.sol";
  • Create a function that will deploy our main contract with new keyword from solidity
function deployContract() external returns (address c) {
    c = address(new Contract());
}

Note:

  • Verifying contract in etherscan can be quite tricky with this approach, since the bytecode (output from compilation process) generated by EVM and etherscan could be different sometimes and causing failed verification.
  • The address of contract deployed with this approach is not predictable, so the address could be different every deployment.
  • The fee we spent on deployment is cheaper than doing manual deployment

2. Minimal Proxy

  • With this approach, we can first create our main contract, which is Contract.sol that have the same code as in previous approach.
  • In this approach, we will call Contract.sol as our implementation contract
  • We need to deploy this implementation contract to the blockchain
  • Next, we can create the factory contract. Let's call it FactoryWithClone.sol
  • In this contract, we will be using Clone from OpenZeppelin
import { Clones } from "openzeppelin/proxy/Clones.sol";
  • Unlike the previous approach, we are not importing the Contract.sol in our factory contract
  • After that, we can create a function that will deploy our main contract. We will be using clone function from Clones here
function deployContract(address _implementation) external returns (address c)
{
    // Clone implementation
    c = Clones.clone(_implementation);
}
  • When we call a function inside a contract that is deployed with this implementation, it will be executed as delegate call, which mean it refer the code from our implementation contract to execute the function. Note:
  • The fee we spent on deployment with this approach is cheaper that the previous one (with new keyword from solidity)
  • The contract deployed with this approach will be automatically verified in etherscan and marked as Minimal Proxy Contract