MEDIUM severity: Forwarders can lose payouts of the holders forwarding to them. **Description:** A holder can have a designated forwarder who will accumulate the payouts earned by the holder.
The vulnerability identified in this report is when the designated forwarder has no pending payouts to claim and zeroes out his PropertyToken's balance, and, time passes (while forwarder.....

Vulnerable code:
function test_forwarderLosesHolderPayouts() public {
        address user1 = users[0];
        address forwarder = users[1];
        address anotherUser = users[2];

        uint256 amountToMint = 1;

        _whitelistAndMintTokensToUser(user1, amountToMint);
        _whitelistAndMintTokensToUser(forwarder, amountToMint);
        // Only whitelist and allow anotherUser
        _whitelistAndMintTokensToUser(anotherUser, 0);

        remoraTokenProxy.setPayoutForwardAddress(user1, forwarder);

        // fund total payout amount to funding wallet
        uint64 payoutDistributionAmount = 100e6;

        // Distribute payouts for the first 5 distributions
        for(uint i = 1; i <= 5; i++) {
            _fundPayoutToPaymentSettler(payoutDistributionAmount);
        }

        // user1 must have 0 payout because it is forwarding to `forwarder`
        uint256 user1PayoutBalance = remoraTokenProxy.payoutBalance(user1);
        assertEq(user1PayoutBalance, 0, "Forwarding payout is not working as expected");

        //forwarder must have the full payout for the 5 distributions because user1 is forwarding to him
        uint256 forwarderPayoutBalance = remoraTokenProxy.payoutBalance(forwarder);
        assertEq(forwarderPayoutBalance, payoutDistributionAmount * 5, "Forwarding payout is not working as expected");

        // forwarder claims all his payout
        vm.startPrank(forwarder);
        remoraTokenProxy.claimPayout();
        assertEq(stableCoin.balanceOf(forwarder), forwarderPayoutBalance);

        // forwarder zeros out his PropertyToken's balance
        remoraTokenProxy.transfer(anotherUser, remoraTokenProxy.balanceOf(forwarder));
        vm.stopPrank();

        assertEq(remoraTokenProxy.balanceOf(forwarder), 0);

        (bool isHolder) = remoraTokenProxy.getHolderStatus(forwarder).isHolder;
        assertEq(isHolder, false);

        // Distribute payouts for distributions 5 - 10
        for(uint i = 1; i <= 5; i++) {
            _fundPayoutToPaymentSettler(payoutDistributionAmount);
        }

        // user1 must have 0 payout because it is forwarding to `forwarder`
        user1PayoutBalance = remoraTokenProxy.payoutBalance(user1);
        assertEq(user1PayoutBalance, 0, "Forwarding payout is not working as expected");

        (uint64 calculatedPayout) = remoraTokenProxy.getHolderStatus(forwarder).calculatedPayout;
        assertEq(calculatedPayout, (payoutDistributionAmount * 5) / 2, "Forwarder did not receive payout for holder forwarding to him");

        vm.startPrank(anotherUser);
        // forwarder becomes a holder again
        remoraTokenProxy.transfer(forwarder, remoraTokenProxy.balanceOf(anotherUser));
        vm.stopPrank();

        vm.startPrank(forwarder);
        // forwarder zeroues out his balance again
        remoraTokenProxy.transfer(anotherUser, remoraTokenProxy.balanceOf(forwarder));
        vm.stopPrank();

        //@audit => When this vulnerability is fixed, we expect finalCalculatedPayout to be equals than calculatedPayout!
        (uint64 finalCalculatedPayout) = remoraTokenProxy.getHolderStatus(forwarder).calculatedPayout;
        assertEq(finalCalculatedPayout, 0, "Forwarder did not lose payout of holder");
    }

function _updateHolders(address from, address to) internal {
        ...

        if (from != address(0)) {
            ...
            HolderStatus storage fromHolderStatus = $._holderStatus[from];
-           if (fromBalance == 0 && payoutBalance(from) == 0) {
+           if (fromBalance == 0 && payoutBalance(from) == 0 && fromHolderStatus.calculatedPayout == 0) {
                deleteUser(fromHolderStatus);
                return;
            }
            ...
            }
        }
    }