Staking 6.1.8

4 August 2026

This release has upgrade notes. Read them before updating — they describe behaviour changes that need your attention.

POOLSDURATIONSAPRREWARDSPOSITIONSMONEYSETTLEMENTAUDITADMINAPIMIGRATIONBUG-FIXES

Staking v6.1.8

Release Date: August 4, 2026 Tags: POOLS, DURATIONS, APR, REWARDS, POSITIONS, MONEY, SETTLEMENT, AUDIT, ADMIN, API, MIGRATION, BUG-FIXES

Overview

A pool can now offer several lock terms at once, each with its own rate and its own payout schedule — 365 days at 10% paid at the end, 90 days at 8% paid weekly, 30 days at 5% paid daily, out of one pool and one capacity budget.

Until now a pool had exactly one APR, one lock period and one payout schedule, so an operator who wanted to reward a longer commitment had to publish a second pool — which competed with the first for the same tokens and could not even be activated.

Separately: your staking activity feed is missing every automated entry, and repairing it needs a command run against your database. The platform's automatic schema updates cannot do it, for a reason explained in Upgrade Notes.

Requires Core v6.6.2.

Update Instructions

pnpm updator

Post-update: rebuild the backend and restart, then run the audit repair below.

The new duration tiers need no migration and no backfill. The table and columns they use are created when the backend restarts, and every pool you already have keeps working exactly as it did — a pool with no terms defined still uses its own APR, lock period and payout schedule, which is the same single term it has always offered. Existing positions are untouched.

The interface strings for the new term controls ship in the core message file, so update Core first or the tier editor renders key names instead of labels.


Highlights

Why the work was larger than adding a table

It comes down to where a staking pool's terms are actually read. The rate, the schedule and the compounding behaviour were being read live off the pool every time a reward was calculated, which was survivable while a pool had one of each. With several terms in one pool it stops being survivable in two directions at once: a staker on the weekly term would have been paid on the daily term's cadence, and — worse — an admin editing a pool would have re-priced positions that were already running.

The terms a staker agrees to are now recorded on their position at the moment they stake, and every reward calculation reads them from there. That also closes a defect that predates this release: the admin position list and the staker's own position card were both showing the pool's current rate rather than the rate the position was locked at.

The staking activity feed has never recorded the reward engine

Found while testing the above. The staking cron records an audit entry for every position it credits or settles, marked as done by the system rather than by a person. Every one of those entries has been rejected by the database and discarded, because the column holding the acting admin still refused to be empty. The write is deliberately best-effort so that a failed audit entry can never undo a payout that already happened, and that safety net is exactly what hid it: the failure produced a single line in the log and nothing else.

The consequence is quiet and complete. The staking activity feed has been listing admin actions only, and nothing at all from the engine that moves most of the money. An operator asking "who credited this position" found no record.


Upgrade Notes

Your staking activity feed is missing every automated entry — run the repair

The reward engine's audit entries have been rejected since the column recording the acting admin was left unable to hold "the system". Nothing was lost except the record itself: no payout was affected, no balance is wrong, and no staker was short-paid. What is missing is the history of what the engine did.

Run this once, against each installation:

cd backend
pnpm staking:audit:check     # reports what it would change, changes nothing
pnpm staking:audit:repair    # applies it

It is safe on a live database and safe to run twice — it inspects the schema first and does nothing when the schema is already correct.

  • Fixed the staking cron's audit entries being discarded. From the next scheduled run onwards, accrual and settlement appear in the activity feed with no admin attached, which is what marks them as automated.
  • Entries already lost cannot be recovered. The feed begins recording from the moment you run the repair.
  • Restarting the backend will not fix this on its own. The platform's automatic schema updates compare the code's description of a column against the description it recorded last time, never against the database itself — so once it had noted that this column was allowed to be empty, it considered the work done and skipped it on every subsequent start, whether or not the change ever reached the database.

Staking through the API now names a term

Anything that opens positions over the API — a bot, an integration, your own tooling — is affected once a pool publishes more than one term.

  • Changed the stake request to require the chosen term when a pool offers a choice. It is refused rather than guessed, because guessing opens a 365-day lock for someone who meant to pick 30 days. A pool offering a single term, or none at all, still accepts the request exactly as before.
  • A pool that publishes no terms refuses a request that names one, rather than ignoring it, so an out-of-date client fails loudly instead of quietly opening the wrong lock.

You choose which term the pool advertises

Wherever a single figure still has to stand for the whole pool — the analytics averages, the public landing page, an exported report — the pool's own APR, lock period and payout schedule are what gets shown. Leaving them frozen at whatever was configured before the ladder existed would have advertised a rate the pool no longer offers.

  • Added a headline term per pool, marked with the star in the tier editor. Its rate, length and schedule are what the pool advertises, and it is the term preselected on the staking form. Most operators will want to lead with their best rate rather than their shortest lock, and that is the whole point of it being a choice.
  • Changed those three pool values to track the headline term. If you mark none, the shortest open term is used, which is exactly what a pool without a ladder already advertised — so no existing pool changes what it shows by being upgraded, and there is nothing to set unless you want to.
  • Marking a term does not reorder the ladder. Terms always read shortest-first on the staking form, because a ladder that does not run in order of length reads as a mistake; the headline is a separate question from the reading order, and this release keeps them separate.
  • Closing your headline term is safe: the pool falls through to the next open term rather than advertising a rate nobody can stake into. The closed term keeps the mark, so reopening it restores your choice.
  • The pool card, the pool page and the staking form are unaffected by this — they show the full range and every term, and this only governs the surfaces that can print one number.

Added

