Introducing Our First P2E Smart Contract for the $ALEIN Arcade

By Andrew Holness (Developer of The ALEIN Ascension Protocol) • 5 min read • October 15, 2025

Greetings to the ALEIN community and our valued investors,

Today marks a monumental step forward in our mission to build a vibrant and sustainable Play-to-Earn (P2E) ecosystem. We are thrilled to introduce the foundational piece of the ALEIN Ascension Protocol: the official rewards smart contract for our flagship title, $ALEIN Invaders.

This contract is more than just code; it's a transparent, secure, and automated vault that brings true on-chain rewards to our players, marking the official launch of the P2E $ALEIN Arcade. This dev blog will provide a detailed look into what this contract is, how it secures the ecosystem, and how it will function to reward our community.

What is the Alein Invaders Smart Contract?

At its core, the Alein Invaders smart contract is a self-executing program that lives on the Binance Smart Chain. Its sole purpose is to hold the P2E reward pool for the game and distribute $ALEIN tokens to players based on their performance, all without any manual intervention.

This contract is designed with three core principles in mind:

  • Security: To protect the project's and the community's assets.
  • Sustainability: To ensure the long-term health of the game's economy.
  • Transparency: To allow anyone to verify the reward logic on the blockchain.

How It Works: A Secure, Player-First Reward System

To prevent cheating and ensure fairness, we have implemented an industry-leading security model using cryptographic signatures. A player cannot simply "tell" the contract they got a high score. Instead, they must prove it.

Think of it like a bank vault that only opens with a special, single-use key.

  1. Score Validation: When a player finishes a game, the score is sent to our secure backend server. This server acts as our referee, validating the score against our game logic and anti-cheat systems.
  2. Forging the "Key": If the score is legitimate, our server uses its private key—the master key of the contract—to generate a unique, unforgeable digital signature. This signature is the "permission slip" that approves that specific score for that specific player.
  3. Player-Initiated Claim: The player's game receives this signature. When the player clicks "Claim Tokens," they initiate the final transaction on the blockchain, presenting the signature to the smart contract.
  4. The Vault Unlocks: The smart contract performs a final cryptographic check. It verifies that the signature was indeed created by our server and hasn't been used before. If everything is valid, it automatically transfers the earned $ALEIN tokens from its vault directly to the player's wallet.

This model provides the best of both worlds: the robust security of centralized validation and the decentralized, trustless execution that Web3 promises.

The P2E Economy: Seasons, Rewards, and Sustainability

A successful P2E game requires a carefully managed economy. Our contract is built with several powerful levers to ensure long-term sustainability.

The Seasonal Model

The game will operate in "seasons." For Season 1 of Alein Invaders, we will fund the contract with a specific allocation of $ALEIN tokens (e.g., 1% of the total supply). This batch of tokens represents the total reward pool for that season. This approach allows us to:

  • Analyze player engagement and reward distribution at the end of each season.
  • Fine-tune the reward parameters to ensure the economy remains balanced and exciting for future seasons.
  • Provide clear checkpoints and create a predictable economic cycle for our players and investors.

Reward Calculation & Economic Safeguards

  • Reward Formula: For Season 1, the rewards will be based on a simple, transparent formula: Player Score / 1000. For example, a score of 126,800 will yield a reward of 126 $ALEIN tokens.
  • Weekly Claim Limit: To manage the outflow of tokens and maintain stability, the contract will enforce a weekly distribution limit of 7,500 $ALEIN.
  • Holder Requirement: To reward our most dedicated community members, players will be required to hold at least 50,000 $ALEIN in their wallet to be eligible to claim P2E rewards.

Security: Protecting the Ecosystem

Protecting the rewards pool is our highest priority. The contract is built with multiple layers of security, utilizing audited, industry-standard code from OpenZeppelin.

  • Owner-Controlled Signatures: Our primary defense against cheating.
  • Replay Attack Prevention: The contract uses a "nonce" system, ensuring that each signature for a high score can only be used once.
  • Administrative Control: All critical functions—like adjusting the reward rate or weekly limit—are restricted to the team's secure owner wallet.
  • Re-Entrancy Guards: The contract is protected from a common form of attack where a malicious actor could try to drain funds by repeatedly calling the claim function within a single transaction.

The Bigger Picture: 13 Games, One Vision

The Alein Invaders contract is the blueprint. It represents the first step in our broader vision for the $ALEIN Arcade. We will be deploying a similar independent and secure rewards contract for each of our 13 upcoming games.

The 15% of the total token supply allocated to P2E will be strategically distributed across these 13 contracts. Some games may receive a 1% seasonal allocation, while others might receive 1.5%, depending on their design and player base. This multi-contract architecture ensures that our ecosystem is resilient, secure, and scalable.

We are incredibly excited to embark on this next phase of the ALEIN journey with you. The launch of this first P2E smart contract is a testament to our commitment to building real, sustainable value for our community.

Stay tuned for deployment announcements and the launch of Season 1!

The Official Alein Invaders P2E Contract

For full transparency, the complete source code for the smart contract is provided below for community review and audit.

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

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/token/ERC20/IERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/access/Ownable.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/utils/ReentrancyGuard.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/utils/cryptography/EIP712.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.0.1/contracts/utils/cryptography/ECDSA.sol";

/**
 * @title AleinInvaders
 * @dev This contract uses EIP-712 signed messages to securely reward players.
 * A backend server signs a player's score, and the player submits that signature
 * to claim their tokens, preventing cheating while maintaining a good user experience.
 */
