reNFT - 0xabhay's results

Collateral-free, permissionless, and highly customizable EVM NFT rentals.

General Information

Platform: Code4rena

Start Date: 08/01/2024

Pot Size: $83,600 USDC

Total HM: 23

Participants: 116

Period: 10 days

Judge: 0xean

Total Solo HM: 1

Id: 317

League: ETH

reNFT

Findings Distribution

Researcher Performance

Rank: 40/116

Findings: 2

Award: $230.09

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: plasmablocks

Also found by: 0xabhay, BARW, hals, serial-coder

Labels

bug
2 (Med Risk)
satisfactory
duplicate-538

Awards

227.371 USDC - $227.37

External Links

Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Create.sol#L570-L576

Vulnerability details

Impact

The lack of a check on the size of the rentalAssets array in the Accumulator.sol::_insert function can lead to denial of service (DoS) attacks. An attacker could repeatedly call a function that uses _insert, causing the array to grow until the transaction consumes all available gas and fails. This could prevent legitimate users from successfully interacting with the contract, as their transactions may also run out of gas or become prohibitively expensive due to the increased computational overhead.

Proof of Concept

the Create.sol::validateOrder function is part of a contract that interacts with a rental system, possibly within a marketplace like Seaport. The function decodes a RentPayload from the extraData parameter, performs various checks, and if all checks pass, it calls Create.sol::_rentFromZone to handle the rental logic. The _rentFromZone function iterates over a list of items and, for each item that is a rental, calls the Accumulator.sol::_insert function to add a RentalAssetUpdate to the rentalAssetUpdates dynamic array.

The potential vulnerability lies in the _insert function, which does not check the size of the rentalAssetUpdates array, potentially leading to out-of-gas errors if the array grows too large

Setup: An attacker identifies a contract that uses the validateOrder function to process rental orders. This function, upon successful validation, calls _rentFromZone, which in turn calls _insert to add rental updates to an array.

Payload Crafting: The attacker crafts a valid RentPayload and corresponding signature that will pass all the checks within validateOrder. This includes ensuring the signature has not expired, the fulfiller is correct, and the signer has the appropriate role.

Repeated Execution: The attacker then repeatedly calls validateOrder with the crafted payload. Each call processes a rental order and adds a new entry to the rentalAssetUpdates array via the _insert function.

Unchecked Growth: Since _insert does not check the size of the rentalAssetUpdates array, the attacker can continue to add entries until the transaction consumes all available gas.

Resulting Denial of Service: Eventually, the gas cost for processing an additional entry exceeds the transaction's gas limit, causing it to fail. If the attacker can automate and sustain this process, it could lead to a denial of service, where legitimate users are unable to process their rental orders due to out-of-gas errors or prohibitively high gas costs.

Tools Used

Manual review

Limiting the Size of the Array: Introduce a maximum size for the rentalAssets array to prevent it from growing indefinitely.

Requiring Fees for Orders: Charge a fee for processing orders to disincentivize spamming and reduce the risk of DoS attacks.

Gas Checks: Implement checks to ensure that the gas usage of the validateOrder and rentFromZone functions does not approach the block gas limit

Assessed type

DoS

#0 - c4-pre-sort

2024-01-21T17:47:33Z

141345 marked the issue as duplicate of #544

#1 - c4-judge

2024-01-27T18:26:59Z

0xean marked the issue as partial-25

#2 - c4-judge

2024-01-27T18:27:17Z

0xean marked the issue as satisfactory

#3 - serial-coder

2024-01-30T07:23:29Z

Hi @0xean,

This issue (#309) is incorrect and is not a duplicate of #538.

Point 1: Whereas #538 refers to the DoS issue on rental stop transactions, this issue (#309) refers to the DoS issue on a start transaction.

Point 2: In fact, the author of #309 refers to the unchecked growth of the rentalAssetUpdates array, which can require gas exceeding the block gas limit and cause DoS to other protocol users (how?). This issue is incorrect (Please read the issue thoroughly).

#4 - 0xean

2024-01-30T14:54:13Z

I am going to leave this duplicated and call this final.

Please look at the proposed mitigations of these issues to understand why they are different, but have the same high level root cause.

Awards

2.7205 USDC - $2.72

Labels

bug
2 (Med Risk)
satisfactory
edited-by-warden
duplicate-64

External Links

Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/policies/Stop.sol#L296 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/modules/PaymentEscrow.sol#L271 https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L201 https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/modules/PaymentEscrow.sol#L100-L118

Vulnerability details

Impact

The inability to settle payments due to a Lender or Renter being blacklisted on the ERC20 contract. (e.g. USDC, USDT)

Proof of Concept

A lender who is blacklisted by the USDT contract creates a rental agreement where USDT is the consideration(Base Order). A renter fulfills the order, and the USDT is transferred to the PaymentEscrow.sol contract. Upon rental expiration, the PaymentEscrow attempts to transfer USDT to the lender. The transfer fails due to the blacklist restriction in the USDT contract, and the transaction reverts.

   function _settlePaymentInFull(
        address token,
        uint256 amount,
        SettleTo settleTo,
        address lender,
        address renter
    ) internal {
        // Determine the address that this payment will settle to.
        address settleToAddress = settleTo == SettleTo.LENDER ? lender : renter;

        // Send the payment.
        _safeTransfer(token, settleToAddress, amount);
    }

The PaymentEscrow::_settlePaymentInFull function is intended to transfer the specified amount of the token (in this case, USDT) to either the lender or the renter, depending on the settleTo parameter. If the settleTo is SettleTo.LENDER, the payment will be sent to the lender's address.

However, if the lender's address is blacklisted by the USDT contract, the _safeTransfer call within _settlePaymentInFullwill fail. This is because the USDT contract will likely have a modifier or require statement that checks if the recipient is blacklisted and, if so, reverts the transaction.

When the transaction reverts, the state changes made by the transaction are rolled back, and the USDT tokens would not be transferred from the PaymentEscrow to the lender. This would leave the system in a state where the rental agreement's financial settlement cannot be completed as intended. Also, prevent the rental from stopping even if it has expired.

Note: This bug can repeat if the renter's address is blacklisted. Similarly, if it is a pay order and the renter is blacklisted, the _settlePaymentInFull function won't be able to transfer the token.

Tools Used

Manual Review

Implement a verification step to check if the lender's or renter address is blacklisted before creating a rental Order.

Assessed type

Other

#0 - c4-pre-sort

2024-01-21T17:36:15Z

141345 marked the issue as duplicate of #64

#1 - c4-judge

2024-01-28T21:01:00Z

0xean marked the issue as satisfactory

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter