2018-07-13 13:46:14 -07:00
package types
import (
"math/rand"
"testing"
"github.com/stretchr/testify/require"
sdk "github.com/cosmos/cosmos-sdk/types"
)
//changing the int in NewSource will allow you to test different, deterministic, sets of operations
var r = rand . New ( rand . NewSource ( 6595 ) )
func TestGetInflation ( t * testing . T ) {
pool := InitialPool ( )
params := DefaultParams ( )
// Governing Mechanism:
// BondedRatio = BondedTokens / TotalSupply
// inflationRateChangePerYear = (1- BondedRatio/ GoalBonded) * MaxInflationRateChange
tests := [ ] struct {
name string
setBondedTokens , setLooseTokens ,
2018-08-14 17:15:02 -07:00
setInflation , expectedChange sdk . Dec
2018-07-13 13:46:14 -07:00
} {
// with 0% bonded atom supply the inflation should increase by InflationRateChange
2018-08-14 17:15:02 -07:00
{ "test 1" , sdk . ZeroDec ( ) , sdk . ZeroDec ( ) , sdk . NewDecWithPrec ( 7 , 2 ) , params . InflationRateChange . Quo ( hrsPerYrDec ) } ,
2018-07-13 13:46:14 -07:00
// 100% bonded, starting at 20% inflation and being reduced
// (1 - (1/0.67))*(0.13/8667)
2018-08-14 17:15:02 -07:00
{ "test 2" , sdk . OneDec ( ) , sdk . ZeroDec ( ) , sdk . NewDecWithPrec ( 20 , 2 ) ,
sdk . OneDec ( ) . Sub ( sdk . OneDec ( ) . Quo ( params . GoalBonded ) ) . Mul ( params . InflationRateChange ) . Quo ( hrsPerYrDec ) } ,
2018-07-13 13:46:14 -07:00
// 50% bonded, starting at 10% inflation and being increased
2018-08-14 17:15:02 -07:00
{ "test 3" , sdk . OneDec ( ) , sdk . OneDec ( ) , sdk . NewDecWithPrec ( 10 , 2 ) ,
sdk . OneDec ( ) . Sub ( sdk . NewDecWithPrec ( 5 , 1 ) . Quo ( params . GoalBonded ) ) . Mul ( params . InflationRateChange ) . Quo ( hrsPerYrDec ) } ,
2018-07-13 13:46:14 -07:00
// test 7% minimum stop (testing with 100% bonded)
2018-08-14 17:15:02 -07:00
{ "test 4" , sdk . OneDec ( ) , sdk . ZeroDec ( ) , sdk . NewDecWithPrec ( 7 , 2 ) , sdk . ZeroDec ( ) } ,
{ "test 5" , sdk . OneDec ( ) , sdk . ZeroDec ( ) , sdk . NewDecWithPrec ( 70001 , 6 ) , sdk . NewDecWithPrec ( - 1 , 6 ) } ,
2018-07-13 13:46:14 -07:00
// test 20% maximum stop (testing with 0% bonded)
2018-08-14 17:15:02 -07:00
{ "test 6" , sdk . ZeroDec ( ) , sdk . ZeroDec ( ) , sdk . NewDecWithPrec ( 20 , 2 ) , sdk . ZeroDec ( ) } ,
{ "test 7" , sdk . ZeroDec ( ) , sdk . ZeroDec ( ) , sdk . NewDecWithPrec ( 199999 , 6 ) , sdk . NewDecWithPrec ( 1 , 6 ) } ,
2018-07-13 13:46:14 -07:00
// perfect balance shouldn't change inflation
2018-08-14 17:15:02 -07:00
{ "test 8" , sdk . NewDec ( 67 ) , sdk . NewDec ( 33 ) , sdk . NewDecWithPrec ( 15 , 2 ) , sdk . ZeroDec ( ) } ,
2018-07-13 13:46:14 -07:00
}
for _ , tc := range tests {
pool . BondedTokens , pool . LooseTokens = tc . setBondedTokens , tc . setLooseTokens
pool . Inflation = tc . setInflation
inflation := pool . NextInflation ( params )
diffInflation := inflation . Sub ( tc . setInflation )
require . True ( t , diffInflation . Equal ( tc . expectedChange ) ,
"Name: %v\nDiff: %v\nExpected: %v\n" , tc . name , diffInflation , tc . expectedChange )
}
}
// Test that provisions are correctly added to the pool and validators each hour for 1 year
func TestProcessProvisions ( t * testing . T ) {
pool := InitialPool ( )
params := DefaultParams ( )
var (
initialTotalTokens int64 = 550000000
2018-08-14 17:15:02 -07:00
cumulativeExpProvs = sdk . ZeroDec ( )
2018-07-13 13:46:14 -07:00
)
2018-08-14 17:15:02 -07:00
pool . LooseTokens = sdk . NewDec ( initialTotalTokens )
2018-07-13 13:46:14 -07:00
// process the provisions for a year
for hr := 0 ; hr < 100 ; hr ++ {
2018-08-14 17:15:02 -07:00
var expProvisions sdk . Dec
2018-07-13 13:46:14 -07:00
_ , expProvisions , pool = updateProvisions ( t , pool , params , hr )
cumulativeExpProvs = cumulativeExpProvs . Add ( expProvisions )
}
//get the pool and do the final value checks from checkFinalPoolValues
2018-08-14 17:15:02 -07:00
checkFinalPoolValues ( t , pool , sdk . NewDec ( initialTotalTokens ) , cumulativeExpProvs )
2018-07-13 13:46:14 -07:00
}
//_________________________________________________________________________________________
////////////////////////////////HELPER FUNCTIONS BELOW/////////////////////////////////////
// Final check on the global pool values for what the total tokens accumulated from each hour of provisions
2018-08-14 17:15:02 -07:00
func checkFinalPoolValues ( t * testing . T , pool Pool , initialTotalTokens , cumulativeExpProvs sdk . Dec ) {
2018-07-13 13:46:14 -07:00
calculatedTotalTokens := initialTotalTokens . Add ( cumulativeExpProvs )
2018-08-14 17:15:02 -07:00
require . True ( sdk . DecEq ( t , calculatedTotalTokens , pool . TokenSupply ( ) ) )
2018-07-13 13:46:14 -07:00
}
// Processes provisions are added to the pool correctly every hour
// Returns expected Provisions, expected Inflation, and pool, to help with cumulative calculations back in main Tests
2018-08-14 17:15:02 -07:00
func updateProvisions ( t * testing . T , pool Pool , params Params , hr int ) ( sdk . Dec , sdk . Dec , Pool ) {
2018-07-20 08:24:03 -07:00
expInflation := pool . NextInflation ( params )
2018-08-14 17:15:02 -07:00
expProvisions := expInflation . Mul ( pool . TokenSupply ( ) ) . Quo ( hrsPerYrDec )
2018-07-20 08:24:03 -07:00
startTotalSupply := pool . TokenSupply ( )
pool = pool . ProcessProvisions ( params )
2018-07-13 13:46:14 -07:00
//check provisions were added to pool
2018-08-14 17:15:02 -07:00
require . True ( sdk . DecEq ( t , startTotalSupply . Add ( expProvisions ) , pool . TokenSupply ( ) ) )
2018-07-13 13:46:14 -07:00
return expInflation , expProvisions , pool
}
// Checks that The inflation will correctly increase or decrease after an update to the pool
2018-08-14 17:15:02 -07:00
func checkInflation ( t * testing . T , pool Pool , previousInflation , updatedInflation sdk . Dec , msg string ) {
2018-07-13 13:46:14 -07:00
inflationChange := updatedInflation . Sub ( previousInflation )
switch {
//BELOW 67% - Rate of change positive and increasing, while we are between 7% <= and < 20% inflation
2018-08-14 17:15:02 -07:00
case pool . BondedRatio ( ) . LT ( sdk . NewDecWithPrec ( 67 , 2 ) ) && updatedInflation . LT ( sdk . NewDecWithPrec ( 20 , 2 ) ) :
require . Equal ( t , true , inflationChange . GT ( sdk . ZeroDec ( ) ) , msg )
2018-07-13 13:46:14 -07:00
//BELOW 67% - Rate of change should be 0 while inflation continually stays at 20% until we reach 67% bonded ratio
2018-08-14 17:15:02 -07:00
case pool . BondedRatio ( ) . LT ( sdk . NewDecWithPrec ( 67 , 2 ) ) && updatedInflation . Equal ( sdk . NewDecWithPrec ( 20 , 2 ) ) :
if previousInflation . Equal ( sdk . NewDecWithPrec ( 20 , 2 ) ) {
2018-07-13 13:46:14 -07:00
require . Equal ( t , true , inflationChange . IsZero ( ) , msg )
//This else statement covers the one off case where we first hit 20%, but we still needed a positive ROC to get to 67% bonded ratio (i.e. we went from 19.99999% to 20%)
} else {
2018-08-14 17:15:02 -07:00
require . Equal ( t , true , inflationChange . GT ( sdk . ZeroDec ( ) ) , msg )
2018-07-13 13:46:14 -07:00
}
//ABOVE 67% - Rate of change should be negative while the bond is above 67, and should stay negative until we reach inflation of 7%
2018-08-14 17:15:02 -07:00
case pool . BondedRatio ( ) . GT ( sdk . NewDecWithPrec ( 67 , 2 ) ) &&
updatedInflation . LT ( sdk . NewDecWithPrec ( 20 , 2 ) ) && updatedInflation . GT ( sdk . NewDecWithPrec ( 7 , 2 ) ) :
require . Equal ( t , true , inflationChange . LT ( sdk . ZeroDec ( ) ) , msg )
2018-07-13 13:46:14 -07:00
//ABOVE 67% - Rate of change should be 0 while inflation continually stays at 7%.
2018-08-14 17:15:02 -07:00
case pool . BondedRatio ( ) . GT ( sdk . NewDecWithPrec ( 67 , 2 ) ) &&
updatedInflation . Equal ( sdk . NewDecWithPrec ( 7 , 2 ) ) :
if previousInflation . Equal ( sdk . NewDecWithPrec ( 7 , 2 ) ) {
2018-07-13 13:46:14 -07:00
require . Equal ( t , true , inflationChange . IsZero ( ) , msg )
//This else statement covers the one off case where we first hit 7%, but we still needed a negative ROC to continue to get down to 67%. (i.e. we went from 7.00001% to 7%)
} else {
2018-08-14 17:15:02 -07:00
require . Equal ( t , true , inflationChange . LT ( sdk . ZeroDec ( ) ) , msg )
2018-07-13 13:46:14 -07:00
}
}
}