Skip to main content

Block Mining (5x5 Grid + Chainlink VRF)

Block Mining is MINERAL's second mining mechanism — a 5x5 grid lottery where players deploy ETH onto squares and a verifiably random winner is selected every ~60 seconds using Chainlink VRF v2.5.


Overview​

ParameterValue
Grid Size5x5 (25 squares)
Round Duration30 blocks (~60 seconds on Base)
Intermission5 blocks (~10 seconds between rounds)
Minimum Deploy0.001 ETH per transaction
Maximum Deploy100 ETH per transaction
Winner Payout90% of total pool
Motherlode Odds1 in 625 per round
Randomness SourceChainlink VRF v2.5

How a Round Works​

Each round follows a precise lifecycle:

┌─────────────────────────────────────────────────────────────────┐
│ ROUND LIFECYCLE │
│ │
│ DEPLOY PHASE SETTLEMENT CLAIM PHASE │
│ (30 blocks) (VRF callback) (anytime after) │
│ │
│ Users deploy ETH → VRF selects → Winners claim │
│ onto squares winning square their ETH │
│ │
│ ├── 5 blocks ──┤ │
│ INTERMISSION │
│ (next round starts) │
└─────────────────────────────────────────────────────────────────┘

Phase 1: Deploy (30 blocks, ~60 seconds)​

Players deploy ETH onto one or more squares on the 5x5 grid:

  • Call deploy([0, 5, 12, 24]) with ETH attached
  • Your ETH is split evenly across your selected squares
  • If there's a remainder (ETH doesn't divide evenly), the extra wei goes to the first square in your list
  • You can deploy multiple times during a round (amounts accumulate)
  • Multiple players can deploy on the same square

Grid Layout:

┌────┬────┬────┬────┬────┐
│ 0 │ 1 │ 2 │ 3 │ 4 │
├────┼────┼────┼────┼────┤
│ 5 │ 6 │ 7 │ 8 │ 9 │
├────┼────┼────┼────┼────┤
│ 10 │ 11 │ 12 │ 13 │ 14 │
├────┼────┼────┼────┼────┤
│ 15 │ 16 │ 17 │ 18 │ 19 │
├────┼────┼────┼────┼────┤
│ 20 │ 21 │ 22 │ 23 │ 24 │
└────┴────┴────┴────┴────┘

Phase 2: Settlement​

After the round's 30 blocks have passed, anyone can call settle():

  1. The contract requests a random number from Chainlink VRF v2.5
  2. Chainlink's oracle network generates a verifiably random number
  3. The VRF callback delivers the random word to the contract
  4. Two decisions are computed from the random word:
Winning Square = randomWord % 25          (lower 128 bits)
Motherlode Hit = (randomWord >> 128) % 625 == 0 (upper 128 bits)
  1. Revenue is distributed:
    • 90% allocated to the winner pool
    • 3% added to the Motherlode jackpot
    • 3% sent to StakingVault
    • 4% sent to Treasury

Phase 3: Claim​

After settlement, miners who deployed on the winning square can claim their share:

Your Claim = winnerPool * yourDeployOnWinningSquare / totalDeployOnWinningSquare

Winnings are proportional to how much ETH you deployed on the winning square relative to all deployments on that square.


Revenue Distribution (90-3-3-4)​

RecipientShareDescription
Winners90%Split among miners on the winning square, proportional to deployment
Motherlode3%Accumulates in jackpot pool (1/625 chance to trigger)
StakingVault3%ETH rewards for MINERAL stakers
Treasury4%Protocol development fund

90% to winners is the highest payout ratio among comparable mining protocols.

Revenue Flow​

Total ETH deployed in round
│
├── 90% → Winner Pool
│ └── Proportional to deployment on winning square
│
├── 3% → Motherlode Pool
│ └── Accumulates across rounds, 1/625 chance per round
│
├── 3% → StakingVault.fundRewards()
│ └── Distributed to stakers by tier weight
│
└── 4% → Treasury
└── Protocol development

The Motherlode​

The Motherlode is a progressive jackpot that grows with every Block Mining round.

How It Accumulates​

  • 3% of every round's total deployed ETH is added to the Motherlode pool
  • The pool grows continuously, round after round
  • There is no cap on the Motherlode size

