Skip to content
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

Unable to transfer NFTs from a Smart Contract when a fallback fee is present. #12222

Open
kantorcodes opened this issue Mar 19, 2024 · 1 comment
Labels
Bug An error that causes the feature to behave differently than what was expected based on design.

Comments

@kantorcodes
Copy link

kantorcodes commented Mar 19, 2024

Description

There no viable way for smart contracts to actually pay fallback fees on an NFT that has one set (eg 100 HBAR). It seems that without this, there is no way to practical way to send an NFT with a fallback fee to an Account ID unless you execute an atomic transaction with cryptoTransfer involving a fungible token, which is super impractical and hacky. This feels like a bug.

I've attached this transaction where an allowance is set on both the Contract and the user for 200k HBAR, but the transaction returns SPENDER_DOES_NOT_HAVE_ALLOWANCE (which is also very unclear in the context)

https://hashscan.io/testnet/transaction/1710853927.371841027

Utilizing other methods like IERC721(tokenAddress).transferFrom(...) also yields weird results.

https://hashscan.io/testnet/transaction/1710866571.915902005

Steps to reproduce

  1. Create a simple smart contract that exposes a payable method to transfer an NFT into the payers account.
  2. Transfer NFTs into the smart contract
  3. Execute the function

Note the code below is pseudo code, you will need to clean it up to actually work.

address private constant PRECOMPILE_ADDRESS = address(0x167);

 /// Initiates a Non-Fungable Token Transfer
    /// @param token The ID of the token as a solidity address
    /// @param sender the sender of an nft
    /// @param receiver the receiver of the nft sent by the same index at sender
    /// @param serialNumber the serial number of the nft sent by the same index at sender
    function transferNFTs(
        address token,
        address[] memory sender,
        address[] memory receiver,
        int64[] memory serialNumber
    ) internal returns (int256 responseCode) {
        (bool success, bytes memory result) = PRECOMPILE_ADDRESS.call(
            abi.encodeWithSelector(
                IHederaTokenService.transferNFTs.selector,
                token,
                sender,
                receiver,
                serialNumber
            )
        );
        responseCode = success
            ? abi.decode(result, (int32))
            : HederaResponseCodes.UNKNOWN;
    }
    
        function transferFrom(
        address to,
        int64[] memory serialNumbers
    ) external returns (int256) {
        address[] memory senderArray = generateAddressArrayForHTS(address(this), serialNumbers.length);

        address[] memory minterArray = generateAddressArrayForHTS(
            to,
            serialNumbers.length
        );

        int256 responseCode = HederaTokenService.transferNFTs(
            tokenAddress,
            senderArray,
            minterArray,
            serialNumbers
        );

        if (responseCode != HederaResponseCodes.SUCCESS) {
            revert;
        }

        return responseCode;
    }
 
    
    ```

### Additional context

_No response_

### Hedera network

mainnet, testnet

### Version

latest

### Operating system

None
@kantorcodes kantorcodes added the Bug An error that causes the feature to behave differently than what was expected based on design. label Mar 19, 2024
@Nana-EC
Copy link
Contributor

Nana-EC commented Mar 24, 2024

Hi @kantorcodes
Thanks for the ticket and I appreciate the additional context for the flow.

Fallback fees were designed prior to HSCS v2.0 in which we begun to expose native HTS functionality to smart contracts.
https://hips.hedera.com/hip/hip-18 define fallback fees to requires a user to send HBAR value to receive an NFT. In accordance with the networks security model a signature, prior approval or additional authority needs to be given to allow value be transferred from the users accounts.
This leaves limited options for a flow like a smart contract execution that does not utilize the signatures of a HAPI transaction.

The options include

I would recommend you take a look at HIP 906 as it provides a pathway to one of those solutions.
With HIP 906 a user who intends to receive an NFT with a fallback fee could provide an HBAR allowance to a smart contract in advance of the transfer. This would support a successful transfer and is similar to token logic and allowances and approvals.
Could you kindly review that HIP and leave a comment there to your scenario and if it helps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug An error that causes the feature to behave differently than what was expected based on design.
Projects
None yet
Development

No branches or pull requests

2 participants