// SPDX-License-Identifier: MIT
// Website: www.biblicaltruth.io
// Twitter / X: https://twitter.com/Bible316Truth
// Telegram: https://t.me/biblicaltruthtoken
// Discord: https://discord.gg/xqAkUBMf
// Built with Love by: Decentral Bro's: https://www.decentralbros.xyz/
//███████████████████████████████████████████████████████████████████
//█░░░░░░░░░░░░░░███░░░░░░░░░░░░░░█░░░░░░░░░░░░░░░░███░░░░░░██░░░░░░█
//█░░▄▀▄▀▄▀▄▀▄▀░░███░░▄▀▄▀▄▀▄▀▄▀░░█░░▄▀▄▀▄▀▄▀▄▀▄▀░░███░░▄▀░░██░░▄▀░░█
//█░░▄▀░░░░░░▄▀░░███░░░░░░▄▀░░░░░░█░░▄▀░░░░░░░░▄▀░░███░░▄▀░░██░░▄▀░░█
//█░░▄▀░░██░░▄▀░░███████░░▄▀░░█████░░▄▀░░████░░▄▀░░███░░▄▀░░██░░▄▀░░█
//█░░▄▀░░░░░░▄▀░░░░█████░░▄▀░░█████░░▄▀░░░░░░░░▄▀░░███░░▄▀░░██░░▄▀░░█
//█░░▄▀▄▀▄▀▄▀▄▀▄▀░░█████░░▄▀░░█████░░▄▀▄▀▄▀▄▀▄▀▄▀░░███░░▄▀░░██░░▄▀░░█
//█░░▄▀░░░░░░░░▄▀░░█████░░▄▀░░█████░░▄▀░░░░░░▄▀░░░░███░░▄▀░░██░░▄▀░░█
//█░░▄▀░░████░░▄▀░░█████░░▄▀░░█████░░▄▀░░██░░▄▀░░█████░░▄▀░░██░░▄▀░░█
//█░░▄▀░░░░░░░░▄▀░░█████░░▄▀░░█████░░▄▀░░██░░▄▀░░░░░░█░░▄▀░░░░░░▄▀░░█
//█░░▄▀▄▀▄▀▄▀▄▀▄▀░░█████░░▄▀░░█████░░▄▀░░██░░▄▀▄▀▄▀░░█░░▄▀▄▀▄▀▄▀▄▀░░█
//█░░░░░░░░░░░░░░░░█████░░░░░░█████░░░░░░██░░░░░░░░░░█░░░░░░░░░░░░░░█
//███████████████████████████████████████████████████████████████████
//────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
//─████████████───██████████████─██████──────────██████─██████████████─██████████████─██████████─██████████████─██████──────────██████─██████████████─
//─██░░░░░░░░████─██░░░░░░░░░░██─██░░██████████──██░░██─██░░░░░░░░░░██─██░░░░░░░░░░██─██░░░░░░██─██░░░░░░░░░░██─██░░██████████──██░░██─██░░░░░░░░░░██─
//─██░░████░░░░██─██░░██████░░██─██░░░░░░░░░░██──██░░██─██░░██████░░██─██████░░██████─████░░████─██░░██████░░██─██░░░░░░░░░░██──██░░██─██░░██████████─
//─██░░██──██░░██─██░░██──██░░██─██░░██████░░██──██░░██─██░░██──██░░██─────██░░██───────██░░██───██░░██──██░░██─██░░██████░░██──██░░██─██░░██─────────
//─██░░██──██░░██─██░░██──██░░██─██░░██──██░░██──██░░██─██░░██████░░██─────██░░██───────██░░██───██░░██──██░░██─██░░██──██░░██──██░░██─██░░██████████─
//─██░░██──██░░██─██░░██──██░░██─██░░██──██░░██──██░░██─██░░░░░░░░░░██─────██░░██───────██░░██───██░░██──██░░██─██░░██──██░░██──██░░██─██░░░░░░░░░░██─
//─██░░██──██░░██─██░░██──██░░██─██░░██──██░░██──██░░██─██░░██████░░██─────██░░██───────██░░██───██░░██──██░░██─██░░██──██░░██──██░░██─██████████░░██─
//─██░░██──██░░██─██░░██──██░░██─██░░██──██░░██████░░██─██░░██──██░░██─────██░░██───────██░░██───██░░██──██░░██─██░░██──██░░██████░░██─────────██░░██─
//─██░░████░░░░██─██░░██████░░██─██░░██──██░░░░░░░░░░██─██░░██──██░░██─────██░░██─────████░░████─██░░██████░░██─██░░██──██░░░░░░░░░░██─██████████░░██─
//─██░░░░░░░░████─██░░░░░░░░░░██─██░░██──██████████░░██─██░░██──██░░██─────██░░██─────██░░░░░░██─██░░░░░░░░░░██─██░░██──██████████░░██─██░░░░░░░░░░██─
//─████████████───██████████████─██████──────────██████─██████──██████─────██████─────██████████─██████████████─██████──────────██████─██████████████─
//────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
// John 3:16
// “For God so loved the world, that he gave his only begotten Son, that whosoever believeth in him should not perish,
// but have everlasting life.”
//Imports:
//IERC20.sol: This is the OpenZeppelin interface for ERC20 tokens, used to interact with ERC20-compliant token contracts.
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
pragma solidity ^0.8.17;
//Contract Variables:
//owner: Address of the contract owner.
//totalRaised: Total amount of Ether raised across all campaigns.
//goal: The fundraising goal amount for each campaign.
//campaignCount: Number of campaigns created.
//BiblicalTruthToken: Instance of the ERC20 token contract.
//campaignRaised: Mapping to track the amount of Ether raised for each campaign.
//campaignDetails: Mapping to store details (name, description, image hash) of each campaign.
contract BiblicalTruthDonations {
address public owner;
uint256 public totalRaised;
uint256 public goal;
uint256 public campaignCount;
IERC20 public BiblicalTruthToken;
mapping(uint256 => uint256) public campaignRaised;
mapping(uint256 => CampaignDetails) public campaignDetails;
//Events:
//DonationReceived: Triggered when a donation is received.
//Withdrawal: Triggered when Ether is withdrawn from the contract.
//CampaignReset: Triggered when a new campaign is started or an existing one is reset.
//FundsWithdrawnForCampaign: Triggered when funds are withdrawn for a specific campaign.
event DonationReceived(address donor, uint256 amount, uint256 campaignIndex);
event Withdrawal(address owner, uint256 amount);
event CampaignReset(uint256 campaignIndex, uint256 newGoal, string name, string description, string ipfsImageHash);
event FundsWithdrawnForCampaign(uint256 campaignIndex, uint256 amountWithdrawn);
//Struct:
//CampaignDetails: Struct to store campaign-related information like name, description, and image hash.
struct CampaignDetails {
string name;
string description;
string ipfsImageHash;
}
//Constructor:
// Initializes the contract with the owner address and sets the ERC20 token contract.
constructor(address _BiblicalTruthTokenAddress) {
owner = msg.sender;
BiblicalTruthToken = IERC20(_BiblicalTruthTokenAddress);
campaignCount = 0;
}
//Modifier:
//onlyOwner: Restricts access to functions only to the contract owner.
modifier onlyOwner() {
require(msg.sender == owner, "Not the owner");
_;
}
function donate() public payable {
require(msg.value > 0, "Donation must be greater than 0");
campaignRaised[campaignCount] += msg.value;
if (campaignRaised[campaignCount] > goal) {
// Allow donations to exceed goal, excess will roll over to next campaign
}
totalRaised += msg.value;
emit DonationReceived(msg.sender, msg.value, campaignCount);
}
//Functions:
//donate: Allows users to donate Ether to the current campaign.
//withdraw: Allows the owner to withdraw Ether from the contract.
//resetCampaign: Allows the owner to reset the current campaign or start a new one with specified details.
//getBalance: Returns the Ether balance of the contract.
//getCampaignRaised: Returns the amount of Ether raised for a specific campaign.
//withdrawTokens: Allows the owner to withdraw ERC20 tokens from the contract.
function withdraw() public onlyOwner {
uint256 raised = campaignRaised[campaignCount];
uint256 amountToWithdraw = raised > goal ? goal : raised;
require(address(this).balance >= amountToWithdraw, "Insufficient funds");
(bool success, ) = owner.call{value: amountToWithdraw}("");
require(success, "Failed to send Ether");
uint256 excess = raised - amountToWithdraw;
campaignRaised[campaignCount] = excess;
emit Withdrawal(owner, amountToWithdraw);
}
function resetCampaign(uint256 _newGoal, string memory _name, string memory _description, string memory _ipfsImageHash) public onlyOwner {
require(address(this).balance >= 0, "No funds to start a new campaign");
goal = _newGoal;
campaignCount += 1;
campaignRaised[campaignCount] = address(this).balance;
// Set the new campaign details
campaignDetails[campaignCount] = CampaignDetails({
name: _name,
description: _description,
ipfsImageHash: _ipfsImageHash
});
emit CampaignReset(campaignCount, _newGoal, _name, _description, _ipfsImageHash);
}
function getBalance() public view returns (uint256) {
return address(this).balance;
}
function getCampaignRaised(uint256 campaignIndex) public view returns (uint256) {
return campaignRaised[campaignIndex];
}
function withdrawTokens() public onlyOwner {
require(BiblicalTruthToken.balanceOf(address(this)) > 0, "No tokens to withdraw");
uint256 balance = BiblicalTruthToken.balanceOf(address(this));
BiblicalTruthToken.transfer(owner, balance);
emit Withdrawal(owner, balance);
}
//Fallback and Receive Functions:
//receive: Fallback function to accept Ether sent directly to the contract.
//fallback: Fallback function to accept Ether sent without data.
receive() external payable {}
fallback() external payable {}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
{
"compilationTarget": {
"contracts/BiblicalTruthDonations.sol": "BiblicalTruthDonations"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_BiblicalTruthTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"campaignIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newGoal","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"description","type":"string"},{"indexed":false,"internalType":"string","name":"ipfsImageHash","type":"string"}],"name":"CampaignReset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"donor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"campaignIndex","type":"uint256"}],"name":"DonationReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"campaignIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountWithdrawn","type":"uint256"}],"name":"FundsWithdrawnForCampaign","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"BiblicalTruthToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"campaignCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"campaignDetails","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"description","type":"string"},{"internalType":"string","name":"ipfsImageHash","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"campaignRaised","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"donate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"campaignIndex","type":"uint256"}],"name":"getCampaignRaised","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"goal","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newGoal","type":"uint256"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_description","type":"string"},{"internalType":"string","name":"_ipfsImageHash","type":"string"}],"name":"resetCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalRaised","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]