0

i receive an error upon trying to interact with buy function in my contract below


// 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/ERC20.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 usdt;
    IERC20 internal teToken;

    /// 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 _usdt, IERC20 _teToken) {
        usdt = _usdt;
        teToken = _teToken;
        priceFeed = AggregatorV3Interface(
            0x0d79df66BE487753B02D015Fb622DED7f0E9798d
        );
    }

    /**
     * @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 usdt
     * @dev use chainlink Price feeds
     * @param usdPrice price of item
     * @return converted price in usdt
     */
    function getUsdtPrice(uint256 usdPrice) internal view returns (uint256) {
        // ERC20 usdtNew = ERC20(0x55d398326f99059fF775485246999027B3197955); // contract for usdt

        (, int256 price, , , ) = priceFeed.latestRoundData(); // latest price of usdt
        require(price > 0, "Invalid price feed");
        uint256 usdtPrice = uint256(price).div(1e8).mul(10 ** 18);
        uint256 priceUsd = usdPrice.mul(10 ** 18);
        uint256 priceInUsdt = priceUsd.div(usdtPrice);
        return priceInUsdt;
    }

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

    function getTePrice(uint256 usdPrice) internal pure returns (uint256) {
        uint256 tePrice = 20000000000000000;
        uint256 priceUsd = usdPrice.mul(10 ** 18);
        uint256 newPrice = priceUsd.div(tePrice);
        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 (usdt.balanceOf(msg.sender) >= price) {
            uint256 usdtTokens = getUsdtPrice(item.price);

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

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

            usdt.safeTransferFrom(msg.sender, owner(), feeAmount); // transfer funds to contract owner 
        } else if (teToken.balanceOf(msg.sender) >= price) {
            uint256 teTokens = getTePrice(item.price);

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

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

            teToken.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);
    }

    /**
     * @dev Sets Fee  Percentage
     */
    function setFeePercent(uint256 _feePercent) external onlyOwner {
        require(
            _feePercent >= 0 && _feePercent <= 100,
            "Invalid fee percentage: fee percentage should be between 1 and 99"
        );
        feePercentage = _feePercent;
    }

    function getFeePercentage() external view returns (uint256) {
        return feePercentage;
    }
}

i get an error while using remix idle

Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
VM Exception while processing transaction: revert

teToken is a custom token i created for testing purposes. below is the contract

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

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

contract TE is ERC20 {
    uint256 public constant INITIAL_SUPPLY = 1000000 * 10 ** 18; // Total supply of 1 million tokens

    constructor() ERC20("TE", "TE") {
        _mint(msg.sender, INITIAL_SUPPLY);
    }

}

1 Answer 1

0

I realized where the problem was coming from.. it is the if...else statement in the buy function that was causing the spike in gas estimates. So i created two functions that were to allow transferring of the token to the item seller and contract owner

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.