How It Triggers​

Each round, after the winning square is determined, a second check is performed:

motherlodeTriggered = (randomWord >> 128) % 625 == 0
  • Uses the upper 128 bits of the VRF random word (independent from square selection)
  • Probability: 1 in 625 per round (~0.16%)
  • At ~60 seconds per round, expected trigger: roughly once every 10.4 hours of continuous play

What Happens on a Motherlode Hit​

When the Motherlode triggers:

  1. The entire accumulated Motherlode pool is added to the winner pool for that round
  2. Winners on the winning square receive their normal 90% share plus the Motherlode amount
  3. The Motherlode resets (the 3% from the current round starts the new accumulation)
  4. A MotherlodeHit event is emitted

Example​

Round 500:
Total Deployed: 5 ETH
Motherlode Pool (accumulated): 50 ETH
VRF Result: Square 7 wins, Motherlode TRIGGERED

Normal Winner Pool: 5 ETH * 90% = 4.5 ETH
Motherlode Bonus: 50 ETH
Total Winner Pool: 54.5 ETH (!)

If you deployed 1 ETH on Square 7 and total on Square 7 was 2 ETH:
Your Claim: 54.5 * (1/2) = 27.25 ETH

No-Winner Rollover​

A critical edge case: what if the winning square has zero deployers?

The Problem​

In early rounds with few participants, many squares may be empty. If VRF selects an empty square, the winner pool would have no one to claim it.

The Solution​

When the winning square has zero deployments:

if (totalDeployOnWinningSquare == 0):
winnerPool + motherlodeFee → Motherlode Pool
round.winnerPool = 0
  • The entire winner pool rolls into the Motherlode
  • If a Motherlode was also triggered, the Motherlode amount also rolls forward
  • Nothing is locked or lost
  • The Motherlode grows faster, increasing the jackpot incentive
  • A NoWinnerRollover event is emitted for transparency

This ensures that no ETH is ever permanently locked in the protocol.


VRF Integration Details​

Request Flow​

Round ends (block.number >= roundEndBlock)
│
├── settle() called by anyone (permissionless)
│
├── Contract sends VRF request to Chainlink Coordinator
│ └── Parameters: keyHash, subId, confirmations, callbackGasLimit, 1 word
│
├── Chainlink oracle network generates random word + proof
│
├── rawFulfillRandomWords() callback received
│ └── Verifies: requestId matches, coordinator is caller
│
└── _finalizeRound() processes the randomness
├── winningSquare = random % 25
├── motherlodeCheck = (random >> 128) % 625
└── Distribute revenue, emit events

VRF Timeout Recovery​

If Chainlink VRF fails to respond (network congestion, subscription issues):

ParameterValue
Timeout Threshold300 blocks (~10 minutes on Base)
Recovery FunctionreRequestRandomness()
AccessPermissionless (anyone can call after timeout)

After 300 blocks without a VRF response, anyone can call reRequestRandomness() to send a new VRF request. The old request is invalidated, and the contract tracks the new request ID.

This ensures the protocol never gets permanently stuck waiting for VRF.

VRF Configuration​

ParameterDescription
vrfCoordinatorChainlink VRF v2.5 coordinator address on Base
vrfKeyHashKey hash for the VRF proving key
vrfSubscriptionIdPre-funded Chainlink subscription
vrfRequestConfirmationsNumber of block confirmations before fulfillment
vrfCallbackGasLimitGas limit for the callback function
vrfNativePaymentWhether to pay in native ETH (vs. LINK)

Safety: VRF configuration cannot be changed while there is an active, non-timed-out VRF request. This prevents configuration manipulation during pending settlements.

Empty Round Optimization​

If a round has zero total deployments, settle() skips the VRF request entirely. The round is settled immediately with no winner, no revenue distribution, and no gas cost for VRF. The next round starts without delay.


Claim Mechanics​

Standard Claim​

After a round is settled, winners call claim(roundId):

claimAmount = winnerPool * userDeployOnWinner / totalOnWinner

Last Claimer Gets Remainder​

Due to integer division rounding, tiny dust amounts (wei) can accumulate. The last claimer receives the full remaining balance instead of the calculated amount:

if (winnerClaimCount + 1 == totalWinningMiners):
claimAmount = winnerPool - claimedWinnerPool // gets everything remaining

