Skip to content

DevAyomi/Foundry-FundMe-

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

1 Commit
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

FundMe - Decentralized Crowdfunding Smart Contract

A Solidity-based crowdfunding smart contract built with Foundry that allows users to fund a project with ETH. The contract uses Chainlink Price Feeds to ensure a minimum funding amount in USD, regardless of ETH price fluctuations.

πŸ“‹ Project Overview

FundMe is a smart contract that enables decentralized crowdfunding with the following features:

  • Minimum USD Contribution: Enforces a minimum contribution of $5 USD worth of ETH using Chainlink price feeds
  • Owner-Only Withdrawals: Only the contract owner can withdraw accumulated funds
  • Gas-Optimized: Includes optimized withdrawal functions to reduce gas costs
  • Multi-Network Support: Configured for deployment on Sepolia testnet and local Anvil network
  • Comprehensive Testing: Includes unit and integration tests with gas snapshots

πŸ—οΈ Architecture

Core Contracts

  • FundMe.sol: Main crowdfunding contract with funding and withdrawal logic
  • PriceConverter.sol: Library for converting ETH amounts to USD using Chainlink price feeds

Key Features

  1. Price Feed Integration: Uses Chainlink's AggregatorV3Interface to get real-time ETH/USD prices
  2. Funder Tracking: Maintains a mapping of addresses to funding amounts and an array of funders
  3. Dual Withdrawal Methods:
    • withdraw(): Standard withdrawal function
    • cheaperWithdraw(): Gas-optimized version using memory variables
  4. Fallback Funding: Implements receive() and fallback() functions to accept direct ETH transfers

πŸ› οΈ Technology Stack

  • Solidity: ^0.8.18
  • Foundry: Development framework
    • Forge: Testing framework
    • Cast: Command-line tool for interacting with contracts
    • Anvil: Local Ethereum node
  • Chainlink: Price feed oracles
  • OpenZeppelin: Smart contract libraries (via dependencies)

πŸ“ Project Structure

FundMe/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ FundMe.sol              # Main crowdfunding contract
β”‚   └── PriceConverter.sol      # Price conversion library
β”œβ”€β”€ script/
β”‚   β”œβ”€β”€ DeployFundMe.s.sol      # Deployment script
β”‚   β”œβ”€β”€ HelperConfig.s.sol      # Network configuration helper
β”‚   └── Interaction.s.sol       # Fund and withdraw scripts
β”œβ”€β”€ test/
β”‚   β”œβ”€β”€ FundMeTest.t.sol        # Unit tests
β”‚   β”œβ”€β”€ integration/            # Integration tests
β”‚   └── mocks/                  # Mock contracts for testing
β”œβ”€β”€ foundry.toml                # Foundry configuration
β”œβ”€β”€ Makefile                    # Build and deployment commands
└── .env                        # Environment variables

πŸš€ Getting Started

Prerequisites

  • Foundry installed
  • An Ethereum wallet with testnet ETH (for Sepolia deployment)
  • Etherscan API key (for contract verification)

Installation

  1. Clone the repository:
git clone <repository-url>
cd FundMe
  1. Install dependencies:
forge install
  1. Create a .env file with the following variables:
SEPOLIA_RPC_URL=<your-sepolia-rpc-url>
PRIVATE_KEY=<your-private-key>
ETHERSCAN_API_KEY=<your-etherscan-api-key>
ANVIL_RPC_URL=http://127.0.0.1:8545
ANVIL_PRIVATE_KEY=<anvil-default-private-key>

Build

Compile the smart contracts:

forge build

Or using the Makefile:

make build

πŸ§ͺ Testing

Run All Tests

forge test

Run Tests with Verbosity

forge test -vvv

Generate Gas Snapshots

forge snapshot

View Test Coverage

forge coverage

πŸ“¦ Deployment

Deploy to Sepolia Testnet

make deploy-sepolia

This will:

  • Deploy the FundMe contract to Sepolia
  • Verify the contract on Etherscan
  • Use the Chainlink Sepolia ETH/USD price feed

Deploy to Local Anvil Network

  1. Start Anvil in a separate terminal:
anvil
  1. Deploy the contract:
make deploy-anvil

πŸ’° Interacting with the Contract

Fund the Contract

Using the Makefile (Sepolia):

make fund

Using Forge directly:

forge script script/Interaction.s.sol:FundFundMe --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --broadcast

Withdraw Funds (Owner Only)

Using the Makefile (Sepolia):

make withdraw

Using Forge directly:

forge script script/Interaction.s.sol:WithdrawFundMe --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --broadcast

Using Cast

Check contract balance:

cast balance <CONTRACT_ADDRESS> --rpc-url <RPC_URL>

Call a view function:

cast call <CONTRACT_ADDRESS> "getOwner()" --rpc-url <RPC_URL>

Send a transaction:

cast send <CONTRACT_ADDRESS> "fund()" --value 0.1ether --private-key <PRIVATE_KEY> --rpc-url <RPC_URL>

πŸ“Š Contract Functions

Public Functions

  • fund(): Fund the contract with ETH (minimum $5 USD equivalent)
  • withdraw(): Withdraw all funds (owner only)
  • cheaperWithdraw(): Gas-optimized withdrawal (owner only)
  • getVersion(): Get the Chainlink price feed version

View Functions

  • getAddressToAmountFunded(address): Get the amount funded by a specific address
  • getFunder(uint256): Get the funder address at a specific index
  • getOwner(): Get the contract owner address

Constants

  • MINIMUM_USD: Minimum funding amount (5 USD in wei)

πŸ”§ Configuration

Foundry Configuration (foundry.toml)

  • Source Directory: src/
  • Output Directory: out/
  • Libraries: lib/
  • Remappings: Configured for Chainlink and Forge Standard Library
  • FFI: Enabled for advanced scripting

Network Configuration

The HelperConfig.s.sol script automatically configures the correct Chainlink price feed address based on the network:

  • Sepolia: Uses Chainlink's Sepolia ETH/USD price feed
  • Anvil: Deploys a mock price feed for local testing

🧾 Gas Optimization

The contract includes two withdrawal methods:

  1. withdraw(): Standard implementation
  2. cheaperWithdraw(): Optimized version that:
    • Caches array length in memory
    • Reduces storage reads
    • Saves approximately 20-30% gas

Gas snapshots are tracked in .gas-snapshot for monitoring optimization improvements.

πŸ” Security Features

  • Owner-only withdrawals: Uses custom error FundMe__NotOwner() for gas-efficient access control
  • Minimum funding requirement: Prevents spam transactions
  • Safe type casting: Includes safety checks when converting Chainlink price data
  • Reentrancy protection: Uses checks-effects-interactions pattern

πŸ“š Learning Resources

πŸ“ License

MIT

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

⚠️ Disclaimer

This project is for educational purposes. Always audit smart contracts before deploying to mainnet with real funds.

About

Decentralized Crowdfunding Smart Contract

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages