How to use a Bep20 token and not BNB to pay in a solidity contract?

Greetings, I am new, so far I have a few hours of learning but I am very interested in continuing to learn, I was able to find a solidity contract on Github that uses the Base BNB currency as a means of payment, I would like to be able to make the contract payment method be a Bep20 token instead of paying with BNB.

pragma solidity 0.8.0;

// SPDX-License-Identifier: MIT

abstract contract Context {
  function _msgSender() internal view virtual returns(address payable) {
    return payable(msg.sender);
  }

  function _msgData() internal view virtual returns(bytes memory) {
    this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
    return msg.data;
  }
}

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
contract Ownable is Context {
  address private _owner;

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /**
   * @dev Initializes the contract setting the deployer as the initial owner.
   */
  constructor() {
    address msgSender = _msgSender();
    _owner = msgSender;
    emit OwnershipTransferred(address(0), msgSender);
  }

  /**
   * @dev Returns the address of the current owner.
   */
  function owner() public view returns(address) {
    return _owner;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(_owner == _msgSender(), "Ownable: caller is not the owner");
    _;
  }

  /**
   * @dev Leaves the contract without owner. It will not be possible to call
   * `onlyOwner` functions anymore. Can only be called by the current owner.
   *
   * NOTE: Renouncing ownership will leave the contract without an owner,
   * thereby removing any functionality that is only available to the owner.
   */
  function renounceOwnership() public virtual onlyOwner {
    emit OwnershipTransferred(_owner, address(0));
    _owner = address(0);
  }

  /**
   * @dev Transfers ownership of the contract to a new account (`newOwner`).
   * Can only be called by the current owner.
   */
  function transferOwnership(address newOwner) public virtual onlyOwner {
    require(newOwner != address(0), "Ownable: new owner is the zero address");
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
  }
}

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
  /**
   * @dev Returns the addition of two unsigned integers, reverting on
   * overflow.
   *
   * Counterpart to Solidity's `+` operator.
   *
   * Requirements:
   *
   * - Addition cannot overflow.
   */
  function add(uint256 a, uint256 b) internal pure returns(uint256) {
    uint256 c = a + b;
    require(c >= a, "SafeMath: addition overflow");

    return c;
  }

  /**
   * @dev Returns the subtraction of two unsigned integers, reverting on
   * overflow (when the result is negative).
   *
   * Counterpart to Solidity's `-` operator.
   *
   * Requirements:
   *
   * - Subtraction cannot overflow.
   */
  function sub(uint256 a, uint256 b) internal pure returns(uint256) {
    return sub(a, b, "SafeMath: subtraction overflow");
  }

  /**
   * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
   * overflow (when the result is negative).
   *
   * Counterpart to Solidity's `-` operator.
   *
   * Requirements:
   *
   * - Subtraction cannot overflow.
   */
  function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns(uint256) {
    require(b <= a, errorMessage);
    uint256 c = a - b;

    return c;
  }

  /**
   * @dev Returns the multiplication of two unsigned integers, reverting on
   * overflow.
   *
   * Counterpart to Solidity's `*` operator.
   *
   * Requirements:
   *
   * - Multiplication cannot overflow.
   */
  function mul(uint256 a, uint256 b) internal pure returns(uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
  }

  /**
   * @dev Returns the integer division of two unsigned integers. Reverts on
   * division by zero. The result is rounded towards zero.
   *
   * Counterpart to Solidity's `/` operator. Note: this function uses a
   * `revert` opcode (which leaves remaining gas untouched) while Solidity
   * uses an invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   *
   * - The divisor cannot be zero.
   */
  function div(uint256 a, uint256 b) internal pure returns(uint256) {
    return div(a, b, "SafeMath: division by zero");
  }

  /**
   * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
   * division by zero. The result is rounded towards zero.
   *
   * Counterpart to Solidity's `/` operator. Note: this function uses a
   * `revert` opcode (which leaves remaining gas untouched) while Solidity
   * uses an invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   *
   * - The divisor cannot be zero.
   */
  function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns(uint256) {
    require(b > 0, errorMessage);
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
   * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
   * Reverts when dividing by zero.
   *
   * Counterpart to Solidity's `%` operator. This function uses a `revert`
   * opcode (which leaves remaining gas untouched) while Solidity uses an
   * invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   *
   * - The divisor cannot be zero.
   */
  function mod(uint256 a, uint256 b) internal pure returns(uint256) {
    return mod(a, b, "SafeMath: modulo by zero");
  }

  /**
   * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
   * Reverts with custom message when dividing by zero.
   *
   * Counterpart to Solidity's `%` operator. This function uses a `revert`
   * opcode (which leaves remaining gas untouched) while Solidity uses an
   * invalid opcode to revert (consuming all remaining gas).
   *
   * Requirements:
   *
   * - The divisor cannot be zero.
   */
  function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns(uint256) {
    require(b != 0, errorMessage);
    return a % b;
  }
}

