Platform: Code4rena
Start Date: 16/12/2022
Pot Size: $60,500 USDC
Total HM: 12
Participants: 58
Period: 5 days
Judge: Trust
Total Solo HM: 4
Id: 196
League: ETH
Rank: 11/58
Findings: 1
Award: $1,330.41
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: Jeiwan
Also found by: Koolex, Ruhum, rotcivegaf
1330.4109 USDC - $1,330.41
The collateral is assigned to the operator's vault because of a parameter mismatch. This impacts the ability of third parties to integrate the PaprController contract. You're not able to create an intermediary contract that adds collateral to a user's vault. It has to be the user themselves sending the NFT directly else the collateral is assigned to the calling contract (operator). If the collateral is assigned to the NFT owner's vault you can have two types of integrations:
Only the first integration type is possible in the current form because the collateral is always assigned to the operator (intermediary contract).
Generally, I believe that the collateral being assigned to the operator is unexpected behavior that might cause headaches if the caller doesn't read the contracts properly. To undo that, the operator has to pay back the debt, remove the collateral and send it back to the user. Depending on the contract used to transfer the collateral in the first place, that might not be possible. In that rare scenario that might cause a loss of funds.
The onERC721Received()
function has the following interface
function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
The PaprController contract expects the first parameter to be the NFT owner, although that's the operator's address (see NATSPEC comment):
/// @notice Handler for safeTransferFrom of an NFT /// @dev Should be preferred to `addCollateral` if only one NFT is being added /// to avoid approval call and save gas /// @param from the current owner of the nft /// @param _id the id of the NFT /// @param data encoded IPaprController.OnERC721ReceivedArgs /// @return selector indicating succesful receiving of the NFT function onERC721Received(address from, address, uint256 _id, bytes calldata data) external override returns (bytes4) { IPaprController.OnERC721ReceivedArgs memory request = abi.decode(data, (IPaprController.OnERC721ReceivedArgs)); IPaprController.Collateral memory collateral = IPaprController.Collateral(ERC721(msg.sender), _id); _addCollateralToVault(from, collateral); if (request.swapParams.minOut > 0) { _increaseDebtAndSell(from, request.proceedsTo, ERC721(msg.sender), request.swapParams, request.oracleInfo); } else if (request.debt > 0) { _increaseDebt(from, collateral.addr, request.proceedsTo, request.debt, request.oracleInfo); } return ERC721TokenReceiver.onERC721Received.selector; }
none
Use the owner's address instead of the operator's.
#0 - c4-judge
2022-12-25T14:34:37Z
trust1995 marked the issue as duplicate of #121
#1 - c4-judge
2022-12-25T14:34:45Z
trust1995 marked the issue as satisfactory
#2 - c4-judge
2022-12-25T16:58:11Z
trust1995 changed the severity to 3 (High Risk)
#3 - c4-judge
2022-12-25T17:45:58Z
trust1995 marked the issue as duplicate of #183