Platform: Code4rena
Start Date: 03/05/2022
Pot Size: $50,000 USDC
Total HM: 4
Participants: 46
Period: 5 days
Judge: gzeon
Total Solo HM: 2
Id: 117
League: ETH
Rank: 32/46
Findings: 1
Award: $98.13
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BowTiedWardens
Also found by: 0x1337, 0x1f8b, 0x4non, 0xDjango, David_, Funen, GimelSec, IllIllI, Picodes, TerrierLover, WatchPug, bobi, cryptphi, csanuragjain, delfin454000, dirk_y, ellahi, fatherOfBlocks, hyh, ilan, jayjonah8, kebabsec, leastwood, oyc_109, robee, samruna, simon135, sorrynotsorry, throttle
98.1322 USDC - $98.13
transferFrom
leads to irreversible loss of user ERC721
funds.Assessed risk: 8/10
Urgency: 10/10
Codebase frequency: 1
The validReceive
modifier that checks whether the transaction of ERC721
or ERC1155
tokens has been executed according to the rules(msg.sender == underlying
and operator == address(this)
) is used on functions that would handle the callback on safeTransferFrom
but it can be bypassed by a user that transfers on their own, via transferFrom
.
The onERC721Received
is only triggered via its subsequent safeTransferFrom
function. Should a user transfer their tokens via transferFrom
or any other transfer function facilitated by usual ERC721
contracts, the ERC721
token that they’ve just transferred would be lost, since the onERC721Received
would not trigger to deny the improper(according to the implemented modifier) ERC721
transfer. The user would basically “forcibly” transfer their token, unknowingly that this is not the correct procedure of how the protocol should work.
Although there’s not much that can be done to refuse the transferFrom
transaction, I would suggest considering the following mitigation, for the sake of the users:
underlying
(so no shady business allowed). Moreover, it would transfer the _token
_id
that the user has previously wrongfully transferred. This way, the admins can verify on etherscan that the transaction happened wrongfully beforehand, confirm with the poor user, and send their token back! :). The mitigation could look something like thisfunction retrieveLostERC721(address _token, address _sender, uint256 _id) external onlyOwner { // making sure that the _token is not the underlying, so that no owner could // withdraw at will require(_token != underlying, "cannot withdraw underlying"); ERC721(_token).safeTransferFrom(address(this), _sender, _id); }
#0 - bunkerfinance-dev
2022-05-18T06:26:46Z
This isn't a priority for us because we can add a sweep function to the contract in the future.
#1 - gzeoneth
2022-05-29T11:37:19Z
Downgrading to Low / QA.
#2 - gzeoneth
2022-05-29T13:17:36Z
Treating as warden's QA report.