reNFT - ABAIKUNANBAEV'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: 100/116

Findings: 2

Award: $5.79

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

3.987 USDC - $3.99

Labels

bug
3 (High Risk)
partial-25
upgraded by judge
edited-by-warden
duplicate-418

External Links

Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L162 https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L218

Vulnerability details

Impact

In Signer.sol, there are some functions where constructor of EIP-712 typehash is not made properly when generating hash. This makes the signature verification process not work as expected resulting in functions reverts due to generation of different signatures and non-compliance to EIP-712

Proof of Concept

First, it's _deviateRentalOrderHash() that constructs the typehash like this:

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L248-262

function _deriveRentalOrderHash( RentalOrder memory order ) internal view returns (bytes32) { // Create arrays for items and hooks. bytes32[] memory itemHashes = new bytes32[](order.items.length); bytes32[] memory hookHashes = new bytes32[](order.hooks.length); // Iterate over each item. for (uint256 i = 0; i < order.items.length; ++i) { // Hash the item. itemHashes[i] = _deriveItemHash(order.items[i]); } // Iterate over each hook. for (uint256 i = 0; i < order.hooks.length; ++i) { // Hash the hook. hookHashes[i] = _deriveHookHash(order.hooks[i]); } 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 ) ); }

However, the rentalOrderTypeString is declared like that:

bytes memory rentalOrderTypeString = abi.encodePacked( "RentalOrder(bytes32 seaportOrderHash,Item[] items,Hook[] hooks,uint8 orderType,address lender,address renter,address rentalWallet,uint256 startTimestamp,uint256 endTimestamp)" );

The problem is that the rentalWallet param is missing in this case.

This problem is also present _deriveOrderMetadataHash() function where orderType and emittedExtraData params are missing:

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L218-239

function _deriveOrderMetadataHash( OrderMetadata memory metadata ) internal view returns (bytes32) { // Create array for hooks. bytes32[] memory hookHashes = new bytes32[](metadata.hooks.length); // Iterate over each hook. for (uint256 i = 0; i < metadata.hooks.length; ++i) { // Hash the hook hookHashes[i] = _deriveHookHash(metadata.hooks[i]); } // Derive and return the metadata hash as specified by EIP-712. return keccak256( abi.encode( _ORDER_METADATA_TYPEHASH, metadata.rentDuration, keccak256(abi.encodePacked(hookHashes)) ) ); }

orderMetadataTypeString:

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L384-386

bytes memory orderMetadataTypeString = abi.encodePacked( "OrderMetadata(uint8 orderType,uint256 rentDuration,Hook[] hooks,bytes emittedExtraData)" );

Tools Used

Manual review.

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L248-262

             

keccak256(
                abi.encode(
                    _RENTAL_ORDER_TYPEHASH,
                    order.seaportOrderHash,
                    keccak256(abi.encodePacked(itemHashes)),
                    keccak256(abi.encodePacked(hookHashes)),
                    order.orderType,
                    order.lender,
                    order.renter,
+                   order.rentalWallet,
                    order.startTimestamp,
                    order.endTimestamp
                )
            );

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L218-239



 keccak256(
                abi.encode(
                    _ORDER_METADATA_TYPEHASH,
+                   metadata.orderType,
                    metadata.rentDuration,
                    keccak256(abi.encodePacked(hookHashes)),   
+                   metadata.emittedExtraData
  
));

Assessed type

Other

#0 - c4-pre-sort

2024-01-21T17:51:09Z

141345 marked the issue as duplicate of #239

#1 - c4-judge

2024-01-28T21:05:56Z

0xean marked the issue as satisfactory

#2 - c4-judge

2024-01-30T11:32:24Z

0xean marked the issue as not a duplicate

#3 - c4-judge

2024-01-30T11:33:00Z

0xean marked the issue as duplicate of #385

#4 - c4-judge

2024-01-30T11:33:03Z

0xean marked the issue as partial-25

#5 - c4-judge

2024-01-30T14:24:45Z

0xean changed the severity to 3 (High Risk)

Awards

1.8029 USDC - $1.80

Labels

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

External Links

Lines of code

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L385 https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L363

Vulnerability details

Impact

In Signer.sol, when creating typehashes in _deriveRentalTypehashes(), orderType parameter is assigned to an incorrect type in itemTypeString, rentalOrderTypeString and orderMetadataTypeString. This will make the contract non-compliant to EIP-712 and the functions that use EIP-712 signatures will effectively revert.

Proof of Concept

In _deriveRentalTypehashes(), itemTypeString is created this way:

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L352-354

bytes memory itemTypeString = abi.encodePacked( "Item(uint8 itemType,uint8 settleTo,address token,uint256 amount,uint256 identifier)" );

However, itemType and settleTo are of type Item and SettleTo and not uint8.

For example, rentalPayloadTypeString is created correctly:

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L389-391

bytes memory rentPayloadTypeString = abi.encodePacked( "RentPayload(OrderFulfillment fulfillment,OrderMetadata metadata,uint256 expiration,address intendedFulfiller)" );

It uses OrderFullfillment type for fulfillment param instead of uint8, unlike in the previous example.

The next strings are orderMetadataTypeString and rentalOrderTypeString where also uint8 type used instead of custom types for orderType parameter:

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L362-364

bytes memory rentalOrderTypeString = abi.encodePacked( "RentalOrder(bytes32 seaportOrderHash,Item[] items,Hook[] hooks,uint8 orderType,address lender,address renter,address rentalWallet,uint256 startTimestamp,uint256 endTimestamp)" );

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L384-386

bytes memory orderMetadataTypeString = abi.encodePacked( "OrderMetadata(uint8 orderType,uint256 rentDuration,Hook[] hooks,bytes emittedExtraData)" );

Tools Used

Manual review.

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L362-364


 bytes memory rentalOrderTypeString = abi.encodePacked(
        
-     "RentalOrder(bytes32 seaportOrderHash,Item[] items,Hook[] hooks,uint8 orderType,address lender,address renter,address rentalWallet,uint256 startTimestamp,uint256 endTimestamp)"
                 
+     "RentalOrder(bytes32 seaportOrderHash,Item[] items,Hook[] hooks,OrderType orderType,address lender,address renter,address rentalWallet,uint256 startTimestamp,uint256 endTimestamp)"

        );        

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L384-386


bytes memory orderMetadataTypeString = abi.encodePacked(                
        
-     "OrderMetadata(uint8 orderType,uint256 rentDuration,Hook[] hooks,bytes emittedExtraData)"
            );   
               
+       "OrderMetadata(OrderType orderType,uint256 rentDuration,Hook[] hooks,bytes emittedExtraData)"
            );

https://github.com/re-nft/smart-contracts/blob/3ddd32455a849c3c6dc3c3aad7a33a6c9b44c291/src/packages/Signer.sol#L352-354


bytes memory itemTypeString = abi.encodePacked(
        
-       "Item(uint8 itemType,uint8 settleTo,address token,uint256 amount,uint256 identifier)"
        );      
+       "Item(ItemType itemType,SettleTo settleTo,address token,uint256 amount,uint256 identifier)"
        );

Assessed type

Other

#0 - c4-pre-sort

2024-01-21T17:51:07Z

141345 marked the issue as duplicate of #239

#1 - c4-judge

2024-01-28T21:05:55Z

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