Can Someone Check my code?

I have created a smart contract that will reimburse an employee for miles driven.

The constructor establishes a CFO and the mileage rate.

The CFO can add/remove Managers and Employees while a Manager can only add/remove Employees.

Employees can submit a request by entering their starting miles and ending miles. The smart contract will calculate miles driven and the amount to be paid and submit the request.

CFO and Managers can approve the request by entering the ID in the approve function.

Problem: Everything seems to be working, but I’m having trouble cleaning up the employees array when removing an employee.

Main Contract

pragma solidity 0.7.5;
pragma abicoder v2;

import "./Permissions.sol";

contract Reimburse is Permissions {
    //Employee struct and modifiers are in "./Permissions.sol".
    //CFO Address in "./Permissions.sol"

    uint mileageRate;

    struct Payout{
        uint id;
        address payable requester;
        uint amount;
        uint milesDriven;
        bool approved;
        bool hasBeenSent;
    }
    
    Payout[] payoutRequests;
    mapping(address => mapping(uint => bool)) approved;
   
    //Establishes CFO address/name and the mileageRate when contract is deployed.  //Makes CFO an active employee and a manager for inherited permissions. 
    constructor(address payable _CFO, string memory _name, uint _mileageRate) {
        CFO = _CFO;
        mileageRate = _mileageRate;
        uint _id = employees.length + 1;
        employees.push(Employee(_id, _CFO, _name));
        Active[_CFO] = true;
        Manager[_CFO] = true;
    }
    
    //Updates the mileageRate.
    function updateMileageRate(uint _mileageRate) public onlyCFO {
        mileageRate = _mileageRate;
    }
    
    //Create an instance of the Payout struct and add it to the payoutRequests array.
    function createTransferRequest(uint _startingMiles, uint _endingMiles) public onlyEmployees {
        
        uint _milesDriven = _endingMiles - _startingMiles;
        uint _amountToPay = _milesDriven * mileageRate;
        
        payoutRequests.push(
            Payout(payoutRequests.length, msg.sender, _amountToPay, _milesDriven, false, false)
        );
    }
    
    //Should return all transfer Requests
    function getTransferRequests() public view onlyManagers returns (Payout[] memory){
        return payoutRequests;
    }
    
    //Enter the ID to approve the Transfer Request and sends the funds.
    function approveTransfer(uint _id) public onlyManagers {
        require(payoutRequests[_id].approved == false, "This Request has Already Been Paid");
        require(payoutRequests[_id].hasBeenSent == false, "This Request has Already Been Sent");
        
        payoutRequests[_id].approved = true;
        payoutRequests[_id].hasBeenSent = true;
        
        if(payoutRequests[_id].approved == true){
            payoutRequests[_id].hasBeenSent = true;
            payoutRequests[_id].requester.transfer(payoutRequests[_id].amount);
        }
    }
    

    //Allows the CFO to deposit funds to the contract
    function deposit() public payable onlyEmployees onlyCFO {}
    
    //Allows the CFO to check the contract Balance.
    function getBalance() public view onlyEmployees onlyCFO returns (uint){
        return address(this).balance;
    }
    
    //Allows the CFO and Managers to Add Employees.
    function addEmployee(address payable _address, string memory _name) public onlyEmployees onlyManagers  {
        uint _id = employees.length + 1;
        employees.push(Employee(_id, _address, _name));
        Active[_address] = true;
    }
    
   //Allows the CFO to Add Managers
    function addManager(address payable _address, string memory _name) public onlyEmployees onlyCFO {
        uint _id = employees.length + 1;
        employees.push(Employee(_id, _address, _name));
        
        Active[_address] = true;
        Manager[_address] = true;
    }
    
    //Removes Manager status.
    function removeManager(address payable _address) public onlyEmployees onlyCFO {
      Manager[_address] = false;
    }
    
    //Adds manager Status to existing employee.
    function setManager(address _address) public onlyEmployees onlyCFO {
        Manager[_address] = true;
    }
    
    //Checks if an employee is a manager.
    function getManagerStatus(address _address) public view onlyEmployees returns (bool){
        return Manager[_address];
    }
    
    //Sets Employee as an Active Employee.
    function setActive(address _address) public onlyEmployees onlyManagers {
        Active[_address] = true;
    }
    
    //Checks if an employee is an active employee.
    function getActiveStatus(address _address) public view onlyEmployees onlyManagers returns (bool){
        return Active[_address];
    }
    
    //Removes Employee
    function removeEmployee(address payable _address) public onlyEmployees onlyManagers {
        Active[_address] = false;
    }
   
   //get the entire array of Employees
    function getEmployees() public view onlyEmployees returns(Employee[] memory){
        return employees;
    }
    
}

Permissions Contract

contract Permissions {
   address public CFO;
   
   struct Employee{
        uint id;
        address payable receiver;
        string name;
    }
    
    Employee[] employees;
    
    
     //Maps employement status to the Employee's Wallet Address.
    mapping(address => bool) Active;
    
    //Maps management status to the Employee's Wallet Address.
    mapping(address => bool) Manager;
    
    //Requires Caller to be the CFO.
    modifier onlyCFO(){
        require(msg.sender == CFO, "This Function is Only Available to the CFO");
        _;
    }
    
    //Requires Caller to be a Manager.
    modifier onlyManagers(){
        require(Manager[msg.sender] == true, "This Function is Only Available to Managers and above");
        _;
    }
    
    //Requires Caller to be an Active Emloyee.
    modifier onlyEmployees(){
        require(Active[msg.sender] == true, "This Function is Only Available to Active Employees");
        _;
    }
    

}
2 Likes

I’m doing a straight-line code analysis of this feature, and as soon as I completed the analysis I would give you a feed-back of my findings.

Hey @Mike_C, hope you are ok.

Nice contract, im pretty sure there is a lesson on Ethereum Smart Contract Programming 201 that will teach you how to deal with reordering an array in case that you need to delete one of its value. I advice you to check that course, since could be the only piece for your contract.

Carlos Z

1 Like