A malicious lender can freeze borrower's ERC1155 tokens indefinitely because the guard can't differentiate between rented and non-rented ERC1155 tokens in the borrower's safe.
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Guard.sol#L242


# Vulnerability details

### Pre-requisite knowledge & an overview of the features in question
---

1. **Gnosis safe guards**: A gnosis guard is a contract that acts as a transaction guard which allows the owner of the safe to limit the contracts and functions that may be called by the multisig owners of the safe. ReNFT has created it's own gnosis guard contract, which is [Guard.sol](https://github.com/re-nft/smart-contracts/blob/main/src/policies/Guard.sol).

    **Example utility**: When you ask reNFT to create a rental safe for you by calling [deployRentalSafe()](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Factory.sol#L138) in [Factory.sol](https://github.com/re-nft/smart-contracts/blob/main/src/policies/Factory.sol), reNFT creates a rental safe for you and automatically installs it's own guard contract on it. Everytime you send a call from your gnosis safe, this call has to first pass through that guard. If you're for example, trying to move a NFT token you rented using `transferFrom()`, it'll prevent you from doing so. When it intercepts the transaction you're trying to send, it checks for a [list of function signatures](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Guard.sol#L195) that can be malicious, for example it checks if you're trying to enable/disable a module it has not authorized. It checks if you're trying to change the guard contract address itself, It also checks if you're trying to transfer or approve a rented NFT or ERC1155 token using the most common functions like `approve()`, `safeTransferFrom()`, `transferFrom()`, `setApprovalForAll()`. This guard acts as the single and most important defense line against rented ERC721/1155 token theft.


---
### The Vulnerability & Exploitation Steps

---

The vulnerability exists in the [Guard.sol](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Guard.sol) contract, [L-242](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Guard.sol#L242)

        } else if (selector == e1155_safe_transfer_from_selector) {
            // Load the token ID from calldata.
            uint256 tokenId = uint256(
                _loadValueFromCalldata(data, e1155_safe_transfer_from_token_id_offset)
            );

            // Check if the selector is allowed.
            _revertSelectorOnActiveRental(selector, from, to, tokenId);

The guard does not differentiate between ERC1155 tokens of address of same ID that are actively being rented and those that aren't rented. So for example, you had 2,000 "GameToken" ERC1155 tokens with an id of 5, that are not rented. And you rented 10 "GameToken" ERC1155 tokens of the same id "5", you will not be able to move or trans