Core mechanics
This section covers the Crown (King) system implemented by MineCore.
Takeover pricing
Constants:
- TAKEOVER_PRICE_FLOOR = 0.001 ETH
- TAKEOVER_DECAY_PERIOD = 1 hour
State:
- referencePrice (updated on every takeover)
- currentReignStartTime
- currentKing
Price function (for an arbitrary timestamp nowTs):
- If currentKing == 0x0 (no Crown yet):
- price = TAKEOVER_PRICE_FLOOR
- Else:
- t = min(nowTs - currentReignStartTime, TAKEOVER_DECAY_PERIOD)
- price = max(TAKEOVER_PRICE_FLOOR, referencePrice - referencePrice * t / TAKEOVER_DECAY_PERIOD)
Reference price update (IMPORTANT):
- When a takeover succeeds, MineCore sets:
- referencePrice = pricePaid * 2
Meaning:
- The next takeover starts at double the last paid price.
- The price decays toward 0 over 1 hour, clamped at floor.
- Low-cost takeovers reach floor before 60 min (e.g., 0.002 ETH ref → floor at 30 min).
[//]: # (DONUT salute to heeshilio / GlazeCorp (glazecorp.io, github.com/Heesho) for the KOTH pricing shape: 2x reference price on takeover + 1h linear decay.)
ETH routing on takeover
Let pricePaid be the takeover price at execution.
MineCore stores per-reign routing recipients:
reignEthRecipient[reignId]: receives the 75% dethroned-King ETH share for that reignreignClaimRecipient[reignId]: receives the King-stream mined CLAIM for that reign
Recipients are set at reign start and emitted via ReignRecipientsSet(...).
The active king identity can update recipients mid-reign via setCurrentReignRecipients(...).
Delegates can also call it, but only if their DelegationHub session covers the recipient(s) being changed:
- ETH recipient:
P_SET_REIGN_ETH_RECIPIENTorP_SET_REIGN_ETH_RECIPIENT_TO_CALLER_ONLY - CLAIM recipient:
P_SET_REIGN_CLAIM_RECIPIENTorP_SET_REIGN_CLAIM_RECIPIENT_TO_USER_ONLY
Non-genesis takeovers (prevKing != 0x0):
- 75% of pricePaid is paid to the dethroned reign’s
reignEthRecipient[prevReignId](fallback: prevKing) - 25% of pricePaid is allocated to veCLAIM holders via ShareholderRoyalties
Genesis takeover (prevKing == 0x0):
- 100% of pricePaid goes to ShareholderRoyalties
- ShareholderRoyalties.onTakeover uses reignId = 0
King-stream CLAIM settlement (prevKing != 0x0):
- mined CLAIM for the dethroned reign is minted to
reignClaimRecipient[prevReignId](fallback: prevKing) - if claim recipient equals the king identity, MineCore applies the king’s auto-lock config (best-effort)
- otherwise, MineCore mints liquid CLAIM directly to the recipient
Payout mechanics:
- The dethroned King payout is best-effort in-tx (fixed gas stipend).
- If that transfer fails, MineCore credits
kingEthBalance[ethRecipient]. - The recipient can later withdraw via
withdrawKingBalance()(or delegated wrapper).
Refund mechanics:
- If msg.value (or token swap proceeds) exceeds pricePaid:
- MineCore attempts to refund immediately
- if refund fails, credits refundEthBalance[user]
- user can pull it via withdrawRefundBalance(to)
Delegated takeover (bots)
MineCore supports delegated crown automation via DelegationHub sessions.
takeoverFor(newKing):
msg.senderpays ETH (the bot)newKingbecomes the King identity- requires
DelegationHub.isAuthorized(newKing, msg.sender, P_TAKEOVER_FOR)
Default routing when a delegated takeover starts a new reign:
reignEthRecipient[newReignId] = msg.sender(bot receives the 75% payout when dethroned)reignClaimRecipient[newReignId] = newKing(user receives mined CLAIM)
Optional:
- if the session also includes
P_ROUTE_REIGN_CLAIM_TO_CALLER, MineCore sets:reignClaimRecipient[newReignId] = msg.sender
Mid-reign, the king identity can update recipients:
setCurrentReignRecipients(ethRecipient, claimRecipient)
An authorized delegate can also call it, but only for the recipient(s) covered by their session:
- ETH:
P_SET_REIGN_ETH_RECIPIENTorP_SET_REIGN_ETH_RECIPIENT_TO_CALLER_ONLY(caller-only constrainsethRecipient = msg.sender) - CLAIM:
P_SET_REIGN_CLAIM_RECIPIENTorP_SET_REIGN_CLAIM_RECIPIENT_TO_USER_ONLY(user-only constrainsclaimRecipient = king)
Why this exists:
- enables a bot loop where the bot pays the takeover and automatically receives the 75% dethroned payout to fund the next takeover
- keeps the King identity as the user’s address (indexers and UX remain clean)
Emissions (two streams)
CLAIM emissions are deterministic, linear-decay schedules starting at MineCore.emissionStartTime.
There are two streams:
- Crown stream: minted to the dethroned King when a takeover finalizes a reign
- Furnace stream: minted to the Furnace reserve when a takeover happens
Constants:
- EMISSION_DECAY_PERIOD D = 63,072,000 seconds (2 years)
Crown stream:
- launch rate R0_king = 50 CLAIM/s
- floor rate RF_king = 50/9 CLAIM/s (5.555555555555555555 CLAIM/s)
Furnace stream:
- launch rate R0_furnace = 5 CLAIM/s
- floor rate RF_furnace = 5/9 CLAIM/s (0.555555555555555555 CLAIM/s)
Rate schedule (both streams share the same shape):
rate(t) =
RF, if t >= D
R0 - (R0 - RF) * t / D, if 0 <= t < D
where t = timestamp - emissionStartTimeConcrete rates (for dashboards):
- At launch:
- Crown: 50/sec = 180,000 CLAIM/hour
- Furnace: 5/sec = 18,000 CLAIM/hour
- At floor (2 years and beyond):
- Crown: (50/9)/sec = 20,000 CLAIM/hour
- Furnace: (5/9)/sec = 2,000 CLAIM/hour
Integral (amount minted between ts0 and ts1):
- MineCore uses an exact trapezoid integral across the linear segment and a flat integral in the floor segment.
- See MineCore._kingEmitted(…) and MineCore._furnaceEmitted(…).
Materialization rule (important for integrators):
- CLAIM is minted when actions occur.
- In v1.0.0, the primary materialization point is takeover finalization.
- When someone takes over:
- the dethroned King receives their accrued CLAIM for the reign
- the Furnace receives its accrued CLAIM and credits it to its reserve
- When someone takes over:
Pause clamp (no mining while paused):
- When guardian toggles takeoversPaused (either direction), MineCore clamps currentReignLastAccrualTime to block.timestamp.
- This prevents paused time from being mined later.
Genesis accrual window
- GENESIS_ACCRUAL_DURATION = 10 days
- During the first 10d after emissionStartTime, the Crown stream accrues into a one-shot bucket.
- After 10d, LaunchController (as MineCore.guardian during genesis) collects it once (as the first step in
finalizeGenesis()):- MineCore.collectGenesisKingClaim(to=LaunchController)
- LaunchController uses this bucket to:
- seed the initial WETH/CLAIM liquidity with all accrued CLAIM
- unpause takeovers