github.com/gravity-devs/liquidity@v1.5.3/x/liquidity/types/utils_test.go (about)

     1  package types_test
     2  
     3  import (
     4  	"testing"
     5  
     6  	sdk "github.com/cosmos/cosmos-sdk/types"
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/gravity-devs/liquidity/x/liquidity/types"
    10  )
    11  
    12  func TestAlphabeticalDenomPair(t *testing.T) {
    13  	denomA := "uCoinA"
    14  	denomB := "uCoinB"
    15  	afterDenomA, afterDenomB := types.AlphabeticalDenomPair(denomA, denomB)
    16  	require.Equal(t, denomA, afterDenomA)
    17  	require.Equal(t, denomB, afterDenomB)
    18  
    19  	afterDenomA, afterDenomB = types.AlphabeticalDenomPair(denomB, denomA)
    20  	require.Equal(t, denomA, afterDenomA)
    21  	require.Equal(t, denomB, afterDenomB)
    22  }
    23  
    24  func TestGetReserveAcc(t *testing.T) {
    25  	expectedReserveAcc, _ := sdk.AccAddressFromBech32("cosmos16ddqestwukv0jzcyfn3fdfq9h2wrs83cr4rfm3")
    26  	tests := []struct {
    27  		poolCoinDenom      string
    28  		expectedReserveAcc sdk.AccAddress
    29  		expPass            bool
    30  	}{
    31  		{
    32  			poolCoinDenom:      "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4",
    33  			expectedReserveAcc: expectedReserveAcc,
    34  			expPass:            true,
    35  		},
    36  		{
    37  			poolCoinDenom:      "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A",
    38  			expectedReserveAcc: nil,
    39  			expPass:            false,
    40  		},
    41  		{
    42  			poolCoinDenom:      "D35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4",
    43  			expectedReserveAcc: nil,
    44  			expPass:            false,
    45  		},
    46  		{
    47  			poolCoinDenom:      "ibc/D35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4",
    48  			expectedReserveAcc: nil,
    49  			expPass:            false,
    50  		},
    51  	}
    52  
    53  	for _, tc := range tests {
    54  		reserveAcc, err := types.GetReserveAcc(tc.poolCoinDenom, false)
    55  		if tc.expPass {
    56  			require.Equal(t, tc.expectedReserveAcc, reserveAcc)
    57  		} else {
    58  			require.Nil(t, reserveAcc)
    59  			require.ErrorIs(t, err, types.ErrInvalidDenom)
    60  		}
    61  	}
    62  }
    63  
    64  func TestSortDenoms(t *testing.T) {
    65  	tests := []struct {
    66  		denoms         []string
    67  		expectedDenoms []string
    68  	}{
    69  		{
    70  			denoms:         []string{"uCoinB", "uCoinA"},
    71  			expectedDenoms: []string{"uCoinA", "uCoinB"},
    72  		},
    73  		{
    74  			denoms:         []string{"uCoinC", "uCoinA", "uCoinB"},
    75  			expectedDenoms: []string{"uCoinA", "uCoinB", "uCoinC"},
    76  		},
    77  		{
    78  			denoms:         []string{"uCoinC", "uCoinA", "uCoinD", "uCoinB"},
    79  			expectedDenoms: []string{"uCoinA", "uCoinB", "uCoinC", "uCoinD"},
    80  		},
    81  	}
    82  
    83  	for _, tc := range tests {
    84  		sortedDenoms := types.SortDenoms(tc.denoms)
    85  		require.Equal(t, tc.expectedDenoms, sortedDenoms)
    86  	}
    87  }
    88  
    89  func TestGetPoolInformation(t *testing.T) {
    90  	testCases := []struct {
    91  		reserveCoinDenoms     []string
    92  		poolTypeID            uint32
    93  		expectedPoolName      string
    94  		expectedReserveAcc    string
    95  		expectedPoolCoinDenom string
    96  		len32                 bool
    97  	}{
    98  		{
    99  			reserveCoinDenoms:     []string{"denomX", "denomY"},
   100  			poolTypeID:            uint32(1),
   101  			expectedPoolName:      "denomX/denomY/1",
   102  			expectedReserveAcc:    "cosmos16ddqestwukv0jzcyfn3fdfq9h2wrs83cr4rfm3",
   103  			expectedPoolCoinDenom: "poolD35A0CC16EE598F90B044CE296A405BA9C381E38837599D96F2F70C2F02A23A4",
   104  			len32:                 false,
   105  		},
   106  		{
   107  			reserveCoinDenoms:     []string{"stake", "token"},
   108  			poolTypeID:            uint32(1),
   109  			expectedPoolName:      "stake/token/1",
   110  			expectedReserveAcc:    "cosmos1unfxz7l7q0s3gmmthgwe3yljk0thhg57ym3p6u",
   111  			expectedPoolCoinDenom: "poolE4D2617BFE03E1146F6BBA1D9893F2B3D77BA29E7ED532BB721A39FF1ECC1B07",
   112  			len32:                 false,
   113  		},
   114  		{
   115  			reserveCoinDenoms:     []string{"uatom", "uusd"},
   116  			poolTypeID:            uint32(2),
   117  			expectedPoolName:      "uatom/uusd/2",
   118  			expectedReserveAcc:    "cosmos1xqm0g09czvdp5c7jk0fmz85u7maz52m040eh8g",
   119  			expectedPoolCoinDenom: "pool3036F43CB8131A1A63D2B3D3B11E9CF6FA2A2B6FEC17D5AD283C25C939614A8C",
   120  			len32:                 false,
   121  		},
   122  		{
   123  			reserveCoinDenoms:     []string{"uatom", "usdt"},
   124  			poolTypeID:            uint32(3),
   125  			expectedPoolName:      "uatom/usdt/3",
   126  			expectedReserveAcc:    "cosmos1aqvez6g6wejw8hu35kplycf2taqsfkpj3ns3c5v4dhwazfdzhzastyr290",
   127  			expectedPoolCoinDenom: "pool93E069B333B5ECEBFE24C6E1437E814003248E0DD7FF8B9F82119F4587449BA5",
   128  			len32:                 true,
   129  		},
   130  	}
   131  
   132  	for _, tc := range testCases {
   133  		poolName := types.PoolName(tc.reserveCoinDenoms, tc.poolTypeID)
   134  		require.Equal(t, tc.expectedPoolName, poolName)
   135  
   136  		reserveAcc := types.GetPoolReserveAcc(poolName, tc.len32)
   137  		require.Equal(t, tc.expectedReserveAcc, reserveAcc.String())
   138  
   139  		poolCoinDenom := types.GetPoolCoinDenom(poolName)
   140  		require.Equal(t, tc.expectedPoolCoinDenom, poolCoinDenom)
   141  
   142  		expectedReserveAcc, err := types.GetReserveAcc(poolCoinDenom, tc.len32)
   143  		require.NoError(t, err)
   144  		require.Equal(t, tc.expectedReserveAcc, expectedReserveAcc.String())
   145  	}
   146  }
   147  
   148  func TestGetCoinsTotalAmount(t *testing.T) {
   149  	testCases := []struct {
   150  		coins        sdk.Coins
   151  		expectResult sdk.Int
   152  	}{
   153  		{
   154  			coins:        sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(100)), sdk.NewCoin("uCoinB", sdk.NewInt(100))),
   155  			expectResult: sdk.NewInt(200),
   156  		},
   157  		{
   158  			coins:        sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(100)), sdk.NewCoin("uCoinB", sdk.NewInt(300))),
   159  			expectResult: sdk.NewInt(400),
   160  		},
   161  		{
   162  			coins:        sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(500))),
   163  			expectResult: sdk.NewInt(500),
   164  		},
   165  	}
   166  
   167  	for _, tc := range testCases {
   168  		totalAmount := types.GetCoinsTotalAmount(tc.coins)
   169  		require.Equal(t, tc.expectResult, totalAmount)
   170  	}
   171  }
   172  
   173  func TestValidateReserveCoinLimit(t *testing.T) {
   174  	testCases := []struct {
   175  		name                 string
   176  		maxReserveCoinAmount sdk.Int
   177  		depositCoins         sdk.Coins
   178  		expectErr            bool
   179  	}{
   180  		{
   181  			name:                 "valid case",
   182  			maxReserveCoinAmount: sdk.ZeroInt(), // 0 means unlimited amount
   183  			depositCoins:         sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(100_000_000_000)), sdk.NewCoin("uCoinB", sdk.NewInt(100))),
   184  			expectErr:            false,
   185  		},
   186  		{
   187  			name:                 "valid case",
   188  			maxReserveCoinAmount: sdk.NewInt(1_000_000_000_000),
   189  			depositCoins:         sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(500_000_000_000)), sdk.NewCoin("uCoinB", sdk.NewInt(500_000_000_000))),
   190  			expectErr:            false,
   191  		},
   192  		{
   193  			name:                 "negative value of max reserve coin amount",
   194  			maxReserveCoinAmount: sdk.NewInt(-100),
   195  			depositCoins:         sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(100_000_000_000)), sdk.NewCoin("uCoinB", sdk.NewInt(100))),
   196  			expectErr:            true,
   197  		},
   198  		{
   199  			name:                 "cannot exceed reserve coin limit amount",
   200  			maxReserveCoinAmount: sdk.NewInt(1_000_000_000_000),
   201  			depositCoins:         sdk.NewCoins(sdk.NewCoin("uCoinA", sdk.NewInt(1_000_000_000_000)), sdk.NewCoin("uCoinB", sdk.NewInt(100))),
   202  			expectErr:            true,
   203  		},
   204  	}
   205  
   206  	for _, tc := range testCases {
   207  		t.Run(tc.name, func(t *testing.T) {
   208  			if tc.expectErr {
   209  				err := types.ValidateReserveCoinLimit(tc.maxReserveCoinAmount, tc.depositCoins)
   210  				require.Equal(t, types.ErrExceededReserveCoinLimit, err)
   211  			} else {
   212  				err := types.ValidateReserveCoinLimit(tc.maxReserveCoinAmount, tc.depositCoins)
   213  				require.NoError(t, err)
   214  			}
   215  		})
   216  	}
   217  }
   218  
   219  func TestGetOfferCoinFee(t *testing.T) {
   220  	testDenom := "test"
   221  	testCases := []struct {
   222  		name               string
   223  		offerCoin          sdk.Coin
   224  		swapFeeRate        sdk.Dec
   225  		expectOfferCoinFee sdk.Coin
   226  	}{
   227  		{
   228  			name:               "case1",
   229  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(1)),
   230  			swapFeeRate:        types.DefaultSwapFeeRate,
   231  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(1)),
   232  		},
   233  		{
   234  			name:               "case2",
   235  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(10)),
   236  			swapFeeRate:        types.DefaultSwapFeeRate,
   237  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(1)),
   238  		},
   239  		{
   240  			name:               "case3",
   241  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(100)),
   242  			swapFeeRate:        types.DefaultSwapFeeRate,
   243  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(1)),
   244  		},
   245  		{
   246  			name:               "case4",
   247  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(1000)),
   248  			swapFeeRate:        types.DefaultSwapFeeRate,
   249  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(2)),
   250  		},
   251  		{
   252  			name:               "case5",
   253  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(10000)),
   254  			swapFeeRate:        types.DefaultSwapFeeRate,
   255  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(15)),
   256  		},
   257  		{
   258  			name:               "case6",
   259  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(10001)),
   260  			swapFeeRate:        types.DefaultSwapFeeRate,
   261  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(16)),
   262  		},
   263  		{
   264  			name:               "case7",
   265  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(10700)),
   266  			swapFeeRate:        types.DefaultSwapFeeRate,
   267  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(17)),
   268  		},
   269  		{
   270  			name:               "case8",
   271  			offerCoin:          sdk.NewCoin(testDenom, sdk.NewInt(10000)),
   272  			swapFeeRate:        sdk.ZeroDec(),
   273  			expectOfferCoinFee: sdk.NewCoin(testDenom, sdk.NewInt(0)),
   274  		},
   275  	}
   276  
   277  	for _, tc := range testCases {
   278  		t.Run(tc.name, func(t *testing.T) {
   279  			require.Equal(t, tc.expectOfferCoinFee, types.GetOfferCoinFee(tc.offerCoin, tc.swapFeeRate))
   280  		})
   281  	}
   282  }
   283  
   284  func TestCheckOverflow(t *testing.T) {
   285  	testCases := []struct {
   286  		name      string
   287  		a         sdk.Int
   288  		b         sdk.Int
   289  		expectErr error
   290  	}{
   291  		{
   292  			name:      "valid case",
   293  			a:         sdk.NewInt(10000),
   294  			b:         sdk.NewInt(100),
   295  			expectErr: nil,
   296  		},
   297  		{
   298  			name:      "overflow case",
   299  			a:         sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000),
   300  			b:         sdk.NewInt(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000).MulRaw(1_000_000_000_000_000_000),
   301  			expectErr: types.ErrOverflowAmount,
   302  		},
   303  	}
   304  
   305  	for _, tc := range testCases {
   306  		t.Run(tc.name, func(t *testing.T) {
   307  			err := types.CheckOverflow(tc.a, tc.b)
   308  			require.ErrorIs(t, err, tc.expectErr)
   309  		})
   310  	}
   311  }
   312  
   313  func TestCheckOverflowWithDec(t *testing.T) {
   314  	testCases := []struct {
   315  		name      string
   316  		a         sdk.Dec
   317  		b         sdk.Dec
   318  		expectErr error
   319  	}{
   320  		{
   321  			name:      "valid case",
   322  			a:         sdk.MustNewDecFromStr("1.0"),
   323  			b:         sdk.MustNewDecFromStr("0.0000001"),
   324  			expectErr: nil,
   325  		},
   326  		{
   327  			name:      "overflow case",
   328  			a:         sdk.MustNewDecFromStr("100000000000000000000000000000000000000000000000000000000000.0").MulInt64(10),
   329  			b:         sdk.MustNewDecFromStr("0.000000000000000001"),
   330  			expectErr: types.ErrOverflowAmount,
   331  		},
   332  	}
   333  
   334  	for _, tc := range testCases {
   335  		t.Run(tc.name, func(t *testing.T) {
   336  			err := types.CheckOverflowWithDec(tc.a, tc.b)
   337  			require.ErrorIs(t, err, tc.expectErr)
   338  		})
   339  	}
   340  }