Nominator pool
A Nominator Pool is a smart contract that allows one or more nominators to lend Toncoin for validator staking. It ensures validator funds are used exclusively for validation and guarantees proper reward distribution.
Architecture
Limits
The pool is designed for large amounts of coins, prioritizing security and code simplicity. It doesn't support small deposits or a large number of nominators. The target configuration is:
- Minimum nominator stake: 10,000 TON
- Maximum nominators per pool: 40 (untested beyond this limit)
Fees
Operating in the masterchain requires about 5 TON per validation round, paid by the validator. The pool must maintain a minimum balance of 10 TON for network storage fees (non-withdrawable).
Reward distribution
After each validation round, the pool recovers its stake plus rewards from the elector contract. Rewards are split as follows:
validator_reward = (reward * validator_reward_share) / 10000
nominators_reward = reward - validator_reward
Nominators receive shares proportional to their stakes. For example, if two nominators are in the pool with stakes of 100k and 300k TON, the first one will take 25% and the second 75% of the nominators_reward
.
Slashing
For validation fines:
- Deduct from validator funds first
- If insufficient, deduct from nominators proportionally
- Pool design ensures validator funds always cover the maximum possible fines
Validator requirements
The pool participates in validation only when:
- Validator funds exceed
min_validator_stake
- Validator funds cover maximum possible fines (based on network config)
Nominator's messages
To interact with the nominator pool, nominators send simple messages with a text comment (from any wallet application) to the pool smart contract. All messages must be sent in bounceable mode to prevent fund loss from errors.
Deposit
Send a message with the comment "d" and amount ≥ min_nominator_stake + 1 TON
.
Deposits:
- Credit immediately if pool inactive (
state == 0
) - Queue as
pending_deposit_amount
if pool active - Reject if
max_nominators_count
reached
Withdrawal
Send a message with the comment "w" and 1 TON for fees:
- Executes immediately if funds are available
- Queues as
withdraw_request
otherwise - Full withdrawal only (no partial withdrawals)
Validator withdraw
The validator can withdraw from the pool all the Toncoins that do not belong to the nominators.
Key management
Participants must safeguard private keys:
- Lost nominator wallet = lost pool funds
- Lost validator wallet = lost validator funds
Losing one participant's private key does not impact other participants in the pool.
Emergency operations
If the validator becomes inactive, any party can send operational messages such as process withdraw requests
, update current validator set
, new_stake
, and recover_stake
to enable nominator withdrawals. The validator software mytonctrl
does this automatically.
Voting for network config proposals
The pool implements weighted voting for network config proposals:
- Proposals announced via @tonblockchain or @tonstatus with HEX hashes like
D855FFBCF813E50E10BEAB902D1177529CE79785CAE913EB96A72AE8EFBCBF47
- Nominators vote by sending a message to the nominator pool:
y<HASH>
to supportn<HASH>
to opposePlease attach a small amount of tokens (minimum 1 TON) to this message to cover the network fee. Any unspent TON will be automatically returned to your wallet.
- Validator submits final vote based on pool consensus
- Votes expire after 30 days
Get methods
Get-method get_pool_data
Returns complete pool state information as a tuple containing:
-
state
(uint)
Current operational state:
0
= Not validating
1
= Stake request sent
2
= Validation confirmed -
nominators_count
(uint)
Active nominators count -
stake_amount_sent
(nanotons)
The current validation stake amount -
validator_amount
(nanotons)
Validator's owned funds -
validator_address
(uint, immutable)
Validator wallet address. Convert with"-1:" + dec_to_hex(validator_address)
. -
validator_reward_share
(uint, immutable)
Validator's reward percentage. For example 4000 = 40%
validator_reward = (reward * validator_reward_share) / 10000
-
max_nominators_count
(uint, immutable)
Maximum allowed nominators, typically 40 -
min_validator_stake
(nanotons, immutable)
Minimum validator stake requirement -
min_nominator_stake
(nanotons, immutable)
Minimum nominator deposit -
nominators
(Cell)
Raw dictionary of active nominators -
withdraw_requests
(Cell)
Raw dictionary of pending withdrawals -
stake_at
(uint)
Next validation round ID, which is supposed to start atutime_since
-
saved_validator_set_hash
(uint)
Technical validator info -
validator_set_changes_count
(uint)
Technical validator info -
validator_set_change_time
(uint)
Technical validator info -
stake_held_for
(uint)
Stake lock duration -
config_proposal_votings
(Cell)
Raw dictionary of active proposal votes
Get-method list_nominators
Returns an array of all nominators with their:
address
(uint)
BaseChain address. Convert with"0:" + dec_to_hex(address)
.amount
(nanotons)
Active stake balancepending_deposit_amount
(nanotons)
Queued deposit amountwithdraw_request
(int)
-1
indicates active withdrawal request
Get-method get_nominator_data
Returns detailed nominator information for the specified address.
Address must be in raw format without the
0:
prefix.
amount
(nanotons) - Active stakepending_deposit_amount
(nanotons) - Queued depositwithdraw_request
(int) - Withdrawal flag (-1
if active)
Throws an 86
error if there is no such nominator in the pool.
Example:
For nominator EQA0i8-CdGnF_DhUHHf92R1ONH6sIA9vLZ_WLcCIhfBBXwtG
:
get_nominator_data 0x348bcf827469c5fc38541c77fdd91d4e347eac200f6f2d9fd62dc08885f0415f
Voting Methods
Get-method list_votes
Returns all active proposals with the following:
proposal_hash
(uint) - Convert withdec_to_hex()
votes_create_time
(uint) - Unix timestamp
Get-method list_voters
Returns voting details per proposal:
address
(uint)- Nominator:
"0:" + dec_to_hex(address)
- Validator:
"-1:" + dec_to_hex(address)
- Nominator:
support
(int)-1
= For0
= Against
vote_time
(uint) - Unix timestamp
Note: Voting results calculated off-chain
Integration into wallet applications
For deposits, withdrawals, and votes, send simple messages to the pool with the desired text comments as described above. When sending a deposit, you can store the amount in the local storage. When sending a re-deposit, add it to this amount, too.
Call the get method get_nominator_data(your_address)
and calculate profit as:
current_profit = (amount + pending_deposit_amount) - sent_amount_stored_in_local_storage
To obtain the pool's complete state, you need to query both get_pool_data
and list_nominators
.