chiru-labs / ERC721A

https://ERC721A.org
MIT License
2.5k stars 839 forks source link

onERC721Received #443

Open sayedex opened 1 year ago

sayedex commented 1 year ago

when i try to rcv my erc721 from null address on my contract onERC721Received its not working

Vectorized commented 1 year ago

Can you share your code?

sayedex commented 1 year ago

contract NftMinterA is IERC721Receiver{

address public admin;
mapping(address => uint256[]) private tokenIdsByContract;

constructor(address _admin) {
    admin = _admin;
}

function mint(
    address nft,
    bytes calldata param
    ) external payable {
    (bool success, ) = nft.call{value: msg.value}(param);
    require(success);
}

function transfer(address nft) external {
    uint256[] memory _tokenIds = tokenIdsByContract[nft];
    uint256 _length = _tokenIds.length;

    for (uint256 i = 0; i < _length; i++ ) {
        IERC721(nft).transferFrom(address(this), admin, _tokenIds[i]);
    }
    delete tokenIdsByContract[nft];
}
function onERC721Received(
    address,
    address,
    uint256 _tokenId,
    bytes memory
) public virtual override returns (bytes4) {
    tokenIdsByContract[msg.sender].push(_tokenId);
    return this.onERC721Received.selector;
}

function tokenIdsByNFT(address nft) external view returns(uint256[] memory){
    return tokenIdsByContract[nft];
}

}

Vectorized commented 1 year ago

Why are you calling call instead of mintTo(address to, uint256 quantity) on the nft contract?

sayedex commented 1 year ago

its a subcontract bro! it will be deployed by facotory contract but my question is all about onERC721Received how can i work it to be true?

Vectorized commented 1 year ago

Need to see the code of your NFT contract too.

sayedex commented 1 year ago

// File: @openzeppelin/contracts/utils/introspection/IERC165.sol

// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**

interface IERC721AMock { function safeMint(address to, uint256 quantity) external; } interface ERC721A__IERC721Receiver { function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }

