TypeError: fundMe.getPriceFeed is not a function #1672
Answered
by
alymurtazamemon
Nurnberg-Meistersinger
asked this question in
Q&A
-
DescriptionHey guys, I have a problem with passing the very first unit test from Lesson 7. Any ideas how to solve it? Error
FundMe
constructor
1) Sets the aggregator addresses correctly
fund
✔ Fails if you don't send enough ETH (155ms)
✔ Updates the amount funded data structure (85ms)
✔ Adds funder to array of funders (56ms)
withdraw
✔ withdraws ETH from a single funder
GasCost: 101632715842288
GasUsed: 77744
GasPrice: 1307274077
✔ Allows to withdraw with multiple funders (322ms)
5 passing (2s)
1 failing
1) FundMe
constructor
Sets the aggregator addresses correctly:
TypeError: fundMe.getPriceFeed is not a function
at Context.<anonymous> (test/Unit/FundMe.test.js:24:49)
at processImmediate (node:internal/timers:471:21) FundMe.sol pragma solidity ^0.8.7;
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "./PriceConverter.sol";
contract FundMe {
using PriceConverter for uint256;
uint256 public constant minimumUsd = 50 * 10**18;
address private immutable i_owner;
address[] private s_funders;
mapping(address => uint256) private s_addressToAmountFunded;
AggregatorV3Interface private s_priceFeed;
modifier onlyOwner() {
require(msg.sender == i_owner);
_;
}
constructor(address priceFeed) {
s_priceFeed = AggregatorV3Interface(priceFeed);
i_owner = msg.sender;
}
receive() external payable {
fund();
}
fallback() external payable {
fund();
}
function fund() public payable {
require(
msg.value.getConversionRate(s_priceFeed) >= minimumUsd,
"You need to send more ETH!"
);
s_addressToAmountFunded[msg.sender] += msg.value;
s_funders.push(msg.sender);
}
function withdraw() public onlyOwner {
for (
uint256 funderIndex = 0;
funderIndex < s_funders.length;
funderIndex++
) {
address funder = s_funders[funderIndex];
s_addressToAmountFunded[funder] = 0;
}
s_funders = new address[](0);
(bool success, ) = i_owner.call{value: address(this).balance}("");
require(success, "Call failed!");
}
function cheaperWithdraw() public onlyOwner {
address[] memory funders = s_funders;
for (
uint256 funderIndex = 0;
funderIndex < funders.length;
funderIndex++
) {
address funder = funders[funderIndex];
s_addressToAmountFunded[funder] = 0;
}
s_funders = new address[](0);
(bool success, ) = i_owner.call{value: address(this).balance}("");
require(success);
}
function getAddressToAmountFunded(address fundingAddress)
public
view
returns (uint256)
{
return s_addressToAmountFunded[fundingAddress];
}
function getVersion() public view returns (uint256) {
return s_priceFeed.version();
}
function getFunder(uint256 index) public view returns (address) {
return s_funders[index];
}
function getOwner() public view returns (address) {
return i_owner;
}
function viewBalance() public view returns (uint256) {
uint256 _contractBalance = address(this).balance;
return _contractBalance;
}
} FundMe.test.jsconst { assert, expect } = require("chai")
const { network, deployments, ethers } = require("hardhat")
const { developmentChains } = require("../../helper-hardhat-config")
!developmentChains.includes(network.name)
? describe.skip
: describe("FundMe", function () {
let fundMe
let mockV3Aggregator
let deployer
const sendValue = ethers.utils.parseEther("1")
beforeEach(async () => {
deployer = (await getNamedAccounts()).deployer
await deployments.fixture(["all"])
fundMe = await ethers.getContract("FundMe", deployer)
mockV3Aggregator = await ethers.getContract(
"MockV3Aggregator",
deployer
)
})
describe("constructor", function () {
it("Sets the aggregator addresses correctly", async () => {
const response = await fundMe.getPriceFeed()
assert.equal(response, mockV3Aggregator.address)
})
})
describe("fund", function () {
// https://ethereum-waffle.readthedocs.io/en/latest/matchers.html
// could also do assert.fail
it("Fails if you don't send enough ETH", async () => {
await expect(fundMe.fund()).to.be.revertedWith(
"You need to send more ETH!"
)
})
// we could be even more precise here by making sure exactly $50 works
// but this is good enough for now
it("Updates the amount funded data structure", async () => {
await fundMe.fund({ value: sendValue })
const response = await fundMe.getAddressToAmountFunded(
deployer
)
assert.equal(response.toString(), sendValue.toString())
})
it("Adds funder to array of funders", async () => {
await fundMe.fund({ value: sendValue })
const response = await fundMe.getFunder(0)
assert.equal(response, deployer)
})
})
describe("withdraw", function () {
beforeEach(async () => {
await fundMe.fund({ value: sendValue })
})
it("withdraws ETH from a single funder", async () => {
// Arrange
const startingFundMeBalance =
await fundMe.provider.getBalance(fundMe.address)
const startingDeployerBalance =
await fundMe.provider.getBalance(deployer)
// Act
const transactionResponse = await fundMe.withdraw()
const transactionReceipt = await transactionResponse.wait()
const { gasUsed, effectiveGasPrice } = transactionReceipt
const gasCost = gasUsed.mul(effectiveGasPrice)
const endingFundMeBalance = await fundMe.provider.getBalance(
fundMe.address
)
const endingDeployerBalance =
await fundMe.provider.getBalance(deployer)
// Assert
// Maybe clean up to understand the testing
assert.equal(endingFundMeBalance, 0)
assert.equal(
startingFundMeBalance
.add(startingDeployerBalance)
.toString(),
endingDeployerBalance.add(gasCost).toString()
)
})
// this test is overloaded. Ideally we'd split it into multiple tests
// but for simplicity we left it as one
it("Allows to withdraw with multiple funders", async () => {
// Arrange
const accounts = await ethers.getSigners()
for (i = 1; i < 6; i++) {
const fundMeConnectedContract = await fundMe.connect(
accounts[i]
)
await fundMeConnectedContract.fund({ value: sendValue })
}
const startingFundMeBalance =
await fundMe.provider.getBalance(fundMe.address)
const startingDeployerBalance =
await fundMe.provider.getBalance(deployer)
// Act
const transactionResponse = await fundMe.cheaperWithdraw()
// Let's comapre gas costs :)
// const transactionResponse = await fundMe.withdraw()
const transactionReceipt = await transactionResponse.wait()
const { gasUsed, effectiveGasPrice } = transactionReceipt
const withdrawGasCost = gasUsed.mul(effectiveGasPrice)
console.log(`GasCost: ${withdrawGasCost}`)
console.log(`GasUsed: ${gasUsed}`)
console.log(`GasPrice: ${effectiveGasPrice}`)
const endingFundMeBalance = await fundMe.provider.getBalance(
fundMe.address
)
const endingDeployerBalance =
await fundMe.provider.getBalance(deployer)
// Assert
assert.equal(
startingFundMeBalance
.add(startingDeployerBalance)
.toString(),
endingDeployerBalance.add(withdrawGasCost).toString()
)
// Make a getter for storage variables
await expect(fundMe.getFunder(0)).to.be.reverted
for (i = 1; i < 6; i++) {
assert.equal(
await fundMe.getAddressToAmountFunded(
accounts[i].address
),
0
)
}
})
// this test is required while using custom error in
// FundMe.sol ->
// 1) error FundMe_NotOwner
// 2) if (msg.sender != i_owner) revert FundMe__NotOwner();
/*it("Only allows the owner to withdraw", async function () {
const accounts = await ethers.getSigners()
const fundMeConnectedContract = await fundMe.connect(
accounts[1]
)
await expect(
fundMeConnectedContract.withdraw()
).to.be.revertedWithCustomError(fundMe, "FundMe__NotOwner")
})*/
})
}) |
Beta Was this translation helpful? Give feedback.
Answered by
alymurtazamemon
Aug 10, 2022
Replies: 2 comments 6 replies
-
Add this function at the bottom of your FundMe contract.
|
Beta Was this translation helpful? Give feedback.
5 replies
-
@Nurnberg-Meistersinger Did you remove the artifacts and cache folders after doing changes that @othaime-en mentioned above? |
Beta Was this translation helpful? Give feedback.
1 reply
Answer selected by
Nurnberg-Meistersinger
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@Nurnberg-Meistersinger Did you remove the artifacts and cache folders after doing changes that @othaime-en mentioned above?