-
Notifications
You must be signed in to change notification settings - Fork 56
feat(staking): add stake calculation page #1961
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
coalus
wants to merge
6
commits into
ton-org:main
Choose a base branch
from
coalus:docs/stake-calculation-article
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
f2d3f99
docs(staking): add stake calculation explanation page
coalus 6a91fdf
chore: fix styling
coalus 9e92e6f
chore: remove useless description/title
coalus 78612c7
chore: rename heading
coalus dc0e009
fix(staking): drop non actually used explicit argument
coalus ac1991f
fix: fix table styling
coalus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: | ||
novusnota marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| | 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. | ||
novusnota marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ### 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`. | ||
novusnota marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| - [Single nominator pools](/ecosystem/staking/single-nominator) — recommended staking contract for large holders. | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.