Looking into Tokamak Network’s Staking Contract

Harvey Jo
Tokamak Network
Published in
8 min readJul 23, 2021

--

Intro

The Tokamak Network Stake Contract is one of the contracts available to TON holders in which holders have an advantage of being able to gain seigniorage(TON) when staking.

The dictionary definition of ‘seigniorage’ is the profit earned when the central bank or government issues money. Looking at this from the perspective of Tokamak Network’s staking contract, the TON issued from using the staking contract can be recognized as seigniorage. The staking contract distributes this seigniorage to TON stakers and more according to the design of the contract.

This post explains how the Tokamak Network’s staking contract works, and how seigniorage is calculated and distributed to TON stakers.

Outline of Contract

Contracts show how the user manages the stake values when staking, how the seigniorage is calculated, and how the seigniorage is distributed and managed.

First, the role each contract plays will be discussed.

  1. TON : Issues and manages TON.
  2. WTON : Swaps TON to WTON and deposits WTON to DepositManager Contract
  3. DepositManager : Manages the deposit, redeposit, requestWithdrawal, processRequest of WTON and sets withdrawDelay
  4. SeigManager : Manages and calculates seigniorage
  5. Layer2Registry : Registers coinage
  6. CoinageFactory : Makes coinage
  7. AutoRefactorCoinage : Calculates seigniorage using factor value
  8. PowerTON : Winners are drawn once every two weeks and are given seigniorage accumulated in powerTON

The total TON supply, seigniorage per block, and distribution ratio in the staking contract currently are

  1. Total TON supply : 50,000,000 TON (can be checked via calling TON Contract’s totalSupply(). May change in the future depending on additional seigniorage issued)
  2. Seigniorage per block : 3.92 TON (can be checked via calling SeigManager Contract’s seigPerBlock(). Seigniorage per block does not change)
  3. Distribution ratio : Seigniorage can be divided into 2 categories.
    ⓵ staking seigniorage = Calculated Maximum seigniorage per block * (TON staking supply/Total TON supply)
    ⓶ unstaking seigniorage = Calculated Maximum seigniorage per block * [ (Total TON supply — TON staking supply) / Total TON supply]
    Here, staking seigniorage is only given to TON stakers whereas unstaking seigniorage is distributed by TON staker(40%), powerTON(5%), DAO(50%). (This ratio can be altered using the linked functions. By calling SeigManager Contract’s functions — powerTONSeigRate, daoSeigRate, relativeSeigRate, one can check the ratio.)

The following section will explain how the staking contract giving seigniorage works and how seigniorage is calculated and distributed.

Staking Contract

If a user applies for staking with TON, the staking process is as follows :

  1. The unit of TON is changed to WTON and mint WTON.
  2. After saving TON in WTON CA, deposit WTON in DepositManager.
  3. After saving and recording WTON in DepositManger Contract, notify SeigManager.
  4. SeigManager mints tot and coinage as much as the amount of WTON saved.

CA is a Contract Account, acting as a smart contract and has separate ‘deployed code’ and ‘storage’. CA is responsible for receiving messages and then executing internal code and storing data in internal storage.

The reason for swapping the TON to WTON when Tokamak Network staking is to minimize the decimal point being cut off when calculating and giving seigniorage.

Seigniorage calculation is more accurate with WTON because TON’s decimal point is 18 whereas for WTON it is 27. Therefore, when giving it with WTON it’s precision is higher.

In Tokamak Network’s staking contract, seigniorage is managed through tot, coinage and operator. Below, an explanation of tot, coinage, and operator will be given.

The picture above is an example. Here, coinage is tokamak1, DXM, DSRV and tot is where all coinage is collected and seigniorage is managed. The delegator would be TON staker in each coinage.

Explanation will be given by applying it to the actual Tokamak Network web service.
The picture above is the staking screen in Tokamak Network staking, which is currently in service. Here, Tokamak1, Level 19, DSRV, staked, and Talken become coinage, and the place where they are comprehensively managed is tot. If the user selects one of the coinages and stakes it, he or she will become the coinage’s delegator.

