Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@
"group": "Staking",
"pages": [
"ecosystem/staking/overview",
"ecosystem/staking/stake-calculation",
"ecosystem/staking/liquid-staking",
"ecosystem/staking/single-nominator",
"ecosystem/staking/nominator-pools"
Expand Down
183 changes: 183 additions & 0 deletions ecosystem/staking/stake-calculation.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
---
title: "Stake calculation"
---

import { Aside } from '/snippets/aside.jsx';

<Aside
type="caution"
title="Stake affects locked funds"
>
Stake configuration directly controls how much TON is locked in the elector contract for a full validation round. Misconfiguration can lock the entire balance, leaving no funds for the next election. Review each setting carefully before applying changes on TON Mainnet.
</Aside>

MyTonCtrl automatically calculates the stake amount before submitting an election entry. The calculation balances operator preferences, staking mode, network-imposed limits, and fee reserves to produce a single integer value (in TON) sent to the [elector contract](/foundations/system).

## Inputs

The calculation draws on several sources:

| Source | Parameter | Role |
| ---------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------------------------------------------------------- |
| Operator setting | `stake` | Fixed stake amount (TON). When set, overrides percentage-based calculation. |
| Operator setting | `stakePercent` | Percentage of balance to stake. Defaults to `100` when unset. |
| Wallet state | `balance` | Current TON balance of the staking account (validator wallet, pool, or controller). |
| Validator console | Active validator count | Number of validators currently running on this node. Determines whether the node is new or already participating. |
| [On-chain config #17](/foundations/config#param-17-stake-limits) | `minStake` | Network minimum stake. Submissions below this value are rejected by the elector. |
| [On-chain config #17](/foundations/config#param-17-stake-limits) | `maxStake` | Network maximum stake. Submissions above this value are clamped. |
| Node configuration | Staking mode | Whether the node uses a nominator pool, single nominator pool, liquid staking controller, or direct staking. |

Configure `stake` and `stakePercent` with the [`set`](/ecosystem/nodes/cpp/mytonctrl/core#set) command:

```mytonctrl
set stake 500000
```

```mytonctrl
set stakePercent 99
```

Retrieve current values with `get stake` or `get stakePercent`.

## How the priority cascade works

MyTonCtrl evaluates stake sources in a fixed priority order. The first rule that produces a value wins; later rules are skipped.

### Priority 1: Saved fixed stake

If the operator previously ran `set stake <VALUE>`, MyTonCtrl uses that stored amount directly. No additional fee reserve is subtracted at this stage; the value passes straight to the validation guards.

### Priority 2: Nominator pool mode

When the node operates through a standard nominator pool (not a single nominator pool), MyTonCtrl sets:

```text
stake = balance - 20
```

The 20 TON reserve covers the higher fee overhead of pool operations (deploy, process, and distribute messages).

<Aside type="note">
Single nominator pools are excluded from this rule. They fall through to the percentage-based calculation (Priority 4) because single nominator pools behave like direct staking economically.
</Aside>

### Priority 3: Liquid staking controller mode

When the node uses a liquid staking controller, MyTonCtrl sets:

```text
stake = balance - 50
```

The 50 TON reserve is the largest of all modes. Liquid staking controllers perform complex multi-step transactions (minting, burning, and balance adjustments), requiring a bigger fee cushion.

### Priority 4: Percentage-based calculation (default)

If none of the above rules produce a value, MyTonCtrl falls back to percentage-based calculation using `stakePercent`. This is the most common path for single nominator pools and direct staking.

The logic depends on whether the node already has active validators:

**New validator (no active validators):**

```text
stake = balance * stakePercent / 100 / 2
```

The balance is halved. This solves a cold-start problem: on the first election, the elector locks the entire stake for a full validation round. By staking only half, the node keeps the other half available for the next election, which opens before the current round ends. Without halving, a new validator would be locked out of alternating rounds.

**Exception:** if halving produces a value below `minStake`, MyTonCtrl abandons the halving and stakes the full percentage instead. Participating in one round is better than being rejected by the elector for staking too little.

**Existing validator (active validators present):**

```text
stake = balance * stakePercent / 100
```

No halving is needed. The returning stake from the previous round replenishes the balance in time for the next election.

**Fee deduction at 100%:** when `stakePercent` is exactly `100`, MyTonCtrl subtracts 20 TON from the result to prevent draining the wallet completely. At lower percentages, the non-staked remainder covers fees implicitly.

## Validation guards

After the stake amount is determined, three sequential checks run regardless of which priority rule produced the value:

| Check | Condition | Action |
| -------------------- | ------------------ | -------------------------------------------------------------------------- |
| Maximum stake | `stake > maxStake` | Clamps stake down to `maxStake`. Logs a warning. Election entry continues. |
| Minimum stake | `stake < minStake` | Raises an error. Election entry is aborted. |
| Insufficient balance | `stake > balance` | Raises an error. Election entry is aborted. |

The asymmetry is intentional. Exceeding the maximum is recoverable — MyTonCtrl clamps and continues. Falling below the minimum or exceeding the available balance would waste transaction fees on a doomed submission, so MyTonCtrl aborts instead.

## Safety reserves by mode

Each staking mode reserves a different amount for transaction fees:

| Mode | Reserve (TON) | Reason |
| --------------------------------- | ------------- | ------------------------------------------------------------- |
| Saved fixed stake | 0 | The stored value is used as-is; only validation guards apply. |
| Nominator pool | 20 | Multiple messages for pool lifecycle operations. |
| Liquid staking controller | 50 | Complex multi-step DeFi transactions. |
| Percentage at 100% (default mode) | 20 | General safety margin when no non-staked remainder exists. |

## Examples

### New validator with 800,000 TON balance

Settings: `stakePercent = 99`, no fixed `stake`, single nominator pool mode.

1. No saved fixed stake, not a standard nominator pool, not a controller.
1. Falls through to percentage-based calculation (Priority 4).
1. No active validators detected (new node): halving applies.
1. `stake = 800,000 * 99 / 100 / 2 = 396,000`.
1. `396,000 > minStake` (300,000): halving is kept.
1. Result: **396,000 TON** is submitted. The remaining balance covers the next election.

### Returning validator with 1,600,000 TON balance

Settings: `stakePercent = 99`, single nominator pool mode, already validating.

1. Falls through to percentage-based calculation.
1. Active validators present: no halving.
1. `stake = 1,600,000 * 99 / 100 = 1,584,000`.
1. Result: **1,584,000 TON** is submitted.

### New validator with exactly 600,100 TON (near minimum)

Settings: `stakePercent = 100`, single nominator pool mode.

1. Falls through to percentage-based calculation.
1. No active validators: halving would give `600,100 / 2 = 300,050`.
1. `300,050 > minStake` (300,000): halving is kept.
1. `stakePercent == 100`: 20 TON fee deduction applies: `300,050 - 20 = 300,030`.
1. Result: **300,030 TON** is submitted.

### New validator with exactly 500,000 TON (halving would go below minimum)

Settings: `stakePercent = 100`, single nominator pool mode.

1. Falls through to percentage-based calculation.
1. No active validators: halving would give `500,000 / 2 = 250,000`.
1. `250,000 < minStake` (300,000): halving is abandoned.
1. Full percentage is used: `500,000`.
1. `stakePercent == 100`: 20 TON fee deduction: `500,000 - 20 = 499,980`.
1. Result: **499,980 TON** is submitted.

<Aside type="note">
When halving is abandoned due to minimum stake constraints, the node participates only in every second validation round until the balance grows enough to cover both rounds.
</Aside>

### Nominator pool with 2,000,000 TON balance

Settings: standard nominator pool mode (not single nominator).

1. Pool mode detected (Priority 2).
1. `stake = 2,000,000 - 20 = 1,999,980`.
1. Result: **1,999,980 TON** is submitted.

## See also

- [Staking overview](/ecosystem/staking/overview) — comparison of staking solutions and minimum requirements.
- [Run a validator](/ecosystem/nodes/cpp/run-validator#step-4-set-optimal-stake-for-validator) — step-by-step guide for setting optimal stake.
- [MyTonCtrl settings](/ecosystem/nodes/cpp/mytonctrl/core#supported-settings) — full list of configurable parameters including `stake` and `stakePercent`.
- [Single nominator pools](/ecosystem/staking/single-nominator) — recommended staking contract for large holders.
Loading