Smart Contract Factories
Tags: smartcontracts, defi, blockchain, erc20
Published: 2021-06-24 13:38:44

Factories are a wonderful design pattern, which are not only used with smart contracts, but generally in any other coding language to help facilitate better automation. 

Factories are one of my favorite design patterns when dealing with generic smart contracts, because they eliminate the need to open up my IDE and do another command line deployment, when I could be doing a deployment with a simple transaction through [MetaMask](https://metamask.io/). Along with the benefits of a factory, they are also simple to create. 

## TLDR; Show Me the Goods!
If you are someone that likes to jump right into the code here it is: 
[ApetasticERC20Factory GitHub Repo](https://github.com/DeFiFoFum/ApetasticERC20Factory)

The factory is deployed below and you can start making your very own ERC-20 tokens through the `Write Contract` tab.
[ApetasticERC20Factory Deployed](https://bscscan.com/address/0x8C269841E5a8BC387925325a44c7867DBb3Cd5Cd#code)


## Full Details: How it Works
Solidity language has a very useful feature for creating new contracts using the `new` keyword. 

[Solidity Docs - Creating new contracts via new](https://docs.soliditylang.org/en/v0.8.6/control-structures.html?highlight=new#creating-contracts-via-new)

The `new` keyword works similarly to javascript in that it creates a new instance. In this case, a new deployed contract instance.

In the example below, pulled from the `ApetasticERC20Factory`, you can see that we first need to:
1. Import the contract that we want to deploy. In this case `ApetasticERC20.sol`.
2. Use the `new` keyword in a function using the name of the contract to deploy a new instance. 
3. Pass in arguments which the constructor of the contract needs. 
4. The return value represents the address of the deployed contract. In the factory it is a good idea to record it so that new contracts can be found later if needed. In this case we are pushing the address to the `allTokens` array. 

*`ApetasticERC20 token` is also more than just an address. It also represents an `ApetasticERC20` interface which means `uint256 tokenTotalSupply = token.totalSupply()` would also be possible. This allows your factory contract to call methods on the newly deployed contract for configuration or other purposes.*


```solidity
/* from ApetasticERC20Factory contract */

import "./ApetasticERC20.sol";

/// @notice Create a new ERC-20 contract
/// @dev Tokens created have 18 decimals which means add 18 zeros the integer supply: 000000000000000000 
/// @param name The name of the token
/// @param symbol The symbol of the token
/// @param supply The totalSupply of the token
function createToken(string memory name, string memory symbol, uint256 supply) external returns (address) {
    ApetasticERC20 token = new ApetasticERC20(name, symbol, msg.sender, supply);
    allTokens.push(address(token));
    emit TokenCreated(address(token), supply);
    return address(token);
}
```


## The ApetasticERC20.sol Contract

The `ApetasticERC20` contract is an extension of OpenZeppelin's [`ERC20` implementation](https://docs.openzeppelin.com/contracts/erc20). This was done so the proper parameters could be set in the `constructor` of the token. You could take a similar approach and add a bit more functionality if needed. 

As seen in the contract code below, the constructor is used to mint the initial supply by calling the internal `_mint` function and sending it to the `mintTo` address. 

Because the factory contract is deploying the contract, `msg.sender` would actually send the tokens to the factory which could lock them. To avoid this, the factory passes its `msg.sender` (the address that initiated the creation in this case) into `ApetasticERC20` so that the tokens are sent to the correct address. 

```solidity
/* from ApetasticERC20 contract */

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/// @notice Create an ERC20 token with adjustable initial parameters
contract ApetasticERC20 is ERC20 {

    /// @param name The name of the token
    /// @param symbol The symbol of the token
    /// @param mintTo The address that the initial supply should be sent to
    /// @param supply The totalSupply of the token
    constructor(
        string memory name,
        string memory symbol,
        address mintTo,
        uint256 supply
    ) ERC20(name, symbol) {
        _mint(mintTo, supply);
    }
}
```

## Time to Get Dirty!
Sweet, now you can apply this fairly straightforward concept to ever more and more complex smart contracts. Let's build! 


## Challenge: Factory Improvements
This is just an MVP for factories. From here a good improvement is to make the factory contract upgradeable which allows us to add features without changing the contract address. 

Contracts which don't hold value are good candidates for upgradeability.

Give it a shot & let me know if there are other features you desire!