Building a Donation Smart Contract on Ethereum

·

Introduction

Smart contracts are transforming how we handle digital transactions by enabling trustless and automated agreements on the blockchain. This guide provides a step-by-step approach to creating a secure and transparent donation system on the Ethereum network. You will learn to build a contract that accepts contributions, tracks donor activity, and manages fund withdrawals efficiently.

Whether you are a developer exploring decentralized applications or a nonprofit looking to leverage blockchain technology, this tutorial offers practical insights into smart contract development. By the end, you will have a functional donation contract deployed on a testnet, ready for further customization and real-world use.

Prerequisites

Before diving into the development process, ensure you have the following tools and knowledge:

Setting Up Your Development Environment

A proper setup is crucial for efficient smart contract development. Follow these steps to initialize your project.

  1. Create a new project directory and initialize it with npm.
  2. Install Hardhat, a popular development environment for Ethereum software, along with its toolbox plugin.
mkdir blockchain_payment
cd blockchain_payment
npm init -y
npm install --save-dev hardhat @nomicfoundation/hardhat-toolbox
  1. Initialize a new Hardhat project within your directory and select the default project setup to generate necessary configuration files.

Understanding the Donation Smart Contract Code

The core of our system is a smart contract written in Solidity. It defines the rules and logic for accepting and managing donations.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract Donation {
    address public owner;
    uint256 public minimumDonation;
    mapping(address => uint256) public donations;

    event DonationReceived(address indexed donor, uint256 amount);
    event FundsWithdrawn(address indexed owner, uint256 amount);

    constructor(uint256 _minimumDonation) {
        owner = msg.sender;
        minimumDonation = _minimumDonation;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only owner can call this function");
        _;
    }

    function donate() public payable {
        require(msg.value >= minimumDonation, "Donation amount too small");
        donations[msg.sender] += msg.value;
        emit DonationReceived(msg.sender, msg.value);
    }

    function withdraw() public onlyOwner {
        uint256 balance = address(this).balance;
        require(balance > 0, "No funds to withdraw");
        (bool sent, ) = owner.call{value: balance}("");
        require(sent, "Failed to withdraw funds");
        emit FundsWithdrawn(owner, balance);
    }

    function getDonationAmount(address donor) public view returns (uint256) {
        return donations[donor];
    }
}

Key Features and Functionality

This contract incorporates several important features designed for security, transparency, and usability.

Deployment Process to Sepolia Testnet

Deploying your contract to a testnet allows you to test its functionality in a real-world environment without spending real cryptocurrency.

  1. Network Configuration: Configure your Hardhat configuration file (hardhat.config.js) with Sepolia network details. You will need an Alchemy API key and a funded wallet private key.
module.exports = {
  solidity: "0.8.19",
  networks: {
    sepolia: {
      url: `https://eth-sepolia.g.alchemy.com/v2/${process.env.ALCHEMY_API_KEY}`,
      accounts: [process.env.PRIVATE_KEY]
    }
  },
  etherscan: {
    apiKey: process.env.ETHERSCAN_API_KEY
  }
};
  1. Environment Variables: Store sensitive information like your API keys and private key in a .env file and use the dotenv package to access them securely without exposing them in your code.
  2. Deployment Script: Write a script to deploy the contract. Remember to pass the required constructor argument, such as a minimum donation of 0.01 ETH.

Overcoming Contract Verification Challenges

A common hurdle after deployment is verifying the contract code on block explorers like Etherscan. This process requires providing the compiler settings and constructor arguments used during deployment.

const value = ethers.parseEther("0.01");
const abiCoder = new ethers.AbiCoder();
const encodedArgs = abiCoder.encode(["uint256"], [value]);

Verification ensures your contract's source code is publicly visible and auditable, which builds trust with potential donors.

Final Result and Contract Address

After successful deployment and verification, your contract will be live on the Sepolia testnet. The contract from this guide was deployed at address: 0xf13F51348C1E0071077327ED797c3257945ef645.

You can view the transaction history, internal state, and interact with the functions directly through the Sepolia Etherscan block explorer. 👉 Explore verified contract functionalities

Conclusion and Key Takeaways

Building this donation smart contract provides hands-on experience with core concepts of Ethereum development. The process highlights the importance of thorough testing on testnets, careful management of API configurations, and the value of contract verification for transparency.

The challenges encountered, such as constructor argument encoding, are common learning milestones that deepen your understanding of the blockchain development workflow. The skills acquired here form a solid foundation for creating more complex and feature-rich decentralized applications.

Frequently Asked Questions

What is a smart contract?
A smart contract is a self-executing program stored on a blockchain that automatically enforces the terms of an agreement between parties. It runs exactly as programmed without the possibility of downtime, censorship, or third-party interference.

Why use a testnet like Sepolia for deployment?
Testnets like Sepolia provide a safe and cost-free environment to deploy, test, and debug smart contracts. They simulate the main Ethereum network without requiring real ETH for gas fees, preventing costly errors during development.

How do I get test ETH for the Sepolia network?
You can obtain free test ETH from a Sepolia faucet. These are websites or Discord channels that distribute testnet Ether to developers for free. Simply search for "Sepolia faucet" and provide your wallet address to receive test funds.

What is the purpose of the minimum donation amount?
The minimum donation parameter prevents malicious actors from spamming the contract with dust transactions (extremely small amounts), which could clog the contract and make it inefficient or expensive to use for everyone.

Can anyone withdraw the donated funds?
No. The contract uses an onlyOwner modifier to restrict the withdraw function. Only the address that originally deployed the contract (the owner) is authorized to transfer the accumulated funds out of the contract.

How can I add a user interface to this contract?
You can build a web application using a library like React or Vue.js and integrate it with the contract using a web3 provider such as Ethers.js or Web3.js. This UI would allow users to connect their wallets and call the donate function through a button click.

Next Steps and Project Enhancements

With a functional core contract, consider these ideas to extend your project's capabilities and user experience.