API for Stablecoin-Based Transaction Systems

				
					/**
 * @title MiCA StableCoin for Stabillon sp z o.o. 
 * @author Billon Group / AH
 *
 * Copyright 2025 Billon Group, Ltd. All rights reserved.
 * SPDX-License-Identifier: MIT
 *
 * @notice This is Interface for stablecoin with User-Centric Features: ERC-20 compatible and MiCA-compliant
  */
pragma solidity ^0.8.20;

// key interfaces for wide compatility with blockchain wallets and crypto exchanges
import { ISolidStateERC20 as IERC20 } from "@solidstate/contracts/token/ERC20/ISolidStateERC20.sol";
import { IAccessControl } from "@solidstate/contracts/access/access_control/IAccessControl.sol";
import "./StabillonStorage.sol"; 

/** =======================================================================
 *  IStabillonCoin
 *  -----------------------------------------------------------------------
 * @title IStabillonCoin - The Stablecoin That Actually Gets It
 *  
 * A stablecoin that doesn't sacrifice decentralization for compliance:
 * - Multiple liquidity pools so you're not stuck in one jurisdiction
 * - Governance that actually protects you from regulatory overreach and crazy developers
 * - Sweet rewards for minters (because why should the big guys have all the fun?)
 * - Transparent compliance stuff that won't make you pull your hair out
 *  ======================================================================= */
