Description:
Smart contract deployed on Ethereum.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract EarlyAccess {
// Tracks prepaw selections: player => optionId => quantity selected
mapping(address => mapping(uint256 => uint256)) public prepaws;
// Track total selected per option
mapping(uint256 => uint256) public totalPrePawsPerOption;
// Track all unique players who purchased
address[] public players;
mapping(address => bool) public hasPrePawed;
// Track all unique referrers (separate from players - can refer without buying)
address[] public referrers;
mapping(address => bool) public isReferrer;
// Referral tracking: referrer => tier => count
mapping(address => mapping(uint256 => uint256)) public referralsByTier;
mapping(address => uint256) public totalReferrals;
// Track WHO was referred by each referrer and WHICH tier they bought
mapping(address => address[]) public referredPlayers;
mapping(address => uint256[]) public referredPlayerTiers;
// Option quantities
uint256[4] public optionQuantities = [1, 3, 5, 10];
// Max supply per tier
uint256[4] public maxSupplyPerTier;
// Price per unit in wei (0.025 ETH)
uint256 public constant PRICE_PER_UNIT = 0.025 ether;
address public owner;
bool public paused;
event PrePaw(address indexed player, uint256 indexed optionId, uint256 quantity, address indexed referrer);
event Withdrawal(address indexed to, uint256 amount);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event Paused(address account);
event Unpaused(address account);
event MaxSupplyUpdated(uint256 indexed optionId, uint256 newMaxSupply);
event Referral(address indexed referrer, address indexed player, uint256 indexed optionId);
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier whenNotPaused() {
require(!paused, "Presale is paused");
_;
}
constructor() {
owner = msg.sender;
paused = false;
// Set initial max supplies: [500, 200, 25, 10]
maxSupplyPerTier[0] = 500;
maxSupplyPerTier[1] = 200;
maxSupplyPerTier[2] = 25;
maxSupplyPerTier[3] = 10;
}
function prePaw(uint256 optionId, address referrer) external payable whenNotPaused {
require(optionId < 4, "Invalid option");
require(totalPrePawsPerOption[optionId] < maxSupplyPerTier[optionId], "Tier sold out");
require(prepaws[msg.sender][optionId] == 0, "Already purchased this tier");
require(referrer != msg.sender, "Cannot refer yourself");
uint256 quantity = optionQuantities[optionId];
uint256 cost = quantity * PRICE_PER_UNIT;
require(msg.value == cost, "Incorrect payment");
// Track first-time players
if (!hasPrePawed[msg.sender]) {
players.push(msg.sender);
hasPrePawed[msg.sender] = true;
}
prepaws[msg.sender][optionId] += 1;
totalPrePawsPerOption[optionId] += 1;
// Track referral if valid referrer provided
if (referrer != address(0)) {
// Track first-time referrers
if (!isReferrer[referrer]) {
referrers.push(referrer);
isReferrer[referrer] = true;
}
referralsByTier[referrer][optionId] += 1;
totalReferrals[referrer] += 1;
referredPlayers[referrer].push(msg.sender);
referredPlayerTiers[referrer].push(optionId);
emit Referral(referrer, msg.sender, optionId);
}
emit PrePaw(msg.sender, optionId, quantity, referrer);
}
function withdraw() external onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "No funds");
(bool success, ) = owner.call{value: balance}("");
require(success, "Transfer failed");
emit Withdrawal(owner, balance);
}
function emergencyWithdraw(address payable recipient) external onlyOwner {
require(recipient != address(0), "Invalid recipient");
uint256 balance = address(this).balance;
require(balance > 0, "No funds");
(bool success, ) = recipient.call{value: balance}("");
require(success, "Transfer failed");
emit Withdrawal(recipient, balance);
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "New owner is zero address");
address oldOwner = owner;
owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
function pause() external onlyOwner {
paused = true;
emit Paused(msg.sender);
}
function unpause() external onlyOwner {
paused = false;
emit Unpaused(msg.sender);
}
function setMaxSupply(uint256 optionId, uint256 newMaxSupply) external onlyOwner {
require(optionId < 4, "Invalid option");
require(newMaxSupply >= totalPrePawsPerOption[optionId], "Cannot set below current sales");
maxSupplyPerTier[optionId] = newMaxSupply;
emit MaxSupplyUpdated(optionId, newMaxSupply);
}
function getAllPrePaws(address player) external view returns (uint256[4] memory) {
return [
prepaws[player][0],
prepaws[player][1],
prepaws[player][2],
prepaws[player][3]
];
}
function getPrePaws(address player, uint256 optionId) external view returns (uint256) {
return prepaws[player][optionId];
}
function getPrice(uint256 optionId) external view returns (uint256) {
require(optionId < 4, "Invalid option");
return optionQuantities[optionId] * PRICE_PER_UNIT;
}
function getBalance() external view returns (uint256) {
return address(this).balance;
}
function getTotalPlayers() external view returns (uint256) {
return players.length;
}
function getAllPlayers() external view returns (address[] memory) {
return players;
}
function getPlayerAtIndex(uint256 index) external view returns (address) {
require(index < players.length, "Index out of bounds");
return players[index];
}
function getMaxSupply(uint256 optionId) external view returns (uint256) {
require(optionId < 4, "Invalid option");
return maxSupplyPerTier[optionId];
}
function getRemainingSupply(uint256 optionId) external view returns (uint256) {
require(optionId < 4, "Invalid option");
return maxSupplyPerTier[optionId] - totalPrePawsPerOption[optionId];
}
function getReferralsByTier(address referrer) external view returns (uint256[4] memory) {
return [
referralsByTier[referrer][0],
referralsByTier[referrer][1],
referralsByTier[referrer][2],
referralsByTier[referrer][3]
];
}
function getTotalReferrals(address referrer) external view returns (uint256) {
return totalReferrals[referrer];
}
function getReferralsForTier(address referrer, uint256 optionId) external view returns (uint256) {
require(optionId < 4, "Invalid option");
return referralsByTier[referrer][optionId];
}
function getTotalReferrers() external view returns (uint256) {
return referrers.length;
}
// BATCH FUNCTIONS
function getPlayerDataBatch(uint256 startIndex, uint256 count)
external
view
returns (
address[] memory addresses,
uint256[4][] memory purchases
)
{
require(count <= 50, "Max 50 per batch");
uint256 totalPlayers = players.length;
if (startIndex >= totalPlayers) {
return (new address[](0), new uint256[4][](0));
}
uint256 endIndex = startIndex + count;
if (endIndex > totalPlayers) {
endIndex = totalPlayers;
}
uint256 resultCount = endIndex - startIndex;
addresses = new address[](resultCount);
purchases = new uint256[4][](resultCount);
for (uint256 i = 0; i < resultCount; i++) {
address player = players[startIndex + i];
addresses[i] = player;
purchases[i] = [
prepaws[player][0],
prepaws[player][1],
prepaws[player][2],
prepaws[player][3]
];
}
return (addresses, purchases);
}
function getReferralDataBatch(uint256 startIndex, uint256 count)
external
view
returns (
address[] memory addresses,
uint256[4][] memory referralsByTierData,
uint256[] memory totalReferralsData
)
{
require(count <= 50, "Max 50 per batch");
uint256 totalReferrersCount = referrers.length;
if (startIndex >= totalReferrersCount) {
return (new address[](0), new uint256[4][](0), new uint256[](0));
}
uint256 endIndex = startIndex + count;
if (endIndex > totalReferrersCount) {
endIndex = totalReferrersCount;
}
uint256 resultCount = endIndex - startIndex;
addresses = new address[](resultCount);
referralsByTierData = new uint256[4][](resultCount);
totalReferralsData = new uint256[](resultCount);
for (uint256 i = 0; i < resultCount; i++) {
address referrer = referrers[startIndex + i];
addresses[i] = referrer;
referralsByTierData[i] = [
referralsByTier[referrer][0],
referralsByTier[referrer][1],
referralsByTier[referrer][2],
referralsByTier[referrer][3]
];
totalReferralsData[i] = totalReferrals[referrer];
}
return (addresses, referralsByTierData, totalReferralsData);
}
function getReferredPlayersBatch(address referrer, uint256 startIndex, uint256 count)
external
view
returns (
address[] memory referredAddresses,
uint256[] memory tiers
)
{
require(count <= 50, "Max 50 per batch");
address[] storage referred = referredPlayers[referrer];
uint256 totalReferred = referred.length;
if (startIndex >= totalReferred) {
return (new address[](0), new uint256[](0));
}
uint256 endIndex = startIndex + count;
if (endIndex > totalReferred) {
endIndex = totalReferred;
}
uint256 resultCount = endIndex - startIndex;
referredAddresses = new address[](resultCount);
tiers = new uint256[](resultCount);
for (uint256 i = 0; i < resultCount; i++) {
referredAddresses[i] = referredPlayers[referrer][startIndex + i];
tiers[i] = referredPlayerTiers[referrer][startIndex + i];
}
return (referredAddresses, tiers);
}
function getTotalReferredPlayers(address referrer) external view returns (uint256) {
return referredPlayers[referrer].length;
}
}
Submitted on: 2025-11-01 10:24:59
Comments
Log in to comment.
No comments yet.