Skip to content

Yield Engine

Midgard does not use a flat APR.

Factory inflation is built from:

  • base factory burn
  • an optional bonus rate
  • a linear ramp from a starting bonus to an ending bonus

Yield rates are stored in basis points.

  • 1 bp = 0.01%
  • 100 bp = 1%
  • 200 bp = 2%
  • 350 bp = 3.5%

So when admin shows min_bonus_bp = 300, that means the factory starts at a 3% bonus rate.

Midgard has two yield layers:

  1. Global yield config. The protocol stores one current YieldConfig with:
    • min_bonus_bp
    • max_bonus_bp
    • ramp_duration
  2. Per-factory snapshot. Every factory copies those 3 values when it is created.

That snapshot is the important part:

  • admin shows the current global config
  • a factory page shows that factory’s own snapshot
  • changing global yield later does not rewrite older factories
  • min_bonus_bp: the bonus rate at activation
  • max_bonus_bp: the bonus rate after the ramp finishes
  • ramp_duration: how many seconds it takes to move from min to max

Example:

  • min_bonus_bp = 300
  • max_bonus_bp = 600
  • ramp_duration = 604800

This means:

  • the factory starts at 3%
  • ramps linearly over 7 days
  • ends at 6%

The ramp starts when the factory is activated, not when it is merely created.

That matters because a pending factory has not started its burn / inflation clock yet.

There are two related ideas:

  1. Current bonus rate: the spot rate right now
  2. Bonus inflation earned so far: the bonus already accumulated over the whole life of the factory

The current spot rate is simple:

  • before the ramp ends, it moves linearly from min to max
  • after the ramp ends, it stays at max

In shorthand:

  • if t = 0, current rate = min
  • if 0 < t < ramp, current rate = linear interpolation between min and max
  • if t >= ramp, current rate = max

But Midgard does not apply the current spot rate to all past burn.

Instead, it integrates the bonus over time using the average bonus over elapsed burn.

That means:

  • a factory halfway through the ramp has a lower earned bonus than current rate x all burn
  • long-lived factories benefit more because more burn happens at the higher end of the ramp

At the factory level, the inflation side is:

  • initial_burn
  • plus base burn accumulated over time
  • plus bonus inflation from the yield config

The important design detail is that initial_burn is both:

  • a burn obligation
  • and an initial inflation credit

So initial_burn is not just a fee. It is part of the factory accounting model.

The permissionless adjust_yield() path updates the global config for future factories.

It compares:

  • current total GARD supply
  • against either a fixed target supply or a scheduled target supply

The current logic has no hard floor.

The shape is:

  • if no target is configured: min = 0, max = 0
  • if current supply is at or above target: min = 0, max = 0
  • if current supply is below target:
    • compute the supply deficit in basis points
    • set min_bonus_bp = deficit_bp, capped by max_bonus_cap_bp
    • set max_bonus_bp = min(deficit_bp * 2, max_bonus_cap_bp)
    • set ramp_duration = 7 days

So the controller can reduce new-factory bonus all the way to 0%.

Two different things are happening in the system:

  • Challenge ticket burns are real token burns.
  • Factory daily burn is internal factory accounting against stake.

That means the adaptive controller is a soft supply-shaping tool, not a perfect fixed-supply clamp. It modulates bonus inflation for new factories, while real challenge flow still adds the unpredictable burn side.

If the target is configured and the cap is high enough:

  • exactly on target: 0% -> 0%
  • 1% below target: 1% -> 2%
  • 3% below target: 3% -> 6%
  • 8% below target with a 5% cap: 5% -> 5%

That last case matters:

  • the min rate hits the cap
  • the end rate also hits the cap
  • so the factory becomes a flat-rate factory instead of a ramping one

The runtime admin can also set the global yield config directly.

That means the protocol can run either:

  • the automatic supply-based adjustment flow
  • or a manual config such as:
    • flat 3%
    • 2% -> 5% over 7 days
    • 0% -> 0% for net-zero bonus

When you create a factory, it snapshots whatever the global config is at that moment.

So:

  • the create-factory modal shows what a new factory will inherit
  • the admin page shows the current global config
  • each live factory shows its own initial / current / end bonus values from its snapshot

Yield is separate from the factory’s initial challenge reserve, but the two are often confused.

When a factory is created, the contract also enforces a minimum initial_burn so the factory is immediately challengeable at T0.

That minimum is:

  • ticket cost = 10% of daily burn
  • challenge reward = 190% of ticket cost
  • so minimum initial_burn = 19% of daily burn

Leverage applies the same idea again: if leverage increases daily burn, the contract increases initial_burn when needed so the leveraged factory still supports one challenge reward immediately.