xanoutas/solidity-security-findings huggingface dataset:
Lack of Input Validation in Functions addRentals, removeRentals, and removeRentalsBatch
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/Storage.sol#L189-L203
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/Storage.sol#L216-L235
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/Storage.sol#L244-L257


# Vulnerability details

In the functions addRentals, removeRentals, and removeRentalsBatch within the Storage.sol file, there is a lack of input validation. The code does not verify whether input values, such as indices, are within the expected range. This absence of input validation may lead to unexpected behavior or vulnerabilities.

#Impact

The lack of input validation poses a risk of unintended behavior, potential errors, or vulnerabilities due to invalid input values. Attackers could potentially manipulate the functions by providing malicious or out-of-range input, leading to security risks or disruptions in the intended functionality.

Attack Steps:

The attacker crafts a malicious transaction to call the addRentals function.
In the transaction, the attacker sets a negative value for the amount field in one of the RentalAssetUpdate structs.

Potential Impact:

The vulnerable code does not validate that the rental amount is non-negative.
As a result, the += operation on rentedAssets[asset.rentalId] with a negative value could lead to an underflow, causing unexpected behavior or setting the value to an extremely large number.

This may result in a miscalculation of the rented assets, leading to incorrect data and potentially affecting subsequent operations or business logic relying on accurate rental information.

## Proof of Concept

 The function does not validate whether each `orderHash` exists

## Tools Used

