Overview

Background

As one of the digital financial derivatives on SUN.io, mining provides crypto holders with stable, secure, and reliable services for subscription and redemption of investment products. Governance mining is an important part of SUN.io's mining service. As shown in the graph below, the reward distributed to users is closely related to the number of veSun tokens they hold and the weights of the liquidity pools. And users are free to redeem their assets at any time.

Explanation

After a user stakes tokens in a liquidity pool, a corresponding amount of virtual stake value will be generated:

Suser=min(Luser,Luser0.4+Ltotal(veSunuserveSuntotal)0.6)1S_{user}=min(L_{user},L_{user}*0.4+L_{total}*(\frac{veSun_{user}}{veSun_{total}})*0.6)(1)

LuserL_{user} represents the real value staked by the user. LtotalL_{total} is the total value staked in a liquidity pool. veSunuserveSun_{user} is the number of veSun tokens held by the user. veSuntotalveSun_{total} is the total number of veSun tokens issued by SUN.io. As shown in formula (1), if the user holds enough veSun, then the virtue stake is indicated as LuserL_{user}; if the user holds 0 veSun, then it is indicated as LuserL_{user} * 0.4, meaning that the reward for holding veSUN can be amplified by 2.5 times.

V=WgaugeWtypeWtotalrt2V=\frac{W_{gauge}*W_{type}}{W_{total}}*r_t(2)

WgaugeW_{gauge} represents the weekly gauge weight of the pool. WtypeW_{type} is the weight of the pool type. WtotalW_{total} is the total weight of the pool for the week and rtr_t is the expansion factor of the reward token. According to the reward distribution formula (2) of Smart Mining V1, the user's rewards are calculated in the following way:

f(ti,tn)=i=1mSuserj=startiendi(titi1)VTi3f(t_i,t_n)= \sum_{i=1}^{m}S_{user} \sum_{j=start_i}^{end_i}\frac{(t_i-t_{i-1})V}{T_i}(3)

Here, V represents the final expansion factor of the reward token. tit_i represents the i-th change. TiT_i represents the total virtual stake at the time ti1t_{i-1} to tit_i. SuserS_{user} represents the user's virtual stake value at the time ti1t_{i-1} to tit_i.

Contract code

def _checkpoint(addr: address):
    Controller(_controller).checkpoint_gauge(convert(self.controller_key, bytes32))
    _working_balance: uint256 = self.working_balances[addr]
    _working_supply: uint256 = self.working_supply

    if block.timestamp > _period_time:
        prev_week_time: uint256 = _period_time
        week_time: uint256 = min((_period_time + WEEK) / WEEK * WEEK, block.timestamp)

        for i in range(500):
            dt: uint256 = week_time - prev_week_time
            w: uint256 = Controller(_controller).gauge_relative_weight(convert(self.controller_key, bytes32), prev_week_time / WEEK * WEEK)

            if _working_supply > 0:
                if prev_future_epoch >= prev_week_time and prev_future_epoch < week_time:
                    _integrate_inv_supply += rate * w * (prev_future_epoch - prev_week_time) / _working_supply
                    rate = new_rate
                    _integrate_inv_supply += rate * w * (week_time - prev_future_epoch) / _working_supply
                else:
                    _integrate_inv_supply += rate * w * dt / _working_supply
            if week_time == block.timestamp:
                break
            prev_week_time = week_time
            week_time = min(week_time + WEEK, block.timestamp)

    _period += 1
    self.period = _period
    self.period_timestamp[_period] = block.timestamp
    self.integrate_inv_supply[_period] = _integrate_inv_supply
    
    self.integrate_fraction[addr] += _working_balance * (_integrate_inv_supply - self.integrate_inv_supply_of[addr]) / 10 ** 18
    self.integrate_inv_supply_of[addr] = _integrate_inv_supply
    self.integrate_checkpoint_of[addr] = block.timestamp

Last updated