interface IERC165 { /**

// File: @openzeppelin/contracts/token/ERC721/IERC721.sol

// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.0;

/**

// File: @openzeppelin/contracts/token/ERC721/IERC721Receiver.sol

// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.0;

/**

// File: contracts/nft_minter.sol

pragma solidity ^0.8.0;

contract NftMinter is ERC721A__IERC721Receiver{

address public admin;
uint public sayed = 5;
mapping(address => uint256[]) private tokenIdsByContract;

constructor(address _admin) {
    admin = _admin;
}

function mint(
    address nft,
    bytes calldata param
    ) external payable {
    (bool success, ) = nft.call{value: msg.value}(param);
    require(success);
}
 function _mint(
    address nft,
    bytes calldata param
    ) external payable {
    (bool success, ) = nft.call(param);
    require(success);
}

function transfer(address nft) external {
    uint256[] memory _tokenIds = tokenIdsByContract[nft];
    uint256 _length = _tokenIds.length;

    for (uint256 i = 0; i < _length; i++ ) {
        IERC721(nft).transferFrom(address(this), admin, _tokenIds[i]);
    }
    delete tokenIdsByContract[nft];
}

function onERC721Received( address operator, address from, uint256 tokenId, bytes memory data ) public override returns (bytes4) { tokenIdsByContract[msg.sender].push(tokenId); return this.onERC721Received.selector; }

function tokenIdsByNFT(address nft) external view returns(uint256[] memory){
    return tokenIdsByContract[nft];
}

function Givescon() pure public returns (bytes4) { return IERC721Receiver.onERC721Received.selector; }

}

contract NftMinterA is IERC721Receiver{

address public admin;
mapping(address => uint256[]) private tokenIdsByContract;

constructor(address _admin) {
    admin = _admin;
}

function mint(
    address nft,
    bytes calldata param
    ) external payable {
    (bool success, ) = nft.call{value: msg.value}(param);
    require(success);
}

function transfer(address nft) external {
    uint256[] memory _tokenIds = tokenIdsByContract[nft];
    uint256 _length = _tokenIds.length;

    for (uint256 i = 0; i < _length; i++ ) {
        IERC721(nft).transferFrom(address(this), admin, _tokenIds[i]);
    }
    delete tokenIdsByContract[nft];
}
function onERC721Received(
    address,
    address,
    uint256 _tokenId,
    bytes memory
) public virtual override returns (bytes4) {
    tokenIdsByContract[msg.sender].push(_tokenId);
    return this.onERC721Received.selector;
}

function tokenIdsByNFT(address nft) external view returns(uint256[] memory){
    return tokenIdsByContract[nft];
}

}

// File: contracts/factory.sol

pragma solidity ^0.8.0;

contract Factory is IERC721Receiver{

address public admin;
address[] public minters;
uint256 salt = 0;
uint256 tokenId;

constructor(address _admin) {
    admin = _admin;
}

function getBytecode() internal view returns (bytes memory) {
    bytes memory bytecode = type(NftMinter).creationCode;

    return abi.encodePacked(bytecode, abi.encode(admin));
}

function deploy(uint256 amount) external {
    bytes memory bytecode = getBytecode();
    for(uint256 i = 0; i < amount; i ++) {
        address addr;
        uint256 _salt = salt;
        assembly {
            addr := create2(callvalue(), add(bytecode, 0x20), mload(bytecode), _salt)

            if iszero(extcodesize(addr)) {
                revert(0, 0)
            }
        }
        minters.push(addr);
        salt++;
    }
}

function mintBySubContract(
    address nft,
    uint256 amount,
    bytes calldata param
) external payable {
    uint256 price = msg.value / amount;
    for(uint256 i = 0; i < amount; i ++) {
        NftMinter(minters[i]).mint{value: price}(nft, param);
    }
}

function _mintBySubContract( address nft, uint256 amount, bytes calldata param ) external { for(uint256 i = 0; i < amount; i ++) { NftMinter(minters[i])._mint(nft, param); } }

function transferBySubContract(
    address nft,
    uint256 amount
) external {
    for(uint256 i = 0; i < amount; i ++) {
        NftMinter(minters[i]).transfer(nft);
    }
}

function mintAndTransfer(
    address nft,
    uint256 amount,
    bytes calldata param
) external {
    for(uint256 i = 0; i < amount; i ++) {
        (bool success, ) = nft.call(param);
        require(success);
        IERC721(nft).transferFrom(address(this), admin, tokenId);
    }
}

function mint(
    address nft,
    uint256 amount,
    bytes calldata param
) external {
    for(uint256 i = 0; i < amount; i ++) {
        (bool success, ) = nft.call(param);
        require(success);
    }
}

function onERC721Received(
  address,
  address,
  uint256 _tokenId,
  bytes memory
) public virtual override returns (bytes4) {
    tokenId = _tokenId;
    return this.onERC721Received.selector;
}

}

Vectorized commented 1 year ago

I can't find anything that is subclassing ERC721A.

sayedex commented 1 year ago

how can implement thar if i do that the function onERC721Received( address, address, uint256 _tokenId, bytes memory ) public virtual override returns (bytes4) { ///this one only working on erc721 but when i sens erc721A its not updateing my data tokenIdsByContract[msg.sender].push(_tokenId); return this.onERC721Received.selector; } will work?

Vectorized commented 1 year ago

I think you should just make a single contract inherited from ERC721A that also contains the minting function.

sayedex commented 1 year ago

okey i will try then i will update you !

Vectorized commented 1 year ago

Example: https://gist.github.com/Vectorized/0263fb6c943aeb9cfc7dd93e17f54ffa

sayedex commented 1 year ago

not working! same its not updaing tokenIdsByContract[msg.sender].push(_tokenId); on onERC721Received

Vectorized commented 1 year ago

Use _safeMint for the example.

Vectorized commented 1 year ago

Some general advice:

For the best results, you should just copy the code of an established project if you need it up ASAP with minimum hassle.

It seems that you are trying to implement something beyond your current Solidity level, or trying to over-engineer things, when a simple all-in-one mintable NFT contract will do the job.

You might want to consider the using the OpenZeppelin wizard instead of ERC721A.

As much as I would like, issues should not be used as a step by step tutorial. There are better resources for that.

sayedex commented 1 year ago

thanks! actually its my client requirement only