Lesson 15: Error: VM Exception while processing transaction: reverted with custom error 'NftMarketplace__NoProceeds()' #2484
-
😭 VM Exception while processing transaction: reverted with custom error 'NftMarketplace__NoProceeds()'Hi, I have problems when running a test that should revert. I am getting Error: Can anyone who has this problem solved share his/hers package.json? Here is the Github repo./**
* Code from the test:
* Tried both methods for testing if the code reverts (both not working
*/
describe("Withdraw Proceeds", () => {
it("Should revert with NoProceeds if the amount of the money for the address <=0", async () => {
expect(await nftMarketplace.withdrawProceeds()).to.be.revertedWithCustomError(
"NftMarketplace__NoProceeds"
)
})
it("Should revert with NoProceeds if the amount of the money for the address <=0 Pt2", async () => {
expect(await nftMarketplace.withdrawProceeds()).to.be.revertedWith(
"NftMarketplace__NoProceeds"
)
})
}) //SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
error NftMarketplace__PriceMustBeAboveZero();
error NftMarketplace__NotApprovedForMarletplace();
error NftMarketplace__AlreadyListed(address nftAddress, uint256 tokenId);
error NftMarketplace__NotOwner();
error NftMarketplace__NotListed(address nftAddress, uint256 tokenId);
error NftMarketplace__PriceNotMet(address nftAddress, uint256 tokenId, uint256 price);
error NftMarketplace__NoProceeds();
error NftMarketplace__TransferFailed();
contract NftMarketplace is ReentrancyGuard {
struct Listing {
uint256 price;
address seller;
}
event ItemListed(
address indexed seller,
address indexed nftAddress,
uint256 indexed tokenId,
uint256 price
);
event ItemBought(
address indexed buyer,
address indexed nftAddress,
uint256 indexed tokenId,
uint256 price
);
event ItemCanceled(address indexed seller, address indexed nftAddress, uint256 indexed tokenId);
//NFT Contract address -> NFT TokenID -> Listing
mapping(address => mapping(uint256 => Listing)) private s_listings;
//Seller address -> Amount earned
mapping(address => uint256) private s_proceeds;
//Modifiers
modifier notListed(
address nftAddress,
uint256 tokenId,
address owner
) {
Listing memory listing = s_listings[nftAddress][tokenId];
if (listing.price > 0) {
revert NftMarketplace__AlreadyListed(nftAddress, tokenId);
}
_;
}
modifier isOwner(
address nftAddress,
uint256 tokenId,
address spender
) {
IERC721 nft = IERC721(nftAddress);
address owner = nft.ownerOf(tokenId);
if (owner != spender) {
revert NftMarketplace__NotOwner();
}
_;
}
modifier isListed(address nftAddress, uint256 tokenId) {
Listing memory listing = s_listings[nftAddress][tokenId];
if (listing.price <= 0) {
revert NftMarketplace__NotListed(nftAddress, tokenId);
}
_;
}
//Main Functions
/**
* @notice Method for listing your NFT on the marketplace
* @param nftAddress Address of the NFT
* @param tokenId The token id of the NFT
* @param price The sale price of the listed nft
* @dev We could have the contract be escrow for the NFTs but this way people
* can still hold their NFTs when listed
*/
function listItem(
address nftAddress,
uint256 tokenId,
uint256 price
) external notListed(nftAddress, tokenId, msg.sender) isOwner(nftAddress, tokenId, msg.sender) {
if (price <= 0) {
revert NftMarketplace__PriceMustBeAboveZero();
}
//Owners can still hold their NFT, and give the marketplace approval to sell the NFT for them.
IERC721 nft = IERC721(nftAddress);
if (nft.getApproved(tokenId) != address(this)) {
revert NftMarketplace__NotApprovedForMarletplace();
}
s_listings[nftAddress][tokenId] = Listing(price, msg.sender);
emit ItemListed(msg.sender, nftAddress, tokenId, price);
}
function buyItem(address nftAddress, uint256 tokenId)
external
payable
nonReentrant
isListed(nftAddress, tokenId)
{
Listing memory listedItem = s_listings[nftAddress][tokenId];
if (msg.value < listedItem.price) {
revert NftMarketplace__PriceNotMet(nftAddress, tokenId, listedItem.price);
}
//We don't just send the money to the seller
//https://fravoll.github.io/solidity-patterns/pull_over_push.html
//Sending the money to the user ❌
//Have the users withdraw their money ✅
s_proceeds[listedItem.seller] = s_proceeds[listedItem.seller] + msg.value;
//Remove the nft from the marketplace
delete (s_listings[nftAddress][tokenId]);
//Transfer the nft to the buyer
IERC721(nftAddress).safeTransferFrom(listedItem.seller, msg.sender, tokenId);
emit ItemBought(msg.sender, nftAddress, tokenId, listedItem.price);
}
function cancelListing(address nftAddress, uint256 tokenId)
external
isOwner(nftAddress, tokenId, msg.sender)
isListed(nftAddress, tokenId)
{
delete (s_listings[nftAddress][tokenId]);
emit ItemCanceled(msg.sender, nftAddress, tokenId);
}
function updateListing(
address nftAddress,
uint256 tokenId,
uint256 newPrice
) external isListed(nftAddress, tokenId) isOwner(nftAddress, tokenId, msg.sender) {
s_listings[nftAddress][tokenId].price = newPrice;
emit ItemListed(msg.sender, nftAddress, tokenId, newPrice);
}
function withdrawProceeds() external {
uint256 proceeds = s_proceeds[msg.sender];
if (proceeds <= 0) {
revert NftMarketplace__NoProceeds();
}
s_proceeds[msg.sender] = 0;
(bool success, ) = payable(msg.sender).call{value: proceeds}("");
if (!success) {
revert NftMarketplace__TransferFailed();
}
}
function getListing(address nftAddress, uint256 tokenId)
external
view
returns (Listing memory)
{
return s_listings[nftAddress][tokenId];
}
function getProceeds(address seller) external view returns (uint256) {
return s_proceeds[seller];
}
}
{
"name": "hardhat-starter-kit",
"version": "1.0.0",
"description": "",
"scripts": {
"compile": "hardhat compile",
"test": "hardhat test test/unit/*_test.js --network hardhat",
"test-staging": "hardhat test test/staging/*_test.js --network rinkeby",
"lint": "solhint 'contracts/*.sol'",
"lint:fix": "solhint 'contracts/**/*.sol' --fix",
"format": "prettier --write .",
"coverage": "hardhat coverage --solcoverjs ./.solcover.js",
"fuzzing": "docker run -it --rm -v $PWD:/src trailofbits/eth-security-toolbox"
},
"license": "MIT",
"devDependencies": {
"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers@^0.3.0-beta.13",
"@nomiclabs/hardhat-etherscan": "^3.0.0",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@pinata/sdk": "^1.1.26",
"base64-sol": "^1.1.0",
"chai": "^4.3.4",
"ethereum-waffle": "^3.4.0",
"ethers": "^5.5.1",
"hardhat": "^2.9.0",
"hardhat-contract-sizer": "^2.4.0",
"hardhat-deploy": "^0.9.29",
"hardhat-gas-reporter": "^1.0.7",
"path": "^0.12.7",
"prettier": "^2.4.1",
"prettier-plugin-solidity": "^1.0.0-beta.19",
"solhint": "^3.3.6",
"solidity-coverage": "^0.7.13"
},
"dependencies": {
"@appliedblockchain/chainlink-contracts": "0.0.4",
"@appliedblockchain/chainlink-plugins-fund-link": "0.0.1",
"@chainlink/contracts": "^0.4.1",
"@chainlink/test-helpers": "^0.0.7-alpha",
"@chainlink/token": "^1.1.0",
"@openzeppelin/contracts": "^4.7.3",
"babel-eslint": "^10.1.0",
"dotenv": "^10.0.0"
},
"mocha": {
"timeout": 10000000
}
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 3 replies
-
Hey @boringslav as a start, add an |
Beta Was this translation helpful? Give feedback.
-
It seems you have to add |
Beta Was this translation helpful? Give feedback.
Hey @boringslav as a start, add an
await
before yourexpect
statements.