contract AleinInvaders is Ownable, ReentrancyGuard, EIP712 {
    // The BEP-20 token contract used for rewards.
    IERC20 public immutable aleinToken;

    // A rate to determine how many tokens are awarded per score point.
    uint256 public scoreToTokenRate = 1000;

    // --- Claim Limit Variables ---
    // Note: This limit should include token decimals (e.g., 7500 * 10**18 for 7,500 tokens).
    uint256 public weeklyTokenLimit = 7500 * (10**18);
    uint256 public currentWeekStartTimestamp;
    uint256 public tokensClaimedThisWeek;
    uint256 public minTokenBalanceToClaim = 50000 * (10**18);

    // Mapping to store the highest score claimed by each player to prevent replays.
    mapping(address => uint256) public claimedHighScores;

    // A nonce for each player to prevent signature replay attacks.
    mapping(address => uint256) public playerNonces;

    // Event to log when a player successfully claims a reward.
    event TokensClaimed(address indexed player, uint256 score, uint256 tokensAwarded);

    bytes32 private constant CLAIM_TYPEHASH = keccak256("Claim(address player,uint256 score,uint256 nonce)");

    /**
     * @dev Sets token address, EIP712 domain, and initial weekly timestamp.
     */
    constructor(address _tokenAddress, address initialOwner)
        Ownable(initialOwner)
        EIP712("AleinInvaders", "1")
    {
        require(_tokenAddress != address(0), "Token address cannot be zero");
        aleinToken = IERC20(_tokenAddress);
        currentWeekStartTimestamp = block.timestamp;
    }

    /**
     * @dev Allows a player to claim tokens by providing a valid signature from the owner.
     * @param _player The address of the player receiving the reward.
     * @param _score The score being claimed.
     * @param _signature A signature generated by the owner's private key.
     */
    function claimWithSignature(address _player, uint256 _score, bytes calldata _signature) external nonReentrant {
        require(_player == msg.sender, "Signature is not for you.");
        
        uint256 nonce = playerNonces[_player];

        // Hash the claim data according to EIP-712 standard.
        bytes32 structHash = keccak256(abi.encode(CLAIM_TYPEHASH, _player, _score, nonce));
        bytes32 digest = _hashTypedDataV4(structHash);

        // Recover the address that signed the message.
        address signerAddress = ECDSA.recover(digest, _signature);
        
        // Verify that the signer is the contract owner.
        require(signerAddress == owner(), "Invalid signature.");

        // Check if the player holds the minimum required token balance.
        require(aleinToken.balanceOf(_player) >= minTokenBalanceToClaim, "Insufficient token balance to claim.");

        // Ensure the new score is higher than any previously claimed score.
        require(_score > claimedHighScores[_player], "Score must be higher than your last claimed score.");
        
        // --- Weekly Limit Logic ---
        // Check if a week has passed to reset the weekly counter.
        if (block.timestamp >= currentWeekStartTimestamp + 7 days) {
            currentWeekStartTimestamp = block.timestamp;
            tokensClaimedThisWeek = 0;
        }

        // Calculate the reward.
        uint256 tokensToAward = _score / scoreToTokenRate;
        require(tokensToAward > 0, "Score not high enough for a reward.");

        // Check if this claim exceeds the weekly limit.
        require(tokensClaimedThisWeek + tokensToAward <= weeklyTokenLimit, "Weekly token limit reached.");
        // --- End of Weekly Limit Logic ---

        // Check if the contract has enough tokens.
        uint256 contractBalance = aleinToken.balanceOf(address(this));
        require(contractBalance >= tokensToAward, "Contract has insufficient token balance.");

        // --- Effects (State Changes) ---
        // Increment the nonce to prevent this signature from being used again.
        playerNonces[_player]++;
        // Update the player's claimed high score.
        claimedHighScores[_player] = _score;
        // Update the weekly claim count.
        tokensClaimedThisWeek += tokensToAward;

        // --- Interaction ---
        // Transfer the tokens to the player.
        aleinToken.transfer(_player, tokensToAward);

        emit TokensClaimed(_player, _score, tokensToAward);
    }

    /**
     * @dev Allows the contract owner to withdraw any remaining tokens.
     */
    function withdrawRemainingTokens() external onlyOwner {
        uint256 balance = aleinToken.balanceOf(address(this));
        if (balance > 0) {
            aleinToken.transfer(owner(), balance);
        }
    }

    /**
     * @dev Allows the owner to update the score-to-token conversion rate.
     */
    function setScoreToTokenRate(uint256 _newRate) external onlyOwner {
        require(_newRate > 0, "Rate must be greater than zero.");
        scoreToTokenRate = _newRate;
    }

    /**
     * @dev Allows the owner to update the weekly token claim limit.
     * @param _newLimit The new weekly limit, including decimals (e.g., 10000 * 10**18 for 10,000 tokens).
     */
    function setWeeklyTokenLimit(uint256 _newLimit) external onlyOwner {
        weeklyTokenLimit = _newLimit;
    }

    /**
     * @dev Allows the owner to update the minimum token balance required to claim rewards.
     * @param _newBalance The new minimum balance, including decimals.
     */
    function setMinTokenBalanceToClaim(uint256 _newBalance) external onlyOwner {
        minTokenBalanceToClaim = _newBalance;
    }
}