abstract contract IStabillonCoin is 
    IERC20,              // Interface for key ERC-20 standard token
    IAccessControl       // Now using SolidState's IAccessControl
{
    // ===============================================================
    // Role Definitions
    // ===============================================================
    bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
    bytes32 public constant FREEZER_ROLE = keccak256("FREEZER_ROLE");
    bytes32 public constant COMPLIANCE_ROLE = keccak256("COMPLIANCE_ROLE");
    bytes32 public constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant MASTER_MINTER_ROLE = keccak256("MASTER_MINTER_ROLE");
    bytes32 public constant POOL_MINTER_ROLE = keccak256("POOL_MINTER_ROLE");

    // ===============================================================
    // 1. Core ERC20 Functions & Extensions
    // NOTE: you have access to all standard ERC20 functions (OpenZeppelin) 
    // ===============================================================
    
    /**
     * IERC20 public functions inherited:
     * - totalSupply() - Returns the total minted token supply in circulation
     * - balanceOf(address) - Returns the token balance of a given account
     * - transfer(address,uint256) - Transfers tokens to a given recipient
     * - approve(address,uint256) - Grants approval to spender to spend tokens
     * - transferFrom(address,address,uint256) - Transfers tokens on behalf of a holder
     * - allowance(address,address) - Returns the allowance granted from holder to spender
     * - increaseAllowance(address,uint256) - Increases spend amount granted to spender
     * - decreaseAllowance(address,uint256) - Decreases spend amount granted to spender
     * 
     * Metadata functions:
     * - name() - Returns the token name
     * - symbol() - Returns the token symbol
     * - decimals() - Returns the token decimals (usually set to 2)
     * 
     * Permit functions (EIP-2612):
     * - DOMAIN_SEPARATOR() - Returns the EIP-712 domain separator for the contract
     * - nonces(address) - Gets the current nonce for the given address
     * - permit(address,address,uint256,uint256,uint8,bytes32,bytes32) - Approves tokens via signature
     */
    
    /**
     * @dev Transfers tokens with additional compliance data.
     * @param recipient Address receiving tokens.
     * @param amount Number of tokens to transfer.
     * @param extraData Off-chain compliance data (e.g., travel rule hash).
     * @return success True if transfer succeeds.
     * Purpose: Supports AML and Travel Rule compliance.
     */
    function transferWithCompliance(
        address recipient, 
        uint256 amount, 
        LibStabillonStorage.DocumentationSubmission calldata extraData 
    ) external virtual returns (bool);

    /**
     * @dev Transfers tokens using exclusively the specified fee batch.
     * If the sender does not have sufficient tokens in that fee batch, the transfer reverts.
     * @notice In some circumstances this may the most gas efficient way to transfer tokens, because  
     * it avoids the automatic fee batch selection algorithm that the base trasfer funtion needs to execute.
     * @param recipient The address to transfer tokens to.
     * @param amount The token amount to transfer.
     * @param feeBatch The fee batch identifier to exclusively debit.
     * @return True if the transfer succeeds.
     */
    function transferWithFeeBatch(address recipient, uint256 amount, bytes32 feeBatch) external virtual returns (bool);

    /**
     * @dev Approves a spender (authorised user) using exclusively the specified fee batch.
     * The approval will only be valid if the sender has sufficient balance in that fee batch
     * (i.e. future transfers via transferFromWithFeeBatch will pull tokens only from that fee batch).
     * If there is insufficient balance in that fee batch at the time of approval, the call reverts.
     * @notice This function can only be called by the user (owner of the tokens)
     * @param spender The address to approve.
     * @param amount The token amount to approve.
     * @param feeBatch The fee batch identifier to exclusively associate with the allowance.
     * @return True if the approval is successful.
     */
    function approveWithFeeBatch(address spender, uint256 amount, bytes32 feeBatch) external virtual returns (bool);

    // ===============================================================
    // 2. Token Supply: Minting & Redemption Management (money in circulation)
    // ===============================================================

    /**
     * @dev The standard-derived mint function that follows basic stablecoin minting pattern.
     * @notice This function automatically assigns either the default fee batch, or if user
     *      has registered for rewards the user's preferred fee batch to the minted tokens.
     * @notice This function uses the default liquidity pool for our minter.
     * @param to The address receiving the minted tokens.
     * @param amount The amount of tokens to mint.
     * uses reverts end emits error messages to communicate failure.
     */
    function mint(address to, uint256 amount) external virtual;

    /**
     * @dev Prefered function to mint new tokens from a designated liquidity pool.
     * @param to The recipient address that will receive the newly minted tokens.
     * @param amount The number of tokens to mint.
     * @param poolId Unique identifier for the liquidity pool. Different pools may be used for
     *        different jurisdictions (e.g. EU vs. US) to comply with local regulations.
     * @param fiatReference IPFS hash of the bank statement attesting to the specific liqudity event backing mint operation.
     *
     * @dev Requirements:
     *   - Caller must have the MINTER_ROLE.
     *   - A daily attestation (bank statement) must be recorded for the pool. If the last attestation
     *     is older than ATTESTATION_INTERVAL, the caller must record a new attestation.
     *   - The IPFS hash is stored for transparency.
     *
     * MiCA Reference: Article 49 requires that token issuance is fully backed by fiat reserves,
     * and regular attestation enhance transparency.
     */
    function mintFromPool(address to, uint256 amount, uint256 poolId, string memory fiatReference) external virtual;

    /**
     * @dev Redeems tokens for fiat by burning tokens from the caller's balance.
     * @param amount Number of tokens to redeem.
     * @param processingTime Expected processing duration for off-chain redemption.
     * @param maxGasFee Maximum technical network fee the user is willing to pay
     *
     * MiCA Art. 49: Ensures continuous redemption rights.
     */
    function redeem(uint256 amount, uint256 processingTime, uint256 maxGasFee) external virtual;

    /**
     * @dev Provides a cryptographic attestation of reserve backing.
     * @param poolId Liquidity pool identifier.
     * @return A bytes32 cryptographic proof.
     *
     * MiCA Art. 49: Requires transparent reserve backing.
     */
    function attestReserves(uint256 poolId) external virtual returns (bytes32);

    // ===============================================================
    // Liquidity Pool Management
    // ===============================================================
    
    /**
     * @notice Gets the current total token supply with additional info
     * @return totalSupply The total supply
     * @return circulatingSupply The y
     * @return frozenSupply The datance
     * @return blacklistedSupply The d
     */
    function getSupplyDetails() external view virtual returns (
        uint256 totalSupply,
        uint256 circulatingSupply,
        uint256 frozenSupply,
        uint256 blacklistedSupply
    );
    
    /**
     * @dev Gets information about a liquidity pool
     * @param poolId The unique identifier for the pool
     * @return exists Whether the pool exists
     * @return balance The current balance of the pool
     * @return lastAttestationTime The timestamp of the last attestation
     * @return lastAttestationHash The IPFS hash of the last attestation
     */
    function getLiquidityPoolInfo(uint256 poolId) external view virtual returns (
        bool exists,
        uint256 balance,
        uint256 lastAttestationTime,
        string memory lastAttestationHash
    );

    /**
     * @dev Gets the list of active pool IDs
     * @return List of active pool IDs
     */
    function getActivePools() external view virtual returns (uint256[] memory);

    /**
     * @dev Checks if a pool exists
     * @param poolId The unique identifier for the pool
     * @return Whether the pool exists
     */
    function poolExists(uint256 poolId) external view virtual returns (bool);
    
    /**
     * @dev Gets the balance of a liquidity pool
     * @param poolId The unique identifier for the pool
     * @return The current balance of the pool, returns 0 if pool doesn't exist
     */
    function getPoolBalance(uint256 poolId) external view virtual returns (uint256);
    
    /**
     * @dev Gets the last attestation timestamp for a pool
     * @param poolId The unique identifier for the pool
     * @return The timestamp of the last attestation, returns 0 if pool doesn't exist
     */
    function getLastAttestationTime(uint256 poolId) external view virtual returns (uint256);
    
    /**
     * @dev Gets the last attestation hash for a pool
     * @param poolId The unique identifier for the pool
     * @return The IPFS hash of the last attestation, returns empty string if pool doesn't exist
     */
    function getLastAttestationHash(uint256 poolId) external view virtual returns (string memory);
    
    // ===============================================================
    // 3. Rewards & Fee Batch Management
    // ===============================================================

    /**
     * @dev Requests a specific fee batch and reward percentage for minted tokens.
     * @param batchId The batch ID to request for future minting operations
     * @param rewardPercentage The percentage of fees to be allocated as rewards (0-100)
     * @return True if the request was submitted successfully
     *
     * @notice This function enables users to:
     *   - Request a specific fee batch for their minted tokens
     *   - Specify what percentage of those fees should be accumulated as rewards
     *   - The request must be approved by an admin before taking effect
     */
    function requestRewardFeePreference(bytes32 batchId, uint256 rewardPercentage) external virtual returns (bool);

    /**
     * @dev Checks if a user has requested a fee preference
     * @param user The address to check
     * @return True if the user has a fee preference
     */
    function hasRegisteredForRewardFee(address user) external view virtual returns (bool);

    /**
     * @dev Calculates cummulative rewards for a minter-helper based on their contribution history
     * @param minter The address of the minter-helper
     * @return The calculated rewards amount
     * Purpose:
     * This function provides an aggregate view of a minter’s rewards by calculating the total rewards accrued over the minter’s 
     * entire contribution history. In many reward schemes, the function internally iterates through contribution snapshots (or similar records) 
     * and computes a cumulative reward based on time weighting, multipliers, or other factors.
     * Usage:
     * It is intended as a quick “look-up” to see how many reward points or tokens a minter has earned overall  
     * It is not tied to a particular reward period or claim process.
     */
    function calculateRewards(address minter) external view virtual returns (uint256);
    
    /**
     * @dev Gets a minter-helper's reward for a specific period
     * @param minter The address of the minter-helper
     * @param periodId The ID of the period, use 0 for most recent period rewards
     * @return rewardAmount The reward amount
     * @return claimed Whether the reward has been claimed
     *
     * @dev Requirements:
     *   - Caller must have negotiated a reward for the period.
     */
    function getMinterRewardStatus(address minter, uint256 periodId) external view virtual returns (uint256 rewardAmount, bool claimed);
    
    /**
     * @dev Claims rewards for a minter-helper from a specific period
     * @param minter The address of the minter-helper
     * @param periodId The ID of the period
     * @return rewardAmount The amount of rewards claimed
     *
     * @dev Requirements:
     *   - Caller must have negotiated a reward for the period.
     *   - Caller's proposal for fee batch must be approved and active.
     *   - The reward must be unclaimed.
     */ 
    function claimReward(address minter, uint256 periodId) external virtual returns (uint256 rewardAmount);

    /**
     * @dev Gets the current fee preference for an address
     * @param user The address to check
     * @return batchId The batch ID for the user's preference
     * @return rewardPercentage The percentage of fees allocated as rewards
     * @return isActive Whether the preference is currently active
     */
    function getFeePreference(address user) external view virtual returns (
        bytes32 batchId,
        uint256 rewardPercentage,
        bool isActive
    );

    /**
     * @dev Gets the batch types associated with a user.
     * @param user Address to query.
     * @return Array of batch identifiers.
     */
    function getUserBatchTypes(address user) external view virtual returns (bytes32[] memory);

    /**
     * @dev Gets the balance of a specific batch for a user
     * @param account The account to check
     * @param batchId The batch ID
     * @return The balance for the specified batch
     */
    function getBatchBalance(address account, bytes32 batchId) external view virtual returns (uint256);

    // /**
    //  * @dev Gets the fee percentage for a batch.
    //  * @param batchId Batch identifier.
    //  * @return Fee percentage in basis points (1/100 of a percent).
    //  */
    // function getBatchFeePercentage(bytes32 batchId) external view virtual returns (uint256);


    // ===============================================================
    // 4. Compliance & Regulatory
    // ===============================================================

    /**
     * @dev Checks if a transfer between two addresses is permitted 
     * @param from Sender address.
     * @param to Recipient address.
     * @return allowed True if transfer is allowed.
     * @return reason Reason code if not allowed (0 = allowed, 1 = sender frozen, 2 = recipient frozen)
     */
    function isTransferAllowed(address from, address to) external view virtual returns (bool allowed, uint8 reason);

    /**
     * @dev Removes an address from the on-chain blacklist.
     * @param account Address to remove from blacklist.
     *
     * MiCA Art. 52: Allows external review-based unblocking.
     */
    function isBlacklisted(address account) external view virtual returns (bool);

    /**
     * @dev Universal function for submitting any type of documentation or evidence
     * @param appealType Related appeal type (if applicable)
     * @param actionId Related compliance action ID (if applicable)
     * @param documentation The documentation submission details
     *
     * @notice This function handles all types of documentation submission:
     * - Evidence updates for appeals
     * - Responses to documentation requests
     * - Proactive documentation submission
     *
     * Emits appropriate events based on documentation type
     */
    function submitOrUpdateDocumentation(
        LibStabillonStorage.AppealReason appealType,
        uint256 actionId,
        LibStabillonStorage.DocumentationSubmission memory documentation
    ) external virtual;

    /**
     * @dev Files an objection to a pending freeze notice
     * @param objectionReason The reason for the objection
     * @param evidence Supporting documentation
     */
    function fileFreezeObjection(
        string calldata objectionReason,
        LibStabillonStorage.DocumentationSubmission calldata evidence
    ) external virtual;
    
    /**
     * @dev Files an appeal against a compliance action
     * @param appealType The type of appeal
     * @param reason The reason for the appeal
     * @param evidence Supporting documentation
     * @return appealId Unique identifier for the appeal
     */
    function fileAppeal(
        LibStabillonStorage.AppealReason appealType,
        string calldata reason,
        LibStabillonStorage.DocumentationSubmission calldata evidence
    ) external virtual returns (uint256);
 
    /**
     * @dev Gets the details of an appeal
     * @param appellant The address that filed the appeal
     * @param appealType The type of appeal
     * @return status Current status of the appeal
     * @return filingTimestamp When the appeal was filed
     * @return reviewTimestamp When the appeal was last reviewed
     * @return approvalCount Number of approvals received
     * @return rejectionCount Number of rejections received
     * @return reason Reason provided for the appeal
     */
    function getAppealDetails(
        address appellant,
        LibStabillonStorage.AppealReason appealType
    ) external view virtual returns (
        uint8 status,
        uint256 filingTimestamp,
        uint256 reviewTimestamp,
        uint256 approvalCount,
        uint256 rejectionCount,
        string memory reason
    );
    
    /**
     * @dev Withdraws a pending appeal
     * @param appealType The type of appeal to withdraw
     */
    function withdrawAppeal(LibStabillonStorage.AppealReason appealType) external virtual;

    // ===============================================================
    // 5. Governance & Contract Upgrades
    // ===============================================================

    /**
     * @dev Checks if an address is eligible to vote on governance decisions.
     * @param account The address to check.
     * @return Whether the address is eligible to vote.
     */
    function isEligibleVoter(address account) external view virtual returns (bool);

    /**
     * @dev Allows governance members to approve a proposed upgrade.
     * @param implementation The address of the implementation to approve.
     * 
     * @notice Only governance members can approve upgrades. Token holders
     * can only reject upgrades through a separate mechanism.
     */
    function approveUpgrade(address implementation) public virtual;

    /**
     * @dev Allows token holders to reject a proposed upgrade.
     * 
     * @notice This is part of the democratic safeguard mechanism where token holders
     * can block an upgrade if sufficient opposition exists. Token holders cannot
     * directly approve upgrades - only governance members can do that.
     */
    function rejectUpgrade() external virtual;

    /**
     * @dev Gets current voter information.
     * @return checkpointCount Current checkpoint ID.
     * @return lastActivityTime Timestamp int.
     * @return isRegistered Nums.
     * @return hasVotedOnCurrentUpgrade Whether the address has voted on the current upgrade.
     */
    function getVoterInfo() external view virtual returns (
        uint256 checkpointCount,
        uint256 lastActivityTime,
        bool isRegistered,
        bool hasVotedOnCurrentUpgrade
    );

}