Error sending contract balance to ganache address

Overview
Hello everyone,

I am having a problem when trying to send contract balance to a ganache address.
When I test my smart contract using the remix's VMs (London and Berlin) everything works perfectly as intended, but when I try to test my contract using ganache, it gives me an error.

Thanks in advance for your help.

Functionality of the Smart Contract

  • A seller create a star with an unique ID and any name. For example: 'Star 1', 1. Where 'Star 1' is the name and 1 is the ID for this token.

  • The seller decides to sell one of his star for a given price. For example: He/she wants to sell the token with ID 1 for 3 ether.

  • A buyer is interested in buying a star, the buyer will need to first deposit the EXACT ask value of the star to the smart contract. For example: A buyer is interested in Token with ID 1, he/she will need to transfer the EXACT value into the smart contract, in this case the buyer will deposit 3 ether to the smart contract.

  • Externally an application will call the Smart Contract to transfer the deposited funds to the seller and change the ownership of the token to the buyer. For example: The application will call the smart contract to transfer the 3 ether that the buyer previously deposited, then the smart contract will change the ownership for the Token with ID 1 to the buyer's address.

How to Test the Smart Contract

  1. Deploy the smart contract. Use any address from the listed on the VMs (London, Berling) or Ganache. This address will be known as deployer's address.

  2. Create a star. Choose a different address to create the star, this address will be known as seller's address. Then pass a name and a number for the star's name and ID to the function createStar(string memory _name, uint256 _tokenId). For example: createStar('Test', 1) from Seller's address.

  3. Putting a star for sell. From the seller's address, pass the star's ID and the price in WEI that you are asking for the star to the function putStarForSale(uint256 _tokenId, uint256 _price). For example: putStarForSale(1, 4000000000000000000) from Seller's address.

  4. Depositing funds. Choose a different address to buy the star, this address will be known as buyer's address. Then pass a number for the star's ID to the function sendingFunds(uint256 _tokenId) and send the EXACT amount of the star's price. For example: sendingFunds(1) from Buyer's address with Value 4 ether.

  5. Transfer funds and ownership (this last one is not yet implemented). From the buyer's address pass a number for the star's ID to the function buyStar(uint256 _tokenId). For example: buyStar(1) from Buyer's address.

NOTE: All three addresses (deployer, seller and buyer) must be different

ERC721 Smart Contract Code

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

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

contract StarNotary is ERC721 {
    struct Star {
        string name;
    }
    
    mapping (uint256 => Star) public tokenIdToStarName;
    mapping (uint256 => uint256) public tokenIdToStarPrice;
    
    constructor() ERC721("AstronomyStarNotary", "ASN") { }
    
    function createStar(string memory _name, uint256 _tokenId) external {
        Star memory newStar = Star(_name);
        tokenIdToStarName[_tokenId] = newStar;
        _mint(msg.sender, _tokenId);
    }
    
    function putStarForSale(uint256 _tokenId, uint256 _price) external {
        require(ownerOf(_tokenId) == msg.sender, "You don't own the Star");
        tokenIdToStarPrice[_tokenId] = _price;
    }
    
    function _checkingBuyersEligibility(uint256 _tokenId) private view returns (bool) {
        if (msg.sender.balance >= tokenIdToStarPrice[_tokenId]){
            return true;
        } else {
            return false;
        }
    }
    
    function _viewContractBalance() private view returns (uint256) {
        return address(this).balance;
    }
    
    function sendingFunds(uint256 _tokenId) external payable {
        require(tokenIdToStarPrice[_tokenId] > 0, "The Star should be up for sale");
        require(_checkingBuyersEligibility(_tokenId), "Not enough ether balance in your Wallet");
        require(msg.value == tokenIdToStarPrice[_tokenId], "Incorrect amount, please input the exact value of the Star");
    }
    
    function buyStar(uint256 _tokenId) external payable{
        require(tokenIdToStarPrice[_tokenId] > 0, "The Star should be up for sale");
        require(_viewContractBalance() >= tokenIdToStarPrice[_tokenId], "Not enough funds in the Smart Contract");
        payable(ownerOf(_tokenId)).transfer(tokenIdToStarPrice[_tokenId]);
        //transferFrom(ownerOf(_tokenId), msg.sender, _tokenId);
        //delete tokenIdToStarPrice[_tokenId];
    }
}

NOTE: THE CONTRACT WORKS FINE WHEN YOU TEST IT ON THE REMIX'S JAVASCRIPT VMs (LONDON AND BERLING) BUT IT FAILS WHEN YOU TEST IT ON GANACHE

Screenshot of Error with Ganache
Capture

QUESTIONS

  • Does the error has to be with ganache's default gas value?
    Gas value for remix (default value): 3000000
    Gas value for ganache (default value): 20000000000

  • Is the error from ganache side?

  • Is the error in the contract's code? If so, How do I fix it? And, Why does it work with remix's javascript VMs (London and Berling)?