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 }