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
Rank: 23/116
Findings: 1
Award: $467.84
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: hash
Also found by: ladboy233, piyushshukla
467.8415 USDC - $467.84
An attacker can repeatedly call stopRent, initiating fund transfers before the state is updated. This allows the attacker to exploit reentrancy, potentially stealing more funds than the intended rental amounts.
In the stopRent function of Stop.sol contract. If a lender repeatedly calls stopRent, it triggers the _reclaimRentedItems function. The vulnerability arises because the STORE.removeRentals function, responsible for updating the state, is called after transferring funds in the _reclaimRentedItems function. This creates a window of opportunity for an attacker to exploit reentrancy and steal more funds than intended.
function stopRent(RentalOrder calldata order) external { // Check that the rental can be stopped. _validateRentalCanBeStoped(order.orderType, order.endTimestamp, order.lender); // Create an accumulator which will hold all of the rental asset updates, consisting of IDs and // the rented amount. From this point on, new memory cannot be safely allocated until the // accumulator no longer needs to include elements. bytes memory rentalAssetUpdates = new bytes(0); // Check if each item in the order is a rental. If so, then generate the rental asset update. // Memory will become safe again after this block. for (uint256 i; i < order.items.length; ++i) { if (order.items[i].isRental()) { // Insert the rental asset update into the dynamic array. _insert( rentalAssetUpdates, order.items[i].toRentalId(order.rentalWallet), order.items[i].amount ); } } // Interaction: process hooks so they no longer exist for the renter. if (order.hooks.length > 0) { _removeHooks(order.hooks, order.items, order.rentalWallet); } // Interaction: Transfer rentals from the renter back to lender. _reclaimRentedItems(order); // 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); }
manual
Implement a reentrancy guard at the beginning of the _reclaimRentedItems function to prevent multiple calls before the state changes are finalized.
Reentrancy
#0 - c4-pre-sort
2024-01-21T18:06:54Z
141345 marked the issue as duplicate of #237
#1 - c4-judge
2024-01-28T18:47:40Z
0xean marked the issue as satisfactory
#2 - c4-judge
2024-01-29T21:53:30Z
0xean changed the severity to 2 (Med Risk)