Skip to main content

ValidatorStaking

The ValidatorStaking contract (Solidity name NotareumValidatorStaking) manages the NOTA-denominated stakes that validators post to participate in the network. It enforces tier thresholds, tracks active stake, applies unstake cooldowns, distributes attestation rewards, and exposes the isActive/tierOf view functions that VerificationEngine relies on when admitting attestations.

Tiers

Four tiers, each with a minimum stake, daily attestation cap, reward multiplier, and slash rate: Higher tiers carry higher trust, higher income potential, and higher downside on misbehavior. These parameters are governance-adjustable via FeeManager and SlashingManager respectively; the values above are the initial constants.

Data structures

tier is derived from stake at every state transition; validators cannot override it.

Lifecycle

Functions

stake

Transfers amount NOTA from the caller to the contract (requires prior approve) and increases the caller’s bonded stake. If the caller is new, registers them as an active validator. Recomputes tier based on the new total. Emits Staked(validator, amount, newStake, newTier). Reverts if the new stake is below the Basic tier minimum (the caller stays unregistered until they reach 10,000 NOTA).

unstake

Moves amount NOTA from stake to pendingUnstake and starts the cooldown. Tier is recomputed on the remaining bonded stake. If the remaining stake falls below the Basic minimum, the validator becomes inactive immediately but can still claim pending after cooldown. Cooldown is tier-dependent: Emits UnstakeRequested(validator, amount, unlockAt).

withdrawPending

After cooldown, transfers all pendingUnstake back to the validator. Emits Unstaked(validator, amount).

claimRewards

Transfers accumulated attestation rewards (from VerificationEngine) and staking yield to the validator. Rewards accrue as the validator submits attestations on finalized requests, weighted by the tier multiplier. Emits RewardsClaimed(validator, amount).

isActive / tierOf

Used by VerificationEngine.submitAttestation to gate admittance. isActive returns true only when the validator has bonded stake at or above the Basic minimum and is not currently under a slashing freeze.

Governance-only setters

All setters are delay-gated through AccessManager.

Tier upgrade and downgrade

Tier recomputation is pure and synchronous: every stake, unstake, or slashing event recalculates tier from the resulting bonded amount. There is no upgrade application, fee, or delay beyond the stake transfer itself. A validator at Professional who stakes an additional 200,000 NOTA is instantly Enterprise; a validator slashed below the Enterprise minimum is instantly Professional. The engine also records Tier priorTier in the event when the tier changes:

Cooldown interaction with slashing

If a validator is slashed while funds are in pendingUnstake, slashing applies to stake + pendingUnstake in that order. A validator cannot escape slashing by pre-emptively initiating unstake; the cooldown is long enough to cover normal dispute windows plus safety margin.

Rewards model

Each finalized approval on VerificationEngine credits all approving validators according to:
where the sum is over approving validators. This allocates a fixed pool per attestation round proportional to tier weight. Base rewards per level are governance-set and funded from FeeManager out of the verification fee. A periodic staking yield is also distributed from the treasury allocation for validator incentives:
Rewards accrue off-book (in a rewards[validator] counter) and materialize on claimRewards.

Daily attestation cap

The cap prevents a single cheap validator from dominating a request’s attestation slots. The contract rotates dayOfYear every 24 hours (block.timestamp / 86400 % 366) and resets per-validator counters. Institutional validators have cap = 0, which the engine interprets as unlimited.

Access by other contracts

These interfaces are gated via AccessManager to the exact contract address of VerificationEngine or SlashingManager, wired at initialization.

Events

SDK usage

Invariants

  1. stake + pendingUnstake equals the sum of contract deposits minus withdrawals per validator.
  2. tier == tierFromStake(stake) at every function exit.
  3. A validator’s daily attestation count never exceeds dailyCap(tier) within a 24-hour window.
  4. pendingUnstake cannot be claimed before unstakeUnlockAt.