-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
476 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.20; | ||
|
||
import {Script, console} from "forge-std/Script.sol"; | ||
import {HelperConfig} from "./HelperConfig.s.sol"; | ||
import {FundMe} from "../src/fundme/FundMe.sol"; | ||
|
||
contract DeployFundMe is Script { | ||
function run() external returns (FundMe, HelperConfig) { | ||
HelperConfig helperConfig = new HelperConfig(); // This comes with our mocks! | ||
address priceFeed = helperConfig.activeNetworkConfig(); | ||
|
||
vm.startBroadcast(); | ||
FundMe fundMe = new FundMe(priceFeed); | ||
vm.stopBroadcast(); | ||
return (fundMe, helperConfig); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.19; | ||
|
||
import {MockV3Aggregator} from "../test/mock/MockV3Aggregator.sol"; | ||
import {Script} from "forge-std/Script.sol"; | ||
|
||
contract HelperConfig is Script { | ||
NetworkConfig public activeNetworkConfig; | ||
|
||
uint8 public constant DECIMALS = 8; | ||
int256 public constant INITIAL_PRICE = 2000e8; | ||
|
||
struct NetworkConfig { | ||
address priceFeed; | ||
} | ||
|
||
event HelperConfig__CreatedMockPriceFeed(address priceFeed); | ||
|
||
constructor() { | ||
if (block.chainid == 11155111) { | ||
activeNetworkConfig = getSepoliaEthConfig(); | ||
} else { | ||
activeNetworkConfig = getOrCreateAnvilEthConfig(); | ||
} | ||
} | ||
|
||
function getSepoliaEthConfig() public pure returns (NetworkConfig memory sepoliaNetworkConfig) { | ||
sepoliaNetworkConfig = NetworkConfig({ | ||
priceFeed: 0x694AA1769357215DE4FAC081bf1f309aDC325306 // ETH / USD | ||
}); | ||
} | ||
|
||
function getOrCreateAnvilEthConfig() public returns (NetworkConfig memory anvilNetworkConfig) { | ||
// Check to see if we set an active network config | ||
if (activeNetworkConfig.priceFeed != address(0)) { | ||
return activeNetworkConfig; | ||
} | ||
vm.startBroadcast(); | ||
MockV3Aggregator mockPriceFeed = new MockV3Aggregator(DECIMALS, INITIAL_PRICE); | ||
vm.stopBroadcast(); | ||
emit HelperConfig__CreatedMockPriceFeed(address(mockPriceFeed)); | ||
|
||
anvilNetworkConfig = NetworkConfig({priceFeed: address(mockPriceFeed)}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
import {Address} from "@openzeppelin/contracts/utils/Address.sol"; | ||
import {Script, console} from "forge-std/Script.sol"; | ||
import {FundMe} from "../src/fundme/FundMe.sol"; | ||
//import {DevOpsTools} from "foundry-devops/src/DevOpsTools.sol"; | ||
|
||
contract FundFundMe is Script { | ||
uint256 SEND_VALUE = 0.1 ether; | ||
|
||
function fundFundMe(address mostRecentlyDeployed) public { | ||
vm.startBroadcast(); | ||
FundMe(payable(mostRecentlyDeployed)).fund{value: SEND_VALUE}(); | ||
vm.stopBroadcast(); | ||
console.log("Funded FundMe with %s", SEND_VALUE); | ||
} | ||
|
||
function run() external { | ||
address contractAddress = vm.envAddress("FUNDME_ADDRESS"); | ||
fundFundMe(contractAddress); | ||
} | ||
} | ||
|
||
contract WithdrawFundMe is Script { | ||
function withdrawFundMe(address mostRecentlyDeployed) public { | ||
vm.startBroadcast(); | ||
FundMe(payable(mostRecentlyDeployed)).withdraw(); | ||
vm.stopBroadcast(); | ||
console.log("Withdraw FundMe balance!"); | ||
} | ||
|
||
function run() external { | ||
address contractAddress = vm.envAddress("FUNDME_ADDRESS"); | ||
withdrawFundMe(contractAddress); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// SPDX-License-Identifier: MIT | ||
// 1. Pragma | ||
pragma solidity ^0.8.19; | ||
// 2. Imports | ||
|
||
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; | ||
import {PriceConverter} from "./PriceConverter.sol"; | ||
|
||
// 3. Interfaces, Libraries, Contracts | ||
error FundMe__NotOwner(); | ||
|
||
/** | ||
* @title A sample Funding Contract | ||
* @author Patrick Collins | ||
* @notice This contract is for creating a sample funding contract | ||
* @dev This implements price feeds as our library | ||
*/ | ||
contract FundMe { | ||
// Type Declarations | ||
using PriceConverter for uint256; | ||
|
||
// State variables | ||
uint256 public constant MINIMUM_USD = 5 * 10 ** 18; | ||
address private immutable i_owner; | ||
address[] private s_funders; | ||
mapping(address => uint256) private s_addressToAmountFunded; | ||
AggregatorV3Interface private s_priceFeed; | ||
|
||
// Events (we have none!) | ||
|
||
// Modifiers | ||
modifier onlyOwner() { | ||
// require(msg.sender == i_owner); | ||
if (msg.sender != i_owner) revert FundMe__NotOwner(); | ||
_; | ||
} | ||
|
||
// Functions Order: | ||
//// constructor | ||
//// receive | ||
//// fallback | ||
//// external | ||
//// public | ||
//// internal | ||
//// private | ||
//// view / pure | ||
|
||
constructor(address priceFeed) { | ||
s_priceFeed = AggregatorV3Interface(priceFeed); | ||
i_owner = msg.sender; | ||
} | ||
|
||
/// @notice Funds our contract based on the ETH/USD price | ||
function fund() public payable { | ||
require(msg.value.getConversionRate(s_priceFeed) >= MINIMUM_USD, "You need to spend more ETH!"); | ||
// require(PriceConverter.getConversionRate(msg.value) >= MINIMUM_USD, "You need to spend 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); | ||
// Transfer vs call vs Send | ||
// payable(msg.sender).transfer(address(this).balance); | ||
(bool success,) = i_owner.call{value: address(this).balance}(""); | ||
require(success); | ||
} | ||
|
||
function cheaperWithdraw() public onlyOwner { | ||
address[] memory funders = s_funders; | ||
// mappings can't be in memory, sorry! | ||
for (uint256 funderIndex = 0; funderIndex < funders.length; funderIndex++) { | ||
address funder = funders[funderIndex]; | ||
s_addressToAmountFunded[funder] = 0; | ||
} | ||
s_funders = new address[](0); | ||
// payable(msg.sender).transfer(address(this).balance); | ||
(bool success,) = i_owner.call{value: address(this).balance}(""); | ||
require(success); | ||
} | ||
|
||
/** | ||
* Getter Functions | ||
*/ | ||
|
||
/** | ||
* @notice Gets the amount that an address has funded | ||
* @param fundingAddress the address of the funder | ||
* @return the amount funded | ||
*/ | ||
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 getPriceFeed() public view returns (AggregatorV3Interface) { | ||
return s_priceFeed; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.18; | ||
|
||
import {AggregatorV3Interface} from "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; | ||
|
||
// Why is this a library and not abstract? | ||
// Why not an interface? | ||
library PriceConverter { | ||
// We could make this public, but then we'd have to deploy it | ||
function getPrice(AggregatorV3Interface priceFeed) internal view returns (uint256) { | ||
// Sepolia ETH / USD Address | ||
// https://docs.chain.link/data-feeds/price-feeds/addresses | ||
(, int256 answer,,,) = priceFeed.latestRoundData(); | ||
// ETH/USD rate in 18 digit | ||
return uint256(answer * 10000000000); | ||
} | ||
|
||
// 1000000000 | ||
function getConversionRate(uint256 ethAmount, AggregatorV3Interface priceFeed) internal view returns (uint256) { | ||
uint256 ethPrice = getPrice(priceFeed); | ||
uint256 ethAmountInUsd = (ethPrice * ethAmount) / 1000000000000000000; | ||
// the actual ETH/USD conversion rate, after adjusting the extra 0s. | ||
return ethAmountInUsd; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.19; | ||
|
||
import {DeployFundMe} from "../script/DeployFundMe.s.sol"; | ||
import {FundFundMe, WithdrawFundMe} from "../script/InteractionsFundMe.s.sol"; | ||
import {FundMe} from "../src/fundme/FundMe.sol"; | ||
import {HelperConfig} from "../script/HelperConfig.s.sol"; | ||
import {Test, console} from "forge-std/Test.sol"; | ||
import {StdCheats} from "forge-std/StdCheats.sol"; | ||
|
||
contract InteractionsTest is StdCheats, Test { | ||
FundMe public fundMe; | ||
HelperConfig public helperConfig; | ||
|
||
uint256 public constant SEND_VALUE = 0.1 ether; // just a value to make sure we are sending enough! | ||
uint256 public constant STARTING_USER_BALANCE = 10 ether; | ||
uint256 public constant GAS_PRICE = 1; | ||
|
||
address public constant USER = address(1); | ||
|
||
// uint256 public constant SEND_VALUE = 1e18; | ||
// uint256 public constant SEND_VALUE = 1_000_000_000_000_000_000; | ||
// uint256 public constant SEND_VALUE = 1000000000000000000; | ||
|
||
function setUp() external { | ||
DeployFundMe deployer = new DeployFundMe(); | ||
(fundMe, helperConfig) = deployer.run(); | ||
vm.deal(USER, STARTING_USER_BALANCE); | ||
} | ||
|
||
function testUserCanFundAndOwnerWithdraw() public { | ||
FundFundMe fundFundMe = new FundFundMe(); | ||
fundFundMe.fundFundMe(address(fundMe)); | ||
|
||
WithdrawFundMe withdrawFundMe = new WithdrawFundMe(); | ||
withdrawFundMe.withdrawFundMe(address(fundMe)); | ||
|
||
assert(address(fundMe).balance == 0); | ||
} | ||
} |
Oops, something went wrong.