The operator commit block data mined on Layer 2 on Layer 1. At the same time Layer 1’s tot and coinage distribute the staking seigniorage.
When committing Layer 2 information on Layer 1, the operator must pay a gasFee for the block data update transaction. This will be rewarded with additional seigniorage based on the commissionRate value.

Currently, the above three Layer 2 of the Tokamak Network staking web service are contracts made by DAO candidate. Therefore, anyone can update the seigniorage even though one may not be an operator.

Seigniorage Calculation

Seigniorage, as mentioned above, is divided in seigniorage given to TON stakers, powerTON and DAO.

The distribution ratio of seigniorage is managed by the owner of SeigManager Contract, and below is an example of such ratio.

  • relativeSeigRate(seigniorage given to TON stakers) = 0.4
  • powerTONSeigRate(seigniorage given to powerTON) = 0.05
  • daoSeigRate(seigniorage given to DAO) = 0.5

The remaining 0.05 is discarded.

Seigniorage given per block is seigPerBlock value, which is approximately 3.92. Using this value when the operator updateSeigniorage, the maxSeig(the maximum seigniorage that can be given) value can be calculated. maxSeig = (current block number — the most recent block number that did updateSeigniorage) * seigPerBlock

The maxSeig value is the seigniorage a TON staker can receive if every holder of TON stakes TON. However, in reality not all TON holders stake, so TON stakers and non-staking holders can be divided.

Let’s call seigniorage for TON stakers as stakedSeig and seigniorage for non-staking holders, unstakedSeig(maxSeig-stakedSeig).
stakedSeig is 100% for TON stakers.
However, unstakedSeig will be distributed in the above distribution ratio by TON staker = 40%, powerTON = 5%, DAO = 50%.

Using this ratio, the final seigniorage is given as follows.

Let’s calculate the seigniorage when the operator updateSeigniorage at block.number = 10, and afterwards updateSeigniorage at block.number = 20. (This is just an example value for simple calculation)

  • Total TON Supply = 5,000
  • commissionRate = 0
  • tokamak1 operator = 1,000
  • A staking amount (tokamak1) = 100
  • B staking amount (tokamak1) = 200
  • C staking amount (tokamak1) = 500
  • total staking amount (tokamak1) = 1,800

maxSeig = (20–10) * 3.92 = 39.2
stakedSeig = 39.2 * (1,800/5,000) = 14.112
unstakedSeig = 39.2–14.112 = 25.088

1. Seigniorage given to TON stakers = 14.112 + 25.088*0.4 = 24.147
1–1. A staking seigniorage = 24.147*100/1,800 = 1.3415
1–2. B staking seigniorage = 24.147*200/1,800 = 2.6830
1–3. C staking seigniorage = 24.147*500/1,800 = 6.7075
1–4. operator staking seigniorage = 24.147*1,000/1,800 = 13.4151

2. Seigniorage given to powerTON = 25.088 * 0.05 = 1.2544

3. Seigniorage given to DAO = 25.088 * 0.5 = 12.544

Seigniorage will be distributed as above.

Seigniorage Update Code

The above is SeigManager Contract’s updateSeigniorage function. Let’s see how seigniorage is distributed according to the function.

uint256 operatorAmount = getOperatorAmount(msg.sender);    require(operatorAmount >= minimumAmount);

This is code to examine the requirement. One needs over 100TON to become an operator. Let’s check this and see if the condition is fulfilled.

_increaseTot();

The full code of _increaseTot() is as follows.

prevTotalSupply = _tot.totalSupply();uint256 maxSeig = _calcNumSeigBlocks().mul(_seigPerBlock);

The totalSupply before seigniorage is added is put as the value of prevTotalSupply. _calcNumSeigBlock() is calculates how many block has elapsed from the previous block that issued seignorage to the current block maxSeig = (Calculated block period)*(_seigPerBlock)

uint256 tos = _ton.totalSupply()      .sub(_ton.balanceOf(address(_wton)))      
.mul(10 ** 9)
.add(_tot.totalSupply());uint256 stakedSeig = rdiv(rmul(maxSeig,_tot.totalSupply()),tos);

