Staking (5-Tier System)
MINERAL features a 5-tier staking system where token holders lock MINERAL to earn real ETH yield from protocol mining revenue.
Overview
| Parameter | Value |
|---|---|
| Tiers | 5 (Flex, Bronze, Silver, Gold, Diamond) |
| Reward Token | ETH (not MINERAL — real yield) |
| Revenue Sources | 3% of Auction Mining + 3% of Block Mining |
| Claim Cooldown | 2 days after staking |
| Penalty Recipient | Treasury |
Key distinction: MINERAL staking pays rewards in ETH, not inflationary token emissions. Rewards come directly from protocol mining revenue — real economic activity.
The Five Tiers
| Tier | Name | Lock Period | Early Unstake Penalty | Reward Allocation |
|---|---|---|---|---|
| 0 | Flex | None (0 days) | 0% | 10% |
| 1 | Bronze | 7 days | 5% | 10% |
| 2 | Silver | 30 days | 10% | 20% |
| 3 | Gold | 180 days | 25% | 25% |
| 4 | Diamond | 365 days | 40% | 35% |
| Total: | 100% |
Tier Mechanics Explained
Lock Period: The minimum time your tokens must remain staked. Each new stake extends the lock to now + lockDuration if that's later than your current lock end.
Early Unstake Penalty: If you unstake before the lock period expires, a percentage of your unstaked amount is taken as a penalty and sent to the treasury.
Reward Allocation: When ETH rewards arrive, they're distributed across tiers based on allocation weight * total staked in that tier (see reward formula below).
Example Scenarios
Flex Tier:
- Stake and unstake anytime, no penalty, no lock
- Lowest reward allocation (10%), but maximum flexibility
- Good for users who want exposure without commitment
Diamond Tier:
- Lock for 365 days, 40% penalty if you leave early
- Highest reward allocation (35%)
- Best for long-term conviction holders
- Penalty example: unstake 1000 MINERAL early → receive 600, treasury gets 400
How Rewards Work
Revenue Flow
Auction Mining (3% of revenue) ──┐
├──→ StakingVault.fundRewards()
Block Mining (3% of revenue) ──┘
│
├── Tier 0 (Flex): 10% weighted
├── Tier 1 (Bronze): 10% weighted
├── Tier 2 (Silver): 20% weighted
├── Tier 3 (Gold): 25% weighted
└── Tier 4 (Diamond): 35% weighted
Reward Distribution Formula
When ETH arrives via fundRewards(), it's split across tiers based on effective stake weight:
For each tier:
effectiveStake = totalStakedInTier * allocationBps
Total effective: sum of all tiers' effectiveStake
Tier's share = incomingETH * tierEffectiveStake / totalEffectiveStake
Within each tier, rewards are distributed pro-rata based on individual stake:
Your reward = tierETH * yourStake / totalStakedInTier
This is implemented using an accumulator pattern (O(1) gas cost per claim, regardless of number of stakers):
accEthPerShare += reward * 1e18 / totalStakedInTier
pendingReward = (userStake * accEthPerShare / 1e18) - userDebt
ETH Buffer
If no tokens are staked in any tier (protocol launch scenario), incoming ETH is stored in a buffer. When the first user stakes, the buffer is distributed.
This ensures no ETH is ever lost during the bootstrap period.
Staking Lifecycle
Step 1: Stake
stake(tier, amount)
- Transfer MINERAL tokens to StakingVault
- Lock timer starts (or extends if already staked in this tier)
- Begin earning ETH rewards immediately
- Claim cooldown: cannot claim or unstake for 2 days after staking
Step 2: Earn
- ETH rewards accumulate automatically as mining activity generates revenue
- No action needed — rewards accrue to your account in real time
- View pending rewards anytime via
pendingRewards(user, tier)orpendingRewardsAll(user)
Step 3: Claim
claim(tier, to) // claim from specific tier
claimAll(to) // claim from all tiers at once
- Receive ETH to your wallet (or another address)
- Must wait 2 days after your most recent stake (per tier)
claimAll()skips tiers that are still in cooldown (doesn't revert)- Claiming does not unstake your tokens — you continue earning
Step 4: Unstake
unstake(tier, amount)
- Withdraw your MINERAL tokens
- If lock period has not expired: penalty applied
- If lock period has expired: full amount returned
- Pending rewards are automatically claimed during unstake
- Full unstake resets your lock timer to zero
Penalty System
How Penalties Work
| Condition | Result |
|---|---|
| Unstake after lock expires | Full amount returned (0% penalty) |
| Unstake before lock expires | penalty = amount * penaltyBps / 10000 |
| Penalty destination | Treasury address |
| Penalty tokens | Remain as MINERAL (not burned) |
Penalty Examples
| Tier | Stake | Unstake Early | You Receive | Treasury Gets |
|---|---|---|---|---|
| Flex | 1000 | Anytime | 1000 | 0 |
| Bronze | 1000 | Before 7 days | 950 | 50 |
| Silver | 1000 | Before 30 days | 900 | 100 |
| Gold | 1000 | Before 180 days | 750 | 250 |
| Diamond | 1000 | Before 365 days | 600 | 400 |
Lock Extension Rule
If you stake additional tokens while already staked:
- New lock end =
max(currentLockEnd, now + lockDuration) - Only extends if the new end time is later than the current one
- You cannot "reset" a lock by staking a tiny amount
2-Day Claim Cooldown
After staking, you must wait 2 days (172,800 seconds) before you can:
- Claim rewards
- Unstake tokens
Why? This prevents flash-loan attacks where someone:
- Borrows a large amount of MINERAL
- Stakes it
- Claims accumulated rewards
- Unstakes and repays the loan
The 2-day cooldown makes this economically infeasible.
Strategy Guide
Tier Selection
| Your Goal | Recommended Tier | Why |
|---|---|---|
| Maximum flexibility | Flex | No lock, no penalty, earn 10% allocation |
| Short-term yield | Bronze | 7-day lock, low penalty, reasonable allocation |
| Balanced approach | Silver | 30-day lock, 20% allocation, 10% penalty |
| Long-term conviction | Gold | 180-day lock, 25% allocation |
| Maximum yield | Diamond | 365-day lock, 35% allocation, highest rewards |
Yield Optimization
-
Higher tiers earn more per token staked — the allocation weights are not proportional to lock duration. Diamond's 35% allocation with a 365-day lock is more capital efficient than Flex's 10% with no lock.
-
Early penalty is binary — you either pay the penalty or you don't. There's no graduated penalty based on how early you leave. Unstaking 1 day into a Gold lock costs the same as unstaking 179 days in.
-
Multiple tiers — You can stake in multiple tiers simultaneously. For example, put 50% in Diamond (conviction) and 50% in Flex (liquidity).
-
claimAll()is gas efficient — Claims from all tiers in one transaction. Skips cooldown tiers automatically.
APY Estimation
Staking APY depends on:
- Total mining revenue (ETH flowing in)
- Your stake relative to total stake in your tier
- Your tier's allocation weight
- Protocol activity level
Estimated APY = (annualRevenueToStaking * tierAllocation * yourShare) / yourStakeValue
There is no fixed APY — it fluctuates based on mining activity. More miners = more revenue = higher staking yield.
Technical Details
Contract: StakingVault
| Parameter | Value |
|---|---|
TIER_COUNT | 5 |
MIN_CLAIM_DELAY | 2 days (172,800 seconds) |
PRECISION | 1e18 (accumulator precision) |
View Functions
| Function | Returns |
|---|---|
pendingRewards(user, tier) | Pending ETH for a user in a specific tier |
pendingRewardsAll(user) | Total pending ETH across all tiers |
getUserStake(user, tier) | (staked, lockEndTime, pending, isLocked) |
getTierInfo(tier) | (totalStaked, allocationBps, lockDuration, penaltyBps) |
getAllTierStats() | All tier data in arrays |
calculatePenalty(user, tier, amount) | Preview penalty amount |
totalStaked() | Protocol-wide total staked |
userTotalStaked(user) | User's total across all tiers |
Security Features
- ReentrancyGuard on stake/unstake/claim
- SafeERC20 for all token transfers
- 2-day claim cooldown prevents flash-loan exploits
- receive() reverts — ETH must come through
fundRewards() - Ownable2Step — Two-step ownership transfer
- One-time wiring — AuctionMining and BlockMining addresses set once