I am writing a contract to addReviewProduct however I cannot getReviewProduct and get the error Error: call revert exception [ See: https://links.ethers.org/v5-errors-CALL_EXCEPTION ]
SmartContract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ReviewContract {
uint256 public reviewCount;
mapping(uint256 => Review) public reviews;
event ReviewAdded(
uint256 indexed reviewId,
address indexed reviewer,
uint256 indexed productId,
uint256 rating,
string content
);
struct Review {
address reviewer;
uint256 productId;
uint256 rating;
string content;
}
function addReview(
uint256 _productId,
uint256 _rating,
string memory _content
) external {
require(bytes(_content).length > 0, "Review content cannot be empty");
require(_rating >= 1 && _rating <= 5, "Rating must be between 1 and 5");
reviewCount++;
reviews[reviewCount] = Review(
msg.sender,
_productId,
_rating,
_content
);
emit ReviewAdded(
reviewCount,
msg.sender,
_productId,
_rating,
_content
);
}
function getReviewsByProductId(
uint256 _productId
) external view returns (Review[] memory) {
uint256 count = 0;
// Đếm số lượng đánh giá thuộc về sản phẩm
for (uint256 i = 1; i <= reviewCount; i++) {
if (reviews[i].productId == _productId) {
count++;
}
}
// Tạo mảng để lưu trữ đánh giá thuộc về sản phẩm
Review[] memory productReviews = new Review[](count);
uint256 index = 0;
// Lặp lại và lưu trữ đánh giá thuộc về sản phẩm vào mảng
for (uint256 i = 1; i <= reviewCount; i++) {
if (reviews[i].productId == _productId) {
productReviews[index] = reviews[i];
index++;
}
}
return productReviews;
}
}
ABI :
"abi": [
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "uint256",
"name": "reviewId",
"type": "uint256"
},
{
"indexed": true,
"internalType": "address",
"name": "reviewer",
"type": "address"
},
{
"indexed": true,
"internalType": "uint256",
"name": "productId",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "rating",
"type": "uint256"
},
{
"indexed": false,
"internalType": "string",
"name": "content",
"type": "string"
}
],
"name": "ReviewAdded",
"type": "event"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_productId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "_rating",
"type": "uint256"
},
{
"internalType": "string",
"name": "_content",
"type": "string"
}
],
"name": "addReview",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "_productId",
"type": "uint256"
}
],
"name": "getReviewsByProductId",
"outputs": [
{
"components": [
{
"internalType": "address",
"name": "reviewer",
"type": "address"
},
{
"internalType": "uint256",
"name": "productId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "rating",
"type": "uint256"
},
{
"internalType": "string",
"name": "content",
"type": "string"
}
],
"internalType": "struct ReviewContract.Review[]",
"name": "",
"type": "tuple[]"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "reviewCount",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "reviews",
"outputs": [
{
"internalType": "address",
"name": "reviewer",
"type": "address"
},
{
"internalType": "uint256",
"name": "productId",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "rating",
"type": "uint256"
},
{
"internalType": "string",
"name": "content",
"type": "string"
}
],
"stateMutability": "view",
"type": "function"
}
],
Component:
import React, { useState, useEffect } from "react";
import { ethers } from "ethers";
import Web3Modal from "web3modal";
import { Address, ABI } from "./constants";
const ReviewComponent = () => {
const [reviews, setReviews] = useState([]);
const [rating, setRating] = useState(0);
const [content, setContent] = useState("");
const id = 7;
// const provider = new ethers.providers.JsonRpcProvider('https://data-seed-prebsc-1-s1.binance.org:8545/');
// const contract = new ethers.Contract(Address, ABI, provider);
const handleAddReview = async () => {
try {
const web3Modal = new Web3Modal();
const connection = await web3Modal.connect();
const provider = new ethers.providers.Web3Provider(connection);
const signer = provider.getSigner();
const contract = new ethers.Contract(Address, ABI, signer);
// Gọi hàm addReview trong smart contract để thêm đánh giá mới
// const test = await contract.addReview(id, rating, content); // 1 là id sản phẩm, thay đổi tùy thuộc vào yêu cầu của smart contract
// console.log(test);
const transaction = await contract.addReview(id, rating, content);
console.log("Transaction Hash:", transaction.hash);
// Lấy receipt để kiểm tra trạng thái của giao dịch
const receipt = await transaction.wait();
console.log("Transaction Receipt:", receipt);
const status = receipt.status;
if (status === 1) {
console.log("Review added successfully!");
const event = receipt.events.find((e) => e.event === "ReviewAdded");
if (event) {
const { reviewId, reviewer, productId, rating, content } = event.args;
console.log("Review Details:", {
reviewId,
reviewer,
productId,
rating,
content,
});
// Hiển thị đánh giá mới thêm vào
setReviews([...reviews, { reviewId, reviewer, productId, rating, content }]);
}
} else {
console.error("Review addition failed. Status: ", status);
}
} catch (error) {
console.error("Error adding review:", error.message);
}
};
const fetchReviews = async () => {
try {
const web3Modal = new Web3Modal();
const connection = await web3Modal.connect();
const provider = new ethers.providers.Web3Provider(connection);
const contract = new ethers.Contract(Address, ABI, provider);
// Gọi hàm getProductReviews trong smart contract để lấy danh sách đánh giá theo ID sản phẩm
const productReviewsIndexes = await contract.getReviewsByProductId(7, { gasLimit: 300000 });
console.log(productReviewsIndexes);
// Lặp qua chỉ số đánh giá và gọi hàm getReview để lấy thông tin chi tiết
} catch (error) {
console.error("Error getting product reviews:", error.message);
}
};
// ... (các phần khác của component)
return (
<div>
<h2>Product Reviews</h2>
<div>
<label>Rating:</label>
<input type="number" min="1" max="5" value={rating} onChange={(e) => setRating(e.target.value)} />
</div>
<div>
<label>Review:</label>
<textarea value={content} onChange={(e) => setContent(e.target.value)} />
</div>
<button onClick={handleAddReview}>Add Review</button><br />
<button onClick={fetchReviews}>Get Review</button>
<div>
{reviews?.map((review, index) => (
<div key={index}>
<p>Rating: {review.rating}</p>
<p>Content: {review.content}</p>
</div>
))}
</div>
</div>
);
};
export default ReviewComponent;
Config :
module.exports = {
networks: {
bsc: { // Đặt tên mạng là bscTestnet hoặc bất kỳ tên nào bạn muốn
url: "https://data-seed-prebsc-1-s1.binance.org:8545/", // URL của BSC testnet
accounts: [privateKey],
},
},
solidity: "0.8.19",
};
i am deploying on bsc testnet
Please show me where I'm wrong and help me write the getReview function