# Mining Flow **Published by:** [Bitcoinu](https://paragraph.com/@bitcoinu/) **Published on:** 2025-03-25 **URL:** https://paragraph.com/@bitcoinu/mining-flow ## Content Overall FlowThe mining of Bitcoinu follows the process below for each block:Block Period: Post RecruitmentEnd of Block: Application Deadline and Public Release of Submitted PostsThree Days Later: Announcement of Winners10 Blocks Later: Deadline for Claiming Mining RewardsBlock Period: Post RecruitmentTo participate in mining a specific block, you must post a qualifying post (X post) during the block’s period (4 days) and enter the URL of the post in the site’s application form. Note: Verified accounts are given priority in winning chances. For more details, click here.End of Block: Application Deadline and Public Release of Submitted PostsAny applications submitted after the block’s end will be invalid. Within minutes after the block’s end, a list of all submitted posts will be made public, and their hashes will be recorded on the Base chain. (This ensures that the submitted posts are fixed and cannot be manipulated, including by the administrators.)3 Days Later: Announcement of Winners3 days after the block’s end, the winners will be selected using an algorithm based on the blockhash at that time and will be publicly announced. After this, the winners can claim the BTCu rewards distributed according to the impressions from the Block Rewards on the site.10 Blocks Later: Deadline for Claiming Mining RewardsOnce the winner of the block, 10 blocks after the original block, is announced, the claim for the mining reward will no longer be possible. Therefore, if you win, you must claim your mining rewards within 10 blocks (40 days).Program CodeThe smart contract for mining is as follows:Block Unlock 3 days after the end of the block, the block eligible for mining will be unlocked. Blocks that have passed 10 blocks will be locked and cannot be mined.Mining Users can obtain BTCu from blocks eligible for mining, up to the amount permitted by the administrator, with the administrator’s signature.// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; interface IBlockTimeReceiver { function getLatestBlockTime() external view returns (uint256); } /** * @title BitcoinuBlockRewardManager * @dev A contract on the Base blockchain that manages the 4-day block-based release of Bitcoinu tokens. */ contract BitcoinuBlockRewardManager { using ECDSA for bytes32; // Enumeration representing the status of a block enum BlockStatus { Inactive, // Not unlocked Active, // Unlocked and available for mining Locked // Locked and unavailable for mining (older than 10 blocks) } // Structure to store block information struct BlockInfo { uint256 totalReleaseAmount; // Total release amount for the block (in satoshi) uint256 releasedAmount; // Amount already released (in satoshi) uint256 endTime; // Block end time (timestamp) BlockStatus status; // Status of the block } // Constants uint256 public constant BLOCK_DURATION = 4 days; // Block duration in seconds - 4 days = 345,600 seconds // Immutable variables (set only in the constructor) IBlockTimeReceiver public immutable blockTimeReceiver; // BlockTimeReceiver contract IERC20 public immutable bitcoinuToken; // Bitcoinu token contract uint256 public immutable startTimestamp; // Timestamp at the start // State variables address public admin; // Admin address address public superAdmin; // Super admin address BlockInfo[] public blocks; // Array storing block information uint256[] public blockReleaseAmounts; // Table of release amounts per block number (in satoshi) // Mapping: user ID => mined block number => whether already mined mapping(uint256 => mapping(uint256 => bool)) public userMinedBlocks; // Modifiers modifier onlyAdmin() { require(msg.sender == admin, "Caller is not an admin"); _; } modifier onlySuperAdmin() { require(msg.sender == superAdmin, "Caller is not a super admin"); _; } // Event definitions event BlockUnlocked(uint256 indexed blockNumber, uint256 amount); event BlocksMined(uint256 indexed blockNumber, uint256 userId, address userAddress, uint256 amount); event BlocksLocked(uint256 fromBlock, uint256 toBlock); event AdminChanged(address oldAdmin, address newAdmin); event SuperAdminChanged(address oldSuperAdmin, address newSuperAdmin); /** * @dev Constructor * @param _blockTimeReceiver Address of the BlockTimeReceiver contract * @param _bitcoinuToken Address of the Bitcoinu token * @param _admin Admin address * @param _superAdmin Super admin address */ constructor( address _blockTimeReceiver, address _bitcoinuToken, address _admin, address _superAdmin ) { require(_admin != address(0), "Admin cannot be zero address"); require(_superAdmin != address(0), "SuperAdmin cannot be zero address"); blockTimeReceiver = IBlockTimeReceiver(_blockTimeReceiver); bitcoinuToken = IERC20(_bitcoinuToken); admin = _admin; superAdmin = _superAdmin; // Set the start timestamp to the current block time startTimestamp = blockTimeReceiver.getLatestBlockTime(); // Define release amounts for each block range (in satoshi) blockReleaseAmounts.push(11538461538461); // Blocks 0-90 blockReleaseAmounts.push(5769230769231); // Blocks 91-181 blockReleaseAmounts.push(2884615384615); // Blocks 182-272 blockReleaseAmounts.push(1442307692308); // Blocks 273-363 blockReleaseAmounts.push(1442307692308); // Blocks 364-454 } // === Read-Only Functions (view/pure) === /** * @dev Retrieves the current block number. * @return The current block number. */ function getCurrentBlockNumber() public view returns (uint256) { uint256 currentTime = blockTimeReceiver.getLatestBlockTime(); if (currentTime <= startTimestamp) { return 0; } uint256 elapsedTime = currentTime - startTimestamp; return elapsedTime / BLOCK_DURATION; } /** * @dev Retrieves the release amount for a given block number. * @param blockNumber The block number. * @return The release amount (in satoshi). */ function getReleaseAmountForBlock(uint256 blockNumber) public view returns (uint256) { if (blockNumber <= 90) { return blockReleaseAmounts[0]; } else if (blockNumber <= 181) { return blockReleaseAmounts[1]; } else if (blockNumber <= 272) { return blockReleaseAmounts[2]; } else if (blockNumber <= 363) { return blockReleaseAmounts[3]; } else if (blockNumber <= 454) { return blockReleaseAmounts[4]; } else { return 0; // No release after block 455 } } /** * @dev Retrieves the total number of blocks created so far. * @return The length of the block array. */ function getBlockCount() public view returns (uint256) { return blocks.length; } /** * @dev Retrieves all block information at once. * @return An array of block information. */ function getAllBlocks() external view returns (BlockInfo[] memory) { BlockInfo[] memory result = new BlockInfoUnsupported embed; for (uint256 i = 0; i < blocks.length; i++) { result[i] = blocks[i]; } return result; } // === State-Changing Functions === /** * @dev Unlocks a block (Requires Admin permission). * @param blockNumber The block number to unlock. */ function unlock(uint256 blockNumber) external onlyAdmin { require(blockNumber <= getCurrentBlockNumber(), "Block not reached yet"); // Calculate the release amount uint256 releaseAmount = getReleaseAmountForBlock(blockNumber); require(releaseAmount > 0, "No tokens to release for this block"); // Calculate the block end time uint256 blockEndTime = startTimestamp + ((blockNumber + 1) * BLOCK_DURATION); // Expand the block array if necessary while (blocks.length <= blockNumber) { blocks.push(BlockInfo(0, 0, 0, BlockStatus.Inactive)); } require(blocks[blockNumber].status == BlockStatus.Inactive, "Block already unlocked or locked"); // Update block information blocks[blockNumber].totalReleaseAmount = releaseAmount; blocks[blockNumber].endTime = blockEndTime; blocks[blockNumber].status = BlockStatus.Active; // Lock blocks older than 10 blocks if (blockNumber >= 10) { uint256 lockFromBlock = blockNumber - 10; // Lock only lockFromBlock (earlier blocks should already be locked) if (blocks[lockFromBlock].status == BlockStatus.Active) { blocks[lockFromBlock].status = BlockStatus.Locked; emit BlocksLocked(lockFromBlock, lockFromBlock); } } emit BlockUnlocked(blockNumber, releaseAmount); } // === Administrative Functions === /** * @dev Changes the Admin (Requires SuperAdmin permission). * @param _newAdmin New Admin. */ function changeAdmin(address _newAdmin) external onlySuperAdmin { require(_newAdmin != address(0), "New admin cannot be zero address"); address oldAdmin = admin; admin = _newAdmin; emit AdminChanged(oldAdmin, _newAdmin); } /** * @dev Changes the SuperAdmin (Requires current SuperAdmin permission). * @param _newSuperAdmin New SuperAdmin. */ function changeSuperAdmin(address _newSuperAdmin) external onlySuperAdmin { require(_newSuperAdmin != address(0), "New super admin cannot be zero address"); address oldSuperAdmin = superAdmin; superAdmin = _newSuperAdmin; emit SuperAdminChanged(oldSuperAdmin, _newSuperAdmin); } } ## Publication Information - [Bitcoinu](https://paragraph.com/@bitcoinu/): Publication homepage - [All Posts](https://paragraph.com/@bitcoinu/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@bitcoinu): Subscribe to updates