mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 14:17:28 +00:00 
			
		
		
		
	* Update incentive test to use beginblocker instead manual accumulation * Update integration test suite * Add base integration test, wip staking reward calculation * Get actual staking reward amounts from BeginBlocker events, calculate expected indexes * Simplify event parsing * Add initial earn accum test with real keepers * Add the rest of the accum integration tests with real keepers * Check if delegation rewards are zero before transferring * Update staking integration test to use updated methods
		
			
				
	
	
		
			511 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			511 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package keeper_test
 | 
						|
 | 
						|
import (
 | 
						|
	"testing"
 | 
						|
	"time"
 | 
						|
 | 
						|
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						|
	proposaltypes "github.com/cosmos/cosmos-sdk/x/params/types/proposal"
 | 
						|
	"github.com/stretchr/testify/suite"
 | 
						|
	tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
 | 
						|
 | 
						|
	"github.com/kava-labs/kava/app"
 | 
						|
	cdpkeeper "github.com/kava-labs/kava/x/cdp/keeper"
 | 
						|
	cdptypes "github.com/kava-labs/kava/x/cdp/types"
 | 
						|
	"github.com/kava-labs/kava/x/incentive/keeper"
 | 
						|
	"github.com/kava-labs/kava/x/incentive/testutil"
 | 
						|
	"github.com/kava-labs/kava/x/incentive/types"
 | 
						|
	kavadisttypes "github.com/kava-labs/kava/x/kavadist/types"
 | 
						|
)
 | 
						|
 | 
						|
type USDXIntegrationTests struct {
 | 
						|
	testutil.IntegrationTester
 | 
						|
 | 
						|
	genesisTime time.Time
 | 
						|
	addrs       []sdk.AccAddress
 | 
						|
}
 | 
						|
 | 
						|
func TestUSDXIntegration(t *testing.T) {
 | 
						|
	suite.Run(t, new(USDXIntegrationTests))
 | 
						|
}
 | 
						|
 | 
						|
// SetupTest is run automatically before each suite test
 | 
						|
