-
Notifications
You must be signed in to change notification settings - Fork 672
/
calculator.go
69 lines (57 loc) · 2.44 KB
/
calculator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package reward
import (
"math/big"
"time"
)
var _ Calculator = (*calculator)(nil)
type Calculator interface {
Calculate(stakedDuration time.Duration, stakedAmount, currentSupply uint64) uint64
}
type calculator struct {
maxSubMinConsumptionRate *big.Int
minConsumptionRate *big.Int
mintingPeriod *big.Int
supplyCap uint64
}
func NewCalculator(c Config) Calculator {
return &calculator{
maxSubMinConsumptionRate: new(big.Int).SetUint64(c.MaxConsumptionRate - c.MinConsumptionRate),
minConsumptionRate: new(big.Int).SetUint64(c.MinConsumptionRate),
mintingPeriod: new(big.Int).SetUint64(uint64(c.MintingPeriod)),
supplyCap: c.SupplyCap,
}
}
// Reward returns the amount of tokens to reward the staker with.
//
// RemainingSupply = SupplyCap - ExistingSupply
// PortionOfExistingSupply = StakedAmount / ExistingSupply
// PortionOfStakingDuration = StakingDuration / MaximumStakingDuration
// MintingRate = MinMintingRate + MaxSubMinMintingRate * PortionOfStakingDuration
// Reward = RemainingSupply * PortionOfExistingSupply * MintingRate * PortionOfStakingDuration
func (c *calculator) Calculate(stakedDuration time.Duration, stakedAmount, currentSupply uint64) uint64 {
bigStakedDuration := new(big.Int).SetUint64(uint64(stakedDuration))
bigStakedAmount := new(big.Int).SetUint64(stakedAmount)
bigCurrentSupply := new(big.Int).SetUint64(currentSupply)
adjustedConsumptionRateNumerator := new(big.Int).Mul(c.maxSubMinConsumptionRate, bigStakedDuration)
adjustedMinConsumptionRateNumerator := new(big.Int).Mul(c.minConsumptionRate, c.mintingPeriod)
adjustedConsumptionRateNumerator.Add(adjustedConsumptionRateNumerator, adjustedMinConsumptionRateNumerator)
adjustedConsumptionRateDenominator := new(big.Int).Mul(c.mintingPeriod, consumptionRateDenominator)
remainingSupply := c.supplyCap - currentSupply
reward := new(big.Int).SetUint64(remainingSupply)
reward.Mul(reward, adjustedConsumptionRateNumerator)
reward.Mul(reward, bigStakedAmount)
reward.Mul(reward, bigStakedDuration)
reward.Div(reward, adjustedConsumptionRateDenominator)
reward.Div(reward, bigCurrentSupply)
reward.Div(reward, c.mintingPeriod)
if !reward.IsUint64() {
return remainingSupply
}
finalReward := reward.Uint64()
if finalReward > remainingSupply {
return remainingSupply
}
return finalReward
}