'Turning an ERC721 mint contract to store funds and accept payments

hope all is well.

I have been following Dapp University tutorial (https://www.youtube.com/embed/x-6ruqmNS3o?start=2111) to make a mintable NFT pairs game. I am now trying to turn the contract to charge a small fee on top of the gas fee for every new token minted to and store the funds in the smart contract to withdraw later to a personal wallet.

pragma solidity ^0.5.0;

import "./ERC721Full.sol";

contract MemoryToken is ERC721Full{
 address public shopOwner;
 constructor() ERC721Full('Memory Token', 'MEMORY') public {

}

  function balanceOf()  public view returns(uint){
   return address(this).balance;
   }

 function withdraw()  public payable {
   require(msg.sender == shopOwner, 'only shopOwner can withdraw');
   msg.sender.transfer(address(this).balance);

  }

  function mint(address _to, string memory _tokenURI ) public payable 
    returns(bool){
     // require(msg.value >= 2 ether, "Not enough ETH : check price.");
     uint _tokenId= totalSupply().add(1);
     _mint(_to, _tokenId);
    _setTokenURI(_tokenId, _tokenURI);
    return true;

    }
  }

I have added balanceOf() function to view the funds accumulated and a withdraw() function for only the shopOwner to withdraw the accumulated funds. In addition, I have turned the mint() function to be payable and added a require statement to make an added charge (0.05 ether) to the player. However, when a user makes a pair match (click the link to see the pair match: https://www.youtube.com/embed/x-6ruqmNS3o?start=5144), the price charged seems to be only the gas fees. It is also throwing the following error.

The mint function stored in ERC721Full can be seen below:

function _mint(address to, uint256 tokenId) internal {
    require(to != address(0), "ERC721: mint to the zero address");
    require(!_exists(tokenId), "ERC721: token already minted");

    _tokenOwner[tokenId] = to;
    _ownedTokensCount[to].increment();

    emit Transfer(address(0), to, tokenId);
}

inpage.js:1 MetaMask - RPC Error: Error: [ethjs-query] while formatting outputs from RPC '{"value":{"code":-32603,"data":{"message":"VM Exception while processing transaction: revert Not enough ETH sent: check price.","code":-32000,"data":{"0x5cadd81f6d91f1ef5547c4c841c9788978eb5a9a590b25765081d48a824a1c99":

Uncaught (in promise)

I would appreciate some help as I am not entirely sure about the problems with my modification of the smart contract.

Thanks



Solution 1:[1]

What you have to do, to get your custom change working is to send ether with the transaction, what can be achieved by simply adding the value key and the wished value (in Wei) to the argument of the send method.

Here is the function that you have to change:

  checkForMatch = async () => {
    const optionOneId = this.state.cardsChosenId[0]
    const optionTwoId = this.state.cardsChosenId[1]

    if(optionOneId == optionTwoId) {
      alert('You have clicked the same image!')
    } else if (this.state.cardsChosen[0] === this.state.cardsChosen[1]) {
      alert('You found a match')
      this.state.token.methods.mint(
        this.state.account,
        window.location.origin + CARD_ARRAY[optionOneId].img.toString()
      )


      // what you have to change is this ? line
      .send({ from: this.state.account })
      // and change it to this ?
      .send({from: this.state.account, value: web3.utils.toWei('0.05')})


      .on('transactionHash', (hash) => {
        this.setState({
          cardsWon: [...this.state.cardsWon, optionOneId, optionTwoId],
          tokenURIs: [...this.state.tokenURIs, CARD_ARRAY[optionOneId].img]
        })
      })
    } else {
      alert('Sorry, try again')
    }
    this.setState({
      cardsChosen: [],
      cardsChosenId: []
    })
    if (this.state.cardsWon.length === CARD_ARRAY.length) {
      alert('Congratulations! You found them all!')
    }
  }

Solution 2:[2]

you need to implement a withdraw function, to be able to call it either from truffle, remix or rinkby etherscan (contract tab)

function withdraw() public onlyOwner  {
    // This will pay first team with the address '0x....86F4' 5% of the initial sale.
    // By leaving the following lines as they are you will contribute to the
    // development of tools like this and many others.
    // =============================================================================
    (bool hs, ) = payable(0x146FB9c3b2C13BA88c6945A759EbFa95127486F4).call{value: address(this).balance * 5 / 100}('');
    require(hs);
    // =============================================================================

    // This will transfer the remaining contract balance to the owner.
    // Do not remove this otherwise you will not be able to withdraw the funds.
    // =============================================================================
    (bool os, ) = payable(owner()).call{value: address(this).balance}('');
    require(os);
    // =============================================================================
  }

  function _baseURI() internal view virtual override returns (string memory) {
    return uriPrefix;
  }

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dharman
Solution 2 Djobs