Several lock terms in one pool

  • Added duration tiers: any number of lock terms per pool, each with its own lock period, APR and payout schedule — daily, weekly, monthly, or at the end of the term.
  • Added a per-term auto-compound option, so a pool can offer a compounding long term beside a term that pays out on a cadence. Previously compounding was a property of the whole pool, and every position in it settled the same way.
  • Added optional per-term overrides for minimum stake, maximum stake, admin fee and early-withdrawal fee. Left blank, a term inherits the pool's value — a longer lock is usually priced differently on both sides, and a term that deliberately charges no fee is now expressible.
  • Added a per-term open/closed switch, so a term can be withdrawn from sale without being deleted and without disturbing the people staked into it.
  • Added a headline term per pool — see Upgrade Notes. One open term carries it, it is what the pool advertises wherever a single rate is shown, and it is preselected for the staker.

The term editor

  • Added a Duration Tiers tab to the pool form, with one-click terms at 7, 14, 30, 60, 90, 180, 270 and 365 days and a field for any other length. Terms sort themselves shortest first, and a length already in the ladder cannot be added twice.
  • Added a star on each row that marks the headline term. Marking one clears the others, because a pool advertises one rate; it is disabled on a closed term, and closing the marked term moves the mark to whichever term the pool will actually lead with.
  • Added a per-term label, so a term can read 1 Year rather than 365 days wherever it is offered.
  • Added a warning when a term is set to auto-compound, stating plainly that it will pay nothing during the lock and cannot be claimed against.
  • Added the pool's own values as the placeholder text on every override field, so the figure that will apply is visible without leaving the row.

Choosing a term

  • Added a term picker to the staking form, above the amount. It sits above deliberately: the minimum, the maximum, the MAX button and the reward estimate are all scoped to the chosen term, so an amount typed first would become invalid the moment the term changed.
  • Added the rate, the length and the payout schedule to each choice, so the trade-off is visible before committing rather than after.
  • Added a Featured badge on the headline term, which is also the one preselected — so the selection the staker did not make is explained rather than arbitrary.
  • Added an APR range and a term range to the pool cards and pool page — 8% – 10% over 90 – 365 days — with the number of terms on offer. A single figure on a pool with a ladder is a rate most stakers cannot get.

Rewards calculator

  • Added one quote per term rather than one per pool, each naming the term it belongs to and ordered by the best return. A 10% rate over a year beats a 12% rate over a month, and ordering by rate alone claimed otherwise.
  • Changed the horizon you enter to exclude terms longer than it, per term rather than per pool. A pool whose 30-day term fits your horizon is now quoted for that term instead of being dropped because its longest term does not fit.

Positions show the term they bought

  • Added the term to the position cards, the position detail and the admin position lists — the length, the label, and the payout schedule agreed at the time.

Changed

The terms of a position are fixed when it is opened

  • Changed positions to record the rate, lock period, payout schedule and compounding behaviour at the moment of staking. The rate and the fees were already recorded this way; the schedule was not, and was read live from the pool on every reward calculation.
  • Changed what an admin editing a pool can affect: nothing that is already running. Re-pricing a term, changing its schedule or switching it to auto-compound applies to new positions only. Previously, flipping a pool from daily to end-of-term stopped payouts a staker had already begun receiving, and switching auto-compound on mid-term reclassified rewards they had already earned.
  • Changed the admin position form to refuse edits to any of those recorded terms, alongside the amount and dates it already refused.

Withdrawing a term from sale

  • Changed removal of a term that holds positions: it is closed to new stakes and kept, rather than deleted. It disappears from the staking form immediately, existing stakers keep the terms they agreed to, and the record of what they agreed to survives. A term nobody has ever staked into is deleted outright.
  • Changed the pool save response to state when this has happened, instead of letting the operator believe a term was removed and then find it still listed.

Distributing rewards by hand

  • Changed both admin distribution actions to skip auto-compounding positions individually, reporting how many were skipped, instead of refusing the whole pool. With one pool now holding both kinds, refusing the pool denied a payout to every staker in it because of a term they had not chosen.
  • Changed the guard that prevents a bonus being distributed twice to use the longest schedule across the pool and all of its terms. It can only ever be stricter than before.

Claiming

  • Changed the refusal to claim an auto-compounded reward from a pool-level rule to a per-position one. A staker on a claimable term in a pool that also offers a compounding term can now claim, which they could not before.

Browsing pools

  • Changed the APR and lock-period filters on the public pool list to match a pool when any of its terms qualifies. Filtering on the headline figure alone hid a pool whose 365-day term paid 15% from a search for 12% and above.

Fixed

The admin position list showed today's rate, not the rate the staker was locked at

Positions have recorded the rate they were opened at for some time, so that later pool edits could not re-price them. Two screens then overwrote that recorded rate with the pool's current one before displaying it.

  • Fixed the staking position list, the pool's own position tab and the position update response showing the pool's current APR in place of the position's own. An admin reviewing a position saw a number the staker was never promised. With several terms in a pool it was wrong for every position not on the first term.

The staker's position card did the same

  • Fixed the position card and the position detail dialog reading the pool's current APR rather than the rate recorded on the position. A staker whose pool had since been re-priced was shown the new rate against their old position.

The reward engine's audit entries were rejected and discarded

  • Fixed every audit entry written by the staking cron failing against a database column that would not accept "the system" as the actor. The activity feed showed admin actions only and nothing from accrual or settlement. Repairing this needs a command — see Upgrade Notes.
  • Changed the log message that reports a failed audit entry to state the consequence — that the run will not appear in the activity feed, and that the payout itself already committed and is unaffected — rather than only the database error.