// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
importieren Sie "@openzeppelin/contracts/token/ERC20/ERC20.sol";
importieren Sie "@openzeppelin/contracts/access/Ownable.sol";
Vertrag PhilanthropyToken ist ERC20, Ownable {
uint256 public constant MAX_TOTAL_SUPPLY = 500 * 10 ** 6 * 10 ** 18; // Maximaler Gesamtvorrat von 500 Millionen Token
uint256 public constant MARKET_CAP = 10 * 10 ** 6 * 10 ** 18; // Standard-Marktkapitalisierung von 10 Millionen Token
uint256 public INVESTOR_ALLOCATION = 4 * 10 ** 6 * 10 ** 18; // 4 Millionen Token für Investoren
uint256 public constant GENERAL_PUBLIC_ALLOCATION = 5 * 10 ** 6 * 10 ** 18; // 5 Millionen Token für die Allgemeinheit
uint256 public CHARITY_ALLOCATION = 4 * 10 ** 6 * 10 ** 18; // 4 Millionen Token für Wohltätigkeitsorganisationen
uint256 public constant PRESALE_ALLOCATION = 5 * 10 ** 6 * 10 ** 18; // 5 Millionen Token für den Vorverkauf
uint256 public PRESALE_TOTAL_SOLD = 0;
uint256 public constant INVESTOR_LOCK_PERIOD = 730 Tage; // 2 Jahre Sperrfrist für Anleger
uint256 public constant PRESALE_LOCK_PERIOD = 365 Tage; // 1 Jahr Sperrfrist für Vorverkauf
uint256 public TOTAL_INITIAL_RELEASED = 0;
uint256 public TOTAL_INVESTOR_CLAIMED = 0;
uint256 öffentliche Konstante PRESALE_PRICE = 50 * 10 ** 15; // $0,50 in Euro
uint256 public constant TRANSACTION_THRESHOLD = 1 * 10 ** 6 * 10 ** 18; // 1m Transaktionsschwelle für die Anforderung eines Geheimcodes
uint256 public presaleStartTime;
// Mapping to track buyer purchase timestamps
mapping(address => uint256) public lastPurchaseTimestamp;
string public secretCode;
mapping(address => bool) public admins;
/**
* Nur Admin-Modifikator
*/
Modifikator onlyAdmin() {
require(admins[msg.sender] || msg.sender == owner(), "Not an admin");
_;
}
/**
* Konstrukteur
*/
constructor() ERC20("PhilanthropyToken", "PTPH") {
// Mint the initial supply to the contract owner
_mint(msg.sender, MARKET_CAP);
presaleStartTime = block.timestamp;
// Transfer ownership to the contract deployer!
transferOwnership(msg.sender);
}
// Function to add or remove admins
function setAdmin(address _admin, bool _status) external onlyOwner {
admins[_admin] = _status;
}
/**
* Funktion, die es Nutzern ermöglicht, Token für den Vorverkauf zu kaufen
* @param amount uint256
*/
function buyPresaleTokens(uint256 amount) external payable {
require(amount > 0, "Ungültiger Kaufbetrag");
erfordern(
block.timestamp >= presaleStartTime,
"Der Vorverkauf hat noch nicht begonnen"
);
erfordern(
block.timestamp <= presaleStartTime + 182.5 days,
"Vorverkauf beendet"
);
uint256 totalPrice = Betrag * PRESALE_PRICE;
require(msg.value >= totalPrice, "Unzureichende Mittel gesendet");
// Calculate and check remaining presale allocation
uint256 remainingPresaleAllocation = PRESALE_TOTAL_SOLD;
erfordern(
amount <= remainingPresaleAllocation,
"Nicht genügend Token zum Kauf verfügbar"
);
// Transfer tokens to the buyer
_transfer(address(this), msg.sender, amount);
// Update the buyer's last purchase timestamp
lastPurchaseTimestamp[msg.sender] = block.timestamp;
// Refund any excess funds sent
if (msg.value > totalPrice) {
payable(msg.sender).transfer(msg.value - totalPrice);
}
PRESALE_TOTAL_SOLD += Betrag;
}
/**
* Funktion zur Erhöhung der Marktkapitalisierung
* @param amount uint256
*/
function increaseMarketCap(uint256 amount) external onlyAdmin {
uint256 currentSupply = totalSupply();
erfordern(
currentSupply + amount <= MAX_TOTAL_SUPPLY,
"Übersteigt die maximale Gesamtversorgung"
);
_mint(Eigentümer(), Betrag);
}
/**
* Funktion zur Verteilung von CHARITY_ALLOCATION an mehrere Adressen
* @param recipients string<addresses>
* @param Beträge uint256
*/
Funktion initialRelease(
address[] Speicherempfänger,
uint256[] Speichermengen
) extern onlyAdmin {
erfordern(
recipients.length == amounts.length,
"Array-Längen stimmen nicht überein"
);
erfordern(
block.timestamp >= presaleStartTime + PRESALE_LOCK_PERIOD,
"Sperrfrist noch nicht abgelaufen"
);
for (uint256 i = 0; i < recipients.length; i++) {
Adresse recipient = recipients[i];
uint256 amount = amounts[i];
require(recipient != address(0), "Ungültige Empfängeradresse");
require(Betrag > 0, "Ungültiger Betrag");
TOTAL_INITIAL_RELEASED += Betrag;
erfordern(
TOTAL_INITIAL_RELEASED <= CHARITY_ALLOCATION,
"Gesamtverteilung übersteigt CHARITY_ALLOCATION"
);
// Transfer tokens to the recipient
_transfer(address(this), recipient, amount);
}
}
/**
* Funktion zur Verteilung von INVESTOR_ALLOCATION an mehrere Investoren
* @param Investoren Adresse
* @param Beträge uint256
*/
Funktion claimInvestorTokens(
address[] memory Investoren,
uint256[] Speichermengen
) extern onlyAdmin {
erfordern(
Investoren.Länge == Beträge.Länge,
"Array-Längen stimmen nicht überein"
);
erfordern(
block.timestamp >= presaleStartTime + INVESTOR_LOCK_PERIOD,
"Sperrfrist noch nicht abgelaufen"
);
for (uint256 i = 0; i < investors.length; i++) {
Adresse Investor = Investoren[i];
uint256 amount = amounts[i];
require(investor != address(0), "Ungültige Anlegeradresse");
require(Betrag > 0, "Ungültiger Betrag");
TOTAL_INVESTOR_CLAIMED += Betrag;
// Check if totalDistribution exceeds INVESTOR_ALLOCATION
erfordern(
TOTAL_INVESTOR_CLAIMED <= INVESTOR_ALLOCATION,
"Gesamtausschüttung übersteigt INVESTOR_ALLOCATION"
);
// Transfer tokens to the investor
_transfer(address(this), investor, amount);
}
}
// Function to set a secret code for transactions above the threshold
function setSecretCode(string memory code) external onlyAdmin {
secretCode = code;
}
// Function to perform a transaction above the threshold with the correct secret code
Funktion transfer(
Adresse des Empfängers,
uint256 Betrag,
String-Speichercode
) extern {
require(amount <= TRANSACTION_THRESHOLD, "Amount exceeds threshold");
erfordern(
keccak256(abi.encodePacked(code)) ==
keccak256(abi.encodePacked(secretCode)),
"Falscher Geheimcode"
);
_transfer(msg.Absender, Empfänger, Betrag);
}
/**
* Funktion zur Anzeige des Wertes TOTAL_INITIAL_RELEASED
* @return uint256
*/
Funktion getTotalIInvestorAllocation() external view liefert (uint256) {
return INVESTOR_ALLOCATION;
}
/**
* Funktion zur Anzeige des Wertes TOTAL_INVESTOR_CLAIMED
* @return uint256
*/
Funktion getTotalInitialAllocation() external view liefert (uint256) {
return CHARITY_ALLOCATION;
}
/**
* Funktion zur Anzeige des Wertes TOTAL_INITIAL_RELEASED
* @return uint256
*/
Funktion getTotalInitialReleased() external view liefert (uint256) {
return TOTAL_INITIAL_RELEASED;
}
/**
* Funktion zur Anzeige des Wertes TOTAL_INVESTOR_CLAIMED
* @return uint256
*/
function getTotalInvestorClaimed() external view returns (uint256) {
return TOTAL_INVESTOR_CLAIMED;
}
/**
* Funktion zur Übertragung von Token zwischen TOTAL_INITIAL_RELEASED und TOTAL_INVESTOR_CLAIMED
* @param amount uint256
* @param fromInitialToInvestor boolescher Wert
*/
function transferBetweenCategories(
uint256 Betrag,
bool fromInitialToInvestor
) extern onlyAdmin {
erfordern(
fromInitialToInvestor || TOTAL_INITIAL_RELEASED >= Betrag,
"Nicht genügend Token in INITIAL_RELEASED"
);
erfordern(
!fromInitialToInvestor || TOTAL_INVESTOR_CLAIMED >= Betrag,
"Unzureichende Token in INVESTOR_CLAIMED"
);
if (fromInitialToInvestor) {
CHARITY_ALLOCATION -= Betrag;
INVESTOR_ALLOCATION += Betrag;
} sonst {
INVESTOR_ALLOCATION -= Betrag;
CHARITY_ALLOCATION += Betrag;
}
_transfer(address(this), msg.sender, amount);
}
/**
* Funktion zur Übertragung von Token zwischen TOTAL_INITIAL_RELEASED und TOTAL_INVESTOR_CLAIMED
* @param amount uint256
* @param fromInitialToInvestor boolescher Wert
*/
function topupCategories(
uint256 Betrag,
bool fromInitialToInvestor
) extern onlyAdmin {
erfordern(
fromInitialToInvestor || CHARITY_ALLOCATION >= Betrag,
"Nicht genügend Token in INITIAL_RELEASED"
);
erfordern(
!fromInitialToInvestor || TOTAL_INVESTOR_CLAIMED >= Betrag,
"Unzureichende Token in INVESTOR_CLAIMED"
);
if (fromInitialToInvestor) {
CHARITY_ALLOCATION -= Betrag;
INVESTOR_ALLOCATION += Betrag;
} sonst {
INVESTOR_ALLOCATION -= Betrag;
CHARITY_ALLOCATION += Betrag;
}
_transfer(address(this), msg.sender, amount);
}
/**
* Funktion zum Aufladen von CHARITY_ALLOCATION aus dem verfügbaren Guthaben des Vertrags
* @param amount uint256
*/
function topUpCharityAllocation(uint256 amount) external onlyAdmin {
uint256 availableBalance = balanceOf(address(this));
require(amount <= availableBalance, "Exceeds available balance");
CHARITY_ALLOCATION += Betrag;
_transfer(address(this), owner(), amount);
}
/**
* Funktion zum Auffüllen von INVESTOR_ALLOCATION aus dem verfügbaren Guthaben des Vertrags
* @param amount uint256
*/
function topUpInvestorAllocation(uint256 amount) external onlyAdmin {
uint256 availableBalance = balanceOf(address(this));
require(amount <= availableBalance, "Exceeds available balance");
INVESTOR_ALLOCATION += Betrag;
_transfer(address(this), owner(), amount);
}
}