0
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract Market is Ownable {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    AggregatorV3Interface internal priceFeed;

    struct Item {
        bytes32 id; // unique id of the item
        string name; // name of item
        uint256 price; // price of item
        bool isSold; //
        address payable seller; // seller / owner of item
        address payable buyer; // buyer of the item
    }

    mapping(bytes32 => Item) internal items; // mapping of items
    bytes32[] internal itemIds; // mapping of the unique ids of the items

    uint256 internal itemIndex; // counter
    uint256 internal feePercentage = 10; // default fee precentage

    IERC20 internal tekToken;

    /// events
    event ItemListed(bytes32 id, string name, uint256 price, address seller);
    event ItemSold(
        bytes32 id,
        string name,
        uint256 price,
        address seller,
        address buyer
    );

    constructor( IERC20 _tekToken) {
        tekToken = _teToken;
    
    }

    /**
     * @notice unique id genrator function
     * @param to  address  of the  item owner
     * @param count  counter
     */
    function generateId(
        address to,
        uint256 count
    ) internal view returns (bytes32) {
        return keccak256(abi.encode(address(this), to, count));
    }

    /**
     * @notice function that lists an item
     * @param _name  name of item
     * @param _price  price of item
     */
    function listItem(string memory _name, uint256 _price) external {
        require(bytes(_name).length > 0, "Item name cannot be empty");
        require(_price > 0, "Item price must be greater than 0");
        bytes32 itemId = generateId(msg.sender, itemIndex); // generate unique id
        require(items[itemId].id == 0, "Item already exists");

        items[itemId] = Item({
            id: itemId,
            name: _name,
            price: _price,
            isSold: false,
            seller: payable(msg.sender),
            buyer: payable(address(0))
        });
        itemIds.push(itemId); //creating item
        emit ItemListed(
            generateId(msg.sender, itemIndex),
            _name,
            _price,
            payable(msg.sender)
        );
        itemIndex++; // incrementing itemIndex
    }

    

    /**
     * @notice function that converts price of item to $TE
     * @dev use API call to coinmarketcap to get price
     * @param usdPrice price of item
     * @return converted price in $TE
     */

    function getTeTokenPrice(uint256 usdPrice) internal pure returns (uint256) {
        uint256 teTokenPrice = 20000000000000000;
        uint256 priceUsd = usdPrice.mul(10 ** 18);
        uint256 newPrice = priceUsd.div(teTokenPrice);
        return newPrice;
    }


    /**
     * @notice function to buy an item
     * @param id  unique id for the item
     */
    function buyItem(bytes32 id) external {
        Item storage item = items[id];
        require(item.id != 0, "Item does not exist");
        require(!item.isSold, "Item is already Purchased");

        item.buyer = payable(msg.sender);

        uint256 price= item.price.mul(10**18);

        if (tekToken.balanceOf(msg.sender) >= price) {
            uint256 teTokens = getTeTokenPrice(item.price);

            uint256 feeAmount = teTokens.mul(feePercentage).div(100);

            tekToken.safeTransferFrom(
                msg.sender,
                item.seller,
                teTokens.sub(feeAmount)
            ); // transfer funds to seller account

            tekToken.safeTransferFrom(msg.sender, owner(), feeAmount); // transfer funds to contract owner
        } else {
            revert("Insufficient funds or wrong payment method");
        }

        emit ItemSold(id, item.name, item.price, item.seller, item.buyer);
        item.isSold = true;
        item.seller = item.buyer;
    }

    /**
     * @dev : return all unique ids for the items
     */
    function getAllItemIds() external view returns (bytes32[] memory) {
        return itemIds;
    }

    /**
     * @dev returning an item based on the unique id
     * @param itemId  unique id for the item
     */
    function getItem(
        bytes32 itemId
    ) external view returns (string memory name, uint256 price, bool sold, address seller, address buyer) {
        Item storage item = items[itemId];
        require(item.id != 0, "Item does not exist");
        return (item.name, item.price, item.isSold, item.seller, item.buyer);
    }

  

  
}

I have the contract above . am facing an error of insufficient allowance when I try to buy the item using the tek token. How would I add the approval of TEK tokens to my contract to allow the contract to spend a given number of tek tokens on behalf of the TEKToken contract?

NB: tek token is a test token so it can be any token

1 Answer 1

0

From your code what I understood is that you want to access tek token from your contract when user is calling the buyItem function. You can achieve this using two methods.

  1. approve Your contract code manually using calling you tek token's approve methods using remix, or any external framework.
  2. Approving your contract and calling tek ERC20 approve methods within your contract.

For seconds approach you can do that by,

tekToken.approve(address(this), _amount);

in your buyItem function.

You can use this depending on your situation.

1
  • i tried this and it didn't work
    – kaay
    Commented May 24, 2023 at 6:47

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.