Contents

[ PizzaCoin the Series #5 ] Deploying Children Contracts with Contract Factories

Figure 1. Pizza Hackathon 2018

Figure 1. Pizza Hackathon 2018


Welcome to the 5th part of PizzaCoin the Series. Previously, you have learned how PizzaCoinStaff and PizzaCoinPlayer contracts were developed in the 3rd article. The development details of PizzaCoinTeam contract has been discussed in the 4th article. In this article, you will learn how PizzaCoin contract deploys PizzaCoinStaff, PizzaCoinPlayer and PizzaCoinTeam as its children contracts.

Terms used in this article


PizzaCoin – the mother contract of PizzaCoinStaff, PizzaCoinPlayer and PizzaCoinTeam contracts.

PizzaCoinStaffDeployer – a contract factory library for deploying PizzaCoinStaff contract.

PizzaCoinPlayerDeployer – a contract factory library for deploying PizzaCoinPlayer contract.

PizzaCoinTeamDeployer – a contract factory library for deploying PizzaCoinTeam contract.

PizzaCoinStaff – one of the three PizzaCoin’s children contracts responsible for managing staff-related tasks such as registering staffs, revoking staffs, providing staff information, and managing token balance as well as voting action for the staff.

PizzaCoinPlayer – one of the three PizzaCoin’s children contracts responsible for managing player-related tasks such as registering players, revoking players, providing player information, and managing token balance as well as voting action for a player.

PizzaCoinTeam – one of the three PizzaCoin’s children contracts responsible for managing team-related tasks such as creating teams, registering a player to a specific team, revoking teams, revoking a specific player from a particular team, handling team voting, and providing team information as well as voting results.

Project Deployer – a user who deploys PizzaCoin contract which is considered as one of staffs.

Source files refered to in this article


How a contract factory works?


Figure 2. PizzaCoin contract uses contract factories to deploy its children contracts

Figure 2. PizzaCoin contract uses contract factories to deploy its children contracts


To facilitate as well as avoiding human errors during deploying children contracts, PizzaCoin contract leverages a contract-factory pattern to deploy its children contracts. As you can see in Figure 2, a project deployer initiates three separate transactions to PizzaCoin contract (steps 1.1, 2.1 and 3.1) by invoking createStaffContract, createPlayerContract and createTeamContract functions in any order. Then, each invoked function makes a call to deployContract function on each corresponding deployer libraries (steps 1.2, 2.2 and 3.2). Each deployer then deploys a corresponding child contract onto Ethereum blockchain (steps 1.3, 2.3 and 3.3). The resulting children contract instances would then be returned from the deployers to store on PizzaCoin contract (steps 1.4, 2.4 and 3.4). This way makes PizzaCoin contract know where its children contracts are located. To understand the deployment mechanism in question better, let’s deep dive into the code.

The implementation of the contract factory


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
pragma solidity ^0.4.23;

import "./PizzaCoinStaff.sol";


// ----------------------------------------------------------------------------
// Pizza Coin Staff Deployer Library
// ----------------------------------------------------------------------------
library PizzaCoinStaffDeployer {

    // ------------------------------------------------------------------------
    // Create the staff contract
    // ------------------------------------------------------------------------
    function deployContract(uint256 _voterInitialTokens) 
        public
        returns (
            PizzaCoinStaff _staffContract
        ) 
    {
        require(
            _voterInitialTokens > 0,
            "'_voterInitialTokens' must be larger than 0."
        );

        _staffContract = new PizzaCoinStaff(_voterInitialTokens);
    }
}
Code Snippet 1. PizzaCoinStaffDeployer is a contract factory for PizzaCoinStaff


All the source code for PizzaCoinStaffDeployer library is shown in the code snippet 1. The library contains only one function named deployContract which receives a single function argument _voterInitialTokens in the line no. 14. deployContract function returns an instance of deployed PizzaCoinStaff contract _staffContract to its caller in the line no. 17. What deployContract function actually does is that upon receiving a transaction request the function just executes new operator in order to deploy PizzaCoinStaff contract onto the blockchain in the line no. 25. the new operator will construct and initialize PizzaCoinStaff contract with the received argument _voterInitialTokens. As a result, the new operator returns an instance of the deployed PizzaCoinStaff contract and stores the instance into the return parameter _staffContract. Finally, the function returns the deployed contract instance _staffContract to the caller, which is PizzaCoin mother contract in this case.

You may wonder how PizzaCoinStaffDeployer library deploys PizzaCoinStaff contract. To understand this, you have to understand how Solidity compiler and linker work. During PizzaCoinStaffDeployer.sol getting compiled, the compiler knows that PizzaCoinStaffDeployer refers to PizzaCoinStaff contract from the line no. 25. Hence, the compiler then searches for the existence of PizzaCoinStaff contract’s source file and finds out that the source file is located at the path “./PizzaCoinStaff.sol” as indicated by the import statement in the line no. 3. After that, the compiler will compile both PizzaCoinStaffDeployer.sol and PizzaCoinStaff.sol files into two binary objects. Next, the compiler invokes the linker to link both compiled objects together. The result from objects linking is the EVM bytecode of PizzaCoinStaffDeployer library which is embedded with the bytecode of PizzaCoinStaff contract. Once deployContract function of PizzaCoinStaffDeployer library is invoked, the function is able to execute the new operator in order to deploy the embedded bytecode of PizzaCoinStaff contract onto the blockchain.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// ------------------------------------------------------------------------
// Create the staff contract
// ------------------------------------------------------------------------
function createStaffContract() public onlyInitialState onlyOwner returns (address _contract) {
    require(
        staffContract == address(0),
        "The staff contract got initialized already."
    );

    // Create the staff contract
    staffContract = PizzaCoinStaffDeployer.deployContract(voterInitialTokens);

    // Register an owner as the staff. Note that, we cannot make a call to 
    // PizzaCoin.registerStaff() directly at this moment because 
    // the contract is in Initial state.
    PizzaCoinCodeLib.registerStaff(owner, ownerName, staffContract);

    emit ChildContractCreated(staffContract);
    return staffContract;
}
Code Snippet 2. The function createStaffContract() on PizzaCoin invokes PizzaCoinStaffDeployer in order to deploy PizzaCoinStaff


Code snippet 2 shows the implementation of createStaffContract function on PizzaCoin mother contract. As soon as the function is called by a project deployer (step 1.1 in Figure 2), the function first checks whether PizzaCoinStaff contract is already deployed in the line no’s. 5 - 8. If PizzaCoinStaff contract is already registered (i.e., staffContract != address(0)) then the function reverts a transaction else the function invokes the function deployContract which is on PizzaCoinStaffDeployer library in the line no. 11. The variable staffContract will receive an instance of the newly deployed PizzaCoinStaff contract from the deployer after contract deployment succeeds. In other words, the variable staffContract holds an address of the deployed PizzaCoinStaff contract. Thus, PizzaCoin mother contract can make function calls to PizzaCoinStaff by way of referencing the obtained staffContract.

In addition to implementation of PizzaCoinPlayerDeployer and PizzaCoinTeamDeployer, both libraries also use the similar coding logic like what PizzaCoinStaffDeployer library was implemented. Check out the following source files: PizzaCoinPlayerDeployer library and PizzaCoinTeamDeployer library.

Summary


Let’s summarize. In this article, you have learned how PizzaCoin contract uses deployer libraries to deploy its children contracts. Each deployer acts as a contract factory by embedding the EVM bytecode of PizzaCoin’s child contract into its bytecode. This way makes a deployer to be able to deploy the embedded contract onto the blockchain. This method not only facilitates a project deployer but also avoids human errors when deploying children contracts. In the next article, you will learn how PizzaCoin mother contract was integrated with its dependency components. See you in the next article.




PizzaCoin the series consists of 6 articles as follows.

Part 1: How Did We Develop Ethereum-based Voting System for Pizza Hackathon?

Part 2: Workflow Design for PizzaCoin Voting System

Part 3: Detailed Implementation of Staff and Player Contracts

Part 4: Detailed Implementation of Team Contract

Part 5: Deploying Children Contracts with Contract Factories

Part 6: Integrating PizzaCoin Contract with Dependencies