// SPDX-License-Identifier: MIT
soliditas pragma ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
kontrak PhilanthropyToken adalah ERC20, Dapat Dimiliki {
uint256 public constant MAX_TOTAL_SUPPLY = 500 * 10 ** 6 * 10 ** 18; // Total pasokan maksimum 500 juta token
uint256 public constant MARKET_CAP = 10 * 10 ** 6 * 10 ** 18; // Kapitalisasi pasar default sebesar 10 juta token
uint256 public INVESTOR_ALLOCATION = 4 * 10 ** 6 * 10 ** 18; // 4 juta token untuk investor
uint256 public constant GENERAL_PUBLIC_ALLOCATION = 5 * 10 ** 6 * 10 ** 18; // 5 juta token untuk masyarakat umum
uint256 public CHARITY_ALLOCATION = 4 * 10 ** 6 * 10 ** 18; // 4 juta token untuk amal
uint256 public constant PRESALE_ALLOCATION = 5 * 10 ** 6 * 10 ** 18; // 5 juta token untuk presale
uint256 public PRESALE_TOTAL_TERJUAL = 0;
uint256 public constant INVESTOR_LOCK_PERIODE = 730 days; // 2 tahun periode penguncian untuk investor
uint256 public constant PRESALE_LOCK_PERIOD = 365 days; // 1 tahun periode penguncian untuk presale
uint256 public TOTAL_INITIAL_RELEASED = 0;
uint256 public TOTAL_INVESTOR_CLAIMED = 0;
uint256 public constant HARGA_JUALAN = 50 * 10 ** 15; // $ 0.50 dalam wei
uint256 public constant TRANSACTION_THRESHOLD = 1 * 10 ** 6 * 10 ** 18; // 1m Ambang batas transaksi untuk membutuhkan kode rahasia
uint256 public presaleStartTime;
// Mapping to track buyer purchase timestamps
pemetaan(alamat => uint256) public lastPurchaseTimestamp;
string public secretCode;
pemetaan(alamat => bool) public admins;
/**
* Hanya pengubah admin
*/
pengubah hanyaAdmin() {
require(admins[msg.sender] || msg.sender == owner(), "Bukan admin");
_;
}
/**
* konstruktor
*/
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!
transferKepemilikan(msg.pengirim);
}
// Function to add or remove admins
function setAdmin(alamat _admin, bool _status) external onlyOwner {
admins[_admin] = _status;
}
/**
* Fungsi untuk memungkinkan pengguna membeli token presale
* @param jumlah uint256
*/
function buyPresaleTokens(uint256 amount) hutang eksternal {
require(jumlah > 0, "Jumlah pembelian tidak valid");
memerlukan(
block.timestamp >= presaleStartTime,
"Presale belum dimulai"
);
memerlukan(
block.timestamp <= presaleStartTime + 182.5 days,
"Presale telah berakhir"
);
uint256 totalHarga = jumlah * HARGA_JUALAN;
require(msg.value >= totalHarga, "Dana yang dikirim tidak mencukupi");
// Calculate and check remaining presale allocation
uint256 SisaAllokasiPenjualan = PRESALE_TOTAL_TERJUAL;
memerlukan(
amount <= remainingPresaleAllocation,
"Tidak cukup token yang tersedia untuk dibeli"
);
// Transfer tokens to the buyer
_transfer(alamat(ini), msg.pengirim, jumlah);
// Update the buyer's last purchase timestamp
lastPurchaseTimestamp[msg.sender] = block.timestamp;
// Refund any excess funds sent
if (msg.value > totalHarga) {
payable(msg.sender).transfer(msg.value - totalPrice);
}
PRESALE_TOTAL_TERJUAL += jumlah;
}
/**
* Berfungsi untuk meningkatkan kapitalisasi pasar
* @param jumlah uint256
*/
function increaseMarketCap(uint256 amount) external onlyAdmin {
uint256 currentSupply = totalSupply();
memerlukan(
currentSupply + amount <= MAX_TOTAL_SUPPLY,
"Melebihi total pasokan maksimum"
);
_mint(pemilik(), jumlah);
}
/**
* Fungsi untuk mendistribusikan CHARITY_ALLOCATION ke beberapa alamat
* @param recipients string<addresses>
* @param jumlah uint256
*/
function initialRelease(
alamat[] penerima memori,
uint256[] jumlah memori
) hanya eksternalAdmin {
memerlukan(
penerima.panjang == jumlah.panjang,
"Panjang larik tidak cocok"
);
memerlukan(
block.timestamp >= presaleStartTime + PRESALE_LOCK_PERIODE,
"Periode penguncian belum berakhir"
);
for (uint256 i = 0; i < recipients.length; i++) {
alamat penerima = penerima[i];
uint256 jumlah = jumlah[i];
require(penerima != alamat(0), "Alamat penerima tidak valid");
require(jumlah > 0, "Jumlah tidak valid");
TOTAL_INITIAL_DILEPAS += jumlah;
memerlukan(
TOTAL_INITIAL_RELEASED <= CHARITY_ALLOCATION,
"Total distribusi melebihi CHARITY_ALLOCATION"
);
// Transfer tokens to the recipient
transfer(alamat(ini), penerima, jumlah);
}
}
/**
* Fungsi untuk mendistribusikan INVESTOR_ALLOCATION ke beberapa investor
* Alamat investor @param
* @param jumlah uint256
*/
function claimInvestorTokens(
alamat[] investor memori,
uint256[] jumlah memori
) hanya eksternalAdmin {
memerlukan(
investor.length == jumlah.length,
"Panjang larik tidak cocok"
);
memerlukan(
block.timestamp >= presaleStartTime + INVESTOR_LOCK_PERIODE,
"Periode penguncian belum berakhir"
);
for (uint256 i = 0; i < investors.length; i++) {
alamat investor = investor[i];
uint256 jumlah = jumlah[i];
require(investor != address(0), "Alamat investor tidak valid");
require(jumlah > 0, "Jumlah tidak valid");
TOTAL_INVESTOR_KLAIM += jumlah;
// Check if totalDistribution exceeds INVESTOR_ALLOCATION
memerlukan(
TOTAL_INVESTOR_CLAIMED <= INVESTOR_ALLOCATION,
"Total distribusi melebihi INVESTOR_ALLOCATION"
);
// Transfer tokens to the investor
transfer(alamat(ini), investor, jumlah);
}
}
// Function to set a secret code for transactions above the threshold
function setSecretCode(string kode memori) external onlyAdmin {
secretCode = kode;
}
// Function to perform a transaction above the threshold with the correct secret code
transfer fungsi(
alamat penerima,
uint256 jumlah,
kode memori string
) eksternal {
require(amount <= TRANSACTION_THRESHOLD, "Amount exceeds threshold");
memerlukan(
keccak256(abi.encodePacked(kode)) ==
keccak256(abi.encodePacked(secretCode)),
"Kode rahasia salah"
);
transfer(msg.pengirim, penerima, jumlah);
}
/**
* Fungsi untuk menampilkan nilai TOTAL_INITIAL_RELEASED
* @return uint256
*/
function getTotalIInvestorAllocation() external view returns (uint256) {
return INVESTOR_ALLOCATION;
}
/**
* Fungsi untuk menampilkan nilai TOTAL_INVESTOR_CLAIMED
* @return uint256
*/
function getTotalAllocation() tampilan eksternal mengembalikan (uint256) {
return CHARITY_ALLOCATION;
}
/**
* Fungsi untuk menampilkan nilai TOTAL_INITIAL_RELEASED
* @return uint256
*/
function getTotalInitialReleased() tampilan eksternal mengembalikan (uint256) {
return TOTAL_INITIAL_DILEPAS;
}
/**
* Fungsi untuk menampilkan nilai TOTAL_INVESTOR_CLAIMED
* @return uint256
*/
function getTotalInvestorClaimed() tampilan eksternal mengembalikan (uint256) {
return TOTAL_INVESTOR_CLAIMED;
}
/**
* Fungsi untuk mentransfer token antara TOTAL_INITIAL_RELEASED dan TOTAL_INVESTOR_CLAIMED
* @param jumlah uint256
* @param fromInitialToInvestor boolean
*/
function transferAntaraKategori(
uint256 jumlah,
bool fromInitialToInvestor
) hanya eksternalAdmin {
memerlukan(
fromInitialToInvestor || TOTAL_INITIAL_DILEPAS >= jumlah,
"Token tidak mencukupi di INITIAL_RELEASED"
);
memerlukan(
!fromInitialToInvestor || TOTAL_INVESTOR_CLAIMED >= jumlah,
"Token tidak mencukupi di INVESTOR_CLAIMED"
);
if (fromInitialToInvestor) {
CHARITY_ALLOCATION -= jumlah;
INVESTOR_ALLOCATION += jumlah;
} else {
INVESTOR_ALLOCATION -= jumlah;
CHARITY_ALLOCATION += jumlah;
}
_transfer(alamat(ini), msg.pengirim, jumlah);
}
/**
* Fungsi untuk mentransfer token antara TOTAL_INITIAL_RELEASED dan TOTAL_INVESTOR_CLAIMED
* @param jumlah uint256
* @param fromInitialToInvestor boolean
*/
function topupCategories(
uint256 jumlah,
bool fromInitialToInvestor
) hanya eksternalAdmin {
memerlukan(
fromInitialToInvestor || CHARITY_ALLOCATION >= amount,
"Token tidak mencukupi di INITIAL_RELEASED"
);
memerlukan(
!fromInitialToInvestor || TOTAL_INVESTOR_CLAIMED >= jumlah,
"Token tidak mencukupi di INVESTOR_CLAIMED"
);
if (fromInitialToInvestor) {
CHARITY_ALLOCATION -= jumlah;
INVESTOR_ALLOCATION += jumlah;
} else {
INVESTOR_ALLOCATION -= jumlah;
CHARITY_ALLOCATION += jumlah;
}
_transfer(alamat(ini), msg.pengirim, jumlah);
}
/**
* Fungsi untuk menambah CHARITY_ALLOCATION dari saldo kontrak yang tersedia
* @param jumlah uint256
*/
function topUpCharityAllocation(uint256 amount) external onlyAdmin {
uint256 availableBalance = balanceOf(address(this));
require(amount <= availableBalance, "Exceeds available balance");
CHARITY_ALLOCATION += jumlah;
_transfer(alamat(ini), pemilik(), jumlah);
}
/**
* Fungsi untuk menambah INVESTOR_ALLOCATION dari saldo kontrak yang tersedia
* @param jumlah uint256
*/
function topUpInvestorAllocation(uint256 amount) external onlyAdmin {
uint256 availableBalance = balanceOf(address(this));
require(amount <= availableBalance, "Exceeds available balance");
INVESTOR_ALLOCATION += jumlah;
_transfer(alamat(ini), pemilik(), jumlah);
}
}