Welcome to the final part of PizzaCoin the Series. In the previous article, you have learned how PizzaCoin contract deploys its children contracts using a contract-factory pattern. In this article, you will learn how PizzaCoin contract was implemented in order to integrate and interact with its dependency components.
Terms used in this article
PizzaCoin – the mother contract of PizzaCoinStaff, PizzaCoinPlayer and PizzaCoinTeam contracts.
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.
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.
PizzaCoinCodeLib – one of the two proxy libraries used by PizzaCoin contract.
PizzaCoinCodeLib2 – one of the two proxy libraries used by PizzaCoin contract.
Project Deployer – a user who deploys PizzaCoin contract which is considered as one of staffs.
pragma solidity^0.4.23;import"./ERC20.sol";import"./BasicStringUtils.sol";import"./Owned.sol";import"./PizzaCoinStaff.sol";import"./PizzaCoinPlayer.sol";import"./PizzaCoinTeam.sol";import"./PizzaCoinStaffDeployer.sol";import"./PizzaCoinPlayerDeployer.sol";import"./PizzaCoinTeamDeployer.sol";import"./PizzaCoinCodeLib.sol";import"./PizzaCoinCodeLib2.sol";// ----------------------------------------------------------------------------
// Pizza Coin Contract
// ----------------------------------------------------------------------------
contractPizzaCoinisERC20,Owned{usingBasicStringUtilsforstring;// Contract events (the 'indexed' keyword cannot be used with any string parameter)
eventStateChanged();eventChildContractCreated(addressindexed_contract);eventStaffRegistered();eventStaffKicked();eventPlayerRegistered();eventTeamCreated();eventPlayerKicked();eventTeamKicked();eventTeamVoted(string_teamName,uint256_totalVoted);// Token info
stringpublicconstantsymbol="PZC";stringpublicconstantname="Pizza Coin";uint8publicconstantdecimals=0;stringprivateownerName;uint256privatevoterInitialTokens;addressprivatestaffContract;addressprivateplayerContract;addressprivateteamContract;enumState{Initial,Registration,RegistrationLocked,Voting,VotingFinished}Stateprivatestate=State.Initial;// mapping(keccak256(state) => stateInString)
mapping(bytes32=>string)privatestateMap;// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
constructor(string_ownerName,uint256_voterInitialTokens)public{require(_ownerName.isNotEmpty(),"'_ownerName' might not be empty.");require(_voterInitialTokens>0,"'_voterInitialTokens' must be larger than 0.");initStateMap();ownerName=_ownerName;voterInitialTokens=_voterInitialTokens;emitStateChanged();}.........}
Code Snippet 1. Excerpt from PizzaCoin contract's source code
Code snippet 1 shows some excerpt from PizzaCoin contract’s source code. In the line no’s. 3 - 13, all dependency source files are imported. In the line no. 19, PizzaCoin contract inherits from Owned contract, which you can find out more about the discussion on it in detail in the previous article. Furthermore, the contract also inherits from ERC-20 token standard contract. We will separate out the discussion on ERC-20 implementation into the last section of this article.
In the line no’s. 24 - 32, the contract defines a group of contract events. Events provide logging facilities which enable DApp or backend developer directly read logging messages in the past or subscribe to any specific event to get notified from a contract in real time. You will better understand the benefits of using events after you finish reading this article.
In the line no’s. 36 - 51, a bunch of state variables used under PizzaCoin contract are defined. Most of the variables are self-explanatory. Though there are three interesting variables needed to be emphasized here, namely, staffContract, playerContract and teamContract which are of type address as defined in the line no’s. 43 - 45. These variables will be used to store addresses of deployed children contracts and we will use these variables when communicating with those children contracts. In the line no’s. 57 - 74, PizzaCoin contract’s constructor is defined. The constructor requires a project deployer’s name and initial voting tokens predetermined by the deployer as input arguments.
Firstly, the dependency libraries, including PizzaCoinStaffDeployer, PizzaCoinPlayerDeployer, PizzaCoinTeamDeployer, PizzaCoinCodeLib and PizzaCoinCodeLib2, have to be compiled into separate EVM bytecodes. Secondly, all of the dependency bytecodes have to be deployed onto the blockchain one by one as separate transactions according to the line no’s. 9 - 13 of the snippet 2. Thirdly, the previously deployed libraries’ addresses would then be linked and injected as dependency instances in order to build the bytecode of PizzaCoin mother contract in the line no’s. 15 - 19. Lastly, the bytecode of PizzaCoin contract would be deployed onto the blockchain in the line no. 21. Note that, the second and the third arguments in the line no. 21 are the values passed to PizzaCoin contract’s constructor defined in the line no. 57 of the snippet 1.
Since we injected PizzaCoinStaffDeployer, PizzaCoinPlayerDeployer, PizzaCoinTeamDeployer, PizzaCoinCodeLib and PizzaCoinCodeLib2 library instances into the EVM bytecode of PizzaCoin contract, the injected libraries will be visible to PizzaCoin contract. Thus, PizzaCoin contract is able to refer to any of those libraries like this example statement: PizzaCoinCodeLib.registerStaff(...args...).
Initialization of PizzaCoin contract
Even though PizzaCoin contract has already been deployed, its children contracts are not yet deployed. Actually, the initialization of PizzaCoin contract has already been discussed in the previous article. Nevertheless, let’s quickly recap once again. PizzaCoin contract leverages a contract-factory pattern to deploy its children contracts. As you can see in Figure 3, 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 the corresponding deployer library (steps 1.2, 2.2 and 3.2). Each deployer then deploys the corresponding child contract onto the 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). With the obtained instances, PizzaCoin contract has an approach to communicating with its children contracts. For the sake of understanding, let’s deep dive into the code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ------------------------------------------------------------------------
// Create a player contract
// ------------------------------------------------------------------------
functioncreatePlayerContract()publiconlyInitialStateonlyOwnerreturns(address_contract){require(playerContract==address(0),"The player contract got initialized already.");// Create a player contract
playerContract=PizzaCoinPlayerDeployer.deployContract(voterInitialTokens);emitChildContractCreated(playerContract);returnplayerContract;}
Code Snippet 3. The function createPlayerContract() on PizzaCoin invokes PizzaCoinPlayerDeployer in order to deploy PizzaCoinPlayer
Code snippet 3 describes the implementation of createPlayerContract function on PizzaCoin contract. Let’s say a project deployer would like to deploy PizzaCoinPlayer contract. The deployer makes a call to createPlayerContract function on PizzaCoin contract. The function would verify if PizzaCoinPlayer contract does not get deployed yet in the line no’s. 5 - 8. The transaction would be reverted if PizzaCoinPlayer contract get deployed already in the line no. 7. If it isn’t so, the function communicates with PizzaCoinPlayerDeployer library in order to deploy PizzaCoinPlayer contract with the statement PizzaCoinPlayerDeployer.deployContract(voterInitialTokens) in the line no. 11.
The implementation of deployContract function on PizzaCoinPlayerDeployer library is expressed in the code snippet 4 below. The function would deploy PizzaCoinPlayer contract with the new operator in the line no. 25 and the function would return an address of the deployed contract to PizzaCoin contract if everything went fine. Consequently, the returned address would be stored in the variable playerContract (which is a global state variable previously declared in the line no. 44 of the snippet 1) in the line no. 11 of the snippet 3. Lastly, createPlayerContract function emits the event ChildContractCreated along with returning of the last received address playerContract to the project deployer in the line no’s. 13 and 14.
pragma solidity^0.4.23;import"./PizzaCoinPlayer.sol";// ----------------------------------------------------------------------------
// Pizza Coin Player Deployer Library
// ----------------------------------------------------------------------------
libraryPizzaCoinPlayerDeployer{// ------------------------------------------------------------------------
// Create a player contract
// ------------------------------------------------------------------------
functiondeployContract(uint256_voterInitialTokens)publicreturns(PizzaCoinPlayer_playerContract){require(_voterInitialTokens>0,"'_voterInitialTokens' must be larger than 0.");_playerContract=newPizzaCoinPlayer(_voterInitialTokens);}}
Code Snippet 4. PizzaCoinPlayerDeployer is a contract factory for PizzaCoinPlayer
Interaction among deployed contracts
Once PizzaCoin contract and its depencencies get deployed successfully, PizzaCoin contract would act as a coordinator for its children contracts like what is depicted in Figure 4 above. Let’s get into the code to understand this better.
1
2
3
4
5
6
7
8
9
// ------------------------------------------------------------------------
// Register the new staff
// ------------------------------------------------------------------------
functionregisterStaff(address_newStaff,string_newStaffName)publiconlyRegistrationStateonlyStaffnotRegistered(_newStaff){PizzaCoinCodeLib.registerStaff(_newStaff,_newStaffName,staffContract);emitStaffRegistered();}
Code Snippet 5. The use of PizzaCoinCodeLib as a proxy library for communicating with PizzaCoinStaff contract
Let’s say the staff invokes registerStaff function on PizzaCoin contract in order to register some new staff. The function is as very simple as defined in the line no. 7 of the snippet 5. It just hands over the process to the delegated function which is on PizzaCoinCodeLib library. That is, the function passes three arguments to its delegated function like the following statement PizzaCoinCodeLib.registerStaff(_newStaff, _newStaffName, staffContract). Interestingly, the instance of PizzaCoinStaff contract named staffContract is passed as the third argument.
pragma solidity^0.4.23;import"./BasicStringUtils.sol";import"./PizzaCoinStaff.sol";import"./PizzaCoinPlayer.sol";import"./PizzaCoinTeam.sol";// ----------------------------------------------------------------------------
// Pizza Coin Code Library #1
// ----------------------------------------------------------------------------
libraryPizzaCoinCodeLib{usingBasicStringUtilsforstring;// ------------------------------------------------------------------------
// Register the new staff
// ------------------------------------------------------------------------
functionregisterStaff(address_staff,string_staffName,address_staffContract)public{assert(_staffContract!=address(0));// Get a contract instance from the deployed address
IStaffContractstaffContractInstance=IStaffContract(_staffContract);staffContractInstance.registerStaff(_staff,_staffName);}.........}
Code Snippet 6. The delegated function registerStaff() on PizzaCoinCodeLib library
The implementation of the delegated function registerStaff on PizzaCoinCodeLib library is shown in the line no’s. 19 - 26 of the snippet 6. To process the transaction request, the delegated function converts the third function paramater _staffContract which is of type address to the contract instance variable staffContractInstance of type IStaffContract interface in the line no. 23. Later, the delegated function executes the real worker function which is on PizzaCoinStaff contract with the statement staffContractInstance.registerStaff(_staff, _staffName) in the line no. 25.
One point to notice is that registerStaff function of PizzaCoin mother contract is applied with three modifiers. The three modifiers include onlyRegistrationState, onlyStaff and notRegistered(_newStaff) as defined in the line no. 5 of the snippet 5. This means that the transaction request would be verified before the function invokes its delegated function. The transaction, therefore, would be reverted if it does not satisfy any of the three modifiers.
1
2
3
4
5
6
7
8
9
10
11
12
13
// ------------------------------------------------------------------------
// Allow any staff or any player vote to a favourite team
// ------------------------------------------------------------------------
functionvoteTeam(string_teamName,uint256_votingWeight)publiconlyVotingStateonlyRegistered{uint256totalVoted=PizzaCoinCodeLib.voteTeam(_teamName,_votingWeight,staffContract,playerContract,teamContract);emitTeamVoted(_teamName,totalVoted);}
Code Snippet 7. The implementation of voteTeam() on PizzaCoin contract
Another interesting function to be discussed in this section is voteTeam function on PizzaCoin contract as defined in the snippet 7. This function allows any staff or any player to vote to a favourite team. The staff is freely to give a vote to any team whereas a player can commit to vote to any other different team. Each voter can spend voting tokens according to his/her own balance. In the line no. 5, the function does nothing except forwording the process to its delegated function which is on PizzaCoinCodeLib library and receiving the processing result from the delegated function into the variable totalVoted. Finally, the function returns the processing result to a caller by way of emiting the event TeamVoted(_teamName, totalVoted) in the line no. 12. Note that, the function passes instances of PizzaCoin’s children contracts to the delegated function in the line no’s. 8 - 10.
// ------------------------------------------------------------------------
// Allow any staff or any player vote to a favourite team
// ------------------------------------------------------------------------
functionvoteTeam(string_teamName,uint256_votingWeight,address_staffContract,address_playerContract,address_teamContract)publicreturns(uint256_totalVoted){assert(_staffContract!=address(0));assert(_teamContract!=address(0));// Get contract instances from the deployed addresses
IStaffContractstaffContractInstance=IStaffContract(_staffContract);ITeamContractteamContractInstance=ITeamContract(_teamContract);require(_teamName.isNotEmpty(),"'_teamName' might not be empty.");require(_votingWeight>0,"'_votingWeight' must be larger than 0.");require(teamContractInstance.doesTeamExist(_teamName),"Cannot find the specified team.");if(staffContractInstance.isStaff(msg.sender)){// Voter is the staff
returnvoteTeamByStaff(_teamName,_votingWeight,_staffContract,_teamContract);}else{// Voter is a player
returnvoteTeamByDifferentTeamPlayer(_teamName,_votingWeight,_playerContract,_teamContract);}}// ------------------------------------------------------------------------
// Vote for a team by the staff
// ------------------------------------------------------------------------
functionvoteTeamByStaff(string_teamName,uint256_votingWeight,address_staffContract,address_teamContract)internalreturns(uint256_totalVoted){assert(_staffContract!=address(0));assert(_teamContract!=address(0));// Get contract instances from the deployed addresses
IStaffContractstaffContractInstance=IStaffContract(_staffContract);ITeamContractteamContractInstance=ITeamContract(_teamContract);addressvoter=msg.sender;assert(_teamName.isNotEmpty());assert(_votingWeight>0);assert(teamContractInstance.doesTeamExist(_teamName));assert(staffContractInstance.isStaff(voter));require(_votingWeight<=staffContractInstance.getTokenBalance(voter),"Insufficient voting balance.");// Staff commits to vote to the team
staffContractInstance.commitToVote(voter,_teamName,_votingWeight);teamContractInstance.voteToTeam(voter,_teamName,_votingWeight);// Get the current voting points of the team
_totalVoted=teamContractInstance.getVotingPointsOfTeam(_teamName);}// ------------------------------------------------------------------------
// Vote for a team by a different team's player
// ------------------------------------------------------------------------
functionvoteTeamByDifferentTeamPlayer(string_teamName,uint256_votingWeight,address_playerContract,address_teamContract)internalreturns(uint256_totalVoted){assert(_playerContract!=address(0));assert(_teamContract!=address(0));// Get contract instances from the deployed addresses
IPlayerContractplayerContractInstance=IPlayerContract(_playerContract);ITeamContractteamContractInstance=ITeamContract(_teamContract);addressvoter=msg.sender;assert(_teamName.isNotEmpty());assert(_votingWeight>0);assert(teamContractInstance.doesTeamExist(_teamName));assert(playerContractInstance.isPlayer(voter));require(playerContractInstance.isPlayerInTeam(voter,_teamName)==false,"A player is not permitted to vote to his/her own team.");require(_votingWeight<=playerContractInstance.getTokenBalance(voter),"Insufficient voting balance.");// Player commits to vote to the team
playerContractInstance.commitToVote(voter,_teamName,_votingWeight);teamContractInstance.voteToTeam(voter,_teamName,_votingWeight);// Get the current voting points of the team
_totalVoted=teamContractInstance.getVotingPointsOfTeam(_teamName);}
Code Snippet 8. The delegated function voteTeam() and its dependency functions voteTeamByStaff() and voteTeamByDifferentTeamPlayer() on PizzaCoinCodeLib library
Code snippet 8 shows the implementation of the delegated function voteTeam and its dependency functions which is on PizzaCoinCodeLib library. For the sake of simplicity, I will emphasize only important implementation points. Upon receiving a request, voteTeam function verifies the presence of the team to be voted _teamName in the line no’s. 31 - 34. After that, the function checks if a voter has the role of the staff or a player by consulting with the function isStaff of PizzaCoinStaff contract in the line no. 36. If a voter has the role of the staff the process will be forwarded to the dependency function named voteTeamByStaff in the line no. 38 else the process will be forwarded to another dependency function named voteTeamByDifferentTeamPlayer in the line no. 42.
The implementation of the dependency function voteTeamByStaff is described in the line no’s. 49 - 82. The function verifies that a voter has sufficient tokens to commit a vote by consulting with the function getTokenBalance of PizzaCoinStaff contract in the line no. 72. If a voter has enough voting balance, the function confirms the voting transaction by executing the statements in line no’s. 77 and 78. Eventually, the function returns the current voting points of the voted team to its caller in the line no. 81.
For another dependency function voteTeamByDifferentTeamPlayer as defined in the line no’s. 87 - 124, this function performs the similar logic like the function voteTeamByStaff does. Nonetheless, this function will only handle the voting transaction sent from a player. The only difference between the two functions is that the function voteTeamByDifferentTeamPlayer has an additional user verification check in the line no’s. 108 - 111 to ensure that a voter does not commit to vote to his/her own team.
The last section to be discussed in this article is about the implementation of ERC-20 token standard. The abstract contract ERC20 is defined like the code snippet 9. Our PizzaCoin voting system inherits from ERC20 contract in the line no. 4 of the below code snippet 10. In the line no’s. 7 - 9, PizzaCoin contract defines constant variables for providing token information. In the line no’s. 26 - 70, the contract implements all the functions required by ERC20 contract. Each function does nothing except forwarding the transaction request to its delegated function on PizzaCoinCodeLib2 library.
// ----------------------------------------------------------------------------
// Pizza Coin Contract
// ----------------------------------------------------------------------------
contractPizzaCoinisERC20,Owned{// Token info
stringpublicconstantsymbol="PZC";stringpublicconstantname="Pizza Coin";uint8publicconstantdecimals=0;........./*
*
* This contract is partially compatible with ERC token standard #20 interface.
* That is, only balanceOf() and totalSupply() would really be implemented.
*
*/// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functiontotalSupply()publicviewreturns(uint256_totalSupply){returnPizzaCoinCodeLib2.totalSupply(staffContract,playerContract);}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functionbalanceOf(address_tokenOwner)publicviewreturns(uint256_balance){returnPizzaCoinCodeLib2.balanceOf(_tokenOwner,staffContract,playerContract);}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functionallowance(address_tokenOwner,address_spender)publicviewreturns(uint256){// This function does nothing, just revert a transaction
PizzaCoinCodeLib2.allowance(_tokenOwner,_spender);}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functiontransfer(address_to,uint256_tokens)publicreturns(bool){// This function does nothing, just revert a transaction
PizzaCoinCodeLib2.transfer(_to,_tokens);}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functionapprove(address_spender,uint256_tokens)publicreturns(bool){// This function does nothing, just revert a transaction
PizzaCoinCodeLib2.approve(_spender,_tokens);}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functiontransferFrom(address_from,address_to,uint256_tokens)publicreturns(bool){// This function does nothing, just revert a transaction
PizzaCoinCodeLib2.transferFrom(_from,_to,_tokens);}}
Code Snippet 10. The implementation of ERC-20 token standard on PizzaCoin contract
/*
*
* This contract is partially compatible with ERC token standard #20 interface.
* That is, only balanceOf() and totalSupply() would really be implemented.
*
*/// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functiontotalSupply(address_staffContract,address_playerContract)publicviewreturns(uint256_totalSupply){assert(_staffContract!=address(0));assert(_playerContract!=address(0));// Get contract instances from the deployed addresses
IStaffContractstaffContractInstance=IStaffContract(_staffContract);IPlayerContractplayerContractInstance=IPlayerContract(_playerContract);uint256staffTotalSupply=staffContractInstance.getTotalSupply();uint256playerTotalSupply=playerContractInstance.getTotalSupply();returnstaffTotalSupply.add(playerTotalSupply);}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functionbalanceOf(address_tokenOwner,address_staffContract,address_playerContract)publicviewreturns(uint256_balance){assert(_staffContract!=address(0));assert(_playerContract!=address(0));// Get contract instances from the deployed addresses
IStaffContractstaffContractInstance=IStaffContract(_staffContract);IPlayerContractplayerContractInstance=IPlayerContract(_playerContract);if(staffContractInstance.isStaff(_tokenOwner)){returnstaffContractInstance.getTokenBalance(_tokenOwner);}elseif(playerContractInstance.isPlayer(_tokenOwner)){returnplayerContractInstance.getTokenBalance(_tokenOwner);}else{revert("The specified address was not being registered.");}}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functionallowance(address_tokenOwner,address_spender)publicpurereturns(uint256){// This function does nothing, just revert a transaction
revert("We don't implement this function.");// These statements do nothing, just use to stop compilation warnings
_tokenOwner==_tokenOwner;_spender==_spender;}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functiontransfer(address_to,uint256_tokens)publicpurereturns(bool){// This function does nothing, just revert a transaction
revert("We don't implement this function.");// These statements do nothing, just use to stop compilation warnings
_to==_to;_tokens==_tokens;}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functionapprove(address_spender,uint256_tokens)publicpurereturns(bool){// This function does nothing, just revert a transaction
revert("We don't implement this function.");// These statements do nothing, just use to stop compilation warnings
_spender==_spender;_tokens==_tokens;}// ------------------------------------------------------------------------
// Standard function of ERC token standard #20
// ------------------------------------------------------------------------
functiontransferFrom(address_from,address_to,uint256_tokens)publicpurereturns(bool){// This function does nothing, just revert a transaction
revert("We don't implement this function.");// These statements do nothing, just use to stop compilation warnings
_from==_from;_to==_to;_tokens==_tokens;}
Code Snippet 11. The delegated functions on PizzaCoinCodeLib2 library which implement ERC-20 token standard
Code snippet 11 shows the implementation of the delegated functions on PizzaCoinCodeLib2 library which implement ERC-20 token standard. Actually, our voting system is partially compatible with ERC20. That is, only two ERC20 functions are really implemented including totalSupply and balanceOf functions. totalSupply function provides a total number of voting tokens supplied to all registered users in the system. For that to happen, the function queries two total supply values from PizzaCoinStaff and PizzaCoinPlayer contracts in the line no’s. 21 and 22 respectively. The function then returns its caller the sum of the two obtained total supply values.
balanceOf function provides token balance information of the specified user. The function would determine a role of the specified user. If the specified user is the staff, the function queries a token balance of that specific user from PizzaCoinStaff contract in the line no. 45. If the specified user is a player, the function will communicate with PizzaCoinPlayer contract in order to get a token balance of the specified user in the line no. 48 instead. The resulting token balance would then be returned to a caller. For other ERC20 functions, they do nothing except reverting every incoming transaction request.
Since PizzaCoin voting system is compatible with ERC-20 token standard, the system can be listed on any Ethereum-supported browsers or wallets. Figure 5 shows PZC token listed on the cipher browser application.
Summary
Let’s summarize. In this article, you have learned how PizzaCoin contract was implemented to interact with its children contracts through the help of proxy libraries. You have also learned how PizzaCoin was implemented in order to be compatible with ERC-20 token standard.
Hopefully my articles would give you an idea on how Ethereum’s smart contract can be implemented on production. Please do not hesitate to ask me if you have any questions. Any suggestions would be greatly appreciated. Thank you for reading my articles.
PizzaCoin the series consists of 6 articles as follows.