// SPDX-License-Identifier: MIT /* Get funds from users Withdraw funds Set a minimum funding value in USD */ /***** 1. Pragma *****/ pragma solidity ^0.8.0; /***** 2. Import *****/ import "./PriceConverter.sol"; import "hardhat/console.sol"; // Save Gas by using constant, immutable for variables /***** 3. Error Codes *****/ error FundMe__NotOwner(); /***** 4. Interfaces *****/ /***** 5. Libraries *****/ /***** 6. Contracts *****/ /** * @title A contract for crowd funding * @author hoelee * @notice This contract is to demo a sample funding contract * @dev This implements price feed as our library */ contract FundMe { /* Transaction Fields Nonce Gas Price Gas Limit - Max Gas that this TX can use To - Address Value - Amount of wei to send Data - What to send to the Address (Can Empty) v, r, s - components of TX signature */ /***** 6.1 Type Declarations *****/ using PriceConverter for uint256; uint256 public constant MINIMUM_USD = 50 * 1e18; address[] private s_funders; address private immutable i_owner; // immutable only can declare 1 time at contructor AggregatorV3Interface private s_priceFeed; /***** 6.2 State Variable *****/ mapping(address => uint256) private s_addressToAmountFunded; /***** 6.3 Modifier *****/ modifier onlyOwner() { // require(msg.sender == i_owner, "Sender is not owner!"); if (msg.sender != i_owner) { revert FundMe__NotOwner(); } _; // doing the rest of the code console.log("Log available via 'yarn hardhat test'"); } /***** Function Orders: * Constructor * Receive * Fallback * External * Public Internal * Private * View / Pure * *****/ constructor(address s_priceFeedAddress) { i_owner = msg.sender; s_priceFeed = AggregatorV3Interface(s_priceFeedAddress); } // What happens if someone send this contract ETH without calling the fund function receive() external payable { // people send money / empty money into this contract fund(); } fallback() external payable { // cannot identify which function to run fund(); } /** * @notice Minimum sending USD50, Check Conversion In Real Time * @dev This implements price feed as our library */ function fund() public payable { //require (msg.value >= 1e18, "Didn't send enough"); // 1e18 = 1 * 10 * 18 = 1000000000000000000 require( msg.value.getConversionRate(s_priceFeed) >= MINIMUM_USD, "Didn't send enough" ); // Use error code is gas cheaper s_funders.push(msg.sender); s_addressToAmountFunded[msg.sender] = msg.value; } // Owner of this contract only can withdraw function withdraw() public onlyOwner { // Can use modifier to replace // require(msg.sender == owner, "Sender is not owner"); /* starting index, eding index, step amount */ for ( uint256 funderIndex = 0; funderIndex < s_funders.length; funderIndex++ ) { address funder = s_funders[funderIndex]; s_addressToAmountFunded[funder] = 0; } // reset the array s_funders = new address[](0); /* // transfer - over 2300 gas will cause exception payable(msg.sender).transfer(address(this).balance); // send - over 2300 gas will not cause exception, only will return true or false bool sendSuccess = payable(msg.sender).send(address(this).balance); require(sendSuccess, "Send failed"); */ // call - lower level (bool callSuccess, ) = payable(msg.sender).call{ value: address(this).balance }(""); require(callSuccess, "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; } // reset the array s_funders = new address[](0); (bool callSuccess, ) = i_owner.call{value: address(this).balance}(""); require(callSuccess, "Call failed"); } // private variable is gas cheaper function getOwner() public view returns (address) { return i_owner; } function getFunders(uint256 index) public view returns (address) { return s_funders[index]; } function getAddressToAmountFunded( address funder ) public view returns (uint256) { return s_addressToAmountFunded[funder]; } function getPriceFeed() public view returns (AggregatorV3Interface) { return s_priceFeed; } }