CanFundMe is a decentralized crowdfunding platform built on Ethereum, designed to support projects and ideas with a simple, yet effective, funding mechanism. CanFundMe integrates Gitcoin and IPFS to support user profiles, organic growth, and reduce Sybil attacks. With a focus on user-friendly experience and enhanced security, CanFundMe aims to revolutionize the crowdfunding space.
⚙️ Built using NextJS, RainbowKit, Hardhat, Wagmi, and Typescript.
- CanFundMeFactory contract deploys individual CanFundMe campaigns
- EIPPY and PROFILE verifier contracts utilize EIP712 typed data standards for increased security
- Gitcoin integration rewards projects with a Gitcoin score higher than 10, reducing platform fees to 0%
- IPFS integration allows customizable profiles with an IPFS hash pointing to a JSON object containing profile pictures and project descriptions
- Signatures and typed data attest to project ownership and the validity of information provided
- CanFundMeFactory: The factory contract that deploys CanFundMe campaigns
- EIPPY: A verifier contract using the EIP712 typed data standards
- PROFILE: A verifier contract using the EIP712 typed data standards for user profiles
- CanFundMe: The main crowdfunding contract that enables users to create and participate in crowdfunding campaigns
⚙️ Deployed using Vercel
- ✅ Contract Hot Reload: Your frontend auto-adapts to your smart contract as you edit it.
- 🔥 Burner Wallet & Local Faucet: Quickly test your application with a burner wallet and local faucet.
- 🔐 Integration with Wallet Providers: Connect to different wallet providers and interact with the Ethereum network.
- Requirements
- Quickstart
- Deploying your Smart Contracts to a Live Network
- Deploying your NextJS App
- Disabling Type & Linting Error Checks
- Contributing to Scaffold-ETH 2
Before you begin, you need to install the following tools:
- Node (v18 LTS)
- Yarn (v1 or v2+)
- Git
To get started with Scaffold-ETH 2, follow the steps below:
- Clone this repo & install dependencies
git clone https://github.com/scaffold-eth/scaffold-eth-2.git
cd scaffold-eth-2
yarn install
- Run a local network in the first terminal:
yarn chain
This command starts a local Ethereum network using Hardhat. The network runs on your local machine and can be used for testing and development. You can customize the network configuration in hardhat.config.ts
.
- On a second terminal, deploy the test contract:
yarn deploy
This command deploys a test smart contract to the local network. The contract is located in packages/hardhat/contracts
and can be modified to suit your needs. The yarn deploy
command uses the deploy script located in packages/hardhat/deploy
to deploy the contract to the network. You can also customize the deploy script.
- On a third terminal, start your NextJS app:
yarn start
Visit your app on: http://localhost:3000
. You can interact with your smart contract using the contract component or the example ui in the frontend. You can tweak the app config in packages/nextjs/scaffold.config.ts
.
Run smart contract test with yarn hardhat:test
- Edit your smart contract
YourContract.sol
inpackages/hardhat/contracts
- Edit your frontend in
packages/nextjs/pages
- Edit your deployment scripts in
packages/hardhat/deploy
Once you are ready to deploy your smart contracts, there are a few things you need to adjust.
- Select the network
By default, yarn deploy
will deploy the contract to the local network. You can change the defaultNetwork in packages/hardhat/hardhat.config.ts.
You could also simply run yarn deploy --network target_network
to deploy to another network.
Check the hardhat.config.ts
for the networks that are pre-configured. You can also add other network settings to the hardhat.config.ts file
. Here are the Alchemy docs for information on specific networks.
Example: To deploy the contract to the Sepolia network, run the command below:
yarn deploy --network sepolia
- Generate a new account or add one to deploy the contract(s) from. Additionally you will need to add your Alchemy API key. Rename
.env.example
to.env
and fill the required keys.
ALCHEMY_API_KEY="",
DEPLOYER_PRIVATE_KEY=""
The deployer account is the account that will deploy your contracts. Additionally, the deployer account will be used to execute any function calls that are part of your deployment script.
You can generate a random account / private key with yarn generate
or add the private key of your crypto wallet. yarn generate
will create a random account and add the DEPLOYER_PRIVATE_KEY to the .env file. You can check the generated account with yarn account
.
- Deploy your smart contract(s)
Run the command below to deploy the smart contract to the target network. Make sure to have some funds in your deployer account to pay for the transaction.
yarn deploy --network network_name
- Verify your smart contract
You can verify your smart contract on Etherscan by running:
yarn verify --network network_name
Hint: We recommend connecting your GitHub repo to Vercel (through the Vercel UI) so it gets automatically deployed when pushing to main
.
If you want to deploy directly from the CLI, run yarn vercel
and follow the steps to deploy to Vercel. Once you log in (email, github, etc), the default options should work. It'll give you a public URL.
If you want to redeploy to the same production URL you can run yarn vercel --prod
. If you omit the --prod
flag it will deploy it to a preview/test URL.
Make sure your packages/nextjs/scaffold.config.ts
file has the values you need.
- useScaffoldContractRead
- useScaffoldContractWrite
- useScaffoldEventSubscriber
- useScaffoldEventHistory
- useDeployedContractInfo
- useScaffoldContract
Use this hook to read a value from your deployed contracts.
const { data: totalCounter } = useScaffoldContractRead({
contractName: "YourContract",
functionName: "getGreeting",
args: ["ARGUMENTS IF THE FUNCTION ACCEPTS ANY"],
});
Use this hook to write to your deployed contracts.
const { writeAsync, isLoading } = useScaffoldContractRead({
contractName: "YourContract",
functionName: "setGreeting",
args: ["The value to set"],
//value if the function is payable and sends eth to it
value: "0.01",
});
Use this to listen for an event emitted in the deployed smart contracts.
useScaffoldEventSubscriber({
contractName: "YourContract",
eventName: "GreetingChange",
//parameters that the event emits
//event GreetingChange(address greetingSetter, string newGreeting, bool premium, uint256 value);
listener: (greetingSetter, newGreeting, premium, value) => {
console.log(greetingSetter, newGreeting, premium, value);
},
});
Use this hook to read events from a deployed contract
const {
data: events,
isLoading: isLoadingEvents,
error: errorReadingEvents,
} = useScaffoldEventHistory({
contractName: "YourContract",
eventName: "GreetingChange",
fromBlock: //the block number to start reading events from,
blockData: true,
filters: //filters to be applied to the event (parameterName: value),
transactionData: //if set to true it will return the transaction data for each event (default: false),
receiptData: //if set to true it will return the receipt data for each event (default: false),
});
Use this hook to get the matching contract info from the contracts file generated by yarn deploy
//contractName: name of the deployed contract
const { data: deployedContractData } = useDeployedContractInfo(contractName);
Use to gets a deployed contract by contract name and returns a contract instance Can also be use to read and write to the deployed smart contract
const { data: yourContract } = useScaffoldContract({
contractName: "YourContract",
});
// will return the greeting and can be call in any function unlike useScaffoldContractRead
await yourContract?.greeting();
//can be use to write to a contract and can be called in any function
import { Signer } from "ethers";
import { useSigner } from "wagmi";
const { data: signer, isError, isLoading } = useSigner();
const { data: yourContract } = useScaffoldContract({
contractName: "YourContract",
signerOrProvider: signer as Signer,
});
const setGreeting = async () => {
//call the method in any function
await yourContract?.setGreeting("the greeting here");
};
Hint Typescript helps you catch errors at compile time, which can save time and improve code quality, but can be challenging for those who are new to the language or who are used to the more dynamic nature of JavaScript. Below are the steps to disable type & lint check at different levels
We run pre-commit
git hook which lints the staged files and don't let you commit if there is an linting error.
To disable this, go to .husky/pre-commit
file and comment out yarn lint-staged --verbose
- yarn lint-staged --verbose
+ # yarn lint-staged --verbose
By default, Vercel runs types and lint checks before building your app. The deployment will fail if there are any types or lint errors.
To ignore these checks while deploying from the CLI, use:
yarn vercel:yolo
If your repo is connected to Vercel, you can set NEXT_PUBLIC_IGNORE_BUILD_ERROR
to true
in a environment variable.
We have github workflow setup checkout .github/workflows/lint.yaml
which runs types and lint error checks every time code is pushed to main
branch or pull request is made to main
branch
To disable it, delete .github
directory
We welcome contributions to Scaffold-ETH 2!
Please see CONTRIBUTING.MD for more information and guidelines for contributing to Scaffold-ETH 2.