Using ERC20 `transfer` function in `LiquidInfrastructureERC20::distribute()` will result to USDT being forever locked in the contract
Audit: 2024-02-althea-liquid-infrastructure-findings
Severity: HIGH

# Lines of code

https://github.com/code-423n4/2024-02-althea-liquid-infrastructure/blob/bd6ee47162368e1999a0a5b8b17b701347cf9a7d/liquid-infrastructure/contracts/LiquidInfrastructureERC20.sol#L224


# Vulnerability details

## Impact
The contract `LiquidInfrastructureERC20` is expected to receive ERC20 tokens which may include a non-standard token like USDT. While a standard ERC20 contract returns a boolean on transfers, USDT does not. Using a standard ERC20 interface (IERC20) with a non-standard token will result to transaction failure.

If this is not resolved, two things may happen. First, this will mean that all USDTs of `LiquidInfrastructureERC20` will forever be locked inside the contract. Thus, loss of funds. If for safety reasons USDT is excluded in the token list, then it will add friction to the customers who are already holders of USDT.

## Proof of Concept
- This is a PoC in the form of Foundry test. It shows that USDT reverts when using `transfer`.
- Usage
    1. Copy paste this code in a foundry test suite.
    
    ```solidity
    import "forge-std/Test.sol";
    import "forge-std/console.sol";
    import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

    contract USDTTransferReverts is Test {    
        // @audit-info Prefixing function name with `testFail` it is expected to fail / revert.
        function testFail_Transfer_USDT() external {
            address usdt = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
            uint256 transferAmount = 2e18;

            deal(usdt, address(this), transferAmount);
            address recipient = vm.addr(0x11111);

            assertEq(IERC20(usdt).balanceOf(address(this)), transferAmount);
            assertEq(IERC20(usdt).balanceOf(recipient), 0);

            IERC20(usdt).transfer(recipient, transferAmount); // @audit-info Transaction fails here.
        }
    }
    ```
    2. In the terminal, run the following:
    ```
    > `FORK_URL=https://eth-mainnet.g.alchemy.com/v2/[YOUR_KEY]`
    > `forge test --fork-url $FORK_URL --match-path [PATH/Filename.t.sol] -vvvv`
    ```
## Tools Used
- Manual Review
- Foundry

## Recommended Mitigation Steps
Use SafeERC20 library by Openzeppelin and do the following below.

```diff

++ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract LiquidInfrastructureERC20 is
    ERC20,
    ERC20Burnable,
    Ownable,
    ERC721Holder,
    ReentrancyGuard
{
++  using SafeERC20 for IERC20;
    ...
    function distribute(uint256 numDistributions) public nonReentrant {
        ...
        for (i = nextDistributionRecipient; i < limit; i++) {
            address recipient = holders[i];
            if (isApprovedHolder(recipient)) {
                uint256[] memory receipts = new uint256[](
                    distributableERC20s.length
                );
                for (uint j = 0; j < distributableERC20s.length; j++) {
                    IERC20 toDistribute = IERC20(distributableERC20s[j]);
                    uint256 entitlemen