contract Counfties is Context, Ownable {
  using SafeMath
  for uint256;

  struct Country {
    uint256 price;
    string message;
    address owner;
    string id;
  }

  mapping(string => Country) countries;

  struct leaderboardCountry {
    uint256 price;
    string country;
  }
  leaderboardCountry[5] topCountriesPrice;

  uint256 highest;
  uint256 feeBalance;

  constructor() public {
    topCountriesPrice[0].country = "N/A";
    topCountriesPrice[1].country = "N/A";
    topCountriesPrice[2].country = "N/A";
    topCountriesPrice[3].country = "N/A";
    topCountriesPrice[4].country = "N/A";
  }

  function buyCountry(string memory _country, string memory _message) public payable {
    require(bytes(_message).length <= 140, "Message must be under 140 characters");
    if (countries[_country].price > 0) {
      require(msg.value == countries[_country].price, "Too much money send");
      uint256 transferAmount = countries[_country].price;
      payable(countries[_country].owner).transfer(transferAmount.mul(110).div(120));
      uint256 feeAmount = countries[_country].price;
      feeBalance = feeBalance.add(feeAmount.mul(10).div(120));
    } else {
      require(msg.value == 0.01 ether, "Not enough BNB send");
      feeBalance = feeBalance.add(10000000000000000);
    }

    countries[_country].price = msg.value.mul(120).div(100);
    countries[_country].owner = msg.sender;
    countries[_country].message = _message;
    countries[_country].id = _country;
    addPrice(_country);
    if (countries[_country].price > highest) {
      highest = countries[_country].price;
    }
  }

  function addPrice(string memory _country) internal {
    uint listingNr = 0;
    for (uint i = 4; i > 0; i--) {
      string memory otherCountry = topCountriesPrice[i].country;
      if (compareStrings(otherCountry, _country)) {
        listingNr = i;
        break;
      }
    }

    uint256 price = countries[_country].price;
    for (uint i = 4; i > 0; i--) {
      if (price > topCountriesPrice[i].price ) {
        leaderboardCountry memory info;
        info.price = price;
        info.country = _country;
        topCountriesPrice[listingNr] = info;

        bool swapped;
        uint k;
        uint j;
        uint n = topCountriesPrice.length;
        for (k = 0; k < n - 1; k++) {
          swapped = false;
          for (j = 0; j < n - k - 1; j++) {
            if (topCountriesPrice[j].price > topCountriesPrice[j + 1].price) {
              (topCountriesPrice[j].price, topCountriesPrice[j + 1].price) = (topCountriesPrice[j + 1].price, topCountriesPrice[j].price);
              string memory nextCountry = topCountriesPrice[j + 1].country;
              topCountriesPrice[j + 1].country = topCountriesPrice[j].country;
              topCountriesPrice[j].country = nextCountry;
              swapped = true;
            }
          }
          if (swapped == false) break;
        }

        return;
      }
    }
  }

  function compareStrings(string memory a, string memory b) public view returns(bool) {
    return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));
  }

  function giveCountry(string memory _country, address _target, string memory _message) public onlyOwner {
    require(countries[_country].price == 0, "This country has been bought already");
    countries[_country].price = 12000000000000000;
    countries[_country].owner = _target;
    countries[_country].message = _message;
    addPrice(_country);
  }

  function getTopCountriesPrices() public view returns(leaderboardCountry[5] memory) {
    return topCountriesPrice;
  }

  function getMessage(string memory _country) public view returns(string memory) {
    return countries[_country].message;
  }

  function getHighestPrice() public view returns(uint256) {
    return highest;
  }

  function getCountryOwner(string memory _country) public view returns(address) {
    return countries[_country].owner;
  }

  function getValueOfCountry(string memory _country) public view returns(uint256) {
    return countries[_country].price;
  }

  function getBalance() public view returns(uint256) {
    return feeBalance;
  }

  function withdrawBNB() onlyOwner public {
    payable(owner()).transfer(feeBalance);
    feeBalance = 0;
  }

}```

Hi, welcome to the community! :wave:

I think if you search more and then you will know how to do this, you can change the function buyCountry like this:

function buyCountry(string memory _country, string memory _message) public {
    xxx; // Your Logic
   token.transferFrom(msg.sender, address(this), Transfer_Amount);
}

And of course, you can update this function, such as add a modifier nonReentrant, use the library SafeERC20.

1 Like