mirror of
				https://github.com/0glabs/0g-chain.git
				synced 2025-11-04 10:37:26 +00:00 
			
		
		
		
	Module reserve represents fractional balances, so it should be hidden to consumers to not have a misleading total balance that doubles the fractional balances. This modifies GetBalance() and SpendableCoin() to always return zero coins when fetching the reserve address balance for fractional amounts.
		
			
				
	
	
		
			203 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package keeper_test
 | 
						|
 | 
						|
import (
 | 
						|
	"testing"
 | 
						|
 | 
						|
	sdkmath "cosmossdk.io/math"
 | 
						|
	sdk "github.com/cosmos/cosmos-sdk/types"
 | 
						|
	authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
 | 
						|
	vestingtypes "github.com/cosmos/cosmos-sdk/x/auth/vesting/types"
 | 
						|
 | 
						|
	"github.com/kava-labs/kava/x/precisebank/testutil"
 | 
						|
	"github.com/kava-labs/kava/x/precisebank/types"
 | 
						|
	"github.com/stretchr/testify/suite"
 | 
						|
)
 | 
						|
 | 
						|
type viewIntegrationTestSuite struct {
 | 
						|
	testutil.Suite
 | 
						|
}
 | 
						|
 | 
						|
func (suite *viewIntegrationTestSuite) SetupTest() {
 | 
						|
	suite.Suite.SetupTest()
 | 
						|
}
 | 
						|
 | 
						|
func TestViewIntegrationTestSuite(t *testing.T) {
 | 
						|
	suite.Run(t, new(viewIntegrationTestSuite))
 | 
						|
}
 | 
						|
 | 
						|
