Contract
Fundraiser Contract Documentation and Example
Fundraiser Contract Overview
Campaign Creation: Empowers users to initialize new fundraising campaigns by providing essential details such as campaign name, image, description, goal amount, and beneficiary address. This functionality enables individuals and organizations to kickstart their charitable initiatives seamlessly.
Donation Mechanism: Facilitates the acceptance of donations in Polygon (Formerly MATIC) tokens from users who wish to contribute to the fundraising campaigns. By providing a streamlined and secure donation process, the contract encourages community participation and support for charitable causes.
Receipt Generation: Ensures transparency and accountability by generating receipts for donors upon their contributions. These receipts serve as tangible proof of donation, instilling trust and confidence among contributors regarding the legitimacy and integrity of the fundraising campaigns.
Fund Withdrawal: Enables the secure withdrawal of funds to the designated beneficiary address upon reaching the campaign's goal amount. This functionality ensures that the raised funds are promptly transferred to the intended recipients, allowing them to utilize the resources for their charitable endeavors effectively.
Overall, the Fundraiser contract plays a pivotal role in promoting philanthropy and social impact within the BARK Protocol ecosystem. By providing a robust platform for organizing and executing fundraising campaigns, it empowers individuals and organizations to make a meaningful difference in their communities and beyond.
Security
Security is paramount within the BARK Protocol. The smart contracts adhere to security best practices, including:
Ownership and Access Control: Only the owner of a Fundraiser contract can modify critical parameters or withdraw funds, ensuring secure management of campaigns.
Immutable Records: All transactions and donations are recorded on the blockchain, providing an immutable and transparent record of activities.
Audits and Testing: The smart contracts undergo rigorous audits and testing to identify and mitigate potential vulnerabilities, ensuring the integrity and reliability of the platform.
Solidity Deployment Script
The deployment script for the Fundraiser contract streamlines the process of deploying a new fundraiser instance. It includes essential parameters such as the campaign name, image URL, description, goal amount, beneficiary address, and initial owner address.
How it Works ?
The Fundraiser Factory contract acts as a centralized hub for creating and managing fundraiser instances. It maintains an array of deployed fundraiser contracts and provides functions for creating new fundraisers. The factory contract ensures scalability and organization within the BARK Protocol ecosystem.
Deployment and Interaction
To deploy the BARK Protocol on the Polygon network, follow these steps:
Deploy the Factory Contract: Deploy the FundraiserFactory contract on the Polygon network.
Create a New Fundraiser: Call the createFundraiser function with the required parameters to initiate a new fundraising campaign.
Retrieve All Fundraisers: Utilize the getFundraisers function to retrieve a list of all fundraiser instances created by the factory, enabling easy management and monitoring.
Example deployment script:
solidity const Fundraiser = artifacts.require("Fundraiser");
module.exports = function(deployer) {
deployer.deploy(
Fundraiser,
"Campaign Name",
"https://example.com/image.jpg",
"Campaign description",
web3.utils.toWei("100", "ether"), // Goal amount in wei
"0xBeneficiaryAddress",
"0xInitialOwnerAddress"
);
};
FundraiserFactory.sol Contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/access/Ownable.sol";
// Import the Fundraiser contract
import "./Fundraiser.sol";
contract FundraiserFactory is Ownable {
// Array to store deployed Fundraiser contracts
Fundraiser[] public fundraisers;
// Event emitted when a new fundraiser is created
event FundraiserCreated(address indexed fundraiserAddress, address owner, string name, uint256 goalAmount);
// Constructor to initialize the Ownable contract with the specified initial owner
constructor(address initialOwner) Ownable(initialOwner) {}
// Function to create a new fundraiser
function createFundraiser(
string memory _name,
string memory _image,
string memory _description,
uint256 _goalAmount,
address payable _beneficiary
) external {
// Deploy a new Fundraiser contract
Fundraiser newFundraiser = new Fundraiser(
_name,
_image,
_description,
_goalAmount,
_beneficiary,
msg.sender // Pass the caller's address as the initial owner
);
// Add the new Fundraiser contract to the array
fundraisers.push(newFundraiser);
// Emit an event to signal the creation of a new fundraiser
emit FundraiserCreated(address(newFundraiser), msg.sender, _name, _goalAmount);
}
// Function to get the number of deployed fundraisers
function getFundraisersCount() external view returns (uint256) {
return fundraisers.length;
}
}
Fundraiser.sol Contract:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract Fundraiser is Ownable, ReentrancyGuard {
struct Donation {
uint256 value;
uint256 date;
}
mapping(address => Donation[]) private donations;
event DonationReceived(address indexed donor, uint256 value);
event Withdrawal(address indexed beneficiary, uint256 amount);
event BeneficiaryChanged(address indexed oldBeneficiary, address indexed newBeneficiary);
event GoalReached(uint256 amountRaised);
string public name;
string public image;
string public description;
address payable public beneficiary;
uint256 public goalAmount;
uint256 public totalDonations;
uint256 public donationsCount;
uint256 public fundraisingDeadline;
modifier goalNotReached() {
require(totalDonations < goalAmount, "Goal already reached");
_;
}
constructor(
string memory _name,
string memory _image,
string memory _description,
uint256 _goalAmount,
address payable _beneficiary,
address _initialOwner,
uint256 _fundraisingDuration
) Ownable(_initialOwner) {
name = _name;
image = _image;
description = _description;
goalAmount = _goalAmount;
beneficiary = _beneficiary;
fundraisingDeadline = block.timestamp + _fundraisingDuration;
}
function setBeneficiary(address payable _beneficiary) external onlyOwner {
address oldBeneficiary = beneficiary;
beneficiary = _beneficiary;
emit BeneficiaryChanged(oldBeneficiary, _beneficiary);
}
function donate() external payable nonReentrant goalNotReached {
require(msg.value > 0, "Donation amount must be greater than zero");
require(block.timestamp < fundraisingDeadline, "Fundraising deadline has passed");
donations[msg.sender].push(Donation({
value: msg.value,
date: block.timestamp
}));
totalDonations += msg.value;
donationsCount++;
emit DonationReceived(msg.sender, msg.value);
if (totalDonations >= goalAmount) {
emit GoalReached(totalDonations);
}
}
function myDonationsCount() external view returns (uint256) {
return donations[msg.sender].length;
}
function myDonations() external view returns (uint256[] memory values, uint256[] memory dates) {
uint256 count = donations[msg.sender].length;
values = new uint256[](count);
dates = new uint256[](count);
for (uint256 i = 0; i < count; i++) {
Donation storage donation = donations[msg.sender][i];
values[i] = donation.value;
dates[i] = donation.date;
}
return (values, dates);
}
function withdraw() external onlyOwner nonReentrant {
uint256 balance = address(this).balance;
require(balance > 0, "Insufficient balance to withdraw");
(bool success, ) = beneficiary.call{value: balance}("");
require(success, "Withdrawal failed");
emit Withdrawal(beneficiary, balance);
}
receive() external payable {}
}
Explanation
1. FundraiserFactory Contract:
Fundraiser[] public fundraisers;
: Stores all created fundraiser instances.address public owner;
: Stores the address of the factory owner.event FundraiserCreated(address fundraiserAddress, address owner, string name, uint256 goalAmount);
: Event emitted when a new fundraiser is created.modifier onlyOwner()
: Restricts certain functions to the factory owner.constructor()
: Sets the initial owner of the factory.createFundraiser()
: Creates a new fundraiser instance with the provided parameters and adds it to thefundraisers
array.getFundraisers()
: Returns the list of all fundraiser instances.
2. Fundraiser Contract:
Implementation of the
goalNotReached
modifier to prevent donations after the fundraising goal is reached.An event
GoalReached
to indicate when the fundraising goal has been reached.A constructor to initialize the contract with fundraising parameters.
A
setBeneficiary
function to allow the contract owner to change the beneficiary address.Various getters for donation information and withdrawal functionality.
Deployment and Interaction
Deploy the Factory Contract:
Deploy the
FundraiserFactory
contract.
Create a New Fundraiser:
Call the
createFundraiser
function with the necessary parameters to create a new fundraiser.
Retrieve All Fundraisers:
Call the
getFundraisers
function to get a list of all fundraiser instances created by the factory.
This setup allows easy creation and management of multiple fundraising campaigns through a single factory contract, promoting scalability and organization.
Source Code:
https://github.com/bark-community/fundraiser-contracts
Conclusion
The BARK Protocol aims to revolutionize the fundraising landscape by leveraging blockchain technology to create a transparent, efficient, and secure platform. By addressing the limitations of traditional fundraising methods, BARK provides a robust solution for raising funds for social causes. The platform's integration with the Polygon network ensures low fees and fast transaction times, making it an ideal choice for both donors and beneficiaries.
Last updated