Skip to Content
Core Mechanics

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 reign
  • reignClaimRecipient[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_RECIPIENT or P_SET_REIGN_ETH_RECIPIENT_TO_CALLER_ONLY
  • CLAIM recipient: P_SET_REIGN_CLAIM_RECIPIENT or P_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.sender pays ETH (the bot)
  • newKing becomes 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_RECIPIENT or P_SET_REIGN_ETH_RECIPIENT_TO_CALLER_ONLY (caller-only constrains ethRecipient = msg.sender)
  • CLAIM: P_SET_REIGN_CLAIM_RECIPIENT or P_SET_REIGN_CLAIM_RECIPIENT_TO_USER_ONLY (user-only constrains claimRecipient = 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 - emissionStartTime

Concrete 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

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