Skip to content

Starmand6/payscroll

Repository files navigation

Table of Contents
  1. About The Project
  2. Development Stack and Plugins
  3. CLI and Interaction Steps
  4. Usage Notes
  5. Future Considerations
  6. Lessons Learned
  7. Contributing
  8. License
  9. Contact
  10. Acknowledgments

About The Project

Automated payroll ("payscroll" because I'm a principled fantasy nerd) application using smart contracts to record payment transactions on the blockchain. This specific payroll setup is for an organization that gets paid in lump sums for project or event work. The onlyOwner modifiers have been commented out to enable anyone to call functions on the contract. In production, the Payroll Manager is the user in charge of all functionality aside from the payment and withdrawal functions.

Contract Address on Polygon Mumbai Testnet: 0x7937c01F0Bde6a1F428554DF5cc593a8320DDc9f

Payscroll Contract Page on Polygonscan

Roles

  • Owner (Payroll Manager / Production Manager)
  • External Party (Payer of services)
  • Employees (Wizards)

Functionality

  • Owner / Payroll Manager:
    • addNewEmployee(): Populates payroll. Wizard entries include:
      struct Wizard {
      string name;
      address payable wallet;
      string title;
      uint256 dayRate;
      bool onProductionCrew;
      bool hasBeenPaid;
      }
    • kickOffProduction(): Manager defines each production by productionContractTotal and productionDays
    • setProductionCrew(): Manager sets which wizards are on the current production. Wizards can only be paid if they are on the current crew. Can be different for each event/project.
    • paymentVerified(): This is a quality control placeholder checkpoint. Project cannot move to the payment withdrawal stage until Manager verifies the production payment has been made correctly and/or can trigger any other logic placed here.
    • closeOutProduction(): After all wizards have withdrawn, the owner is able to call this function, which resets the Wizard struct booleans (onProductionCrew and hasBeenPaid) to false for all wizards, effectively closing out the production. Only after a production is closed out can a new production be kicked off and new production crew be set.
    • weAllGoBackToZero(): (Testnet build only) Added this function after first testnet deployment lessons to ensure dApp never gets stuck. This function would not be in a production build or would be highly altered and controlled by a multisig or similar.
    • setContractTotalMax(): (Testnet build only) Added this function after first testnet deployment lessons to minimize stuckness frequency. See Usage Notes for more info.
  • External Parties:
    • payWizards(): Once a production has kicked off and production crew is set, the external party can pay the wizards for their services. Payment must exactly match the productionContractTotal, or the function will revert.
  • Employees/Wizards:
    • withdrawPayment() has several qualifiers (must be at correct production status, registered wallet must match registered ID, must be on production crew, can only withdraw once). Once all qualifiers are met, the wizard can withdraw their precalculated payment (based on their dayRate multiplied by productionDays).
  • Public getters:
    • getWizardData() gets any wizards current data by inputting the wizard ID
    • getContractBalance() gets current contract balance
    • getProductionStatus() gets current production status
    • getPriceFeed() gets current Chainlink price feed address
    • getWizardCount() gets the total count of all wizards on the payscroll (this includes both wizards on and off the current production, if there is one)
    • getAllWizards() gets an array of all the wizard profiles

Project Highlights

  • Struct and Enum use
  • Chainlink Price Feed integration
  • Deployed to Polygon Mumbai Testnet
  • Verified on PolygonScan

Technical Highlights

  • 36 unit tests passing.
  • Hardhat network test coverage: 100% Stmts, 84.62% Branch, 88.89% Funcs, 95.88% Lines

Development Stack and Plugins

  • Your favorite Linux distribution and development environment (I currently use Ubuntu and VS Code, respectively)
  • Nodejs (open-source, cross-platform, back-end JavaScript runtime environment)
  • npm (open-source, online repository; package manager and CLI utility for interacting with repo)
  • Hardhat (local Eth environment for testing, debugging, compiling, and deploying contracts)
  • Hardhat ethers.js plugin (for interacting with the Ethereum blockchain)
  • Hardhat local node and console (to interact with contracts)
  • Mocha, Chai, Waffle, and Chai Matchers (for testing)
  • Alchemy to connect to Polygon Mumbai testnet (Alchemy is a platform that generates APIs and offers scure connections to the Blockchain)

CLI and Interaction Steps

  1. For quickstart, clone the repo

    git clone https://github.com/Starmand6/payscroll.git
    
  2. Install Node Version Manager (nvm), Node.js, and Node Package Manger (npm)

  3. Initialize and Setup Project

    mkdir payscroll 
    cd payscroll
    npm init
    git init
    npm install --save-dev hardhat
    npx hardhat
    
  4. Install Dependencies

    npm install --save-dev @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-etherscan @nomiclabs/hardhat-waffle chai ethereum-waffle hardhat hardhat-contract-sizer hardhat-deploy hardhat-gas-reporter prettier prettier-plugin-solidity solhint solidity-coverage dotenv @openzeppelin/test-helpers @chainlink/contracts
    • Install and populate package.json dependencies
    • Create folders: contracts, deploy, tests, scripts, utils
    • Configure hardhat.config file
  5. Coding, Deploying, and Testing on Local Blockchain

    • Code and compile (see repo for contracts, scripts, and tests)
    • Run local blockchain node
    • Use scripts to deploy contracts
    • Interact with contracts with Hardhat console
    • Test with Chai, Mocha, Waffle, Ethers, and Hardhat plugins
    npx hardhat compile
    npx hardhat node
    npx hardhat run --network localhost scripts/deploy.js
    npx hardhat console --network localhost
    npx hardhat test
    
  6. Deploying and Testing on Public Testnet (Polygon Mumbai)

    • Access testnet node via Alchemy

      • Get a free API Key at https://alchemy.com
      • Enter your API Key in dotenv
        const ALCHEMY_API_KEY = "(ENTER YOUR API)";
    • Create new testnet accounts:

      npx mnemonics
    • Update hardhat.config and dotenv file:

      // hardhat.config.js
      const POLYGON_MUMBAI_RPC_URL = process.env.POLYGON_MUMBAI_RPC_URL;
      const mnemonic = process.env.mnemonic;
      
      module.exports = {
          networks: {
              polygonMumbai: {
                  url: POLYGON_MUMBAI_RPC_URL,
                  accounts: {mnemonic: mnemonic},
                  chainId: 80001,
                  blockConfirmations: 3,
              },
          },
          solidity: {
              compilers: [{ version: "0.8.17" }, { version: "0.6.6" }],
          },
          etherscan: {
              apiKey: POLYGONSCAN_API_KEY,
          },        
      };

      dotenv file:

      ALCHEMY_API_KEY = "Your API Key"
      mnemonic = "your mnemonic here"
      POLYGON_MUMBAI_RPC_URL = "Mumbai RPC with Alchemy Key URL"
      
    • Fill an account with Polygon Mumbai Testnet MATIC:

    • Deploy to Polygon Mumbai Testnet (access testnet node via Alchemy):

      npx hardhat compile
      npx hardhat node
      npx hardhat run --network polygonMumbai scripts/deploy.js
      npx hardhat console --network polygonMumbai
      npx hardhat test
      

Usage Notes

Since the contract is deployed to the Polygon Mumbai Testnet, all payments are in MATIC. For testing/portfolio purposes, I have updated productionContractTotal to have a maximum value of 1 MATIC. Since this is on a testnet, and the Mumbai testnet faucet currently only gives me 2 MATIC per day, in case a tester runs out of MATIC in the middle of a "production," I need to be able to bail the contract out with MATIC, so that it gets unstuck. Keep the productionContractTotal below whatever amount of MATIC you have, so that you can pay the amount back and get it unstuck. This also means that all wizard day rates need to be under 1 MATIC (use less than 18 digits) to enable interaction with all functions throughout a production's life cycle.

For easy testing, I recommend adding a wallet you control to the payscroll with a day rate of 0.1 MATIC, and kicking off a production of 1 day for 0.1 MATIC, just so you can walk through all the functions easily.

(back to top)

Future Considerations

  • Add upgradeability to smart contract.
  • Proof of Humanity / decentralized ID integrations.
  • Implement decentralization (change single owner to multisig, etc) and further autonomy.
  • Add multiple project and crew capability. Would need to utilize a projectID, add a mapping of projects to Enums, etc.
  • Add functions to give to a bonus pool and reward bonuses to wizards.
  • Add an optional coworker tipping function.
  • If the event organization is a DAO, integrate contract with DAO voting, for changing of day rates and other parameters.
  • Add a third party vendor / subcontractor payment function.
  • Add a line item and multisig wallet for operational expenses to be included in production costs.
  • Add one or two additional payscroll manager roles for contingency purposes and/or bigger projects.

(back to top)

Lessons Learned

  • Permanent wizard IDs proved to make iterative testnet testing rather difficult, since partially run tests during debugging led to duplicate wizards being added and the production status being advanced. Future versions would need to give owner ability to clear wizards array, or the staging tests would need to be broken up and be more agile and more forgiving for human error.
  • Use a MUCH lower amount of Eth/Matic for the productionContractTotal. I originally wrote all my tests and deployed to Mumbai before even thinking that I wouldn't have 15 testnet ETH or MATIC to use to satisfy the conditions and advance through the staging test. Overzealous!
  • Make a simpler, more flexible dApp for my next portfolio project!

(back to top)

Contributing

Not Used for this repo.

(back to top)

License

Distributed under the MIT License.

(back to top)

Contact

Armand Daigle - @_Starmand - armanddaoist@gmail.com

(back to top)

Acknowledgments and Resources

Patrick Collins and the FreeCodeCamp tutorials have been amazing resources. I've learned a ton from them. Thanks Patrick and FCC!

https://github.com/smartcontractkit/full-blockchain-solidity-course-js

(back to top)

About

An automated payroll app on the blockchain

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published