2021-07-15 22:29:11 +00:00
|
|
|
package keeper_test
|
|
|
|
|
|
|
|
import (
|
2024-05-01 03:17:24 +00:00
|
|
|
"github.com/0glabs/0g-chain/x/swap/types"
|
|
|
|
"github.com/0glabs/0g-chain/x/swap/types/mocks"
|
2021-07-15 22:29:11 +00:00
|
|
|
|
2023-04-05 23:21:59 +00:00
|
|
|
sdkmath "cosmossdk.io/math"
|
2023-11-21 19:08:07 +00:00
|
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
2021-07-15 22:29:11 +00:00
|
|
|
"github.com/stretchr/testify/mock"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (suite *keeperTestSuite) TestHooks_DepositAndWithdraw() {
|
|
|
|
suite.Keeper.ClearHooks()
|
|
|
|
swapHooks := &mocks.SwapHooks{}
|
|
|
|
suite.Keeper.SetHooks(swapHooks)
|
|
|
|
|
|
|
|
pool := types.NewAllowedPool("ukava", "usdx")
|
|
|
|
suite.Require().NoError(pool.Validate())
|
|
|
|
suite.Keeper.SetParams(suite.Ctx, types.NewParams(types.NewAllowedPools(pool), types.DefaultSwapFee))
|
|
|
|
|
|
|
|
balance := sdk.NewCoins(
|
2023-04-05 23:21:59 +00:00
|
|
|
sdk.NewCoin(pool.TokenA, sdkmath.NewInt(1000e6)),
|
|
|
|
sdk.NewCoin(pool.TokenB, sdkmath.NewInt(1000e6)),
|
2021-07-15 22:29:11 +00:00
|
|
|
)
|
|
|
|
depositor_1 := suite.CreateAccount(balance)
|
|
|
|
|
2023-04-05 23:21:59 +00:00
|
|
|
depositA := sdk.NewCoin(pool.TokenA, sdkmath.NewInt(10e6))
|
|
|
|
depositB := sdk.NewCoin(pool.TokenB, sdkmath.NewInt(50e6))
|
2021-07-15 22:29:11 +00:00
|
|
|
deposit := sdk.NewCoins(depositA, depositB)
|
|
|
|
|
|
|
|
// expected initial shares - geometric mean
|
2023-04-05 23:21:59 +00:00
|
|
|
expectedShares := sdkmath.NewInt(22360679)
|
2021-07-15 22:29:11 +00:00
|
|
|
|
|
|
|
// first deposit creates pool - calls AfterPoolDepositCreated with initial shares
|
|
|
|
swapHooks.On("AfterPoolDepositCreated", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_1.GetAddress(), expectedShares).Once()
|
|
|
|
err := suite.Keeper.Deposit(suite.Ctx, depositor_1.GetAddress(), depositA, depositB, sdk.MustNewDecFromStr("0.0015"))
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// second deposit adds to pool - calls BeforePoolDepositModified
|
|
|
|
// shares given are the initial shares, not the shares added to the pool
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_1.GetAddress(), expectedShares).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor_1.GetAddress(), sdk.NewCoin("ukava", sdkmath.NewInt(5e6)), sdk.NewCoin("usdx", sdkmath.NewInt(25e6)), sdk.MustNewDecFromStr("0.0015"))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// get the shares from the store from the last deposit
|
|
|
|
shareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor_1.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
|
|
|
|
|
|
|
// third deposit adds to pool - calls BeforePoolDepositModified
|
|
|
|
// shares given are the shares added in previous deposit, not the shares added to the pool now
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_1.GetAddress(), shareRecord.SharesOwned).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor_1.GetAddress(), sdk.NewCoin("ukava", sdkmath.NewInt(10e6)), sdk.NewCoin("usdx", sdkmath.NewInt(50e6)), sdk.MustNewDecFromStr("0.0015"))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
depositor_2 := suite.NewAccountFromAddr(
|
2022-01-08 00:39:27 +00:00
|
|
|
sdk.AccAddress("depositor 2---------"),
|
2021-07-15 22:29:11 +00:00
|
|
|
sdk.NewCoins(
|
2023-04-05 23:21:59 +00:00
|
|
|
sdk.NewCoin("ukava", sdkmath.NewInt(100e6)),
|
|
|
|
sdk.NewCoin("usdx", sdkmath.NewInt(100e6)),
|
2021-07-15 22:29:11 +00:00
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
// first deposit deposit into pool creates the deposit and calls AfterPoolDepositCreated
|
2023-04-05 23:21:59 +00:00
|
|
|
expectedShares = sdkmath.NewInt(2236067)
|
2021-07-15 22:29:11 +00:00
|
|
|
swapHooks.On("AfterPoolDepositCreated", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_2.GetAddress(), expectedShares).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor_2.GetAddress(), sdk.NewCoin("ukava", sdkmath.NewInt(1e6)), sdk.NewCoin("usdx", sdkmath.NewInt(5e6)), sdk.MustNewDecFromStr("0.0015"))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// second deposit into pool calls BeforePoolDepositModified with initial shares given
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_2.GetAddress(), expectedShares).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor_2.GetAddress(), sdk.NewCoin("ukava", sdkmath.NewInt(2e6)), sdk.NewCoin("usdx", sdkmath.NewInt(10e6)), sdk.MustNewDecFromStr("0.0015"))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// get the shares from the store from the last deposit
|
|
|
|
shareRecord, found = suite.Keeper.GetDepositorShares(suite.Ctx, depositor_2.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
|
|
|
|
|
|
|
// third deposit into pool calls BeforePoolDepositModified with shares from last deposit
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_2.GetAddress(), shareRecord.SharesOwned).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor_2.GetAddress(), sdk.NewCoin("ukava", sdkmath.NewInt(3e6)), sdk.NewCoin("usdx", sdkmath.NewInt(15e6)), sdk.MustNewDecFromStr("0.0015"))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// test hooks with a full withdraw of all shares
|
|
|
|
shareRecord, found = suite.Keeper.GetDepositorShares(suite.Ctx, depositor_1.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
|
|
|
// all shares given to BeforePoolDepositModified
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_1.GetAddress(), shareRecord.SharesOwned).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Withdraw(suite.Ctx, depositor_1.GetAddress(), shareRecord.SharesOwned, sdk.NewCoin("ukava", sdkmath.NewInt(1)), sdk.NewCoin("usdx", sdkmath.NewInt(1)))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// test hooks on partial withdraw
|
|
|
|
shareRecord, found = suite.Keeper.GetDepositorShares(suite.Ctx, depositor_2.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
2023-04-05 23:21:59 +00:00
|
|
|
partialShares := shareRecord.SharesOwned.Quo(sdkmath.NewInt(3))
|
2021-07-15 22:29:11 +00:00
|
|
|
// all shares given to before deposit modified even with partial withdraw
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_2.GetAddress(), shareRecord.SharesOwned).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Withdraw(suite.Ctx, depositor_2.GetAddress(), partialShares, sdk.NewCoin("ukava", sdkmath.NewInt(1)), sdk.NewCoin("usdx", sdkmath.NewInt(1)))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// test hooks on second partial withdraw
|
|
|
|
shareRecord, found = suite.Keeper.GetDepositorShares(suite.Ctx, depositor_2.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
2023-04-05 23:21:59 +00:00
|
|
|
partialShares = shareRecord.SharesOwned.Quo(sdkmath.NewInt(2))
|
2021-07-15 22:29:11 +00:00
|
|
|
// all shares given to before deposit modified even with partial withdraw
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_2.GetAddress(), shareRecord.SharesOwned).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Withdraw(suite.Ctx, depositor_2.GetAddress(), partialShares, sdk.NewCoin("ukava", sdkmath.NewInt(1)), sdk.NewCoin("usdx", sdkmath.NewInt(1)))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// test hooks withdraw all shares with second depositor
|
|
|
|
shareRecord, found = suite.Keeper.GetDepositorShares(suite.Ctx, depositor_2.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
|
|
|
// all shares given to before deposit modified even with partial withdraw
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, types.PoolIDFromCoins(deposit), depositor_2.GetAddress(), shareRecord.SharesOwned).Once()
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Withdraw(suite.Ctx, depositor_2.GetAddress(), shareRecord.SharesOwned, sdk.NewCoin("ukava", sdkmath.NewInt(1)), sdk.NewCoin("usdx", sdkmath.NewInt(1)))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
swapHooks.AssertExpectations(suite.T())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (suite *keeperTestSuite) TestHooks_NoPanicsOnNilHooks() {
|
|
|
|
suite.Keeper.ClearHooks()
|
|
|
|
|
|
|
|
pool := types.NewAllowedPool("ukava", "usdx")
|
|
|
|
suite.Require().NoError(pool.Validate())
|
|
|
|
suite.Keeper.SetParams(suite.Ctx, types.NewParams(types.NewAllowedPools(pool), types.DefaultSwapFee))
|
|
|
|
|
|
|
|
balance := sdk.NewCoins(
|
2023-04-05 23:21:59 +00:00
|
|
|
sdk.NewCoin(pool.TokenA, sdkmath.NewInt(1000e6)),
|
|
|
|
sdk.NewCoin(pool.TokenB, sdkmath.NewInt(1000e6)),
|
2021-07-15 22:29:11 +00:00
|
|
|
)
|
|
|
|
depositor := suite.CreateAccount(balance)
|
|
|
|
|
2023-04-05 23:21:59 +00:00
|
|
|
depositA := sdk.NewCoin(pool.TokenA, sdkmath.NewInt(10e6))
|
|
|
|
depositB := sdk.NewCoin(pool.TokenB, sdkmath.NewInt(50e6))
|
2021-07-15 22:29:11 +00:00
|
|
|
deposit := sdk.NewCoins(depositA, depositB)
|
|
|
|
|
|
|
|
// deposit create pool should not panic when hooks are not set
|
|
|
|
err := suite.Keeper.Deposit(suite.Ctx, depositor.GetAddress(), depositA, depositB, sdk.MustNewDecFromStr("0.0015"))
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// existing deposit should not panic with hooks are not set
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor.GetAddress(), sdk.NewCoin("ukava", sdkmath.NewInt(5e6)), sdk.NewCoin("usdx", sdkmath.NewInt(25e6)), sdk.MustNewDecFromStr("0.0015"))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
// withdraw of shares should not panic when hooks are not set
|
|
|
|
shareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Withdraw(suite.Ctx, depositor.GetAddress(), shareRecord.SharesOwned, sdk.NewCoin("ukava", sdkmath.NewInt(1)), sdk.NewCoin("usdx", sdkmath.NewInt(1)))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (suite *keeperTestSuite) TestHooks_HookOrdering() {
|
|
|
|
suite.Keeper.ClearHooks()
|
|
|
|
swapHooks := &mocks.SwapHooks{}
|
|
|
|
suite.Keeper.SetHooks(swapHooks)
|
|
|
|
|
|
|
|
pool := types.NewAllowedPool("ukava", "usdx")
|
|
|
|
suite.Require().NoError(pool.Validate())
|
|
|
|
suite.Keeper.SetParams(suite.Ctx, types.NewParams(types.NewAllowedPools(pool), types.DefaultSwapFee))
|
|
|
|
|
|
|
|
balance := sdk.NewCoins(
|
2023-04-05 23:21:59 +00:00
|
|
|
sdk.NewCoin(pool.TokenA, sdkmath.NewInt(1000e6)),
|
|
|
|
sdk.NewCoin(pool.TokenB, sdkmath.NewInt(1000e6)),
|
2021-07-15 22:29:11 +00:00
|
|
|
)
|
|
|
|
depositor := suite.CreateAccount(balance)
|
|
|
|
|
2023-04-05 23:21:59 +00:00
|
|
|
depositA := sdk.NewCoin(pool.TokenA, sdkmath.NewInt(10e6))
|
|
|
|
depositB := sdk.NewCoin(pool.TokenB, sdkmath.NewInt(50e6))
|
2021-07-15 22:29:11 +00:00
|
|
|
deposit := sdk.NewCoins(depositA, depositB)
|
|
|
|
|
|
|
|
poolID := types.PoolIDFromCoins(deposit)
|
2023-04-05 23:21:59 +00:00
|
|
|
expectedShares := sdkmath.NewInt(22360679)
|
2021-07-15 22:29:11 +00:00
|
|
|
|
|
|
|
swapHooks.On("AfterPoolDepositCreated", suite.Ctx, poolID, depositor.GetAddress(), expectedShares).Run(func(args mock.Arguments) {
|
|
|
|
_, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), poolID)
|
|
|
|
suite.Require().True(found, "expected after hook to be called after shares are updated")
|
|
|
|
})
|
|
|
|
err := suite.Keeper.Deposit(suite.Ctx, depositor.GetAddress(), depositA, depositB, sdk.MustNewDecFromStr("0.0015"))
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, poolID, depositor.GetAddress(), expectedShares).Run(func(args mock.Arguments) {
|
|
|
|
shareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), poolID)
|
|
|
|
suite.Require().True(found, "expected share record to exist")
|
|
|
|
suite.Equal(expectedShares, shareRecord.SharesOwned, "expected hook to be called before shares are updated")
|
|
|
|
})
|
|
|
|
err = suite.Keeper.Deposit(suite.Ctx, depositor.GetAddress(), depositA, depositB, sdk.MustNewDecFromStr("0.0015"))
|
|
|
|
suite.Require().NoError(err)
|
|
|
|
|
|
|
|
existingShareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), types.PoolIDFromCoins(deposit))
|
|
|
|
suite.Require().True(found)
|
|
|
|
swapHooks.On("BeforePoolDepositModified", suite.Ctx, poolID, depositor.GetAddress(), existingShareRecord.SharesOwned).Run(func(args mock.Arguments) {
|
|
|
|
shareRecord, found := suite.Keeper.GetDepositorShares(suite.Ctx, depositor.GetAddress(), poolID)
|
|
|
|
suite.Require().True(found, "expected share record to exist")
|
|
|
|
suite.Equal(existingShareRecord.SharesOwned, shareRecord.SharesOwned, "expected hook to be called before shares are updated")
|
|
|
|
})
|
2023-04-05 23:21:59 +00:00
|
|
|
err = suite.Keeper.Withdraw(suite.Ctx, depositor.GetAddress(), existingShareRecord.SharesOwned.Quo(sdkmath.NewInt(2)), sdk.NewCoin("ukava", sdkmath.NewInt(1)), sdk.NewCoin("usdx", sdkmath.NewInt(1)))
|
2021-07-15 22:29:11 +00:00
|
|
|
suite.Require().NoError(err)
|
|
|
|
}
|