Skip to main content

Single Nominator Pool

Single Nominator is a TON smart contract that enables secure validation for TON blockchain. The contract is designed for TON validators that have enough self stake to validate by themselves without relying on third-party nominators stakes. The contract provides an alternative simplified implementation for the Nominator Pool smart contract that supports a Single Nominator only.

Set up single-nominator

caution

Before start make sure you have topped up and activated validator's wallet.

  1. Enable single nominator mode
MyTonCtrl> enable_mode single-nominator
  1. Check if single-nominator mode is enabled.
MyTonCtrl> status_modes
Name Status Description
single-nominator enabled Orbs's single nominator pools.
  1. Create pool
MyTonCtrl> new_single_pool <pool-name> <owner_address>

If you have already created pool it's possible to import it:

MyTonCtrl> import_pool <pool-name> <pool-addr>
  1. Type pools_list to display pool addresses
MyTonCtrl> pools_list
Name Status Balance Version Address
test-pool empty 0.0 spool_r2 kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX
  1. Activate the pool
MyTonCtrl> activate_single_pool <pool-name>

After successfully activated pool:

MyTonCtrl> pools_list
Name Status Balance Version Address
test-pool active 0.99389 spool_r2 kf_JcC5pn3etTAdwOnc16_tyMmKE8-ftNUnf0OnUjAIdDJpX

Now you can work with this pool via mytonctrl like with a standard nominator pool.

info

If the pool's balance is enough to participate in both rounds (balance > min_stake_amount * 2) then MyTonCtrl will automatically participate in both rounds using stake = balance / 2, unless user sets stake manually using command set stake. This behaviour is different from using a nominator pool but similar to staking using validator wallet.

Start without mytonctrl

Prepare launched Validator

If you have mytonctrl installed and validator running:

  1. Stop validation and withdraw all funds.

Prepare from the beginning

If you had no Validator before, do the following:

  1. Run a Validator and make sure it's synced.
  2. Stop validation and withdraw all funds.

Prepare Single Nominator

  1. Install nodejs v.16 and later and npm (detailed instructions)

  2. Install ts-node and arg module

$ sudo apt install ts-node
$ sudo npm i arg -g
  1. Create symlinks for compilers:
$ sudo ln -s /usr/bin/ton/crypto/fift /usr/local/bin/fift
$ sudo ln -s /usr/bin/ton/crypto/func /usr/local/bin/func
  1. Run test to make sure everything is set up properly:
$ npm run test
  1. Replace mytonctrl nominator-pool scripts: https://raw.githubusercontent.com/orbs-network/single-nominator/main/mytonctrl-scripts/install-pool-scripts.sh

Create Single Nominator Pool

  1. Get Toncenter API key from a Telegram @tonapibot
  2. Set env variables:
export OWNER_ADDRESS=<owner_address>
export VALIDATOR_ADDRESS=<validator_wallet_address>
export TON_ENDPOINT=https://toncenter.com/api/v2/jsonRPC
export TON_API_KEY=<toncenter api key>
  1. Create deployer address:
$ npm run init-deploy-wallet
Insufficient Deployer [EQAo5U...yGgbvR] funds 0
  1. Topup deployer address with 2.1 TON
  2. Deploy pool contract, you will get pool address: Ef-kC0..._WLqgs:
$ npm run deploy
  1. Convert address to .addr:
$ fift -s ./scripts/fift/str-to-addr.fif Ef-kC0..._WLqgs

(Saving address to file single-nominator.addr)

  1. Backup deployer private key "./build/deploy.config.json" and "single-nominator.addr" files
  2. Copy "single-nominator.addr" to "mytoncore/pools/single-nominator-1.addr"
  3. Send stake from owner address to single nominator address

Withdrawals from Single Nominator

Using wallets to withdraw from Single Nominator Fift:

  1. Create "withdraw.boc" request with amount:
$ fift -s ./scripts/fift/withdraw.fif <withdraw_amount>
  1. Create and sign request from owner's wallet:
$ fift -s wallet-v3.fif <my-wallet> <single_nominator_address> <sub_wallet_id> <seqno> <amount=1> -B withdraw.boc
  1. Broadcast query:
$ lite-client -C global.config.json -c 'sendfile wallet-query.boc'
tons
  1. Create "withdraw.boc" request with amount:
$ fift -s ./scripts/fift/withdraw.fif <withdraw_amount>
  1. Send request to single nominator address:

a.

$ tons wallet transfer <my-wallet> <single_nominator_address> <amount=1> --body withdraw.boc
tonkeeper

b.

npm link typescript

c.

npx ts-node scripts/ts/withdraw-deeplink.ts <single-nominator-addr> <withdraw-amount>