func (suite *viewIntegrationTestSuite) TestKeeper_SpendableCoin() {
 | 
						|
	tests := []struct {
 | 
						|
		name      string
 | 
						|
		giveDenom string // queried denom for balance
 | 
						|
 | 
						|
		giveBankBal       sdk.Coins   // full balance
 | 
						|
		giveFractionalBal sdkmath.Int // stored fractional balance for giveAddr
 | 
						|
		giveLockedCoins   sdk.Coins   // locked coins
 | 
						|
 | 
						|
		wantSpendableBal sdk.Coin
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			"extended denom, no fractional - locked coins",
 | 
						|
			types.ExtendedCoinDenom,
 | 
						|
			// queried bank balance in ukava when querying for akava
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
 | 
						|
			sdkmath.ZeroInt(),
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))),
 | 
						|
			// (integer + fractional) - locked
 | 
						|
			sdk.NewCoin(
 | 
						|
				types.ExtendedCoinDenom,
 | 
						|
				types.ConversionFactor().MulRaw(1000-10),
 | 
						|
			),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"extended denom, with fractional - locked coins",
 | 
						|
			types.ExtendedCoinDenom,
 | 
						|
			// queried bank balance in ukava when querying for akava
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
 | 
						|
			sdkmath.NewInt(5000),
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))),
 | 
						|
			sdk.NewCoin(
 | 
						|
				types.ExtendedCoinDenom,
 | 
						|
				// (integer - locked) + fractional
 | 
						|
				types.ConversionFactor().MulRaw(1000-10).AddRaw(5000),
 | 
						|
			),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"non-extended denom - ukava returns ukava",
 | 
						|
			types.IntegerCoinDenom,
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
 | 
						|
			sdkmath.ZeroInt(),
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))),
 | 
						|
			sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(990)),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"non-extended denom, with fractional - ukava returns ukava",
 | 
						|
			types.IntegerCoinDenom,
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(1000))),
 | 
						|
			// does not affect balance
 | 
						|
			sdkmath.NewInt(100),
 | 
						|
			sdk.NewCoins(sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(10))),
 | 
						|
			sdk.NewCoin(types.IntegerCoinDenom, sdk.NewInt(990)),
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		suite.Run(tt.name, func() {
 | 
						|
			suite.SetupTest()
 | 
						|
 | 
						|
			addr := sdk.AccAddress([]byte("test-address"))
 | 
						|
 | 
						|
			suite.MintToAccount(addr, tt.giveBankBal)
 | 
						|
 | 
						|
			// Set fractional balance in store before query
 | 
						|
			suite.Keeper.SetFractionalBalance(suite.Ctx, addr, tt.giveFractionalBal)
 | 
						|
 | 
						|
			// Add some locked coins
 | 
						|
			acc := suite.AccountKeeper.GetAccount(suite.Ctx, addr)
 | 
						|
			if acc == nil {
 | 
						|
				acc = authtypes.NewBaseAccount(addr, nil, 0, 0)
 | 
						|
			}
 | 
						|
 | 
						|
			vestingAcc := vestingtypes.NewPeriodicVestingAccount(
 | 
						|
				acc.(*authtypes.BaseAccount),
 | 
						|
				tt.giveLockedCoins,
 | 
						|
				suite.Ctx.BlockTime().Unix(),
 | 
						|
				vestingtypes.Periods{
 | 
						|
					vestingtypes.Period{
 | 
						|
						Length: 100,
 | 
						|
						Amount: tt.giveLockedCoins,
 | 
						|
					},
 | 
						|
				},
 | 
						|
			)
 | 
						|
			suite.AccountKeeper.SetAccount(suite.Ctx, vestingAcc)
 | 
						|
 | 
						|
			fetchedLockedCoins := vestingAcc.LockedCoins(suite.Ctx.BlockTime())
 | 
						|
			suite.Require().Equal(
 | 
						|
				tt.giveLockedCoins,
 | 
						|
				fetchedLockedCoins,
 | 
						|
				"locked coins should be matching at current block time",
 | 
						|
			)
 | 
						|
 | 
						|
			spendableCoinsWithLocked := suite.Keeper.SpendableCoin(suite.Ctx, addr, tt.giveDenom)
 | 
						|
 | 
						|
			suite.Require().Equalf(
 | 
						|
				tt.wantSpendableBal,
 | 
						|
				spendableCoinsWithLocked,
 | 
						|
				"expected spendable coins of denom %s",
 | 
						|
				tt.giveDenom,
 | 
						|
			)
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (suite *viewIntegrationTestSuite) TestKeeper_HiddenReserve() {
 | 
						|
	// Reserve balances should not be shown to consumers of x/precisebank, as it
 | 
						|
	// represents the fractional balances of accounts.
 | 
						|
 | 
						|
	moduleAddr := authtypes.NewModuleAddress(types.ModuleName)
 | 
						|
	addr1 := sdk.AccAddress{1}
 | 
						|
 | 
						|
	// Make the reserve hold a non-zero balance
 | 
						|
	// Mint fractional coins to an account, which should cause a mint of 1
 | 
						|
	// integer coin to the reserve to back it.
 | 
						|
	extCoin := sdk.NewCoin(types.ExtendedCoinDenom, types.ConversionFactor().AddRaw(1000))
 | 
						|
	unrelatedCoin := sdk.NewCoin("unrelated", sdk.NewInt(1000))
 | 
						|
	suite.MintToAccount(
 | 
						|
		addr1,
 | 
						|
		sdk.NewCoins(
 | 
						|
			extCoin,
 | 
						|
			unrelatedCoin,
 | 
						|
		),
 | 
						|
	)
 | 
						|
 | 
						|
	// Check underlying x/bank balance for reserve
 | 
						|
	reserveIntCoin := suite.BankKeeper.GetBalance(suite.Ctx, moduleAddr, types.IntegerCoinDenom)
 | 
						|
	suite.Require().Equal(
 | 
						|
		sdkmath.NewInt(1),
 | 
						|
		reserveIntCoin.Amount,
 | 
						|
		"reserve should hold 1 integer coin",
 | 
						|
	)
 | 
						|
 | 
						|
	tests := []struct {
 | 
						|
		name       string
 | 
						|
		giveAddr   sdk.AccAddress
 | 
						|
		giveDenom  string
 | 
						|
		wantAmount sdkmath.Int
 | 
						|
	}{
 | 
						|
		{
 | 
						|
			"reserve account - hidden extended denom",
 | 
						|
			moduleAddr,
 | 
						|
			types.ExtendedCoinDenom,
 | 
						|
			sdkmath.ZeroInt(),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"reserve account - visible integer denom",
 | 
						|
			moduleAddr,
 | 
						|
			types.IntegerCoinDenom,
 | 
						|
			sdkmath.OneInt(),
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"user account - visible extended denom",
 | 
						|
			addr1,
 | 
						|
			types.ExtendedCoinDenom,
 | 
						|
			extCoin.Amount,
 | 
						|
		},
 | 
						|
		{
 | 
						|
			"user account - visible integer denom",
 | 
						|
			addr1,
 | 
						|
			types.IntegerCoinDenom,
 | 
						|
			extCoin.Amount.Quo(types.ConversionFactor()),
 | 
						|
		},
 | 
						|
	}
 | 
						|
 | 
						|
	for _, tt := range tests {
 | 
						|
		suite.Run(tt.name, func() {
 | 
						|
			coin := suite.Keeper.GetBalance(suite.Ctx, tt.giveAddr, tt.giveDenom)
 | 
						|
			suite.Require().Equal(tt.wantAmount.Int64(), coin.Amount.Int64())
 | 
						|
 | 
						|
			spendableCoin := suite.Keeper.SpendableCoin(suite.Ctx, tt.giveAddr, tt.giveDenom)
 | 
						|
			suite.Require().Equal(tt.wantAmount.Int64(), spendableCoin.Amount.Int64())
 | 
						|
		})
 | 
						|
	}
 | 
						|
}
 |