Provide a way to raise funds, for yourself as an organization, or on behalf of an organization, through donations, raising on behalf of organizations has an approval process to indicate whether the campaign is "official". Contract can also function as an escrow with minimum target amounts, refunding donors if the target is not met. Campaigns can be time-based.
An EVM adaptation of the NEAR Campaign contracts as part of Potlock Protocol https://github.com/PotLock/core/tree/feat/campaigns/contracts/campaigns For more on Potlock https://docs.potlock.io
βοΈ Built using NextJS, RainbowKit, Hardhat, Wagmi, Viem, and Typescript.- β Contract Hot Reload: Your frontend auto-adapts to your smart contract as you edit it.
- πͺ Custom hooks: Collection of React hooks wrapper around wagmi to simplify interactions with smart contracts with typescript autocompletion.
- 𧱠Components: Collection of common web3 components to quickly build your frontend.
- π₯ 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.
Before you begin, you need to install the following tools:
- Node (>= v18.18)
- 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 Debug Contracts
page. You can tweak the app config in packages/nextjs/scaffold.config.ts
.
What's next:
- Edit your smart contract
Campaigns.sol
inpackages/hardhat/contracts
- Edit your frontend homepage at
packages/nextjs/app/page.tsx
. For guidance on routing and configuring pages/layouts checkout the Next.js documentation. - Edit your deployment scripts in
packages/hardhat/deploy
- Edit your smart contract test in:
packages/hardhat/test
. To run test useyarn hardhat:test
- You can add your Alchemy API Key in
scaffold.config.ts
if you want more reliability in your RPC requests.
Visit our docs to learn how to start building with Scaffold-ETH 2.
To know more about its features, check out our website.
We welcome contributions to Scaffold-ETH 2!
Please see CONTRIBUTING.MD for more information and guidelines for contributing to Scaffold-ETH 2.
This smart contract implements a decentralized fundraising platform on the Ethereum blockchain. It allows users to create and manage fundraising campaigns, accept donations in ETH or ERC20 tokens, and handle the distribution of funds to recipients and fee collectors. The contract is inspired by the PotLock campaigns contract.
- Create and manage fundraising campaigns
- Accept donations in ETH or ERC20 tokens
- Implement referral and creator fee systems
- Escrow functionality for campaigns with minimum funding goals
- Refund mechanism for failed campaigns
- Flexible fee structure with configurable protocol, referral, and creator fees
The main contract Campaigns.sol
contains the following key components:
- Campaign and Donation structs
- State variables for managing campaign and donation IDs, fees, and configuration
- Mappings for storing campaign and donation data
- Functions for creating and updating campaigns
- Donation processing and refund functions
- Getter functions for retrieving campaign and donation information
- Admin functions for updating fee structures and withdrawing stuck funds
createCampaign
: Create a new fundraising campaignupdateCampaign
: Update an existing campaign (only by owner, before start)
donate
: Make a donation to a specific campaignprocessEscrowedDonations
: Process escrowed donations after reaching the minimum goalrefundDonations
: Refund donations for failed campaigns
getCampaign
: Get campaign detailsgetDonation
: Get donation detailsgetCampaignsByOwner
: Get campaigns created by a specific ownergetCampaignsByRecipient
: Get campaigns for a specific recipientgetDonationsByCampaign
: Get donations for a specific campaigngetDonationsByDonor
: Get donations made by a specific donor
- Update fee structures (protocol, referral, creator)
- Withdraw stuck ETH or ERC20 tokens (emergency functions)
- Uses OpenZeppelin's
Ownable
andReentrancyGuard
to enhance security - Implements input validation to ensure data integrity
- Includes emergency functions to withdraw stuck funds, accessible only by the owner
- Uses
uint256
for most numeric values - Employs structs to group related data
- Emits events for important state changes
- This Ethereum implementation uses Solidity instead of Rust
- Adapts to Ethereum's transaction model and global state storage
- Utilizes OpenZeppelin libraries for standard functionalities
- Implement a multi-signature wallet for the protocol fee recipient and contract ownership
- Add support for batch operations to optimize gas usage
- Implement a time-lock mechanism for critical parameter changes
- Develop a factory contract for easier deployment and management of multiple campaign contracts
-
Claim Functionality: Implemented a pull-based refund system with
claimRefund
andclaimAllRefunds
functions, allowing donors to claim refunds for failed campaigns. -
Official Campaign Status: Added an
isOfficial
boolean to the Campaign struct, which is set to true if the campaign creator is also the recipient. This can be updated using thesetOfficialStatus
function. -
Commit-Reveal Scheme: Implemented a two-step process for creating campaigns using a commit-reveal scheme to prevent front-running.
-
Gas Optimization: Improved gas efficiency by using
uint256
for most numeric values and employing structs to group related data.
createCampaignCommitment
: Create a new campaign commitmentrevealCampaign
: Reveal the campaign details after commitmentupdateCampaign
: Update an existing campaign (only by owner, before start)donate
: Make a donation to a specific campaignprocessEscrowedDonations
: Process escrowed donations after reaching the minimum goalclaimRefund
: Claim a refund for a specific donationclaimAllRefunds
: Claim all refunds for a campaignsetOfficialStatus
: Set the official status of a campaign (only by recipient)
The contract is tested using the Hardhat testing framework with Chai assertions. The test file Campaigns.ts
contains various test suites that cover different aspects of the contract functionality.
- Deployment: Tests the initial state of the contract after deployment.
- Campaign Creation and Management: Tests creating, revealing, and updating campaigns.
- Donations: Tests making donations, processing escrowed donations, and handling campaign end conditions.
- Refunds: Tests the refund claiming process for failed campaigns.
- Admin Functions: Tests owner-only functions for updating fee structures and withdrawing stuck funds.
- Edge Cases and Attack Vectors: Tests various edge cases and potential attack scenarios.
- Gas Limit and Large Scale Operations: Tests handling of large numbers of donations and refunds.
- Official Campaign Status: Tests setting and checking the official status of campaigns.
- The tests use the
ethers
library to interact with the smart contract. - Before each test suite, the contract is deployed to a local Hardhat network.
- Test cases use
async/await
syntax to handle asynchronous contract interactions. - Chai assertions (
expect
) are used to verify the expected outcomes of contract function calls. - The
ethers.provider
is used to manipulate the blockchain state (e.g., increasing time) for testing time-dependent functionality. - Events emitted by the contract are captured and verified in relevant test cases.
To run the tests, use the command yarn hardhat test
in the project directory.
For more detailed information on the contract implementation and tests, please refer to the Campaigns.sol
and Campaigns.ts
files in the repository.
Referrals are utilized for campaign creators, Potlock protocol, and referrers. These amounts are also escrowed until the campaign is successful.
Referral fees are calculated at the time of donation . When a user makes a donation, the contract calculates the referral fee based on the referralFeeBasisPoints set for the campaign. For campaigns with a minimum amount (escrow-based): If the campaign's minimum amount has not been reached, all funds, including the referral fee, are held in escrow1 . The escrowBalance of the campaign is increased by the full donation amount. The referral fee is not immediately paid out. Instead, it's stored as part of the Donation struct1 . If the campaign reaches its minimum amount, the processEscrowedDonations function can be called1 . This function will transfer the escrowed funds, including paying out the referral fees for all donations. If the campaign ends without reaching its minimum amount, donors can claim refunds using the claimRefund or claimAllRefunds functions1 . In this case, the full donation amount is refunded to the donor, including the portion that would have been the referral fee. For campaigns without a minimum amount or when the minimum has already been reached: The referral fee is immediately transferred to the referrer at the time of donation