d. Open deeplink on the owner's phone

Deposit pool

You can make a deposit using MyTonCtrl, using the following commands:

MyTonCtrl> mg <from-wallet-name> <pool-account-addr> <amount>

or

MyTonCtrl> deposit_to_pool <pool-addr> <amount>

which deposits pool from validator wallet.

Or use the following steps:

  1. Go to the pool’s page https://tonscan.org/nominator/<pool_address>.

  2. Make sure that the information about the pool is fully displayed, if the pool has the wrong smart contract, there will be no information.

  3. Press the ADD STAKE button or scan the QR-code using Tonkeeper or any other TON Wallet.

  4. After you are transferred to the wallet, please, enter the amount of TON and then send the transaction. After that TON coins will be added to staking.

If the wallet does not open automatically, you can send the transaction manually by copying the pool address. Send it through any TON wallet. From the sent transaction, 1 TON will be debited as a commission for processing the deposit.

Withdraw funds

To get coins back after staking, send 1 TON to the pool’s address, add a comment w (small letter) to the transaction. This 1 TON minus commission will be returned, and a smart-contract will understand that you want to bring the coins back and it will send them back right after the end of the validator’s work cycle. It usually takes up to 18 hours on Mainnet and 2 hours on Testnet.

You can also withdraw funds using the following command:

MyTonCtrl> withdraw_from_pool <pool-addr> <amount>

Or you can create and send transaction manually:

import { Address, beginCell, internal, storeMessageRelaxed, toNano } from "@ton/core";

async function main() {
const single_nominator_address = Address.parse('single nominator address');
const WITHDRAW_OP = 0x1000
const amount = 50000

const messageBody = beginCell()
.storeUint(WITHDRAW_OP, 32) // op code for withdrawal
.storeUint(0, 64) // query_id
.storeCoins(amount) // amount to withdraw
.endCell();

const internalMessage = internal({
to: single_nominator_address,
value: toNano('1'),
bounce: true,
body: messageBody
});
}

Election process

Set up a Single Nominator Pool

Configure the Single Nominator Pool contract using the following instructions.

Join the elections

Deposit minimum stake amount to the Single Nominator Pool.

MyTonCtrl will automatically join the elections. You can set the stake amount that mytonctrl sends to the Elector contract ~ every 18 hours on Mainnet and 2 hours on Testnet.

MyTonCtrl> set stake 90000

Minimum stake amount could be found using status command.

You can set stake as null and it will be calculated according to the stakePercent value (could be checked with status_settings command).

It's possible to check is election has already been started:

MyTonCtrl> status

and for Testnet:

MyTonCtrl> status fast

As example:

If the election has been started and Single Nominator Pool is activated, validator should automatically send ElectorNewStake message to the Elector contract at the beginning of the next round.

Check validator wallet:

MyTonCtrl> wl
Name Status Balance Ver Wch Address
validator_wallet_001 active 995.828585374 v1 -1 kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct

Then check it transaction history:

MyTonCtrl> vas kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct
Address Status Balance Version
kf_dctjwS4tqWdeG4GcCLJ53rkgxZOGGrdDzHJ_mxPkm_Xct active 995.828585374 v1r3

Code hash
c3b9bb03936742cfbb9dcdd3a5e1f3204837f613ef141f273952aa41235d289e

Time Coins From/To
39 minutes ago >>> 1.3 kf_hz3BIXrn5npis1cPX5gE9msp1nMTYKZ3l4obzc8phrBfF

This ElectorNewStake transaction in Single Nominator contract history in Tonviewer:

On the above example MyTonCtrl automatically stake 90000 Toncoins on the Elector contract.

Checking Validator Status

At the beginning of the next round check MyTonCtrl validator status with status command (status fast on Testnet).

You can confirm if your node has become a full validator by checking the following conditions:

  1. Validator Efficiency - An efficiency of the local validator should be green and not n/a.
  2. Validator Index - The validator index should be greater than -1.

Checking profit

At the end of the round MyTonCtrl sends ElectorRecoverStakeRequest message to the Elector contract. It responses with stake + profit amount of Toncoins to your Single Nominator Pool.

You can also check transactions history of your pool with vas command:

Stop participating

If user doesn't want to take part in validating anymore:

  1. Disable validator mode:
MyTonCtrl> disable_mode validator
  1. Withdraw all funds from the Single Nominator contract to the owner wallet.

Transitioning a Regular Validator to Nominator Pool Mode

  1. Disable validator mode to discontinue election participation.
  2. Await the return of both your stakes from the elector.
  3. Proceed with the following steps.

See Also