MEDIUM severity: `ComplianceServiceRegulated` applies double locking to investor transferable tokens leading to DoS of transfers. **Description:** `ComplianceServiceRegulated::getComplianceTransferableTokens()` enforces a double locking on the investors' transferable tokens, causing more tokens to be considered locked up than what they really are, leading to investors getting
DoS when transferring tokens when they should be...

Vulnerable code:
function getComplianceTransferableTokens(
        address _who,
        uint256 _time,
        uint64 _lockTime
    ) public view override returns (uint256) {
        ...

//@audit-info => amount of transferable tokens that are not locked anymore (500)
        uint256 balanceOfInvestor = getLockManager().getTransferableTokens(_who, _time);

        ...

        for (uint256 i = 0; i < investorIssuancesCount; i++) {
            uint256 issuanceTimestamp = issuancesTimestamps[investor][i];

            if (uint256(_lockTime) > _time || issuanceTimestamp > (_time - uint256(_lockTime))) {
                uint256 tokens = getRebasingProvider().convertSharesToTokens(issuancesValues[investor][i]);
//@audit-info => amount of locked tokens (1000)
                totalLockedTokens = totalLockedTokens + tokens;
            }
        }

//@audit-issue => transferable is calculated as 0 even though the investor has 500 transferable tokens
        uint256 transferable = balanceOfInvestor - Math.min(totalLockedTokens, balanceOfInvestor);

        return transferable;
    }

it.only('Double Locking Count leads to DoS even when using InvestorLockManager', async function () {
      const [owner, wallet1, wallet2, walletOtherInvestor] = await hre.ethers.getSigners();
      const { dsToken, registryService, complianceConfigurationService, lockManager, complianceService } = await loadFixture(deployDSTokenRegulated);

      const usLockPeriod = 1000;
      await complianceConfigurationService.setUSLockPeriod(usLockPeriod);
      await complianceConfigurationService.setCountryCompliance(INVESTORS.Country.USA, INVESTORS.Compliance.US);

      await registryService.registerInvestor(INVESTORS.INVESTOR_ID.INVESTOR_ID_1, '');
      await registryService.setCountry(INVESTORS.INVESTOR_ID.INVESTOR_ID_1, INVESTORS.Country.USA);
      await registryService.addWallet(wallet1, INVESTORS.INVESTOR_ID.INVESTOR_ID_1);//wallet1 => INVESTOR_ID_1
      await registryService.addWallet(wallet2, INVESTORS.INVESTOR_ID.INVESTOR_ID_1);//wallet2 -> INVESTOR_ID_1

      await registryService.registerInvestor(INVESTORS.INVESTOR_ID.INVESTOR_ID_2, '');
      await registryService.addWallet(walletOtherInvestor, INVESTORS.INVESTOR_ID.INVESTOR_ID_2);//walletOtherInvestor -> INVESTOR_ID_2

      const currentTime = await time.latest();

      await dsToken.issueTokensCustom(wallet1, 500, currentTime, 500, 'TEST', currentTime + 1_000); //lock for INVESTOR_ID_1

      //@audit-info => forward time so 500 issued tokens to Wallet1 are transferable
      await time.increaseTo(currentTime + 1000);

      //@audit-info => Any of the investor's wallet has 500 transferable tokens bcs the Investor as a whole has 500 transferable tokens!
      expect(await lockManager.getTransferableTokens(wallet1, await time.latest())).equal(500);
      expect(await lockManager.getTransferableTokens(wallet2, await time.latest())).equal(500);

      //@audit-info => complianceTransferableTokens for any of the wallets is 500 before the new issuance
      expect(await complianceService.getComplianceTransferableTokens(wallet1, time.latest(), usLockPeriod)).equals(500);
      expect(await complianceService.getComplianceTransferableTokens(wallet2, time.latest(), usLockPeriod)).equals(500);

      //@audit-info => issue 1000 locked tokens to Wallet2
      await dsToken.issueTokensCustom(wallet2, 1000, await time.latest(), 1000, 'TEST', await time.latest() + 1_000); //lock for INVESTOR_ID_1

      //@audit-info => Any of the investor's wallet has 500 transferable tokens bcs the Investor as a whole has 500 transferable tokens!
      expect(await lockManager.getTransferableTokens(wallet1, await time.latest())).equal(500);
      expect(await lockManager.getTransferableTokens(wallet2, await time.latest())).equal(500);

//@audit-issue => Both wallets have 0 transferable tokens because of the double locking count
      expect(await complianceService.getComplianceTransferableTokens(wallet1, time.latest(), usLockPeriod)).equals(0);
      expect(await complianceService.getComplianceTransferableTokens(wallet2, time.latest(), usLockPeriod)).equals(0);

//@audit-issue => Investor as a whole (can't transfer from any of his wallets) is DoS from transferring even though it has transferable tokens because of the double locking count
      const dsTokenWallet1 = await dsToken.connect(wallet1);
      await expect(dsTokenWallet1.transfer(walletOtherInvestor, 500)).revertedWith('Under lock-up');

      const dsTokenWallet2 = await dsToken.connect(wallet2);
      await expect(dsTokenWallet2.transfer(walletOtherInvestor, 500)).revertedWith('Under lock-up');
    });

function getComplianceTransferableTokens(
        address _who,
        uint256 _time,
        uint64 _lockTime
    ) public view override returns (uint256) {
        require(_time != 0, "Time must be greater than zero");
        string memory investor = getRegistryService().getInvestor(_who);

-       uint256 balanceOfInvestor = getLockManager().getTransferableTokens(_who, _time);
+      uint256 balanceOfInvestor = getToken().balanceOfInvestor(investor);

        ...
}