0g-chain/x/earn/keeper/vault_share_test.go
2024-08-03 17:51:56 +08:00

134 lines
3.6 KiB
Go

package keeper_test
import (
"testing"
sdkmath "cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
"github.com/0glabs/0g-chain/x/earn/testutil"
"github.com/0glabs/0g-chain/x/earn/types"
)
type vaultShareTestSuite struct {
testutil.Suite
}
func (suite *vaultShareTestSuite) SetupTest() {
suite.Suite.SetupTest()
suite.Keeper.SetParams(suite.Ctx, types.DefaultParams())
}
func TestVaultShareTestSuite(t *testing.T) {
suite.Run(t, new(vaultShareTestSuite))
}
func (suite *vaultShareTestSuite) TestConvertToShares() {
vaultDenom := "usdx"
tests := []struct {
name string
beforeConvert func()
giveAmount sdk.Coin
wantShares types.VaultShare
}{
{
name: "initial 1:1",
beforeConvert: func() {},
giveAmount: sdk.NewCoin(vaultDenom, sdkmath.NewInt(100)),
wantShares: types.NewVaultShare(vaultDenom, sdk.NewDec(100)),
},
{
name: "value doubled",
beforeConvert: func() {
// set total shares set total value for hard
// value is double than shares
// shares is 2x price now
suite.addTotalShareAndValue(vaultDenom, sdk.NewDec(100), sdkmath.NewInt(200))
},
giveAmount: sdk.NewCoin(vaultDenom, sdkmath.NewInt(100)),
wantShares: types.NewVaultShare(vaultDenom, sdk.NewDec(50)),
},
{
name: "truncate",
beforeConvert: func() {
suite.addTotalShareAndValue(vaultDenom, sdk.NewDec(1000), sdkmath.NewInt(1001))
},
giveAmount: sdk.NewCoin(vaultDenom, sdkmath.NewInt(100)),
// 100 * 100 / 101 = 99.0099something
wantShares: types.NewVaultShare(vaultDenom, sdk.NewDec(100).MulInt64(1000).QuoInt64(1001)),
},
}
for _, tt := range tests {
suite.Run(tt.name, func() {
// Reset state
suite.Suite.SetupTest()
suite.CreateVault(vaultDenom, types.StrategyTypes{types.STRATEGY_TYPE_HARD}, false, nil)
err := suite.App.FundModuleAccount(
suite.Ctx,
types.ModuleName,
sdk.NewCoins(sdk.NewInt64Coin(vaultDenom, 10000)),
)
suite.Require().NoError(err)
// Run any deposits or any other setup
tt.beforeConvert()
issuedShares, err := suite.Keeper.ConvertToShares(suite.Ctx, tt.giveAmount)
suite.Require().NoError(err)
suite.Equal(tt.wantShares, issuedShares)
})
}
}
func (suite *vaultShareTestSuite) addTotalShareAndValue(
vaultDenom string,
vaultShares sdk.Dec,
hardDeposit sdkmath.Int,
) {
macc := suite.AccountKeeper.GetModuleAccount(suite.Ctx, types.ModuleName)
vaultRecord, found := suite.Keeper.GetVaultRecord(suite.Ctx, vaultDenom)
if !found {
vaultRecord = types.NewVaultRecord(vaultDenom, sdk.ZeroDec())
}
// Add to vault record
vaultRecord.TotalShares.Amount = vaultRecord.TotalShares.Amount.Add(vaultShares)
// set total shares
suite.Keeper.UpdateVaultRecord(
suite.Ctx,
vaultRecord,
)
// add value for hard -- this does not set
err := suite.HardKeeper.Deposit(
suite.Ctx,
macc.GetAddress(),
sdk.NewCoins(sdk.NewCoin(vaultDenom, hardDeposit)),
)
suite.Require().NoError(err)
}
func TestPrecisionMulQuoOrder(t *testing.T) {
assetAmount := sdk.NewDec(100)
totalShares := sdk.NewDec(100)
totalValue := sdk.NewDec(105)
// issuedShares = assetAmount * (totalValue / totalShares)
// = (assetAmount * totalShares) / totalValue
mulFirst := assetAmount.Mul(totalShares).QuoTruncate(totalValue)
quoFirst := assetAmount.Mul(totalShares.QuoTruncate(totalValue))
assert.Equal(t, sdk.MustNewDecFromStr("95.238095238095238095"), mulFirst)
assert.Equal(t, sdk.MustNewDecFromStr("95.238095238095238000"), quoFirst)
assert.NotEqual(t, mulFirst, quoFirst)
}