{
    "Function": "changeOrder",
    "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": [
        "Tasks",
        "Tasks",
        "Tasks"
    ],
    "Internal Calls": [
        "checkPrecision",
        "require(bool,string)",
        "nonReentrant",
        "abi.decode()",
        "checkSignatureTask",
        "autoWithdraw",
        "_msgSender",
        "_inviteSC"
    ],
    "Library Calls": [
        "unApprove",
        "unAllocateFunds",
        "unApprove"
    ],
    "Low-Level Calls": [],
    "Code": "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    }"
}