## Recommended Mitigation Steps
```solidity
// ... (other  code no change)

/**
 * @notice Adds an order hash to storage. Once an order hash is added to storage,
 *         the assets contained within are considered actively rented. Additionally,
 *         rental asset IDs are added to storage which creates a blocklist on those
 *         assets. When the blocklist is active, the protocol guard becomes active on
 *         them and prevents transfer or approval of the assets by the owner of the
 *         safe.
 *
 * @param orderHash          Hash of the rental order which is added to storage.
 * @param rentalAssetUpdates Asset update structs which are added to storage.
 */
function addRentals(
    bytes32 orderHash,
    RentalAssetUpdate[] memory rentalAssetUpdates
) external onlyByProxy permissioned {
    // Add the order to storage.
    orders[orderHash] = true;

    // Add the rented items to storage.
    for (uint256 i = 0; i < rentalAssetUpdates.length; ++i) {
        RentalAssetUpdate memory asset = rentalAssetUpdates[i];

        // Validate input to prevent out-of-bounds access.
        require(asset.rentalId.recipient != address(0), "Invalid r
Wrong assumption that the same hook is reNFT-approved to execute on rental `start` and `stop`.
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L194-L250
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Create.sol#L464-L520


# Vulnerability details

In `Create._rentFromZone()` the function `_addHooks()` is used to process each hook but only if the hook's status is set to execute on a rental `start`.
The array of hooks is used to generate the rental order, which is then hashed and saved to storage.
```solidity
  function _addHooks(
        Hook[] memory hooks,
        SpentItem[] memory offerItems,
        address rentalWallet
    ) internal {
        // Define hook target, offer item index, and an offer item.
        address target;
        uint256 itemIndex;
        SpentItem memory offer;


        // Loop through each hook in the payload.
        for (uint256 i = 0; i < hooks.length; ++i) {
            // Get the hook's target address.
            target = hooks[i].target;


            // Check that the hook is reNFT-approved to execute on rental start.
            if (!STORE.hookOnStart(target)) {
                revert Errors.Shared_DisabledHook(target);
            }
         //More Code...
}

```
When a rental order is being stopped the same `RentalOrder` struct generated and emitted during rental creation (that is in `Create._rentFromZone()`) is used as the input value for the function `Stop.stopRent()`, this means that the values under this order (struct) remain the same. 
```solidity
    function _removeHooks(
        Hook[] calldata hooks,
        Item[] calldata rentalItems,
        address rentalWallet
    ) internal {
        // Define hook target, item index, and item.
        address target;
        uint256 itemIndex;
        Item memory item;


        // Loop through each hook in the payload.
        for (uint256 i = 0; i < hooks.length; ++i) {
            // Get the hook address.
            target = hooks[i].target;


            // Check that the hook is reNFT-approved to execute on rental stop.
            if (!STORE.hookOnStop(target)) {
                revert Errors.Shared_DisabledHook(target);
            }


            // Get the rental item index for this hook.
            itemIndex = hooks[i].itemIndex;
        //More Code...
 }


```

Since the elements in the `Hooks` array remain the same the protocol assumes that the same hooks will be approved for both `OnStart` and `OnStop` transactions.
In a scenario where the hook being used for the rental order is approved for `OnStart` but not `OnStop` the `_removeHooks()` function will keep reverting thereby preventing the function `stopRent()` from executing.

## Impact
This scenario will lead to rentals being open forever, preventing the lender from getting their tokens back.

## Proof of Concept
* `Create._addHooks()` is executed during rental order creation using a `hook` array.
* An element in the `hooks` array is approved for `OnSta
Disabling Hooks leads to DoS issue on rental stop transactions
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L210-L212


# Vulnerability details

The rental stop transaction will be reverted (DoS) if one of the hook contracts is disabled, resulting in freezing all ERC-721/ERC-1155 rented items and ERC-20 payments managed by the affected rental order.

## Proof of Concept

> This report does not raise an admin trust issue, as the admin is trusted. 
> 
> This report raises an issue regarding the risky design choice of the `Stop::_removeHooks()`.

When a user executes the `Safe::stopRent()` (or `Safe::stopRentBatch()`) to stop a rental order, one of several tasks of the `stopRent()` is to invoke the [`Safe::_removeHooks()`](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L289) to trigger the [`onStop()`](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L227-L233) of all hook contracts attached to the stopping rental order.

Before invoking each hook contract, the `_removeHooks()` checks whether the hook is disabled. If one of the hooks is disabled, [the rental stop transaction will be reverted](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L210-L212) (DoS).

The revert issue will affect every rental order attached with any disabled hook.

```solidity
    function _removeHooks(
        Hook[] calldata hooks,
        Item[] calldata rentalItems,
        address rentalWallet
    ) internal {
        ...

        // Loop through each hook in the payload.
        for (uint256 i = 0; i < hooks.length; ++i) {
            // Get the hook address.
            target = hooks[i].target;

            // Check that the hook is reNFT-approved to execute on rental stop.
@>          if (!STORE.hookOnStop(target)) {
@>              revert Errors.Shared_DisabledHook(target);
@>          } //@audit -- During the rental stop transaction, if one of the Hook contracts attached to the rental order is disabled, the transaction will be reverted

            ...

            // Call the hook with data about the rented item.
            try
                IHook(target).onStop(
                    rentalWallet,
                    item.token,
                    item.identifier,
                    item.amount,
                    hooks[i].extraData
                )
            {} ...

            ...
        }
    }
```

- `During the rental stop transaction, if one of the Hook contracts attached to the rental order is disabled, the transaction will be reverted`: https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L210-L212

## Impact

> This report does not raise an admin trust issue, as the admin is trusted. 
> 
> This report raises an issue regarding the risky design choice of the `Stop::_removeHooks()`.

The rev
Blacklisted Borrowers could lock the NFTs in their Safe
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L265-L306


# Vulnerability details

## Impact

This is a big issue as it would not let the lender get back the NFT.

## Proof of Concept

When finishing a `PAY` order, an order for which the lender is paying the borrower. The [`stopRent(...)`](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L265-L306) function is in charge of transferring the NFT to the lender and the paiement to the borrower.
Its logic is the folllowing:

- Transfer the NFT back to the lender
- Settle the payment to the borrower and lender

For some famous tokens like USDT or USDC, the borrower could be a blacklisted address. In the context of a `PAY` order the borrower is the one receiving the payment.
In order to settle the paiement at the end (or during) a PAY order, the protocol is using the [safeTransfer(...)](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L100-L118) function of the ERC20 standard. This function will check that the payment did not fail and will revert if it did.
EVM blockchains being atomic, if the payment fails, the NFT transfer will also fail and the NFT will not be transferred back to the lender.

It would be stuck in the borrower Safe. 

## Tools Used

Manual review

## Recommendation

- use the normal transfer function of the ERC20 standard



## Assessed type

ERC20
Lack of events for critical
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/Storage.sol#L360-L363


# Vulnerability details

## Impact

Some functons that include important state changes are not covered by events. Most notably in the modules:

- [Storage.sol](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/Storage.sol)
- [PaymentEscrow.sol](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol)

This is problematic because it makes it more difficult to track the state of the contract. For example with the [upgrade(...)](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/Storage.sol#L360-L363) function, admin could upgrade the proxy to a malicious contract and it would be difficult to track this change.

## Proof of Concept

None

## Tools Used

Manual review

## Recommendation

Add events for all the modules contracts function that change the state of the contract.



## Assessed type

Context
Rental stop transaction will be blocked if the payment recipient gets blacklisted
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L175
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L178
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L201


# Vulnerability details

The `_settlePaymentProRata()` and `_settlePaymentInFull()` of the `PaymentEscrow` contract are responsible for sending ERC-20 payments to respective recipients (lender and/or renter) during the process of stopping a rental order. 

Both functions apply a push model for sending the payments, which assumes that the recipients will always be available to receive the payments. However, **if any recipient gets blacklisted by the token or if the token gets paused, the rental stop transaction will be blocked suddenly, refusing a rental order from being stopped.**

## Impact

To elaborate on the vulnerability, for instance, consider the case of the PAY rental order, where a lender pays for a renter to service something. This type of rental order allows a lender to stop the order before the scheduled order expiration. The lender will only pay for a duration that has passed for a renter, and the remaining funds locked in the `PaymentEscrow` contract will be refunded to the lender (after deducting a protocol fee). In other words, the payment will be a pro-rata split between the lender and renter managed by the `PaymentEscrow::_settlePaymentProRata()`.

Imagine the renter got blacklisted by the payment token (ERC-20) or the payment token got paused. The [rental stop transaction will be reverted](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L178) by the `_settlePaymentProRata()`. 

The following lists some impacts to the lender:
1. The lender cannot stop the rental order before the order expiration and is forced to pay the full amount once the expiration has reached (*Impact: MEDIUM*).
2. If the renter gets blacklisted for a very long time or forever, the lender cannot retrieve their ERC-721/ERC-1155 rented items (*Impact: may vary between MEDIUM and HIGH based on the type of services*).

For the BASE rental order, the impact on the lender is similar to the 2nd impact listed above. Specifically, if a lender who is a recipient of the payment gets blacklisted, the [rental order stop transaction will be reverted](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L201) by the `_settlePaymentInFull()`. Consequently, the lender cannot retrieve their ERC-721/ERC-1155 rented items (*Impact: HIGH*).

## Proof of Concept

The `PaymentEscrow::_settlePaymentProRata()` has two push-payment transfers in [L175](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L17
onERC721Received could fail if the lender is a contract
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L265-L306


# Vulnerability details

## Impact

`onERC721Received` could fail if the lender is a contract. We could end up with a situation where the lender would not get the NFT back and the borrower would not get the payment.

## Proof of Concept

When finishing a `PAY` order, an order for which the lender is paying the borrower. The [`stopRent(...)`](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L265-L306) function is in charge of transferring the NFT to the lender and the paiement to the borrower.
Its logic is the folllowing:

- Transfer the NFT back to the lender
- Settle the payment to the borrower and lender (if there is any)

If the NFT transfer was to fail, we would not be able to process the due payments.

The transfer of the NFT is done through the [`_transferERC721_(...)`](https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Reclaimer.sol#L32-L34) of the [Reclaimer]() contract. It uses the safeTransferFrom function of the ERC721 standard. This function will check if the receiver is a contract and call the `onERC721Received` function on it.
If the receiver contract does not implement this function, the transfer will fail and the payments will not be settled.

## Recommendation

- We could avoid this issue by using the normal transfer function of the ERC721 standard. This function does not check if the receiver is a contract and does not call the `onERC721Received` function.
- Make sure that the lender is not a smart contract when creating the rental order.



## Assessed type

ERC721
Asset can be stuck in renters safe and funds stolen from the escrow preventing other lenders from settling their positions.
Audit: 2024-01-renft-findings
Severity: MEDIUM

# Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L320-L330
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L265-L306


# Vulnerability details

if `ESCRW::settlePayment(...)` is called before `Stop.stopRent(...)` for a given Base rental order, funds can be stolen from the escrow preventing other users from stopping their rental leading to loss of funds for lenders and asset stuck in renters safe.

## Vulnerability Description

This is a different finding I submitted for a reentrancy in the `ESCRW::settlePayment(...)`  as this one is a different attack path although a related underlying issue

## POC Summary

 `settlePayment(...)` is an external function that has a wrongly implemented check

Summary

- Alice creates a `BASE` `aliceRentalOrder` with 100 wei, for 500s
- Carol creates a `BASE` `carolRentalOrdercarolRentalOrder with 100 wei, for 500s
- Bob fulfills both orders and 200wei is held to the `ESCRW`
- Authorised policy calls `settlePayment(...)` with Alice’s `aliceRentalOrder` after 200s
- Alice is settled with 100 wei
- 500s pass, both rentals have expired
- Alice calls `Stop.stopRent(...)` with `aliceRentalOrder`, she is settled with another 100 wei and now she has a balance of 200 wei
- Carol calls `Stop.stopRent(...)` with `carolRentalOrder` and it reverts because the `ESCROW` does not have enough balance to settle Carol and the call reverts.

Because `ESCRW::settlePayment(...)`  can be called before `Stop.stopRent(...)` is called, it can lead to other lenders being unable to settle their positions leading to a loss of funds from the escrow and 

```solidity
function stopRent(RentalOrder calldata order) external {
        // Check that the rental can be stopped.
        _validateRentalCanBeStoped(order.orderType, order.endTimestamp, order.lender);

        ...
        // Interaction: Transfer ERC20 payments from the escrow contract to the respective recipients.
        ESCRW.settlePayment(order);

        // Interaction: Remove rentals from storage by computing the order hash.
        STORE.removeRentals(
            _deriveRentalOrderHash(order),
            _convertToStatic(rentalAssetUpdates)
        );

        // Emit rental order stopped.
        _emitRentalOrderStopped(order.seaportOrderHash, msg.sender);
    }
```

the `_settlePayment(...)` does not remove rentals after settling due payment which in itself will be disastrous if the payment is settled and rentalOrder is removed without settliing asset

```solidity
function _settlePayment(
        Item[] calldata items,
        OrderType orderType,
        address lender,
        address renter,
        uint256 start,
        uint256 end
    ) internal {
        ...
        for (uint256 i = 0; i < items.length; ++i) {
            // Get the item.
            Item memory item = items[i];

            ...
            }
        }
    }
``
Upgraded Q -> 3 from #74 [1717590433591]
Audit: 2024-05-munchables-findings
Severity: HIGH

Judge has assessed an item in Issue #74 as 3 risk. The relevant finding follows:

 ## **[L-01] Donation to extend the unlocking time of other players**

The [lockOnBehalf()](https://github.com/code-423n4/2024-05-munchables/blob/main/src/managers/LockManager.sol#L275-L294) allows any user to donate 1 wei to extend the unlocking time of any player's locks.

Location: [LockManager::lockOnBehalf()](https://github.com/code-423n4/2024-05-munchables/blob/main/src/managers/LockManager.sol#L275-L294)
```solidity
        function lockOnBehalf(
        address _tokenContract,
        uint256 _quantity,
        address _onBehalfOf
    )
        external
        payable
        notPaused
        onlyActiveToken(_tokenContract)
        onlyConfiguredToken(_tokenContract)
        nonReentrant
    {
        address tokenOwner = msg.sender;
        address lockRecipient = msg.sender;
        if (_onBehalfOf != address(0)) {
            lockRecipient = _onBehalfOf;
        }

        _lock(_tokenContract, _quantity, tokenOwner, lockRecipient);
    }
```
Location: [LockManager::_lock()](https://github.com/code-423n4/2024-05-munchables/blob/main/src/managers/LockManager.sol#L311-L398)

```solidity
    function _lock(
        address _tokenContract,
        uint256 _quantity,
        address _tokenOwner,
        address _lockRecipient
    ) private {

        // SNIPPED 
        
        lockedToken.lastLockTime = uint32(block.timestamp);
        lockedToken.unlockTime =
            uint32(block.timestamp) +
            uint32(_lockDuration);
    }
```