code-423n4 / 2024-01-renft-findings

2 stars 0 forks source link

Wrong assumption that the same hook is reNFT-approved to execute on rental `start` and `stop`. #558

Closed c4-bot-4 closed 10 months ago

c4-bot-4 commented 10 months ago

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.

  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.

    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

Tools Used

Manual Review

Recommended Mitigation Steps

The Create._addHooks() and Stop._removeHooks() functions should be corrected from reverting on hooks that are not approved to skipping the current iteration in the loop. This change will account for hooks not approved for both OnStart and OnStop transactions.

Assessed type

Invalid Validation

c4-pre-sort commented 10 months ago

141345 marked the issue as duplicate of #501

c4-judge commented 10 months ago

0xean marked the issue as satisfactory