sherlock-audit / 2024-08-flayer-judging

2 stars 0 forks source link

heeze - Contract cannot receive native token #639

Open sherlock-admin2 opened 1 month ago

sherlock-admin2 commented 1 month ago

heeze

Medium

Contract cannot receive native token

Summary

The Contract ERC721Bridgable cannot receive native token paid in for royalties.

Vulnerability Detail

The ERC721Bridgable::claimRoyalties function transfers native token or any token sent to the contract as royalties. But the contract does not have the functionality to accept native token.

POC Add to the ./test/RiftTest.t.sol


function test_CannotRecieveEthOnL2() public {
        // Set the royalty information for the L1 contract
        l1NFT.setDefaultRoyalty(address(this), 1000);

        // Create an ERC721 that implements ERC2981 for royalties
        _bridgeNft(address(this), address(l1NFT), 0);

        // Get our 'L2' address
        Test721 l2NFT = Test721(riftBelow.l2AddressForL1Collection(address(l1NFT), false));

        //Add some native token to ALICE to buy the nft
        deal(ALICE, 10 ether);
        deal(address(USDC), ALICE, 1000 ether);

        uint256 startEthBalance0 = payable(address(this)).balance;

        //ALice buys the Nft from the contract in the L2
        l2NFT.transferFrom(address(this), ALICE, 0);
        //retrieve royalty information for the L1 contract
        (address reciever, uint256 royaltyAmount) = l1NFT.royaltyInfo(0, 3 ether);

        vm.startPrank(ALICE);
        //Alice pays 3 ether for the NFT, the royalty paid to the l2Nft contract is removed 
        (bool success,) = address(this).call{value: 3 ether - royaltyAmount}("");
        require(success);
        assertEq(reciever, address(this));
        assertEq(address(this).balance, startEthBalance0 + 3 ether - royaltyAmount);

        //The royalty is sent to the l2NFT contract but it reverts because the l2Nft contract cannot recieve token
        (bool success1,) = address(l2NFT).call{value: royaltyAmount}("");
        require(success1);
        vm.stopPrank();

        // Set up our tokens array to try and claim native ETH
        address[] memory tokens = new address[](1);
        tokens[0] = address(0);

        // Capture the starting ETH of this caller
        uint256 startEthBalance = payable(address(this)).balance;

        // Make a claim call to an external recipient address
        riftAbove.claimRoyalties(address(l1NFT), address(this), tokens, 0);

        // Confirm that tokens have been sent to ALICE and not the caller
        assertEq(payable(address(this)).balance, startEthBalance + royaltyAmount, "Invalid caller ETH");
        assertEq(payable(ALICE).balance, 7 ether, "Invalid ALICE ETH");
    }

Impact

Native token cannot be sent to the contract to be used in paying royalties.

Code Snippet

In https://github.com/sherlock-audit/2024-08-flayer/blob/main/moongate/src/libs/ERC721Bridgable.sol#L157 the functionality for transferring native token from the ERC721Bridgable contract to the royalties owner/reciever on the L1 is implemented

Tool used

Manual Review

Recommendation

Add a receive or fallback function to the ERC721Bridgable contract