This ensures that no dust is stranded in the contract.

Claim Tracking​

VariablePurpose
claimedWinnerPoolRunning total of ETH claimed from this round
winnerClaimCountNumber of miners who have claimed
outstandingWinnerClaimsProtocol-wide total of unclaimed winner ETH

Strategy Guide​

Basic Strategies​

StrategyDescriptionRisk/Reward
Single squareDeploy all ETH on one squareHigh risk, high reward (25:1 if alone)
Spread (5 squares)Deploy across 5 squaresMedium risk, ~20% chance of winning
Wide spread (10+)Deploy across many squaresLower risk, lower reward per win
All 25Deploy on every squareGuaranteed win, but only profit from others' deployments
Motherlode hunterPlay many rounds, deploy minimalLow cost, hoping for Motherlode hit

Advanced Considerations​

  1. Square selection: There is no "best" square — VRF is truly random. All squares have equal 4% chance of winning.

  2. Timing: Deploy as late as possible in the round to see where others have deployed. Deploying on less-crowded squares gives you a larger share if that square wins.

  3. Motherlode math: The Motherlode triggers 1 in 625 rounds. If you play 625 rounds, you have a ~63% chance of seeing at least one Motherlode hit (but not necessarily being on the winning square when it hits).

  4. Expected value: Deploying on an empty square that wins gives you 90% of the entire pool (minus fees). Deploying on a crowded square means splitting the 90% with others.


AutoMiner — Automated Play​

Don't want to manually deploy every 60 seconds? AutoMiner is an on-chain contract that plays Block Mining on your behalf.

How It Works​

  1. Configure — Choose a strategy and set your budget per round
  2. Deposit — Deposit ETH into the AutoMiner contract
  3. Sit back — An executor bot deploys for you every round automatically
  4. Claim — Claim your winnings directly from BlockMining whenever you win

Strategies​

StrategyDescription
SPREADDeploy equally across all 25 squares every round (safest)
RANDOMDeploy to N random squares each round (configurable)
SELECTDeploy to your chosen squares every round

Key Parameters​

ParameterValue
Minimum Budget0.001 ETH per round
Maximum Budget10 ETH per round
Auto-deactivationWhen balance falls below budget
Re-activationDeposit more ETH or call activate()

Architecture​

User configures strategy + deposits ETH
│
├── AutoMiner contract holds user funds
│
├── Executor bot monitors rounds (off-chain)
│ └── Every ~60s: calls executeAll()
│
├── AutoMiner calls BlockMining.deployFor(user, squares)
│ └── Position recorded under user's address
│
└── User claims winnings from BlockMining directly

deployFor() — Third-Party Deployment​

BlockMining supports a deployFor(address miner, uint8[] squares) function:

  • Permissionless — anyone can deploy on behalf of anyone else
  • The caller pays the ETH
  • The position is recorded under the miner's address
  • The miner claims their own winnings

This is the mechanism that enables AutoMiner and future AI agent integrations.


Technical Details​

Contract Parameters​

ParameterValueType
GRID_SIZE25constant
ROUND_DURATION30 blocksconstant
INTERMISSION5 blocksconstant
WINNER_BPS9000 (90%)constant
MOTHERLODE_BPS300 (3%)constant
STAKING_BPS300 (3%)constant
TREASURY_BPS400 (4%)constant
MOTHERLODE_ODDS625constant
MIN_DEPLOY0.001 ETHconstant
MAX_DEPLOY_PER_TX100 ETHconstant
VRF_REQUEST_TIMEOUT_BLOCKS300constant
ADDRESS_UPDATE_DELAY1 dayconstant

Security Features​

  • ReentrancyGuard on all state-modifying functions
  • Pausable — Owner can pause deploys in emergencies
  • Chainlink VRF — Tamper-proof randomness
  • VRF timeout recovery — Permissionless re-request after 300 blocks
  • No-winner rollover — No funds ever locked
  • Last claimer remainder — No dust stranded
  • Tracked balance — All obligations accounted on-chain
  • 1-day timelock — Admin address changes require 24-hour delay
  • receive() reverts — Contract cannot receive direct ETH transfers
  • Ownable2Step — Two-step ownership transfer