{
    "Function": "slitherConstructorConstantVariables",
    "File": "contracts/Project.sol",
    "Parent Contracts": [
        "node_modules/@openzeppelin/contracts-upgradeable/metatx/ERC2771ContextUpgradeable.sol",
        "node_modules/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol",
        "node_modules/@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol",
        "node_modules/@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol",
        "contracts/interfaces/IProject.sol"
    ],
    "High-Level Calls": [],
    "Internal Calls": [],
    "Library Calls": [],
    "Low-Level Calls": [],
    "Code": "contract Project is\n    IProject,\n    ReentrancyGuardUpgradeable,\n    ERC2771ContextUpgradeable\n{\n    // Using Tasks library for Task struct\n    using Tasks for Task;\n\n    // Using SafeERC20Upgradeable library for IDebtToken\n    using SafeERC20Upgradeable for IDebtToken;\n\n    /*******************************************************************************\n     * ------------------------FIXED INTERNAL STORED PROPERTIES------------------------- *\n     *******************************************************************************/\n\n    /// @notice Disputes contract instance\n    address internal disputes;\n\n    /// @notice mapping of tasks index to Task struct.\n    mapping(uint256 => Task) internal tasks;\n\n    /// @notice array of indexes of change ordered tasks\n    uint256[] internal _changeOrderedTask;\n\n    /*******************************************************************************\n     * ----------------------FIXED PUBLIC STORED PROPERTIES----------------------- *\n     *******************************************************************************/\n    /// @inheritdoc IProject\n    IHomeFi public override homeFi;\n    /// @inheritdoc IProject\n    IDebtToken public override currency;\n    /// @inheritdoc IProject\n    uint256 public override lenderFee;\n    /// @inheritdoc IProject\n    address public override builder;\n    /// @inheritdoc IProject\n    uint256 public constant override VERSION = 25000;\n\n    /*******************************************************************************\n     * ---------------------VARIABLE PUBLIC STORED PROPERTIES--------------------- *\n     *******************************************************************************/\n    /// @inheritdoc IProject\n    address public override contractor;\n    /// @inheritdoc IProject\n    bool public override contractorConfirmed;\n    /// @inheritdoc IProject\n    uint256 public override hashChangeNonce;\n    /// @inheritdoc IProject\n    uint256 public override totalLent;\n    /// @inheritdoc IProject\n    uint256 public override totalAllocated;\n    /// @inheritdoc IProject\n    uint256 public override taskCount;\n    /// @inheritdoc IProject\n    bool public override contractorDelegated;\n    /// @inheritdoc IProject\n    uint256 public override lastAllocatedTask;\n    /// @inheritdoc IProject\n    uint256 public override lastAllocatedChangeOrderTask;\n    /// @inheritdoc IProject\n    mapping(address => mapping(bytes32 => bool)) public override approvedHashes;\n\n    /// @dev Added to make sure master implementation cannot be initialized\n    // solhint-disable-next-line no-empty-blocks\n    constructor() initializer {}\n\n    /*******************************************************************************\n     * ---------------------------EXTERNAL TRANSACTION---------------------------- *\n     *******************************************************************************/\n    /// @inheritdoc IProject\n    function initialize(\n        address _currency,\n        address _sender,\n        address _homeFiAddress\n    ) external override initializer {\n        // Initialize variables\n        homeFi = IHomeFi(_homeFiAddress);\n        disputes = homeFi.disputesContract();\n        lenderFee = homeFi.lenderFee();\n        builder = _sender;\n        currency = IDebtToken(_currency);\n    }\n\n    /// @inheritdoc IProject\n    function approveHash(bytes32 _hash) external override {\n        address _sender = _msgSender();\n        // Allowing anyone to sign, as its hard to add restrictions here.\n        // Store _hash as signed for sender.\n        approvedHashes[_sender][_hash] = true;\n\n        emit ApproveHash(_hash, _sender);\n    }\n\n    /// @inheritdoc IProject\n    function inviteContractor(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n    {\n        // Revert if contractor has already confirmed his invitation\n        require(!contractorConfirmed, \"Project::GC accepted\");\n\n        // Decode params from _data\n        (address _contractor, address _projectAddress) = abi.decode(\n            _data,\n            (address, address)\n        );\n\n        // Revert if decoded project address does not match this contract. Indicating incorrect _data.\n        require(_projectAddress == address(this), \"Project::!projectAddress\");\n\n        // Revert if contractor address is invalid.\n        require(_contractor != address(0), \"Project::0 address\");\n\n        // Store new contractor\n        contractor = _contractor;\n        contractorConfirmed = true;\n\n        // Check signature for builder and contractor\n        checkSignature(_data, _signature);\n\n        emit ContractorInvited(contractor);\n    }\n\n    /// @inheritdoc IProject\n    function delegateContractor(bool _bool) external override {\n        // Revert if sender is not builder\n        require(_msgSender() == builder, \"Project::!B\");\n\n        // Revert if contract not assigned\n        require(contractor != address(0), \"Project::0 address\");\n\n        // Store new bool for contractorDelegated\n        contractorDelegated = _bool;\n\n        emit ContractorDelegated(_bool);\n    }\n\n    /// @inheritdoc IProject\n    function updateProjectHash(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n    {\n        // Check for required signatures\n        checkSignature(_data, _signature);\n\n        // Decode params from _data\n        (bytes memory _hash, uint256 _nonce) = abi.decode(\n            _data,\n            (bytes, uint256)\n        );\n\n        // Revert if decoded nonce is incorrect. This indicates wrong _data.\n        require(_nonce == hashChangeNonce, \"Project::!Nonce\");\n\n        // Increment to ensure a set of data and signature cannot be re-used.\n        hashChangeNonce += 1;\n\n        emit HashUpdated(_hash);\n    }\n\n    /// @inheritdoc IProject\n    function lendToProject(uint256 _cost) external override nonReentrant {\n        address _sender = _msgSender();\n\n        // Revert if sender is not builder or Community Contract (lender)\n        require(\n            _sender == builder || _sender == homeFi.communityContract(),\n            \"Project::!Builder&&!Community\"\n        );\n\n        // Revert if try to lend 0\n        require(_cost > 0, \"Project::!value>0\");\n\n        // Revert if try to lend more than project cost\n        uint256 _newTotalLent = totalLent + _cost;\n        require(\n            projectCost() >= uint256(_newTotalLent),\n            \"Project::value>required\"\n        );\n\n        if (_sender == builder) {\n            // Transfer assets from builder to this contract\n            currency.safeTransferFrom(_sender, address(this), _cost);\n        }\n\n        // Update total lent with added lend\n        totalLent = _newTotalLent;\n\n        emit LendToProject(_cost);\n\n        // Allocate funds to tasks and mark then as allocated\n        allocateFunds();\n    }\n\n    /// @inheritdoc IProject\n    function addTasks(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n    {\n        // If the sender is disputes contract, then do not check for signatures.\n        if (_msgSender() != disputes) {\n            // Check for required signatures\n            checkSignature(_data, _signature);\n        }\n\n        // Decode params from _data\n        (\n            bytes[] memory _hash,\n            uint256[] memory _taskCosts,\n            uint256 _taskCount,\n            address _projectAddress\n        ) = abi.decode(_data, (bytes[], uint256[], uint256, address));\n\n        // Revert if decoded taskCount is incorrect. This indicates wrong data.\n        require(_taskCount == taskCount, \"Project::!taskCount\");\n\n        // Revert if decoded project address does not match this contract. Indicating incorrect _data.\n        require(_projectAddress == address(this), \"Project::!projectAddress\");\n\n        // Revert if IPFS hash array length is not equal to task cost array length.\n        uint256 _length = _hash.length;\n        require(_length == _taskCosts.length, \"Project::Lengths !match\");\n\n        // Loop over all the new tasks.\n        for (uint256 i = 0; i < _length; i++) {\n            // Increment local task counter.\n            _taskCount += 1;\n\n            // Check task cost precision. Revert if too precise.\n            checkPrecision(_taskCosts[i]);\n\n            // Initialize task.\n            tasks[_taskCount].initialize(_taskCosts[i]);\n        }\n\n        // Update task counter equal to local task counter.\n        taskCount = _taskCount;\n\n        emit TasksAdded(_taskCosts, _hash);\n    }\n\n    /// @inheritdoc IProject\n    function updateTaskHash(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n    {\n        // Decode params from _data\n        (bytes memory _taskHash, uint256 _nonce, uint256 _taskID) = abi.decode(\n            _data,\n            (bytes, uint256, uint256)\n        );\n\n        // Revert if decoded nonce is incorrect. This indicates wrong data.\n        require(_nonce == hashChangeNonce, \"Project::!Nonce\");\n\n        // If subcontractor has confirmed then check signature using `checkSignatureTask`.\n        // Else check signature using `checkSignature`.\n        if (getAlerts(_taskID)[2]) {\n            // If subcontractor has confirmed.\n            checkSignatureTask(_data, _signature, _taskID);\n        } else {\n            // If subcontractor not has confirmed.\n            checkSignature(_data, _signature);\n        }\n\n        // Increment to ensure a set of data and signature cannot be re-used.\n        hashChangeNonce += 1;\n\n        emit TaskHashUpdated(_taskID, _taskHash);\n    }\n\n    /// @inheritdoc IProject\n    function inviteSC(uint256[] calldata _taskList, address[] calldata _scList)\n        external\n        override\n    {\n        // Revert if sender is neither builder nor contractor.\n        require(\n            _msgSender() == builder || _msgSender() == contractor,\n            \"Project::!Builder||!GC\"\n        );\n\n        // Revert if taskList array length not equal to scList array length.\n        uint256 _length = _taskList.length;\n        require(_length == _scList.length, \"Project::Lengths !match\");\n\n        // Invite subcontractor for each task.\n        for (uint256 i = 0; i < _length; i++) {\n            _inviteSC(_taskList[i], _scList[i], false);\n        }\n\n        emit MultipleSCInvited(_taskList, _scList);\n    }\n\n    /// @inheritdoc IProject\n    function acceptInviteSC(uint256[] calldata _taskList) external override {\n        // Accept invitation for each task in taskList.\n        uint256 _length = _taskList.length;\n        for (uint256 i = 0; i < _length; i++) {\n            tasks[_taskList[i]].acceptInvitation(_msgSender());\n        }\n\n        emit SCConfirmed(_taskList);\n    }\n\n    /// @inheritdoc IProject\n    function setComplete(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n    {\n        // Decode params from _data\n        (uint256 _taskID, address _projectAddress) = abi.decode(\n            _data,\n            (uint256, address)\n        );\n\n        // Revert if decoded project address does not match this contract. Indicating incorrect _data.\n        require(_projectAddress == address(this), \"Project::!Project\");\n\n        // If the sender is disputes contract, then do not check for signatures.\n        if (_msgSender() != disputes) {\n            // Check signatures.\n            checkSignatureTask(_data, _signature, _taskID);\n        }\n\n        // Mark task as complete. Only works when task is active.\n        tasks[_taskID].setComplete();\n\n        // Transfer funds to subcontractor.\n        currency.safeTransfer(\n            tasks[_taskID].subcontractor,\n            tasks[_taskID].cost\n        );\n\n        emit TaskComplete(_taskID);\n    }\n\n    /// @inheritdoc IProject\n    function recoverTokens(address _tokenAddress) external override {\n        /* If the token address is same as currency of this project,\n            then first check if all tasks are complete */\n        if (_tokenAddress == address(currency)) {\n            // Iterate for each task and check if it is complete.\n            uint256 _length = taskCount;\n            for (uint256 _taskID = 1; _taskID <= _length; _taskID++) {\n                require(tasks[_taskID].getState() == 3, \"Project::!Complete\");\n            }\n        }\n\n        // Create token instance.\n        IDebtToken _token = IDebtToken(_tokenAddress);\n\n        // Check the balance of _token in this contract.\n        uint256 _leftOutTokens = _token.balanceOf(address(this));\n\n        // If balance is present then it to the builder.\n        if (_leftOutTokens > 0) {\n            _token.safeTransfer(builder, _leftOutTokens);\n        }\n    }\n\n    /// @inheritdoc IProject\n    function changeOrder(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n        nonReentrant\n    {\n        // Decode params from _data\n        (\n            uint256 _taskID,\n            address _newSC,\n            uint256 _newCost,\n            address _project\n        ) = abi.decode(_data, (uint256, address, uint256, address));\n\n        // If the sender is disputes contract, then do not check for signatures.\n        if (_msgSender() != disputes) {\n            // Check for required signatures.\n            checkSignatureTask(_data, _signature, _taskID);\n        }\n\n        // Revert if decoded project address does not match this contract. Indicating incorrect _data.\n        require(_project == address(this), \"Project::!projectAddress\");\n\n        // Local variable for task cost. For gas saving.\n        uint256 _taskCost = tasks[_taskID].cost;\n\n        // Local variable indicating if subcontractor is already unapproved.\n        bool _unapproved = false;\n\n        // If task cost is to be changed.\n        if (_newCost != _taskCost) {\n            // Check new task cost precision. Revert if too precise.\n            checkPrecision(_newCost);\n\n            // Local variable for total cost allocated. For gas saving.\n            uint256 _totalAllocated = totalAllocated;\n\n            // If tasks are already allocated with old cost.\n            if (tasks[_taskID].alerts[1]) {\n                // If new task cost is less than old task cost.\n                if (_newCost < _taskCost) {\n                    // Find the difference between old - new.\n                    uint256 _withdrawDifference = _taskCost - _newCost;\n\n                    // Reduce this difference from total cost allocated.\n                    // As the same task is now allocated with lesser cost.\n                    totalAllocated -= _withdrawDifference;\n\n                    // Withdraw the difference back to builder's account.\n                    // As this additional amount may not be required by the project.\n                    autoWithdraw(_withdrawDifference);\n                }\n                // If new cost is more than task cost but total lent is enough to cover for it.\n                else if (totalLent - _totalAllocated >= _newCost - _taskCost) {\n                    // Increase the difference of new cost and old cost to total allocated.\n                    totalAllocated += _newCost - _taskCost;\n                }\n                // If new cost is more than task cost and totalLent is not enough.\n                else {\n                    // Un-confirm SC, mark task as inactive, mark allocated as false, mark lifecycle as None\n\n                    // Mark task as inactive by unapproving subcontractor.\n                    // As subcontractor can only be approved if task is allocated\n                    _unapproved = true;\n                    tasks[_taskID].unApprove();\n\n                    // Mark task as not allocated.\n                    tasks[_taskID].unAllocateFunds();\n\n                    // Reduce total allocation by old task cost.\n                    // As as needs to go though funding process again.\n                    totalAllocated -= _taskCost;\n\n                    // Add this task to _changeOrderedTask array. These tasks will be allocated first.\n                    _changeOrderedTask.push(_taskID);\n                }\n            }\n\n            // Store new cost for the task\n            tasks[_taskID].cost = _newCost;\n\n            emit ChangeOrderFee(_taskID, _newCost);\n        }\n\n        // If task subcontractor is to be changed.\n        if (_newSC != tasks[_taskID].subcontractor) {\n            // If task is not already unapproved, then un-approve it.\n            // Un-approving task means marking subcontractor as unconfirmed.\n            if (!_unapproved) {\n                tasks[_taskID].unApprove();\n            }\n\n            // If new subcontractor is not zero address.\n            if (_newSC != address(0)) {\n                // Invite the new subcontractor for the task.\n                _inviteSC(_taskID, _newSC, true);\n            }\n            // Else store zero address for the task subcontractor.\n            // This implies that a subcontractor is not invited from the task.\n            else {\n                tasks[_taskID].subcontractor = address(0);\n            }\n\n            emit ChangeOrderSC(_taskID, _newSC);\n        }\n    }\n\n    /// @inheritdoc IProject\n    function raiseDispute(bytes calldata _data, bytes calldata _signature)\n        external\n        override\n    {\n        // Recover the signer from the signature\n        address signer = SignatureDecoder.recoverKey(\n            keccak256(_data),\n            _signature,\n            0\n        );\n\n        // Decode params from _data\n        (address _project, uint256 _task, , , ) = abi.decode(\n            _data,\n            (address, uint256, uint8, bytes, bytes)\n        );\n\n        // Revert if decoded project address does not match this contract. Indicating incorrect _data.\n        require(_project == address(this), \"Project::!projectAddress\");\n\n        if (_task == 0) {\n            // Revet if sender is not builder or contractor\n            require(\n                signer == builder || signer == contractor,\n                \"Project::!(GC||Builder)\"\n            );\n        } else {\n            // Revet if sender is not builder, contractor or task's subcontractor\n            require(\n                signer == builder ||\n                    signer == contractor ||\n                    signer == tasks[_task].subcontractor,\n                \"Project::!(GC||Builder||SC)\"\n            );\n\n            if (signer == tasks[_task].subcontractor) {\n                // If sender is task's subcontractor, revert if invitation is not accepted.\n                require(getAlerts(_task)[2], \"Project::!SCConfirmed\");\n            }\n        }\n\n        // Make a call to Disputes contract raiseDisputes.\n        IDisputes(disputes).raiseDispute(_data, _signature);\n    }\n\n    /*******************************************************************************\n     * ------------------------------EXTERNAL VIEWS------------------------------- *\n     *******************************************************************************/\n\n    /// @inheritdoc IProject\n    function getTask(uint256 id)\n        external\n        view\n        override\n        returns (\n            uint256 cost,\n            address subcontractor,\n            TaskStatus state\n        )\n    {\n        cost = tasks[id].cost;\n        subcontractor = tasks[id].subcontractor;\n        state = tasks[id].state;\n    }\n\n    /// @inheritdoc IProject\n    function changeOrderedTask()\n        external\n        view\n        override\n        returns (uint256[] memory)\n    {\n        return _changeOrderedTask;\n    }\n\n    /*******************************************************************************\n     * ----------------------------PUBLIC TRANSACTIONS---------------------------- *\n     *******************************************************************************/\n\n    /// @inheritdoc IProject\n    function allocateFunds() public override {\n        // Max amount out times this loop will run\n        // This is to ensure the transaction do not run out of gas (max gas limit)\n        uint256 _maxLoop = 50;\n\n        // Difference of totalLent and totalAllocated is what can be used to allocate new tasks\n        uint256 _costToAllocate = totalLent - totalAllocated;\n\n        // Bool if max loop limit is exceeded\n        bool _exceedLimit;\n\n        // Local instance of lastAllocatedChangeOrderTask. To save gas.\n        uint256 i = lastAllocatedChangeOrderTask;\n\n        // Local instance of lastAllocatedTask. To save gas.\n        uint256 j = lastAllocatedTask;\n\n        // Initialize empty array in which allocated tasks will be added.\n        uint256[] memory _tasksAllocated = new uint256[](\n            taskCount - j + _changeOrderedTask.length - i\n        );\n\n        // Number of times a loop has run.\n        uint256 _loopCount;\n\n        /// CHANGE ORDERED TASK FUNDING ///\n\n        // Any tasks added to _changeOrderedTask will be allocated first\n        if (_changeOrderedTask.length > 0) {\n            // Loop from lastAllocatedChangeOrderTask to _changeOrderedTask length (until _maxLoop)\n            for (; i < _changeOrderedTask.length; i++) {\n                // Local instance of task cost. To save gas.\n                uint256 _taskCost = tasks[_changeOrderedTask[i]].cost;\n\n                // If _maxLoop limit is reached then stop looping\n                if (_loopCount >= _maxLoop) {\n                    _exceedLimit = true;\n                    break;\n                }\n\n                // If there is enough funds to allocate this task\n                if (_costToAllocate >= _taskCost) {\n                    // Reduce task cost from _costToAllocate\n                    _costToAllocate -= _taskCost;\n\n                    // Mark the task as allocated\n                    tasks[_changeOrderedTask[i]].fundTask();\n\n                    // Add task to _tasksAllocated array\n                    _tasksAllocated[_loopCount] = _changeOrderedTask[i];\n\n                    // Increment loop counter\n                    _loopCount++;\n                }\n                // If there are not enough funds to allocate this task then stop looping\n                else {\n                    break;\n                }\n            }\n\n            // If all the change ordered tasks are allocated, then delete\n            // the changeOrderedTask array and reset lastAllocatedChangeOrderTask.\n            if (i == _changeOrderedTask.length) {\n                lastAllocatedChangeOrderTask = 0;\n                delete _changeOrderedTask;\n            }\n            // Else store the last allocated change order task index.\n            else {\n                lastAllocatedChangeOrderTask = i;\n            }\n        }\n\n        /// TASK FUNDING ///\n\n        // If lastAllocatedTask is lesser than taskCount, that means there are un-allocated tasks\n        if (j < taskCount) {\n            // Loop from lastAllocatedTask + 1 to taskCount (until _maxLoop)\n            for (++j; j <= taskCount; j++) {\n                // Local instance of task cost. To save gas.\n                uint256 _taskCost = tasks[j].cost;\n\n                // If _maxLoop limit is reached then stop looping\n                if (_loopCount >= _maxLoop) {\n                    _exceedLimit = true;\n                    break;\n                }\n\n                // If there is enough funds to allocate this task\n                if (_costToAllocate >= _taskCost) {\n                    // Reduce task cost from _costToAllocate\n                    _costToAllocate -= _taskCost;\n\n                    // Mark the task as allocated\n                    tasks[j].fundTask();\n\n                    // Add task to _tasksAllocated array\n                    _tasksAllocated[_loopCount] = j;\n\n                    // Increment loop counter\n                    _loopCount++;\n                }\n                // If there are not enough funds to allocate this task then stop looping\n                else {\n                    break;\n                }\n            }\n\n            // If all pending tasks are allocated store lastAllocatedTask equal to taskCount\n            if (j > taskCount) {\n                lastAllocatedTask = taskCount;\n            }\n            // If not all tasks are allocated store updated lastAllocatedTask\n            else {\n                lastAllocatedTask = --j;\n            }\n        }\n\n        // If any tasks is allocated, then emit event\n        if (_loopCount > 0) emit TaskAllocated(_tasksAllocated);\n\n        // If allocation was incomplete, then emit event\n        if (_exceedLimit) emit IncompleteAllocation();\n\n        // Update totalAllocated with all allocations\n        totalAllocated = totalLent - _costToAllocate;\n    }\n\n    /*******************************************************************************\n     * -------------------------------PUBLIC VIEWS-------------------------------- *\n     *******************************************************************************/\n\n    /// @inheritdoc IProject\n    function projectCost() public view override returns (uint256 _cost) {\n        // Local instance of taskCount. To save gas.\n        uint256 _length = taskCount;\n\n        // Iterate over all tasks to sum their cost\n        for (uint256 _taskID = 1; _taskID <= _length; _taskID++) {\n            _cost += tasks[_taskID].cost;\n        }\n    }\n\n    /// @inheritdoc IProject\n    function getAlerts(uint256 _taskID)\n        public\n        view\n        override\n        returns (bool[3] memory _alerts)\n    {\n        return tasks[_taskID].getAlerts();\n    }\n\n    /// @inheritdoc IProject\n    function isTrustedForwarder(address _forwarder)\n        public\n        view\n        override(ERC2771ContextUpgradeable, IProject)\n        returns (bool)\n    {\n        return homeFi.isTrustedForwarder(_forwarder);\n    }\n\n    /*******************************************************************************\n     * ---------------------------INTERNAL TRANSACTIONS--------------------------- *\n     *******************************************************************************/\n\n    /**\n     * @dev Invite subcontractors for a single task. This can be called by builder or contractor.\n     * _taskList must not have a task which already has approved subcontractor.\n     \n     * @param _taskID uint256 task index\n     * @param _sc address addresses of subcontractor for the respective task\n     * @param _emitEvent whether to emit event for each sc added or not\n     */\n    function _inviteSC(\n        uint256 _taskID,\n        address _sc,\n        bool _emitEvent\n    ) internal {\n        // Revert if sc to invite is address 0\n        require(_sc != address(0), \"Project::0 address\");\n\n        // Internal call to tasks invite contractor\n        tasks[_taskID].inviteSubcontractor(_sc);\n\n        // If `_emitEvent` is true (called via changeOrder) then emit event\n        if (_emitEvent) {\n            emit SingleSCInvited(_taskID, _sc);\n        }\n    }\n\n    /**\n     * @dev Transfer excess funds back to builder wallet.\n     * Called internally in task changeOrder when new task cost is lower than older cost.\n\n     * @param _amount uint256 - amount of excess funds\n     */\n    function autoWithdraw(uint256 _amount) internal {\n        // Reduce amount from totalLent\n        totalLent -= _amount;\n\n        // Transfer amount to builder address\n        currency.safeTransfer(builder, _amount);\n\n        emit AutoWithdrawn(_amount);\n    }\n\n    /**\n     * @dev Check if recovered signatures match with builder and contractor address.\n     * Signatures must be in sequential order. First builder and then contractor.\n     * Reverts if signature do not match.\n     * If contractor is not assigned then only checks for builder signature.\n     * If contractor is assigned but not delegated then only checks for builder and contractor signature.\n     * If contractor is assigned and delegated then only checks for contractor signature.\n\n     * @param _data bytes encoded parameters\n     * @param _signature bytes appended signatures\n     */\n    function checkSignature(bytes calldata _data, bytes calldata _signature)\n        internal\n    {\n        // Calculate hash from bytes\n        bytes32 _hash = keccak256(_data);\n\n        // When there is no contractor\n        if (contractor == address(0)) {\n            // Check for builder's signature\n            checkSignatureValidity(builder, _hash, _signature, 0);\n        }\n        // When there is a contractor\n        else {\n            // When builder has delegated his rights to contractor\n            if (contractorDelegated) {\n                //  Check contractor's signature\n                checkSignatureValidity(contractor, _hash, _signature, 0);\n            }\n            // When builder has not delegated rights to contractor\n            else {\n                // Check for both B and GC signatures\n                checkSignatureValidity(builder, _hash, _signature, 0);\n                checkSignatureValidity(contractor, _hash, _signature, 1);\n            }\n        }\n    }\n\n    /**\n     * @dev Check if recovered signatures match with builder, contractor and subcontractor address for a task.\n     * Signatures must be in sequential order. First builder, then contractor, and then subcontractor.\n     * reverts if signatures do not match.\n     * If contractor is not assigned then only checks for builder and subcontractor signature.\n     * If contractor is assigned but not delegated then only checks for builder, contractor and subcontractor signature.\n     * If contractor is assigned and delegated then only checks for contractor and subcontractor signature.\n\n     * @param _data bytes encoded parameters\n     * @param _signature bytes appended signatures\n     * @param _taskID index of the task.\n     */\n    function checkSignatureTask(\n        bytes calldata _data,\n        bytes calldata _signature,\n        uint256 _taskID\n    ) internal {\n        // Calculate hash from bytes\n        bytes32 _hash = keccak256(_data);\n\n        // Local instance of subcontractor. To save gas.\n        address _sc = tasks[_taskID].subcontractor;\n\n        // When there is no contractor\n        if (contractor == address(0)) {\n            // Just check for B and SC sign\n            checkSignatureValidity(builder, _hash, _signature, 0);\n            checkSignatureValidity(_sc, _hash, _signature, 1);\n        }\n        // When there is a contractor\n        else {\n            // When builder has delegated his rights to contractor\n            if (contractorDelegated) {\n                // Check for GC and SC sign\n                checkSignatureValidity(contractor, _hash, _signature, 0);\n                checkSignatureValidity(_sc, _hash, _signature, 1);\n            }\n            // When builder has not delegated rights to contractor\n            else {\n                // Check for B, SC and GC signatures\n                checkSignatureValidity(builder, _hash, _signature, 0);\n                checkSignatureValidity(contractor, _hash, _signature, 1);\n                checkSignatureValidity(_sc, _hash, _signature, 2);\n            }\n        }\n    }\n\n    /**\n     * @dev Internal function for checking signature validity\n     * @dev Checks if the signature is approved or recovered\n     * @dev Reverts if not\n\n     * @param _address address - address checked for validity\n     * @param _hash bytes32 - hash for which the signature is recovered\n     * @param _signature bytes - signatures\n     * @param _signatureIndex uint256 - index at which the signature should be present\n     */\n    function checkSignatureValidity(\n        address _address,\n        bytes32 _hash,\n        bytes memory _signature,\n        uint256 _signatureIndex\n    ) internal {\n        address _recoveredSignature = SignatureDecoder.recoverKey(\n            _hash,\n            _signature,\n            _signatureIndex\n        );\n        require(\n            _recoveredSignature == _address || approvedHashes[_address][_hash],\n            \"Project::invalid signature\"\n        );\n        // delete from approvedHash\n        delete approvedHashes[_address][_hash];\n    }\n\n    /*******************************************************************************\n     * -------------------------------INTERNAL PURE------------------------------- *\n     *******************************************************************************/\n\n    /**\n     * @dev Check if precision is greater than 1000, if so, it reverts\n\n     * @param _amount amount needed to be checked for precision.\n     */\n    function checkPrecision(uint256 _amount) internal pure {\n        // Divide and multiply amount with 1000 should be equal to amount.\n        // This ensures the amount is not too precise.\n        require(\n            ((_amount / 1000) * 1000) == _amount,\n            \"Project::Precision>=1000\"\n        );\n    }\n}"
}