add Fund Me Foundry Smart Contract
This commit is contained in:
@@ -1,24 +0,0 @@
|
||||
// SPDX-License-Identifier: UNLICENSED
|
||||
pragma solidity ^0.8.13;
|
||||
|
||||
import {Test, console} from "forge-std/Test.sol";
|
||||
import {Counter} from "../src/Counter.sol";
|
||||
|
||||
contract CounterTest is Test {
|
||||
Counter public counter;
|
||||
|
||||
function setUp() public {
|
||||
counter = new Counter();
|
||||
counter.setNumber(0);
|
||||
}
|
||||
|
||||
function test_Increment() public {
|
||||
counter.increment();
|
||||
assertEq(counter.number(), 1);
|
||||
}
|
||||
|
||||
function testFuzz_SetNumber(uint256 x) public {
|
||||
counter.setNumber(x);
|
||||
assertEq(counter.number(), x);
|
||||
}
|
||||
}
|
||||
34
fund-me/test/integration/InteractionsTest.t.sol
Normal file
34
fund-me/test/integration/InteractionsTest.t.sol
Normal file
@@ -0,0 +1,34 @@
|
||||
// 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";
|
||||
import {FundFundMe, WithdrawFundMe} from "../../script/Interactions.s.sol";
|
||||
|
||||
contract InteractionsTest 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 {
|
||||
DeployFundMe deploy = new DeployFundMe();
|
||||
fundMe = deploy.run();
|
||||
vm.deal(USER, STARTING_BALANCE);
|
||||
}
|
||||
|
||||
function testUserCanFundInteractions() public {
|
||||
FundFundMe fundFundMe = new FundFundMe();
|
||||
fundFundMe.fundFundMe(address(fundMe));
|
||||
|
||||
WithdrawFundMe withdrawFundMe = new WithdrawFundMe();
|
||||
withdrawFundMe.withdrawFundMe(address(fundMe));
|
||||
|
||||
assert(address(fundMe).balance == 0);
|
||||
}
|
||||
}
|
||||
74
fund-me/test/mocks/MockV3Aggregator.sol
Normal file
74
fund-me/test/mocks/MockV3Aggregator.sol
Normal file
@@ -0,0 +1,74 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol";
|
||||
|
||||
/**
|
||||
* @title MockV3Aggregator
|
||||
* @notice Based on the FluxAggregator contract
|
||||
* @notice Use this contract when you need to test
|
||||
* other contract's ability to read data from an
|
||||
* aggregator contract, but how the aggregator got
|
||||
* its answer is unimportant
|
||||
*/
|
||||
contract MockV3Aggregator is AggregatorV3Interface {
|
||||
uint256 public constant version = 4;
|
||||
|
||||
uint8 public decimals;
|
||||
int256 public latestAnswer;
|
||||
uint256 public latestTimestamp;
|
||||
uint256 public latestRound;
|
||||
|
||||
mapping(uint256 => int256) public getAnswer;
|
||||
mapping(uint256 => uint256) public getTimestamp;
|
||||
mapping(uint256 => uint256) private getStartedAt;
|
||||
|
||||
constructor(uint8 _decimals, int256 _initialAnswer) {
|
||||
decimals = _decimals;
|
||||
updateAnswer(_initialAnswer);
|
||||
}
|
||||
|
||||
function updateAnswer(int256 _answer) public {
|
||||
latestAnswer = _answer;
|
||||
latestTimestamp = block.timestamp;
|
||||
latestRound++;
|
||||
getAnswer[latestRound] = _answer;
|
||||
getTimestamp[latestRound] = block.timestamp;
|
||||
getStartedAt[latestRound] = block.timestamp;
|
||||
}
|
||||
|
||||
function updateRoundData(uint80 _roundId, int256 _answer, uint256 _timestamp, uint256 _startedAt) public {
|
||||
latestRound = _roundId;
|
||||
latestAnswer = _answer;
|
||||
latestTimestamp = _timestamp;
|
||||
getAnswer[latestRound] = _answer;
|
||||
getTimestamp[latestRound] = _timestamp;
|
||||
getStartedAt[latestRound] = _startedAt;
|
||||
}
|
||||
|
||||
function getRoundData(uint80 _roundId)
|
||||
external
|
||||
view
|
||||
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
|
||||
{
|
||||
return (_roundId, getAnswer[_roundId], getStartedAt[_roundId], getTimestamp[_roundId], _roundId);
|
||||
}
|
||||
|
||||
function latestRoundData()
|
||||
external
|
||||
view
|
||||
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)
|
||||
{
|
||||
return (
|
||||
uint80(latestRound),
|
||||
getAnswer[latestRound],
|
||||
getStartedAt[latestRound],
|
||||
getTimestamp[latestRound],
|
||||
uint80(latestRound)
|
||||
);
|
||||
}
|
||||
|
||||
function description() external pure returns (string memory) {
|
||||
return "v0.6/test/mock/MockV3Aggregator.sol";
|
||||
}
|
||||
}
|
||||
152
fund-me/test/unit/FundMeTest.t.sol
Normal file
152
fund-me/test/unit/FundMeTest.t.sol
Normal file
@@ -0,0 +1,152 @@
|
||||
// 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()));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user