func (suite *USDXIntegrationTests) SetupTest() {
 | 
						|
	_, suite.addrs = app.GeneratePrivKeyAddressPairs(5)
 | 
						|
 | 
						|
	suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXIntegrationTests) ProposeAndVoteOnNewRewardPeriods(committeeID uint64, voter sdk.AccAddress, newPeriods types.RewardPeriods) {
 | 
						|
	suite.ProposeAndVoteOnNewParams(
 | 
						|
		voter,
 | 
						|
		committeeID,
 | 
						|
		[]proposaltypes.ParamChange{{
 | 
						|
			Subspace: types.ModuleName,
 | 
						|
			Key:      string(types.KeyUSDXMintingRewardPeriods),
 | 
						|
			Value:    string(types.ModuleCdc.LegacyAmino.MustMarshalJSON(newPeriods)),
 | 
						|
		}})
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXIntegrationTests) TestSingleUserAccumulatesRewardsAfterSyncing() {
 | 
						|
	userA := suite.addrs[0]
 | 
						|
 | 
						|
	authBulder := app.NewAuthBankGenesisBuilder().
 | 
						|
		WithSimpleModuleAccount(kavadisttypes.ModuleName, cs(c(types.USDXMintingRewardDenom, 1e18))). // Fill kavadist with enough coins to pay out any reward
 | 
						|
		WithSimpleAccount(userA, cs(c("bnb", 1e12)))                                                  // give the user some coins
 | 
						|
 | 
						|
	incentBuilder := testutil.NewIncentiveGenesisBuilder().
 | 
						|
		WithGenesisTime(suite.genesisTime).
 | 
						|
		WithMultipliers(types.MultipliersPerDenoms{{
 | 
						|
			Denom:       types.USDXMintingRewardDenom,
 | 
						|
			Multipliers: types.Multipliers{types.NewMultiplier("large", 12, d("1.0"))}, // keep payout at 1.0 to make maths easier
 | 
						|
		}}).
 | 
						|
		WithSimpleUSDXRewardPeriod("bnb-a", c(types.USDXMintingRewardDenom, 1e6))
 | 
						|
 | 
						|
	suite.SetApp()
 | 
						|
	suite.WithGenesisTime(suite.genesisTime)
 | 
						|
	suite.StartChain(
 | 
						|
		NewPricefeedGenStateMultiFromTime(suite.App.AppCodec(), suite.genesisTime),
 | 
						|
		NewCDPGenStateMulti(suite.App.AppCodec()),
 | 
						|
		authBulder.BuildMarshalled(suite.App.AppCodec()),
 | 
						|
		incentBuilder.BuildMarshalled(suite.App.AppCodec()),
 | 
						|
	)
 | 
						|
 | 
						|
	// User creates a CDP to begin earning rewards.
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverMsgCreateCDP(userA, c("bnb", 1e10), c(cdptypes.DefaultStableDenom, 1e9), "bnb-a"),
 | 
						|
	)
 | 
						|
 | 
						|
	// Let time pass to accumulate interest on the deposit
 | 
						|
	// Use one long block instead of many to reduce any rounding errors, and speed up tests.
 | 
						|
	suite.NextBlockAfter(1e6 * time.Second) // about 12 days
 | 
						|
 | 
						|
	// User repays and borrows just to sync their CDP
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverCDPMsgRepay(userA, "bnb-a", c(cdptypes.DefaultStableDenom, 1)),
 | 
						|
	)
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverCDPMsgBorrow(userA, "bnb-a", c(cdptypes.DefaultStableDenom, 1)),
 | 
						|
	)
 | 
						|
 | 
						|
	// Accumulate more rewards.
 | 
						|
	// The user still has the same percentage of all CDP debt (100%) so their rewards should be the same as in the previous block.
 | 
						|
	suite.NextBlockAfter(1e6 * time.Second) // about 12 days
 | 
						|
 | 
						|
	// User claims all their rewards
 | 
						|
	msg := types.NewMsgClaimUSDXMintingReward(userA.String(), "large")
 | 
						|
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						|
 | 
						|
	// The users has always had 100% of cdp debt, so they should receive all rewards for the previous two blocks.
 | 
						|
	// Total rewards for each block is block duration * rewards per second
 | 
						|
	accuracy := 1e-18 // using a very high accuracy to flag future small calculation changes
 | 
						|
	suite.BalanceInEpsilon(userA, cs(c("bnb", 1e12-1e10), c(cdptypes.DefaultStableDenom, 1e9), c(types.USDXMintingRewardDenom, 2*1e6*1e6)), accuracy)
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXIntegrationTests) TestSingleUserAccumulatesRewardsWithoutSyncing() {
 | 
						|
	user := suite.addrs[0]
 | 
						|
	initialCollateral := c("bnb", 1e9)
 | 
						|
 | 
						|
	authBuilder := app.NewAuthBankGenesisBuilder().
 | 
						|
		WithSimpleModuleAccount(kavadisttypes.ModuleName, cs(c(types.USDXMintingRewardDenom, 1e18))). // Fill kavadist with enough coins to pay out any reward
 | 
						|
		WithSimpleAccount(user, cs(initialCollateral))
 | 
						|
 | 
						|
	collateralType := "bnb-a"
 | 
						|
 | 
						|
	incentBuilder := testutil.NewIncentiveGenesisBuilder().
 | 
						|
		WithGenesisTime(suite.genesisTime).
 | 
						|
		WithMultipliers(types.MultipliersPerDenoms{{
 | 
						|
			Denom:       types.USDXMintingRewardDenom,
 | 
						|
			Multipliers: types.Multipliers{types.NewMultiplier("large", 12, d("1.0"))}, // keep payout at 1.0 to make maths easier
 | 
						|
		}}).
 | 
						|
		WithSimpleUSDXRewardPeriod(collateralType, c(types.USDXMintingRewardDenom, 1e6))
 | 
						|
 | 
						|
	suite.SetApp()
 | 
						|
	suite.WithGenesisTime(suite.genesisTime)
 | 
						|
	suite.StartChain(
 | 
						|
		authBuilder.BuildMarshalled(suite.App.AppCodec()),
 | 
						|
		NewPricefeedGenStateMultiFromTime(suite.App.AppCodec(), suite.genesisTime),
 | 
						|
		NewCDPGenStateMulti(suite.App.AppCodec()),
 | 
						|
		incentBuilder.BuildMarshalled(suite.App.AppCodec()),
 | 
						|
	)
 | 
						|
 | 
						|
	// Setup cdp state containing one CDP
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverMsgCreateCDP(user, initialCollateral, c("usdx", 1e8), collateralType),
 | 
						|
	)
 | 
						|
 | 
						|
	// Skip ahead a few blocks blocks to accumulate both interest and usdx reward for the cdp
 | 
						|
	// Don't sync the CDP between the blocks
 | 
						|
	suite.NextBlockAfter(1e6 * time.Second) // about 12 days
 | 
						|
	suite.NextBlockAfter(1e6 * time.Second)
 | 
						|
	suite.NextBlockAfter(1e6 * time.Second)
 | 
						|
 | 
						|
	msg := types.NewMsgClaimUSDXMintingReward(user.String(), "large")
 | 
						|
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						|
 | 
						|
	// The users has always had 100% of cdp debt, so they should receive all rewards for the previous two blocks.
 | 
						|
	// Total rewards for each block is block duration * rewards per second
 | 
						|
	accuracy := 1e-18 // using a very high accuracy to flag future small calculation changes
 | 
						|
	suite.BalanceInEpsilon(user, cs(c(cdptypes.DefaultStableDenom, 1e8), c(types.USDXMintingRewardDenom, 3*1e6*1e6)), accuracy)
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXIntegrationTests) TestReinstatingRewardParamsDoesNotTriggerOverPayments() {
 | 
						|
	userA := suite.addrs[0]
 | 
						|
	userB := suite.addrs[1]
 | 
						|
 | 
						|
	authBuilder := app.NewAuthBankGenesisBuilder().
 | 
						|
		WithSimpleModuleAccount(kavadisttypes.ModuleName, cs(c(types.USDXMintingRewardDenom, 1e18))). // Fill kavadist with enough coins to pay out any reward
 | 
						|
		WithSimpleAccount(userA, cs(c("bnb", 1e10))).
 | 
						|
		WithSimpleAccount(userB, cs(c("bnb", 1e10)))
 | 
						|
 | 
						|
	incentBuilder := testutil.NewIncentiveGenesisBuilder().
 | 
						|
		WithGenesisTime(suite.genesisTime).
 | 
						|
		WithMultipliers(types.MultipliersPerDenoms{{
 | 
						|
			Denom:       types.USDXMintingRewardDenom,
 | 
						|
			Multipliers: types.Multipliers{types.NewMultiplier("large", 12, d("1.0"))}, // keep payout at 1.0 to make maths easier
 | 
						|
		}}).
 | 
						|
		WithSimpleUSDXRewardPeriod("bnb-a", c(types.USDXMintingRewardDenom, 1e6))
 | 
						|
 | 
						|
	suite.SetApp()
 | 
						|
	suite.WithGenesisTime(suite.genesisTime)
 | 
						|
	suite.StartChain(
 | 
						|
		authBuilder.BuildMarshalled(suite.App.AppCodec()),
 | 
						|
		NewPricefeedGenStateMultiFromTime(suite.App.AppCodec(), suite.genesisTime),
 | 
						|
		NewCDPGenStateMulti(suite.App.AppCodec()),
 | 
						|
		incentBuilder.BuildMarshalled(suite.App.AppCodec()),
 | 
						|
		NewCommitteeGenesisState(suite.App.AppCodec(), 0, userA), // create a committtee to change params
 | 
						|
	)
 | 
						|
 | 
						|
	// Accumulate some CDP rewards, requires creating a cdp so the total borrowed isn't 0.
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverMsgCreateCDP(userA, c("bnb", 1e10), c("usdx", 1e9), "bnb-a"),
 | 
						|
	)
 | 
						|
	suite.NextBlockAfter(1e6 * time.Second)
 | 
						|
 | 
						|
	// Remove the USDX reward period
 | 
						|
	suite.ProposeAndVoteOnNewRewardPeriods(0, userA, types.RewardPeriods{})
 | 
						|
	// next block so proposal is enacted
 | 
						|
	suite.NextBlockAfter(1 * time.Second)
 | 
						|
 | 
						|
	// Create a CDP when there is no reward periods. In a previous version the claim object would not be created, leading to the bug.
 | 
						|
	// Withdraw the same amount of usdx as the first cdp currently has. This make the reward maths easier, as rewards will be split 50:50 between each cdp.
 | 
						|
	firstCDP, f := suite.App.GetCDPKeeper().GetCdpByOwnerAndCollateralType(suite.Ctx, userA, "bnb-a")
 | 
						|
	suite.True(f)
 | 
						|
	firstCDPTotalPrincipal := firstCDP.GetTotalPrincipal()
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverMsgCreateCDP(userB, c("bnb", 1e10), firstCDPTotalPrincipal, "bnb-a"),
 | 
						|
	)
 | 
						|
 | 
						|
	// Add back the reward period
 | 
						|
	suite.ProposeAndVoteOnNewRewardPeriods(0, userA,
 | 
						|
		types.RewardPeriods{types.NewRewardPeriod(
 | 
						|
			true,
 | 
						|
			"bnb-a",
 | 
						|
			suite.Ctx.BlockTime(), // start accumulating again from this block
 | 
						|
			suite.genesisTime.Add(365*24*time.Hour),
 | 
						|
			c(types.USDXMintingRewardDenom, 1e6),
 | 
						|
		)},
 | 
						|
	)
 | 
						|
	// next block so proposal is enacted
 | 
						|
	suite.NextBlockAfter(1 * time.Second)
 | 
						|
 | 
						|
	// Sync the cdp and claim by borrowing a bit
 | 
						|
	// In a previous version this would create the cdp with incorrect indexes, leading to overpayment.
 | 
						|
	suite.NoError(
 | 
						|
		suite.DeliverCDPMsgBorrow(userB, "bnb-a", c(cdptypes.DefaultStableDenom, 1)),
 | 
						|
	)
 | 
						|
 | 
						|
	// Claim rewards
 | 
						|
	msg := types.NewMsgClaimUSDXMintingReward(userB.String(), "large")
 | 
						|
	suite.NoError(suite.DeliverIncentiveMsg(&msg))
 | 
						|
 | 
						|
	// The cdp had half the total borrows for a 1s block. So should earn half the rewards for that block
 | 
						|
	suite.BalanceInEpsilon(
 | 
						|
		userB,
 | 
						|
		cs(firstCDPTotalPrincipal.Add(c(cdptypes.DefaultStableDenom, 1)), c(types.USDXMintingRewardDenom, 0.5*1e6)),
 | 
						|
		1e-18, // using very high accuracy to catch small changes to the calculations
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
// Test suite used for all keeper tests
 | 
						|
type USDXRewardsTestSuite struct {
 | 
						|
	suite.Suite
 | 
						|
 | 
						|
	keeper    keeper.Keeper
 | 
						|
	cdpKeeper cdpkeeper.Keeper
 | 
						|
 | 
						|
	app app.TestApp
 | 
						|
	ctx sdk.Context
 | 
						|
 | 
						|
	genesisTime time.Time
 | 
						|
	addrs       []sdk.AccAddress
 | 
						|
}
 | 
						|
 | 
						|
// SetupTest is run automatically before each suite test
 | 
						|
func (suite *USDXRewardsTestSuite) SetupTest() {
 | 
						|
	config := sdk.GetConfig()
 | 
						|
	app.SetBech32AddressPrefixes(config)
 | 
						|
 | 
						|
	_, suite.addrs = app.GeneratePrivKeyAddressPairs(5)
 | 
						|
 | 
						|
	suite.genesisTime = time.Date(2020, 12, 15, 14, 0, 0, 0, time.UTC)
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXRewardsTestSuite) SetupApp() {
 | 
						|
	suite.app = app.NewTestApp()
 | 
						|
 | 
						|
	suite.keeper = suite.app.GetIncentiveKeeper()
 | 
						|
	suite.cdpKeeper = suite.app.GetCDPKeeper()
 | 
						|
 | 
						|
	suite.ctx = suite.app.NewContext(true, tmproto.Header{Height: 1, Time: suite.genesisTime})
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXRewardsTestSuite) SetupWithGenState(authBuilder *app.AuthBankGenesisBuilder, incentBuilder testutil.IncentiveGenesisBuilder) {
 | 
						|
	suite.SetupApp()
 | 
						|
 | 
						|
	suite.app.InitializeFromGenesisStatesWithTime(
 | 
						|
		suite.genesisTime,
 | 
						|
		authBuilder.BuildMarshalled(suite.app.AppCodec()),
 | 
						|
		NewPricefeedGenStateMultiFromTime(suite.app.AppCodec(), suite.genesisTime),
 | 
						|
		NewCDPGenStateMulti(suite.app.AppCodec()),
 | 
						|
		incentBuilder.BuildMarshalled(suite.app.AppCodec()),
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXRewardsTestSuite) TestAccumulateUSDXMintingRewards() {
 | 
						|
	type args struct {
 | 
						|
		ctype                 string
 | 
						|
		rewardsPerSecond      sdk.Coin
 | 
						|
		initialTotalPrincipal sdk.Coin
 | 
						|
		timeElapsed           int
 | 
						|
		expectedRewardFactor  sdk.Dec
 | 
						|
	}
 | 
						|
	type test struct {
 | 
						|
		name string
 | 
						|
		args args
 | 
						|
	}
 | 
						|
	testCases := []test{
 | 
						|
		{
 | 
						|
			"7 seconds",
 | 
						|
			args{
 | 
						|
				ctype:                 "bnb-a",
 | 
						|
				rewardsPerSecond:      c("ukava", 122354),
 | 
						|
				initialTotalPrincipal: c("usdx", 1000000000000),
 | 
						|
				timeElapsed:           7,
 | 
						|
				expectedRewardFactor:  d("0.000000856478000000"),
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"1 day",
 | 
						|
			args{
 | 
						|
				ctype:                 "bnb-a",
 | 
						|
				rewardsPerSecond:      c("ukava", 122354),
 | 
						|
				initialTotalPrincipal: c("usdx", 1000000000000),
 | 
						|
				timeElapsed:           86400,
 | 
						|
				expectedRewardFactor:  d("0.0105713856"),
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"0 seconds",
 | 
						|
			args{
 | 
						|
				ctype:                 "bnb-a",
 | 
						|
				rewardsPerSecond:      c("ukava", 122354),
 | 
						|
				initialTotalPrincipal: c("usdx", 1000000000000),
 | 
						|
				timeElapsed:           0,
 | 
						|
				expectedRewardFactor:  d("0.0"),
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, tc := range testCases {
 | 
						|
		suite.Run(tc.name, func() {
 | 
						|
			incentBuilder := testutil.NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime).WithSimpleUSDXRewardPeriod(tc.args.ctype, tc.args.rewardsPerSecond)
 | 
						|
 | 
						|
			suite.SetupWithGenState(app.NewAuthBankGenesisBuilder(), incentBuilder)
 | 
						|
 | 
						|
			// setup cdp state
 | 
						|
			suite.cdpKeeper.SetTotalPrincipal(suite.ctx, tc.args.ctype, cdptypes.DefaultStableDenom, tc.args.initialTotalPrincipal.Amount)
 | 
						|
 | 
						|
			updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * tc.args.timeElapsed))
 | 
						|
			suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
 | 
						|
			rewardPeriod, found := suite.keeper.GetUSDXMintingRewardPeriod(suite.ctx, tc.args.ctype)
 | 
						|
			suite.Require().True(found)
 | 
						|
			suite.keeper.AccumulateUSDXMintingRewards(suite.ctx, rewardPeriod)
 | 
						|
 | 
						|
			rewardFactor, _ := suite.keeper.GetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype)
 | 
						|
			suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXRewardsTestSuite) TestSynchronizeUSDXMintingReward() {
 | 
						|
	type args struct {
 | 
						|
		ctype                string
 | 
						|
		rewardsPerSecond     sdk.Coin
 | 
						|
		initialCollateral    sdk.Coin
 | 
						|
		initialPrincipal     sdk.Coin
 | 
						|
		blockTimes           []int
 | 
						|
		expectedRewardFactor sdk.Dec
 | 
						|
		expectedRewards      sdk.Coin
 | 
						|
	}
 | 
						|
	type test struct {
 | 
						|
		name string
 | 
						|
		args args
 | 
						|
	}
 | 
						|
 | 
						|
	testCases := []test{
 | 
						|
		{
 | 
						|
			"10 blocks",
 | 
						|
			args{
 | 
						|
				ctype:                "bnb-a",
 | 
						|
				rewardsPerSecond:     c("ukava", 122354),
 | 
						|
				initialCollateral:    c("bnb", 1000000000000),
 | 
						|
				initialPrincipal:     c("usdx", 10000000000),
 | 
						|
				blockTimes:           []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
						|
				expectedRewardFactor: d("0.001223540000000000"),
 | 
						|
				expectedRewards:      c("ukava", 12235400),
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"10 blocks - long block time",
 | 
						|
			args{
 | 
						|
				ctype:                "bnb-a",
 | 
						|
				rewardsPerSecond:     c("ukava", 122354),
 | 
						|
				initialCollateral:    c("bnb", 1000000000000),
 | 
						|
				initialPrincipal:     c("usdx", 10000000000),
 | 
						|
				blockTimes:           []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
 | 
						|
				expectedRewardFactor: d("10.57138560000000000"),
 | 
						|
				expectedRewards:      c("ukava", 105713856000),
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, tc := range testCases {
 | 
						|
		suite.Run(tc.name, func() {
 | 
						|
			authBuilder := app.NewAuthBankGenesisBuilder().WithSimpleAccount(suite.addrs[0], cs(tc.args.initialCollateral))
 | 
						|
			incentBuilder := testutil.NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime).WithSimpleUSDXRewardPeriod(tc.args.ctype, tc.args.rewardsPerSecond)
 | 
						|
 | 
						|
			suite.SetupWithGenState(authBuilder, incentBuilder)
 | 
						|
 | 
						|
			// setup cdp state
 | 
						|
			err := suite.cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype)
 | 
						|
			suite.Require().NoError(err)
 | 
						|
 | 
						|
			claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
 | 
						|
			suite.Require().True(found)
 | 
						|
			suite.Require().Equal(sdk.ZeroDec(), claim.RewardIndexes[0].RewardFactor)
 | 
						|
 | 
						|
			var timeElapsed int
 | 
						|
			previousBlockTime := suite.ctx.BlockTime()
 | 
						|
			for _, t := range tc.args.blockTimes {
 | 
						|
				timeElapsed += t
 | 
						|
				updatedBlockTime := previousBlockTime.Add(time.Duration(int(time.Second) * t))
 | 
						|
				previousBlockTime = updatedBlockTime
 | 
						|
				blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
 | 
						|
				rewardPeriod, found := suite.keeper.GetUSDXMintingRewardPeriod(blockCtx, tc.args.ctype)
 | 
						|
				suite.Require().True(found)
 | 
						|
				suite.keeper.AccumulateUSDXMintingRewards(blockCtx, rewardPeriod)
 | 
						|
			}
 | 
						|
			updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed))
 | 
						|
			suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
 | 
						|
			cdp, found := suite.cdpKeeper.GetCdpByOwnerAndCollateralType(suite.ctx, suite.addrs[0], tc.args.ctype)
 | 
						|
			suite.Require().True(found)
 | 
						|
			suite.Require().NotPanics(func() {
 | 
						|
				suite.keeper.SynchronizeUSDXMintingReward(suite.ctx, cdp)
 | 
						|
			})
 | 
						|
 | 
						|
			rewardFactor, _ := suite.keeper.GetUSDXMintingRewardFactor(suite.ctx, tc.args.ctype)
 | 
						|
			suite.Require().Equal(tc.args.expectedRewardFactor, rewardFactor)
 | 
						|
 | 
						|
			claim, found = suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
 | 
						|
			suite.Require().True(found)
 | 
						|
			suite.Require().Equal(tc.args.expectedRewardFactor, claim.RewardIndexes[0].RewardFactor)
 | 
						|
			suite.Require().Equal(tc.args.expectedRewards, claim.Reward)
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (suite *USDXRewardsTestSuite) TestSimulateUSDXMintingRewardSynchronization() {
 | 
						|
	type args struct {
 | 
						|
		ctype                string
 | 
						|
		rewardsPerSecond     sdk.Coin
 | 
						|
		initialCollateral    sdk.Coin
 | 
						|
		initialPrincipal     sdk.Coin
 | 
						|
		blockTimes           []int
 | 
						|
		expectedRewardFactor sdk.Dec
 | 
						|
		expectedRewards      sdk.Coin
 | 
						|
	}
 | 
						|
	type test struct {
 | 
						|
		name string
 | 
						|
		args args
 | 
						|
	}
 | 
						|
 | 
						|
	testCases := []test{
 | 
						|
		{
 | 
						|
			"10 blocks",
 | 
						|
			args{
 | 
						|
				ctype:                "bnb-a",
 | 
						|
				rewardsPerSecond:     c("ukava", 122354),
 | 
						|
				initialCollateral:    c("bnb", 1000000000000),
 | 
						|
				initialPrincipal:     c("usdx", 10000000000),
 | 
						|
				blockTimes:           []int{10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
 | 
						|
				expectedRewardFactor: d("0.001223540000000000"),
 | 
						|
				expectedRewards:      c("ukava", 12235400),
 | 
						|
			},
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"10 blocks - long block time",
 | 
						|
			args{
 | 
						|
				ctype:                "bnb-a",
 | 
						|
				rewardsPerSecond:     c("ukava", 122354),
 | 
						|
				initialCollateral:    c("bnb", 1000000000000),
 | 
						|
				initialPrincipal:     c("usdx", 10000000000),
 | 
						|
				blockTimes:           []int{86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400, 86400},
 | 
						|
				expectedRewardFactor: d("10.57138560000000000"),
 | 
						|
				expectedRewards:      c("ukava", 105713856000),
 | 
						|
			},
 | 
						|
		},
 | 
						|
	}
 | 
						|
	for _, tc := range testCases {
 | 
						|
		suite.Run(tc.name, func() {
 | 
						|
			authBuilder := app.NewAuthBankGenesisBuilder().WithSimpleAccount(suite.addrs[0], cs(tc.args.initialCollateral))
 | 
						|
			incentBuilder := testutil.NewIncentiveGenesisBuilder().WithGenesisTime(suite.genesisTime).WithSimpleUSDXRewardPeriod(tc.args.ctype, tc.args.rewardsPerSecond)
 | 
						|
 | 
						|
			suite.SetupWithGenState(authBuilder, incentBuilder)
 | 
						|
 | 
						|
			// setup cdp state
 | 
						|
			err := suite.cdpKeeper.AddCdp(suite.ctx, suite.addrs[0], tc.args.initialCollateral, tc.args.initialPrincipal, tc.args.ctype)
 | 
						|
			suite.Require().NoError(err)
 | 
						|
 | 
						|
			claim, found := suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
 | 
						|
			suite.Require().True(found)
 | 
						|
			suite.Require().Equal(sdk.ZeroDec(), claim.RewardIndexes[0].RewardFactor)
 | 
						|
 | 
						|
			var timeElapsed int
 | 
						|
			previousBlockTime := suite.ctx.BlockTime()
 | 
						|
			for _, t := range tc.args.blockTimes {
 | 
						|
				timeElapsed += t
 | 
						|
				updatedBlockTime := previousBlockTime.Add(time.Duration(int(time.Second) * t))
 | 
						|
				previousBlockTime = updatedBlockTime
 | 
						|
				blockCtx := suite.ctx.WithBlockTime(updatedBlockTime)
 | 
						|
				rewardPeriod, found := suite.keeper.GetUSDXMintingRewardPeriod(blockCtx, tc.args.ctype)
 | 
						|
				suite.Require().True(found)
 | 
						|
				suite.keeper.AccumulateUSDXMintingRewards(blockCtx, rewardPeriod)
 | 
						|
			}
 | 
						|
			updatedBlockTime := suite.ctx.BlockTime().Add(time.Duration(int(time.Second) * timeElapsed))
 | 
						|
			suite.ctx = suite.ctx.WithBlockTime(updatedBlockTime)
 | 
						|
 | 
						|
			claim, found = suite.keeper.GetUSDXMintingClaim(suite.ctx, suite.addrs[0])
 | 
						|
			suite.Require().True(found)
 | 
						|
			suite.Require().Equal(claim.RewardIndexes[0].RewardFactor, sdk.ZeroDec())
 | 
						|
			suite.Require().Equal(claim.Reward, sdk.NewCoin("ukava", sdk.ZeroInt()))
 | 
						|
 | 
						|
			updatedClaim := suite.keeper.SimulateUSDXMintingSynchronization(suite.ctx, claim)
 | 
						|
			suite.Require().Equal(tc.args.expectedRewardFactor, updatedClaim.RewardIndexes[0].RewardFactor)
 | 
						|
			suite.Require().Equal(tc.args.expectedRewards, updatedClaim.Reward)
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func TestUSDXRewardsTestSuite(t *testing.T) {
 | 
						|
	suite.Run(t, new(USDXRewardsTestSuite))
 | 
						|
}
 |