Description
I'm making NFT marketplace and there are smart contract and frontend
I'll call NFT mint and NFT CreateSale for sale and then I'll buy that NFT.
I tried with metamask and immutable passport wallet for testing.
On metamask, it worked well but on immutable passport, it shows this error.
Error: transaction execution reverted (action="sendTransaction", data=null, reason=null, invocation=null, revert=null, transaction={ "data": "", "from": "0xDF3569B056b5CA0bf38952353dc402326ABDb68c", "to": "0x8CC5B4748cBf9810Be73A90b0CB6802EBae06B59" }, receipt={ "_type": "TransactionReceipt", "blobGasPrice": null, "blobGasUsed": null, "blockHash": "0x35fbfa36dd03ac565033172f2da2322f71f5075909d8286aa5acbd10ed7961ca", "blockNumber": 24037913, "contractAddress": null, "cumulativeGasUsed": "60790", "from": "0xDF3569B056b5CA0bf38952353dc402326ABDb68c", "gasPrice": "10000000049", "gasUsed": "60790", "hash": "0x5533cf6cf93efa0de2659fef5e6d39d0332f6c9dfb115ee26bbf9eea2910558f", "index": 0, "logs": [ ], "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", "root": null, "status": 0, "to": "0x8CC5B4748cBf9810Be73A90b0CB6802EBae06B59" }, code=CALL_EXCEPTION, version=6.14.0)
at makeError (webpack-internal:///(app-pages-browser)/./node_modules/ethers/lib.esm/utils/errors.js:137:21)
at assert (webpack-internal:///(app-pages-browser)/./node_modules/ethers/lib.esm/utils/errors.js:156:15)
at checkReceipt (webpack-internal:///(app-pages-browser)/./node_modules/ethers/lib.esm/providers/provider.js:1141:68)
at BrowserProvider.txListener (webpack-internal:///(app-pages-browser)/./node_modules/ethers/lib.esm/providers/provider.js:1187:33)
I've got this error when buy
here is smart contract code
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.27;
import "@openzeppelin/contracts/interfaces/IERC721.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "./interfaces/IWOMs.sol";
contract WOMsMarketplace is
OwnableUpgradeable,
ReentrancyGuardUpgradeable,
IERC721Receiver,
UUPSUpgradeable
{
uint256 private platformFee;
address private feeRecipient;
struct ListNFT {
address nft;
uint256 tokenId;
address seller;
uint256 price;
uint256 royaltyFee;
address royaltyRecipient;
uint256 date;
}
// nft => tokenId => list struct
mapping(address => mapping(uint256 => ListNFT)) private listNfts;
// events
event ListedNFT(
address indexed nft,
uint256 indexed tokenId,
uint256 price,
uint256 date,
address indexed seller,
uint256 royaltyFee,
address royaltyRecipient
);
event BoughtNFT(
address indexed nft,
uint256 indexed tokenId,
uint256 price,
uint256 date,
address seller,
address indexed buyer,
uint256 royaltyFee,
address royaltyRecipient
);
function initialize(
uint256 _platformFee,
address _feeRecipient
) public initializer {
__Ownable_init(msg.sender);
__ReentrancyGuard_init();
require(_platformFee <= 1000, "can't more than 10 percent");
platformFee = _platformFee;
feeRecipient = _feeRecipient;
}
modifier isListedNFT(address _nft, uint256 _tokenId) {
ListNFT memory listedNFT = listNfts[_nft][_tokenId];
require(listedNFT.seller != address(0), "not listed");
_;
}
modifier isNotListedNFT(address _nft, uint256 _tokenId) {
ListNFT memory listedNFT = listNfts[_nft][_tokenId];
require(listedNFT.seller == address(0), "already listed");
_;
}
/**
* @notice put the NFT on marketplace
* @param _nft specified NFT collection address
* @param _tokenId specified NFT id to sell
* @param _price the price of NFT
*/
function createSell(
address _nft,
uint256 _tokenId,
uint256 _price
) external isNotListedNFT(_nft, _tokenId) {
IERC721 nft = IERC721(_nft);
require(nft.ownerOf(_tokenId) == msg.sender, "not nft owner");
IWOMs WOMS_nft = IWOMs(_nft);
address royaltyRecipient = WOMS_nft.getRoyaltyRecipient();
uint256 royaltyFee = WOMS_nft.getRoyaltyFee();
listNfts[_nft][_tokenId] = ListNFT({
nft: _nft,
tokenId: _tokenId,
seller: msg.sender, // Changed to msg.sender
price: _price,
royaltyFee: royaltyFee,
royaltyRecipient: royaltyRecipient,
date: block.timestamp
});
emit ListedNFT(
_nft,
_tokenId,
_price,
block.timestamp,
msg.sender, // Changed to msg.sender
royaltyFee,
royaltyRecipient
);
}
/**
* @notice buy a NFT from marketplace
* @param _nft NFT collection address to buy
* @param _tokenId specified NFT id to buy
*/
function buy(
address _nft,
uint256 _tokenId
) external payable isListedNFT(_nft, _tokenId) {
ListNFT storage listedNft = listNfts[_nft][_tokenId];
require(msg.value >= listedNft.price, "invalid price");
uint256 totalPrice = msg.value;
IWOMs nft = IWOMs(listedNft.nft);
address royaltyRecipient = nft.getRoyaltyRecipient();
uint256 royaltyFee = nft.getRoyaltyFee();
if (royaltyFee > 0) {
uint256 royaltyTotal = calculateRoyalty(royaltyFee, msg.value);
payable(royaltyRecipient).transfer(royaltyTotal);
totalPrice -= royaltyTotal;
}
// Calculate & Transfer platform fee
uint256 platformFeeTotal = calculatePlatformFee(msg.value);
payable(feeRecipient).transfer(platformFeeTotal);
// Transfer to seller
payable(listedNft.seller).transfer(totalPrice - platformFeeTotal);
// Transfer NFT directly from seller to buyer
IERC721(listedNft.nft).safeTransferFrom(
listedNft.seller,
msg.sender,
listedNft.tokenId
);
address sender = listedNft.seller;
delete listNfts[_nft][_tokenId];
emit BoughtNFT(
_nft,
_tokenId,
msg.value,
block.timestamp,
sender,
msg.sender,
royaltyFee,
royaltyRecipient
);
}
/**
* @notice send a NFT from marketplace
* @param _nft NFT collection address to buy
* @param _tokenId specified NFT id to buy
*/
function send(address _nft, uint256 _tokenId, address getter) external {
IERC721 nft = IERC721(_nft);
require(nft.ownerOf(_tokenId) == msg.sender, "not nft owner");
// Check if the NFT is listed for sale
ListNFT storage listedNft = listNfts[_nft][_tokenId];
if (listedNft.seller != address(0)) {
// If listed, remove the listing
delete listNfts[_nft][_tokenId];
}
function calculatePlatformFee(
uint256 _price
) public view returns (uint256) {
return (_price * platformFee) / 10000;
}
function calculateRoyalty(
uint256 _royalty,
uint256 _price
) public pure returns (uint256) {
return (_price * _royalty) / 10000;
}
function getListedNFT(
address _nft,
uint256 _tokenId
) public view returns (ListNFT memory) {
return listNfts[_nft][_tokenId];
}
function updatePlatformFee(uint256 _platformFee) external onlyOwner {
require(_platformFee <= 1000, "can't more than 10 percent");
platformFee = _platformFee;
}
function changeFeeRecipient(address _feeRecipient) external onlyOwner {
require(_feeRecipient != address(0), "can't be 0 address");
feeRecipient = _feeRecipient;
}
function onERC721Received(
address,
address,
uint256,
bytes calldata
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
for frotend code,
first createSale code
let signer: ethers.Signer | null = null;
if (connectName === 'MetaMask') {
await window.ethereum.request({ method: "eth_requestAccounts" });
const provider = new ethers.BrowserProvider(window.ethereum);
signer = await provider.getSigner();
} else if (connectName === 'Immutable Passport') {
const passportProvider = await passportInstance.connectEvm();
const provider = new ethers.BrowserProvider(passportProvider);
signer = await provider.getSigner();
// Verify network
const network = await provider.getNetwork();
console.log("Connected network:", network);
}
if (signer) {
try {
// Parse the price input
const price = ethers.parseUnits(inputValue.toString(), "ether");
if (id) {
// Extract token ID from composite id
const [nftAddress, tokenId] = id.split('-');
if (!nftAddress || !tokenId) throw new Error("Invalid NFT ID");
const tokenIdNumber = parseInt(tokenId, 10); // Ensure correct base (e.g., 10 for decimal)
const NftContract = new ethers.Contract(NFTContract.address, NFTContract.abi, signer);
// Check current approval
const currentApproved = await NftContract.getApproved(tokenId);
if (currentApproved !== MarketplaceContract.address) {
const approve = await NftContract.approve(MarketplaceContract.address as 0x${string}, nft.index, {
gasLimit: 5000000, // Set a custom gas limit
});
await approve.wait();
console.log({ approve })
toast.success("Success to Approve!");
const marketplaceContract = new ethers.Contract(MarketplaceContract.address, MarketplaceContract.abi, signer);
const tx = await marketplaceContract.createSell(NFTContract.address as 0x${string},
tokenIdNumber,
price,
{
gasLimit: 5000000, // Set a custom gas limit
});
await tx.wait(); // Wait for the transaction to be mined
console.log("Transaction successful:", tx.hash);
// Update transaction and step state
setTx(tx.hash);
setIsModalOpen(true)
toast.success("Success for Sale!");
router.push('/synapCreatorProfile');
}
else {
const marketplaceContract = new ethers.Contract(MarketplaceContract.address, MarketplaceContract.abi, signer);
const tx = await marketplaceContract.createSell(NFTContract.address as 0x${string},
tokenIdNumber,
price,
address, {
gasLimit: 5000000, // Set a custom gas limit
});
await tx.wait(); // Wait for the transaction to be mined
console.log("Transaction successful:", tx.hash);
// Update transaction and step state
setTx(tx.hash);
setIsModalOpen(true)
toast.success("Success for Sale!");
router.push('/synapCreatorProfile');
}
}
} catch (error) {
console.error("Error:", error);
}
}
second buy code
let signer: ethers.Signer | null = null;
if (connectName === 'MetaMask') {
await window.ethereum.request({ method: "eth_requestAccounts" });
const provider = new ethers.BrowserProvider(window.ethereum);
signer = await provider.getSigner();
// Verify network
const network = await provider.getNetwork();
console.log("Connected network:", network);
} else if (connectName === 'Immutable Passport') {
const passportProvider = await passportInstance.connectEvm();
const provider = new ethers.BrowserProvider(passportProvider);
signer = await provider.getSigner();
// Verify network
const network = await provider.getNetwork();
console.log("Connected network:", network);
}
if (signer) {
const mintPrice = nft.listNFTs[0].price;
if (parseInt(mintPrice.toString()) >= (balance?.value ?? 0)) {
toast.error("Insufficient Balance for Purchasing");
return;
}
const contract = new ethers.Contract(MarketplaceContract.address, MarketplaceContract.abi, signer);
const tokenIdNumber = parseInt(nft.index, 10); // Ensure correct base (e.g., 10 for decimal)
const tx = await contract.buy(nft.collection, tokenIdNumber, {
value: BigInt(mintPrice),
gasLimit: 5000000, // Set a custom gas limit
});
await tx.wait();
console.log("Transaction:", tx);
// Update transaction and step state
setTx(tx.hash);
setIsModalOpen(true)
router.push('/synapCreatorProfile');
}
In the past, it worked well and after v2.
It didn't work.
Plz tell me.