1

I'm working on a project where I need to implement an ERC721 marketplace. It doesn't work for some reason and wanted to know if I'm doing everything correctly.

The way I approached this was:

The seller approves the contract address to act on their behalf.
The token is listed as available for sale in the marketplace.
Then, when the buyer wants to buy the token, the contract transfers the token from the seller to the buyer, and transfers the payment from buyer to seller.

I couldn't find many resources but found these as references:

https://github.com/status-im/embark-tutorial-erc721/tree/tutorial-series/contracts

Proper way to implement "buyable" ERC721 tokens

So here's the code I implemented:

The code is here:

 struct Token {
        uint id;
        uint price;
        uint prevPrice;
        bool forSale;
    }


function buyMarketplaceToken(uint _tokenId) public payable whenNotPaused() isForSale(_tokenId) {
        address ticketOwner = ownerOf(_tokenId);
        require(msg.value >= tokens[_tokenId].price, "It costs more!");
        ticketOwner.transfer(msg.value);
        safeTransferFrom(ticketOwner, msg.sender, _ticketId);
        clearApproval(this, _ticketId);
        tokens[_tokenId].forSale = false;
    }

    function addTokenForSale(uint _tokenId, uint newPrice) public onlyOwner(_tokenId) whenNotPaused() {
        tokens[_tokenId].forSale = true;
        tokens[_tokenId].prevPrice = tokens[_tokenId].price;
        tokens[_tokenId].price = newPrice;
        approve(address(this), _tokenId);
        emit TokenOnSale(_tokenId, newPrice);
    }

        function removeTokenForSale(uint _tokenId) public onlyOwner(_tokenId) whenNotPaused() {
        tokens[_tokenId].forSale = false;
        tokens[_tokenId].price = tokens[_tokenId].prevPrice;
        clearApproval(address(this), _tokenId);
        emit TokenOffSale(_tokenId, tokens[_tokenId].prevPrice);
    }

So my logic is that seller calls addTokenForSale with tokenId and a price for sale. This function approves the contract to transfer token on owners behalf and sets the forSale boolean for this token to true.

The buyer calls buyMarketplaceToken with tokenId and pays the token price which is transferred to original token owner. The token is transferred to msg.sender by the contract and approval is cleared. Then the token forSale boolean is set to false meaning its not for sale anymore.

The code stops working at safeTransferFrom because even though the contract has approval to transfer token, contract is not msg.sender.

How do I make sure that safeTransferFrom caller is the contract and not msg.sender?

What am I missing here? Any help would be appreciated.

1
  • can you show your safeTransferFrom function?
    – Sanjay S B
    Jul 24, 2019 at 5:13

1 Answer 1

2

ERC721 is similar to ERC20 in the approve/transferFrom. It has to be the user whom approves your market contract, the market contract cannot request for approval.

For example to approve the market the user will execute

token721.approve(marketAddress, id, { from: userAddress })

Now the market can transfer user tokens to the recipient (or you can use safeTransferFrom)

token721.transferFrom(userAddress, recipient, id)
2
  • But what happens if the owner of the token gives approval to another marketplace? May 5, 2022 at 9:28
  • @MiratCanBayrak Then the other marketplace will be able to transfer the tokens. If you have more doubts it is better to create a new question.
    – Ismael
    May 5, 2022 at 14:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.