Call approve function from Solidity


I was following the Rarible clone youtube tutorial. I see the approve function is being called from React.js. How can I call approve function from solidity? I want buyer will again add item to the market for re-sell. Here I attached the related code


ensureMarketPlaceIsApproved = async(tokenId, tokenAddress) => {
    user = await Moralis.User.current();
    const userAddress = user.get("ethAddress");
    const contract = new web3.eth.Contract(tokenContractAbi, tokenAddress);
    const approveAddress = await contract.methods.getApproved(tokenId).call({from: userAddress});
    if (approveAddress != MARKETPLACE_CONTRACT_ADDRESS) {
        // bring up metamask window to permit transfer token
        //approve(address to, uint256 tokenId) : By calling this method, 
        //the sender authorizes the address to to transfer one of his tokens with the Id tokenId.
        await contract.methods.approve(MARKETPLACE_CONTRACT_ADDRESS, tokenId).send({from: userAddress});


// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC721/ERC721.sol)

pragma solidity ^0.8.0;

import "../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "../node_modules/@openzeppelin/contracts/utils/Counters.sol";

contract MorarableToken is ERC721 {

    //we nned to access the counter struct from the counter file
    //this is used as equivelent for us to say id = 0 and then increment
    //in our functions saying id++
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    //we need to pass some values into our constructer
    //namely the ERC721 instances for name symbol decimals etc
    constructor () ERC721("MorarableToken", "MORA"){}

    //we now need to initialise our item as a struct
    struct Item {
        uint256 id;
        address creator;
        string uri;

    //now we need to make a mapping to our user account to the item struct
    mapping(uint256 => Item) public Items; 

    //create item function
    function createItem(string memory uri) public returns (uint256) {
        uint256 newItemId = _tokenIds.current();

        //we can call mint from the ERC721 contract to mint our nft token
        _safeMint(msg.sender, newItemId);

        Items[newItemId] = Item(newItemId, msg.sender, uri);

        return newItemId;

    //we now need to override the tokenURI function form the ERC721 function to add
    //a piece of extra functionality that is not provided by the base contratc function
    //namely we need return the item url with the id
    function tokenURI(uint256 tokenId) public view  override returns (string memory) {
        require(_exists(tokenId), "ERC721Metadata: URI query for nonexistent token");

        return Items[tokenId].uri;


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";

contract MorarableMarketContract {

    //we need to create a struct for the auction item
    struct AuctionItem {
        uint256 id;
        address tokenAddress;
        uint256 tokenId;
        address payable seller;
        uint256 askingPrice;
        bool isSold;

    //now we want to create an array of auctionItem struct instances to keep
    //track of all of the auction items
    AuctionItem[] public itemsForSale;

    //we also want to create a mapping of active items which allows us to keep
    //track of whicg items are for sale. this mapping prevents us rom looping
    //through the array above
    mapping(address => mapping(uint256 => bool)) activeItems;

    event itemAdded(uint256 id, uint256 tokenId, address tokenAddress, uint256 askingPrice);
    event itemSold (uint256 id, address buyer, uint256 askingPrice);

    //we waant to create a modifier to check if the caller is the item owner
    modifier onlyItemOwner (address tokenAddress, uint256 tokenId) {
        IERC721 tokenContract = IERC721(tokenAddress);
        require(tokenContract.ownerOf(tokenId) == msg.sender);

    //the next modifier we create checks if the marketplace has the approval of transferring
    //the item on behalf of the user
    modifier hasTransferApproval (address tokenAddress, uint256 tokenId) {
        IERC721 tokenContract = IERC721(tokenAddress);
        require(tokenContract.getApproved(tokenId) == address(this));

    //modifier which checks if the item actuall does exist
    modifier itemExists(uint256 id){
        require(id < itemsForSale.length && itemsForSale[id].id == id, "could not find item");

    modifier isForSale(uint256 id) {
        require(itemsForSale[id].isSold == false, "item is already sold");

    //next we will create a function which adds an item for sale to the marketplace
    function addItemToMarket(uint256 tokenId, address tokenAddress, uint256 askingPrice) onlyItemOwner(tokenAddress, tokenId) hasTransferApproval(tokenAddress, tokenId) external returns(uint256) {
        require(activeItems[tokenAddress][tokenId] == false, "item is already up for sale");
        uint256 newItemId = itemsForSale.length;
        itemsForSale.push(AuctionItem(newItemId, tokenAddress, tokenId, payable(msg.sender), askingPrice, false));
        activeItems[tokenAddress][tokenId] = true;

        assert(itemsForSale[newItemId].id == newItemId);
        emit itemAdded(newItemId, tokenId, tokenAddress, askingPrice);
        return newItemId;

    //the next function allows us to actually buy an item
    function buyItem(uint256 id) payable external itemExists(id) isForSale(id) hasTransferApproval(itemsForSale[id].tokenAddress, itemsForSale[id].tokenId) {
        require(msg.value >= itemsForSale[id].askingPrice, "Not enough funds for purchase");
        require(msg.sender != itemsForSale[id].seller);

        itemsForSale[id].isSold = true;
        activeItems[itemsForSale[id].tokenAddress][itemsForSale[id].tokenId] = false;
        IERC721(itemsForSale[id].tokenAddress).safeTransferFrom(itemsForSale[id].seller, msg.sender, itemsForSale[id].tokenId);

        emit itemSold(id, msg.sender, itemsForSale[id].askingPrice);


from a discussion on Discord, I would say that you don’t need to call approve from the smart contract, as you can transfer directly the NFT to the buyer from the smart contract