-
Notifications
You must be signed in to change notification settings - Fork 819
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add mint/epoch/distribution tests/helpers
- Loading branch information
Showing
9 changed files
with
281 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package tests | ||
|
||
import ( | ||
"testing" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
"github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock/msgs" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock/verify" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestDistribution(t *testing.T) { | ||
app := processblock.NewTestApp() | ||
processblock.CommonPreset(app) | ||
signer1 := app.NewSignableAccount("signer1") | ||
app.FundAccount(signer1, 100000000) | ||
alice := app.NewAccount() | ||
|
||
sendAliceMsg := msgs.Send(signer1, alice, 1000) | ||
tx1 := app.Sign(signer1, []sdk.Msg{sendAliceMsg}, 20000) | ||
|
||
// block T (no distribution yet since this is the first block) | ||
block := []signing.Tx{tx1} | ||
blockRunner := func() []uint32 { return app.RunBlock(block) } | ||
require.Equal(t, []uint32{0}, blockRunner()) | ||
|
||
// block T+1 (distribution of fees from T) | ||
blockRunner = func() []uint32 { return app.RunBlock([]signing.Tx{}) } | ||
blockRunner = verify.Allocation(t, app, blockRunner) | ||
|
||
require.Equal(t, []uint32{}, blockRunner()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package tests | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock/verify" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestEpoch(t *testing.T) { | ||
app := processblock.NewTestApp() | ||
processblock.CommonPreset(app) | ||
app.FastEpoch() | ||
|
||
blockRunner := func() []uint32 { return app.RunBlock([]signing.Tx{}) } | ||
blockRunner = verify.Epoch(t, app, blockRunner) | ||
|
||
require.Equal(t, []uint32{}, blockRunner()) | ||
|
||
time.Sleep(6 * time.Second) | ||
|
||
blockRunner = func() []uint32 { return app.RunBlock([]signing.Tx{}) } | ||
blockRunner = verify.Epoch(t, app, blockRunner) | ||
|
||
require.Equal(t, []uint32{}, blockRunner()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package tests | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/cosmos/cosmos-sdk/x/auth/signing" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock/verify" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func TestMint(t *testing.T) { | ||
app := processblock.NewTestApp() | ||
processblock.CommonPreset(app) | ||
app.NewMinter(1000000) | ||
app.FastEpoch() | ||
|
||
blockRunner := func() []uint32 { return app.RunBlock([]signing.Tx{}) } | ||
blockRunner = verify.MintRelease(t, app, blockRunner) | ||
|
||
require.Equal(t, []uint32{}, blockRunner()) | ||
|
||
time.Sleep(6 * time.Second) | ||
|
||
blockRunner = func() []uint32 { return app.RunBlock([]signing.Tx{}) } | ||
blockRunner = verify.MintRelease(t, app, blockRunner) | ||
|
||
require.Equal(t, []uint32{}, blockRunner()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package processblock | ||
|
||
import "time" | ||
|
||
func (a *App) FastEpoch() { | ||
epoch := a.EpochKeeper.GetEpoch(a.Ctx()) | ||
epoch.EpochDuration = 5 * time.Second | ||
a.EpochKeeper.SetEpoch(a.Ctx(), epoch) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package processblock | ||
|
||
import ( | ||
"time" | ||
|
||
minttypes "github.com/sei-protocol/sei-chain/x/mint/types" | ||
) | ||
|
||
func (a *App) NewMinter(amount uint64) { | ||
today := time.Now() | ||
dayAfterTomorrow := today.Add(48 * time.Hour) | ||
a.MintKeeper.SetMinter(a.Ctx(), minttypes.Minter{ | ||
StartDate: today.Format(minttypes.TokenReleaseDateFormat), | ||
EndDate: dayAfterTomorrow.Format(minttypes.TokenReleaseDateFormat), | ||
Denom: "usei", | ||
TotalMintAmount: amount, | ||
RemainingMintAmount: amount, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package verify | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
"github.com/cosmos/cosmos-sdk/x/distribution/types" | ||
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" | ||
"github.com/sei-protocol/sei-chain/testutil/processblock" | ||
"github.com/sei-protocol/sei-chain/utils" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
// assuming only `usei` will get distributed | ||
func Allocation(t *testing.T, app *processblock.App, f BlockRunnable) BlockRunnable { | ||
return func() []uint32 { | ||
// fees collected in T-1 are allocated in T's BeginBlock, so we can simply | ||
// query fee collector's balance since this function is called between T-1 | ||
// and T. | ||
feeCollector := app.AccountKeeper.GetModuleAccount(app.Ctx(), authtypes.FeeCollectorName) | ||
feesCollectedInt := app.BankKeeper.GetBalance(app.Ctx(), feeCollector.GetAddress(), "usei") | ||
feesCollected := sdk.NewDecCoinFromCoin(feesCollectedInt) | ||
|
||
prevProposer := sdk.ValAddress(app.DistrKeeper.GetPreviousProposerConsAddr(app.Ctx())).String() | ||
votedValidators := utils.Map(app.GetAllValidators(), func(v stakingtypes.Validator) string { | ||
return v.GetOperator().String() | ||
}) | ||
expectedOutstandingRewards := getOutstandingRewards(app) | ||
|
||
baseProposerReward := app.DistrKeeper.GetBaseProposerReward(app.Ctx()) | ||
bonusProposerReward := app.DistrKeeper.GetBonusProposerReward(app.Ctx()) | ||
proposerMultiplier := baseProposerReward.Add(bonusProposerReward.MulTruncate(sdk.OneDec())) // in test, every val always signs | ||
proposerReward := sdk.DecCoin{ | ||
Denom: "usei", | ||
Amount: feesCollected.Amount.MulTruncate(proposerMultiplier), | ||
} | ||
expectedOutstandingRewards[prevProposer] = expectedOutstandingRewards[prevProposer].Add(proposerReward) | ||
|
||
communityTax := app.DistrKeeper.GetCommunityTax(app.Ctx()) | ||
voteMultiplier := sdk.OneDec().Sub(proposerMultiplier).Sub(communityTax).QuoInt(sdk.NewInt(int64(len(votedValidators)))) | ||
voterReward := sdk.DecCoin{ | ||
Denom: "usei", | ||
Amount: feesCollected.Amount.MulTruncate(voteMultiplier), | ||
} | ||
|
||
for _, validator := range votedValidators { | ||
expectedOutstandingRewards[validator] = expectedOutstandingRewards[validator].Add(voterReward) | ||
} | ||
|
||
res := f() | ||
|
||
actualOutstandingRewards := getOutstandingRewards(app) | ||
|
||
require.Equal(t, len(expectedOutstandingRewards), len(actualOutstandingRewards)) | ||
|
||
for val, reward := range expectedOutstandingRewards { | ||
require.True(t, reward.Equal(actualOutstandingRewards[val])) | ||
} | ||
|
||
return res | ||
} | ||
} | ||
|
||
func getOutstandingRewards(app *processblock.App) map[string]sdk.DecCoin { | ||
outstandingRewards := map[string]sdk.DecCoin{} | ||
for _, val := range app.GetAllValidators() { | ||
outstandingRewards[val.GetOperator().String()] = sdk.NewDecCoin("usei", sdk.NewInt(0)) | ||
} | ||
app.DistrKeeper.IterateValidatorOutstandingRewards( | ||
app.Ctx(), | ||
func(val sdk.ValAddress, rewards types.ValidatorOutstandingRewards) (stop bool) { | ||
if len(rewards.Rewards) == 0 { | ||
return false | ||
} | ||
if len(rewards.Rewards) > 1 { | ||
panic("expecting only usei as validator reward denom but found multiple") | ||
} | ||
if rewards.Rewards[0].Denom != "usei" { | ||
panic(fmt.Sprintf("expecting only usei as validator reward denom but found %s", rewards.Rewards[0].Denom)) | ||
} | ||
outstandingRewards[val.String()] = rewards.Rewards[0] | ||
return false | ||
}, | ||
) | ||
return outstandingRewards | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package verify | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/sei-protocol/sei-chain/testutil/processblock" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Epoch(t *testing.T, app *processblock.App, f BlockRunnable) BlockRunnable { | ||
return func() []uint32 { | ||
oldEpoch := app.EpochKeeper.GetEpoch(app.Ctx()) | ||
res := f() | ||
if app.Ctx().BlockTime().Sub(oldEpoch.CurrentEpochStartTime) > oldEpoch.EpochDuration { | ||
newPoch := app.EpochKeeper.GetEpoch(app.Ctx()) | ||
require.Equal(t, oldEpoch.CurrentEpoch+1, newPoch.CurrentEpoch) | ||
} | ||
return res | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package verify | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
|
||
"github.com/sei-protocol/sei-chain/testutil/processblock" | ||
minttypes "github.com/sei-protocol/sei-chain/x/mint/types" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func MintRelease(t *testing.T, app *processblock.App, f BlockRunnable) BlockRunnable { | ||
return func() []uint32 { | ||
oldMinter := app.MintKeeper.GetMinter(app.Ctx()) | ||
oldEpoch := app.EpochKeeper.GetEpoch(app.Ctx()) | ||
oldSupply := app.BankKeeper.GetSupply(app.Ctx(), "usei") | ||
res := f() | ||
// if minter minted, it must be a new epoch, but not the other way around | ||
newMinter := app.MintKeeper.GetMinter(app.Ctx()) | ||
if newMinter.RemainingMintAmount == oldMinter.RemainingMintAmount { | ||
return res | ||
} | ||
newPoch := app.EpochKeeper.GetEpoch(app.Ctx()) | ||
require.Equal(t, oldEpoch.CurrentEpoch+1, newPoch.CurrentEpoch) | ||
startDate, err := time.Parse(minttypes.TokenReleaseDateFormat, oldMinter.StartDate) | ||
if err != nil { | ||
panic(err) | ||
} | ||
endDate, err := time.Parse(minttypes.TokenReleaseDateFormat, oldMinter.EndDate) | ||
if err != nil { | ||
panic(err) | ||
} | ||
expectedMintedAmount := oldMinter.TotalMintAmount / uint64(endDate.Sub(startDate)/(24*time.Hour)) | ||
require.Equal(t, expectedMintedAmount, oldMinter.RemainingMintAmount-newMinter.RemainingMintAmount) | ||
newSupply := app.BankKeeper.GetSupply(app.Ctx(), "usei") | ||
require.Equal(t, expectedMintedAmount, uint64(newSupply.Amount.Int64()-oldSupply.Amount.Int64())) | ||
return res | ||
} | ||
} |