Using tos(amount of TON staking), maxSeig(maximum seigniorage per block), totalSupply(total TON supply), stakedSeig value can be calculated. This is the same as the stakedSieg mentioned above, calculated seigniorage per block * (TON staking supply/Total TON supply)

uint256 totalPseig = rmul(maxSeig.sub(stakedSeig),relativeSeigRate); 

nextTotalSupply = prevTotalSupply.add(stakedSeig).add(totalPseig);_lastSeigBlock = block.number;_tot.setFactor(_calcNewFactor(prevTotalSupply, nextTotalSupply, _tot.factor()));

totalPseig is the additional seigniorage given to TON stakers out of unstakedSeig. Therefore, stakedSeig and totalPseig are added to prevTotalSupply to get the nextTotalSupply.
When prevTotalSupply and nextTotalSupply values are used in _tot.setFactor function, seigniorage is distributed to the TON staker.

Once the TON staker is given seigniorage, the remaining seigniorage is distributed to powerTON and DAO through the code below.

if (address(_powerton) != address(0)) {      
powertonSeig = rmul(unstakedSeig, powerTONSeigRate);
_wton.mint(address(_powerton), powertonSeig);
}if (dao != address(0)) {
daoSeig = rmul(unstakedSeig, daoSeigRate);
_wton.mint(address(dao), daoSeig);
}

Through __increaseTot() function, seigniorage is distributed to TON staker, powerTON and DAO and returns to updateSeigniorage function.

(nextTotalSupply, operatorSeigs) = _calcSeigsDistribution(            
msg.sender,
coinage,
prevTotalSupply,
seigs,
isCommissionRateNegative,
operator
);// gives seigniorages to the layer2 as coinage
coinage.setFactor(
_calcNewFactor(
prevTotalSupply,
nextTotalSupply,
coinage.factor()
)
);// give commission to operator or delegators
if (operatorSeigs != 0) {
if (isCommissionRateNegative) {
coinage.burnFrom(operator, operatorSeigs);
} else {
coinage.mint(operator, operatorSeigs);
}
}_wton.mint(address(_depositManager), seigs);

Now, in the updateSeigniorage function, data of who and when they ran the function is saved and changed values are updated. Seigniorage is calculated and given to the operator who correctly updated the seigniorage.

Through the codes above we have seen how seigniorage is distributed. The following section will predict TON’s inflation due to seigniorage issuance.

Nominal Additional Seigniorage

The additional seigniorage will be 9,500,000TON per year if all TON holders stake. Thus, for the first year, nominal interest rate will be 19% for the initial TON supply of 50,000,000 TON.

The table above shows how each seigniorage is given and the total amount of TON issued depending on the staking rate for the first year.

For the maximum seigniorage to be issued, 100% of TON holders have to stake. In this case, 9,500,000 TON will be issued via seigniorage, and after 5 years the total TON supply will become 97,500,000 TON.

Current seigniorage is distributed as TON staker seigniorage, PowerTON seigniorage, and DAO seigniorage. However, categories or the ratio may change as new services of the Tokamak Network are added.

Conclusion

  • When the user stakes TON, TON will be swapped to WTON. The seigniorage system is managed by tot, coinage and operator.
  • tot : Manages coinages’ seigniorage.
  • coinage : Users can choose to stake.
  • operator : Coinage Manager(commits block information created on Layer 2 on Layer 1)
  • Seigniorage is comprised of TON staker seigniorage, PowerTON seigniorage, and DAO seigniorage.
  • Seigniorage given to TON stakers : Seigniorage TON stakers receive
  • Seigniorage given to powerTON : If a user becomes a TON staker, one participates in powerTON. Winners are drawn once every two weeks and are given seigniorage accumulated in powerTON
  • Seigniorage given to DAO : Seigniorage used in the Tokamak DAO contract. More information on DAO is in Everything of Tokamak DAO.
  • For those who want to calculate expected profit of TON staking, Tokamak Network Staking Simulator will help.

Thank you.

--

--