Skip to content

Inverted Selector Check Causes All ERC721 Safe Transfers to Contract Addresses to Fail #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
howlbot-integration bot opened this issue Sep 16, 2024 · 1 comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-148 🤖_09_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards sufficient quality report This report is of sufficient quality

Comments

@howlbot-integration
Copy link

Lines of code

https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/sol/OwnershipNFTs.sol#L73

Vulnerability details

Summary

There is a critical bug in the _onTransferReceived function. The function incorrectly checks the return value from the onERC721Received callback, causing all safe transfers to contract addresses to fail, even when the receiving contract correctly implements the ERC721 receiver interface.

Code Snippet

https://github.com/code-423n4/2024-08-superposition/blob/main/pkg/sol/OwnershipNFTs.sol#L73

function _onTransferReceived(
    address _sender,
    address _from,
    address _to,
    uint256 _tokenId
) internal {
    if (_to.code.length == 0) return;

    bytes4 data = IERC721TokenReceiver(_to).onERC721Received(
        _sender,
        _from,
        _tokenId,
        ""
    );

    require(
        data != IERC721TokenReceiver.onERC721Received.selector,
        "bad nft transfer received data"
    );
}

The bug is in the require statement. It's checking if the returned data is NOT equal to the expected selector, which is the opposite of what it should do.

Impact

  1. All safe transfers to contract addresses will fail, even if the receiving contract correctly implements onERC721Received.
  2. Users will be unable to transfer NFTs to smart contract wallets or other contracts designed to hold NFTs.
  3. This severely limits the functionality and interoperability of the NFT contract.

Scenario

  1. A user attempts to transfer an NFT to a smart contract wallet using safeTransferFrom.
  2. The smart contract wallet correctly implements onERC721Received and returns the expected selector.
  3. The transfer fails because the require statement in _onTransferReceived reverts the transaction.

Fix

The fix is to change the != operator to == in the require statement:

require(
    data == IERC721TokenReceiver.onERC721Received.selector,
    "bad nft transfer received data"
);

This change ensures that the function only proceeds if the receiving contract returns the correct selector, indicating it can handle ERC721 tokens.

Assessed type

Invalid Validation

@howlbot-integration howlbot-integration bot added 2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value 🤖_09_group AI based duplicate group recommendation bug Something isn't working duplicate-55 sufficient quality report This report is of sufficient quality labels Sep 16, 2024
howlbot-integration bot added a commit that referenced this issue Sep 16, 2024
@c4-judge
Copy link
Contributor

alex-ppg marked the issue as satisfactory

@c4-judge c4-judge added the satisfactory satisfies C4 submission criteria; eligible for awards label Sep 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 (Med Risk) Assets not at direct risk, but function/availability of the protocol could be impacted or leak value bug Something isn't working duplicate-148 🤖_09_group AI based duplicate group recommendation satisfactory satisfies C4 submission criteria; eligible for awards sufficient quality report This report is of sufficient quality
Projects
None yet
Development

No branches or pull requests

1 participant