// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {console} from "forge-std/console.sol"; import {Test} from "forge-std/Test.sol"; import {FundMe} from "../../src/FundMe.sol"; import {DeployFundMe} from "../../script/DeployFundMe.s.sol"; contract FundMeTest is Test { FundMe fundMe; address USER = makeAddr("user"); uint256 constant SEND_VALUE = 0.1 ether; uint256 constant STARTING_BALANCE = 10 ether; // uint256 constant GAS_PRICE = 1; function setUp() external { // fundMe = new FundMe(0x694AA1769357215DE4FAC081bf1f309aDC325306); DeployFundMe deployFundMe = new DeployFundMe(); fundMe = deployFundMe.run(); vm.deal(USER, STARTING_BALANCE); } function testMinimumDollarIsFive() public view { assertEq(fundMe.MINIMUM_USD(), 5e18); } function testOwnerIsMsgSender() public view { assertEq(fundMe.getOwner(), msg.sender); } function testPriceFeedVersionIsAccurate() public view { uint256 version = fundMe.getVersion(); assertEq(version, 4); } function testFundFailsWithoutEnoughETH() public { vm.expectRevert(); fundMe.fund(); } function testFundUpdatesFundedDataStructure() public { vm.prank(USER); // the next tx will be sent by USER fundMe.fund{value: SEND_VALUE}(); uint256 amountFunded = fundMe.getAddressToAmountFunded(USER); assertEq(amountFunded, SEND_VALUE); } function testAddsFunderToArrayOfFunders() public { vm.prank(USER); // the next tx will be sent by USER fundMe.fund{value: SEND_VALUE}(); address funder = fundMe.getFunder(0); assertEq(funder, USER); } modifier funded() { vm.prank(USER); // the next tx will be sent by USER fundMe.fund{value: SEND_VALUE}(); _ ; } function testOnlyOwnerCanWithdraw() public funded { vm.expectRevert(); vm.prank(USER); fundMe.withdraw(); } function testWithdrawFromASingleFunder() public funded { // Arrange uint256 startingOwnerBalance = fundMe.getOwner().balance; uint256 startingFundMeBalance = address(fundMe).balance; // Act vm.prank(fundMe.getOwner()); fundMe.withdraw(); // Assert uint256 endingOwnerBalance = fundMe.getOwner().balance; uint256 endingFundMeBalance = address(fundMe).balance; assertEq(endingFundMeBalance, 0); assertEq(startingFundMeBalance + startingOwnerBalance, endingOwnerBalance); } function testWithdrawFromMultipleFunders() public funded { // Arrange uint160 numberOfFunders = 10; uint160 startingFunderIndex = 2; for(uint160 i = startingFunderIndex; i < numberOfFunders; i++) { hoax(address(i), SEND_VALUE); fundMe.fund{value: SEND_VALUE}(); } uint256 startingOwnerBalance = fundMe.getOwner().balance; uint256 startingFundMeBalance = address(fundMe).balance; // Act // uint256 gasStart = gasleft(); // vm.txGasPrice(GAS_PRICE); // vm.prank(fundMe.getOwner()); // or vm.startPrank() and vm.endPrank() vm.startPrank(fundMe.getOwner()); fundMe.withdraw(); vm.stopPrank(); // uint256 gasEnd = gasleft(); // uint256 gasUsed = (gasStart - gasEnd) * tx.gasprice; // Assert assert(address(fundMe).balance == 0); assert(startingFundMeBalance + startingOwnerBalance == fundMe.getOwner().balance); } function testWithdrawFromMultipleFundersCheaper() public funded { // Arrange uint160 numberOfFunders = 10; uint160 startingFunderIndex = 2; for(uint160 i = startingFunderIndex; i < numberOfFunders; i++) { hoax(address(i), SEND_VALUE); fundMe.fund{value: SEND_VALUE}(); } uint256 startingOwnerBalance = fundMe.getOwner().balance; uint256 startingFundMeBalance = address(fundMe).balance; // Act // uint256 gasStart = gasleft(); // vm.txGasPrice(GAS_PRICE); // vm.prank(fundMe.getOwner()); // or vm.startPrank() and vm.endPrank() vm.startPrank(fundMe.getOwner()); fundMe.cheaperWithdraw(); vm.stopPrank(); // uint256 gasEnd = gasleft(); // uint256 gasUsed = (gasStart - gasEnd) * tx.gasprice; // Assert assert(address(fundMe).balance == 0); assert(startingFundMeBalance + startingOwnerBalance == fundMe.getOwner().balance); } function testPrintStorageData() public view { for (uint256 i = 0; i < 3; i++) { bytes32 value = vm.load(address(fundMe), bytes32(i)); console.log("Value at location i", i, ":"); console.logBytes32(value); } console.log("PriceFeed address:", address(fundMe.getPriceFeed())); } }