github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/farm/handler_test.go (about)

     1  //go:build ignore
     2  // +build ignore
     3  
     4  package farm
     5  
     6  import (
     7  	"errors"
     8  	"fmt"
     9  	"math"
    10  	"math/rand"
    11  	"testing"
    12  
    13  	"github.com/fibonacci-chain/fbc/x/common"
    14  
    15  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    16  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
    17  	swap "github.com/fibonacci-chain/fbc/x/ammswap"
    18  	swaptypes "github.com/fibonacci-chain/fbc/x/ammswap/types"
    19  	"github.com/fibonacci-chain/fbc/x/farm/keeper"
    20  	"github.com/fibonacci-chain/fbc/x/farm/types"
    21  	"github.com/fibonacci-chain/fbc/x/token"
    22  	"github.com/stretchr/testify/require"
    23  )
    24  
    25  type testContext struct {
    26  	ctx               sdk.Context
    27  	k                 Keeper
    28  	mockKeeper        keeper.MockFarmKeeper
    29  	swapTokenPairs    []swaptypes.SwapTokenPair
    30  	tokenOwner        sdk.AccAddress
    31  	nonPairTokenName  []string
    32  	nonExistTokenName []string
    33  	addrList          []sdk.AccAddress // 1000 fibo per address
    34  	handler           sdk.Handler
    35  }
    36  
    37  type getMsgFunc func(tCtx *testContext, preData interface{}) sdk.Msg
    38  
    39  type preExecFunc func(t *testing.T, tCtx *testContext) interface{}
    40  
    41  type verificationFunc func(t *testing.T, tCtx *testContext, err sdk.Error, testCase testCaseItem, preCoins, afterCoins sdk.SysCoins, preData interface{})
    42  
    43  var verification verificationFunc = func(t *testing.T, context *testContext, err sdk.Error, testCase testCaseItem, preCoins, afterCoins sdk.SysCoins, preData interface{}) {
    44  	if testCase.expectedErr == nil {
    45  		require.Nil(t, err)
    46  	} else {
    47  		require.Equal(t, testCase.expectedErr.Error(), err.Error())
    48  	}
    49  }
    50  
    51  type testCaseItem struct {
    52  	caseName     string           // the name of the case
    53  	preExec      preExecFunc      // function "preExec" executes the code before executing the specific handler to be tested
    54  	getMsg       getMsgFunc       // function "getMsg" returns a sdk.Msg for testing, this msg will be tested by executing the function "handler"
    55  	verification verificationFunc // function "verification" Verifies that the test results are the same as expected
    56  	expectedErr  sdk.Error        // expectedCode represents the expected code in the test result
    57  }
    58  
    59  func testCaseTest(t *testing.T, testCaseList []testCaseItem) {
    60  	for _, testCase := range testCaseList {
    61  		tCtx := initEnvironment(t)
    62  		preData := testCase.preExec(t, tCtx)
    63  		msg := testCase.getMsg(tCtx, preData)
    64  		addrList := msg.GetSigners()
    65  		addr := addrList[0]
    66  		preCoins := tCtx.k.TokenKeeper().GetCoins(tCtx.ctx, addr)
    67  		_, err := tCtx.handler(tCtx.ctx, msg)
    68  		afterCoins := tCtx.k.TokenKeeper().GetCoins(tCtx.ctx, addr)
    69  		testCase.verification(t, tCtx, err, testCase, preCoins, afterCoins, preData)
    70  	}
    71  }
    72  
    73  func testCaseCombinationTest(t *testing.T, testCaseList []testCaseItem) {
    74  	tCtx := initEnvironment(t)
    75  	for _, testCase := range testCaseList {
    76  		preData := testCase.preExec(t, tCtx)
    77  		msg := testCase.getMsg(tCtx, preData)
    78  		addrList := msg.GetSigners()
    79  		addr := addrList[0]
    80  		preCoins := tCtx.k.TokenKeeper().GetCoins(tCtx.ctx, addr)
    81  		_, err := tCtx.handler(tCtx.ctx, msg)
    82  		afterCoins := tCtx.k.TokenKeeper().GetCoins(tCtx.ctx, addr)
    83  		testCase.verification(t, tCtx, err, testCase, preCoins, afterCoins, preData)
    84  	}
    85  }
    86  
    87  func initEnvironment(t *testing.T) *testContext {
    88  	// init
    89  	ctx, mk := keeper.GetKeeper(t)
    90  	k := mk.Keeper
    91  
    92  	var blockHeight int64 = 10
    93  	ctx.SetBlockHeight(blockHeight)
    94  	BeginBlocker(ctx, abci.RequestBeginBlock{Header: abci.Header{Height: blockHeight}}, k)
    95  
    96  	testBaseTokenName := swaptypes.TestBasePooledToken
    97  	testQuoteTokenName := swaptypes.TestBasePooledToken2
    98  	testQuoteTokenName2 := swaptypes.TestBasePooledToken3
    99  	nonExistTokenName := "fff"
   100  
   101  	token.NewTestToken(t, ctx, mk.TokenKeeper, mk.BankKeeper, testBaseTokenName, keeper.Addrs)
   102  	token.NewTestToken(t, ctx, mk.TokenKeeper, mk.BankKeeper, testQuoteTokenName, keeper.Addrs)
   103  	token.NewTestToken(t, ctx, mk.TokenKeeper, mk.BankKeeper, testQuoteTokenName2, keeper.Addrs)
   104  
   105  	var initPoolTokenAmount int64 = 100
   106  	testBaseToken := sdk.NewDecCoinFromDec(testBaseTokenName, sdk.NewDec(initPoolTokenAmount))
   107  	testQuoteToken := sdk.NewDecCoinFromDec(testQuoteTokenName, sdk.NewDec(initPoolTokenAmount))
   108  	testAddr := keeper.Addrs[0]
   109  	testSwapTokenPair := swap.NewTestSwapTokenPairWithInitLiquidity(t, ctx, mk.SwapKeeper, testBaseToken, testQuoteToken, keeper.Addrs)
   110  
   111  	//acc := mk.AccKeeper.GetAccount(ctx, Addrs[0])
   112  	//fmt.Println(acc)
   113  
   114  	handler := NewHandler(k)
   115  
   116  	return &testContext{
   117  		ctx:               ctx,
   118  		k:                 k,
   119  		mockKeeper:        mk,
   120  		swapTokenPairs:    []swap.SwapTokenPair{testSwapTokenPair},
   121  		tokenOwner:        testAddr,
   122  		nonPairTokenName:  []string{testQuoteTokenName2},
   123  		nonExistTokenName: []string{nonExistTokenName},
   124  		addrList:          keeper.Addrs[1:],
   125  		handler:           handler,
   126  	}
   127  }
   128  
   129  var normalGetCreatePoolMsg getMsgFunc = func(tCtx *testContext, preData interface{}) sdk.Msg {
   130  	testSwapTokenPair := tCtx.swapTokenPairs[0]
   131  	testYieldTokenName := testSwapTokenPair.BasePooledCoin.Denom
   132  	owner := tCtx.tokenOwner
   133  	poolName := "abc"
   134  	minLockAmount := sdk.NewDecCoinFromDec(testSwapTokenPair.PoolTokenName, sdk.ZeroDec())
   135  	createPoolMsg := types.NewMsgCreatePool(owner, poolName, minLockAmount, testYieldTokenName)
   136  	return createPoolMsg
   137  }
   138  
   139  var normalGetDestroyPoolMsg getMsgFunc = func(tCtx *testContext, preData interface{}) sdk.Msg {
   140  	createPoolMsg := preData.(types.MsgCreatePool)
   141  	addr := createPoolMsg.Owner
   142  	poolName := createPoolMsg.PoolName
   143  	destroyPoolMsg := types.NewMsgDestroyPool(addr, poolName)
   144  	return destroyPoolMsg
   145  }
   146  
   147  var normalGetProvideMsg getMsgFunc = func(tCtx *testContext, preData interface{}) sdk.Msg {
   148  	createPoolMsg := preData.(types.MsgCreatePool)
   149  	poolName := createPoolMsg.PoolName
   150  	address := createPoolMsg.Owner
   151  	amount := sdk.NewDecCoinFromDec(createPoolMsg.YieldedSymbol, sdk.NewDec(10))
   152  	amountYieldedPerBlock := sdk.NewDec(1)
   153  	startBlockHeight := tCtx.ctx.BlockHeight() + 1
   154  	provideMsg := types.NewMsgProvide(poolName, address, amount, amountYieldedPerBlock, startBlockHeight)
   155  	return provideMsg
   156  }
   157  
   158  var normalGetLockMsg getMsgFunc = func(tCtx *testContext, preData interface{}) sdk.Msg {
   159  	createPoolMsg := preData.(types.MsgCreatePool)
   160  	poolName := createPoolMsg.PoolName
   161  	address := createPoolMsg.Owner
   162  	amount := sdk.NewDecCoinFromDec(createPoolMsg.MinLockAmount.Denom, sdk.NewDec(1))
   163  	lockMsg := types.NewMsgLock(poolName, address, amount)
   164  	return lockMsg
   165  }
   166  
   167  var normalGetUnlockMsg getMsgFunc = func(tCtx *testContext, preData interface{}) sdk.Msg {
   168  	createPoolMsg := preData.(types.MsgCreatePool)
   169  	poolName := createPoolMsg.PoolName
   170  	address := createPoolMsg.Owner
   171  	amount := sdk.NewDecCoinFromDec(createPoolMsg.MinLockAmount.Denom, sdk.NewDec(1))
   172  	unlockMsg := types.NewMsgUnlock(poolName, address, amount)
   173  	return unlockMsg
   174  }
   175  
   176  var normalGetClaimMsg getMsgFunc = func(tCtx *testContext, preData interface{}) sdk.Msg {
   177  	createPoolMsg := preData.(types.MsgCreatePool)
   178  	claimMsg := types.NewMsgClaim(createPoolMsg.PoolName, createPoolMsg.Owner)
   179  	return claimMsg
   180  }
   181  
   182  func createPool(t *testing.T, tCtx *testContext) types.MsgCreatePool {
   183  	createPoolMsg := normalGetCreatePoolMsg(tCtx, nil).(types.MsgCreatePool)
   184  	_, err := tCtx.handler(tCtx.ctx, createPoolMsg)
   185  	require.Nil(t, err)
   186  
   187  	k := tCtx.k
   188  	found := k.HasFarmPool(tCtx.ctx, createPoolMsg.PoolName)
   189  	require.True(t, found)
   190  	return createPoolMsg
   191  }
   192  
   193  func destroyPool(t *testing.T, tCtx *testContext, createPoolMsg types.MsgCreatePool) {
   194  	k := tCtx.k
   195  	found := k.HasFarmPool(tCtx.ctx, createPoolMsg.PoolName)
   196  	require.True(t, found)
   197  	destroyPoolMsg := normalGetDestroyPoolMsg(tCtx, createPoolMsg)
   198  	_, err := tCtx.handler(tCtx.ctx, destroyPoolMsg)
   199  	require.Nil(t, err)
   200  	found = k.HasFarmPool(tCtx.ctx, createPoolMsg.PoolName)
   201  	require.False(t, found)
   202  }
   203  
   204  func provide(t *testing.T, tCtx *testContext, createPoolMsg types.MsgCreatePool) types.MsgProvide {
   205  	provideMsg := normalGetProvideMsg(tCtx, createPoolMsg)
   206  	_, err := tCtx.handler(tCtx.ctx, provideMsg)
   207  	require.Nil(t, err)
   208  	return provideMsg.(types.MsgProvide)
   209  }
   210  
   211  func lock(t *testing.T, tCtx *testContext, createPoolMsg types.MsgCreatePool) types.MsgLock {
   212  	lockMsg := normalGetLockMsg(tCtx, createPoolMsg)
   213  	_, err := tCtx.handler(tCtx.ctx, lockMsg)
   214  	require.Nil(t, err)
   215  	return lockMsg.(types.MsgLock)
   216  }
   217  
   218  func unlock(t *testing.T, tCtx *testContext, createPoolMsg types.MsgCreatePool) {
   219  	unlockMsg := normalGetUnlockMsg(tCtx, createPoolMsg)
   220  	_, err := tCtx.handler(tCtx.ctx, unlockMsg)
   221  	require.Nil(t, err)
   222  }
   223  
   224  func claim(t *testing.T, tCtx *testContext, createPoolMsg types.MsgCreatePool) {
   225  	claimMsg := normalGetClaimMsg(tCtx, createPoolMsg)
   226  	_, err := tCtx.handler(tCtx.ctx, claimMsg)
   227  	require.Nil(t, err)
   228  }
   229  
   230  func TestHandlerMsgCreatePool(t *testing.T) {
   231  	preExec := func(t *testing.T, tCtx *testContext) interface{} {
   232  		return nil
   233  	}
   234  
   235  	tests := []testCaseItem{
   236  		{
   237  			caseName:     "success",
   238  			preExec:      preExec,
   239  			getMsg:       normalGetCreatePoolMsg,
   240  			verification: verification,
   241  			expectedErr:  nil,
   242  		},
   243  		{
   244  			caseName: "success. create again after destroying",
   245  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   246  				createPoolMsg := createPool(t, tCtx)
   247  
   248  				provide(t, tCtx, createPoolMsg)
   249  
   250  				lock(t, tCtx, createPoolMsg)
   251  
   252  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   253  
   254  				claim(t, tCtx, createPoolMsg)
   255  
   256  				unlock(t, tCtx, createPoolMsg)
   257  
   258  				destroyPool(t, tCtx, createPoolMsg)
   259  
   260  				return nil
   261  			},
   262  			getMsg:       normalGetCreatePoolMsg,
   263  			verification: verification,
   264  			expectedErr:  nil,
   265  		},
   266  		{
   267  			caseName: "failed. farm pool already exists",
   268  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   269  				return createPool(t, tCtx)
   270  			},
   271  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   272  				createPoolMsg := preData.(types.MsgCreatePool)
   273  				return createPoolMsg
   274  			},
   275  			verification: verification,
   276  			expectedErr:  types.ErrPoolAlreadyExist("abc"),
   277  		},
   278  		{
   279  			caseName: "failed. lock token does not exists",
   280  			preExec:  preExec,
   281  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   282  				createPoolMsg := normalGetCreatePoolMsg(tCtx, preData).(types.MsgCreatePool)
   283  				createPoolMsg.MinLockAmount = sdk.NewDecCoinFromDec(tCtx.nonExistTokenName[0], sdk.ZeroDec())
   284  				return createPoolMsg
   285  			},
   286  			verification: verification,
   287  			expectedErr:  types.ErrTokenNotExist("fff"),
   288  		},
   289  		{
   290  			caseName: "failed. yield token does not exists",
   291  			preExec:  preExec,
   292  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   293  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil).(types.MsgCreatePool)
   294  				createPoolMsg.YieldedSymbol = tCtx.nonExistTokenName[0]
   295  				return createPoolMsg
   296  			},
   297  			verification: verification,
   298  			expectedErr:  types.ErrTokenNotExist("fff"),
   299  		},
   300  		{
   301  			caseName: "failed. insufficient fee coins",
   302  			preExec: func(t *testing.T, context *testContext) interface{} {
   303  				params := context.k.GetParams(context.ctx)
   304  				params.CreatePoolFee = sdk.NewDecCoinFromDec(context.nonExistTokenName[0], sdk.NewDec(1))
   305  				context.k.SetParams(context.ctx, params)
   306  				return nil
   307  			},
   308  			getMsg:       normalGetCreatePoolMsg,
   309  			verification: verification,
   310  			expectedErr: errors.New(
   311  				"insufficient coins: insufficient funds: insufficient account funds; 89900.000000000000000000aab,101.000000000000000000ammswap_aab_ccb,89900.000000000000000000ccb,100000.000000000000000000ddb,1000.000000000000000000fibo < 1.000000000000000000fff",
   312  			),
   313  		},
   314  		{
   315  			caseName: "failed. insufficient coins",
   316  			preExec: func(t *testing.T, context *testContext) interface{} {
   317  				params := context.k.GetParams(context.ctx)
   318  				params.CreatePoolDeposit = sdk.NewDecCoinFromDec(context.nonExistTokenName[0], sdk.NewDec(1))
   319  				context.k.SetParams(context.ctx, params)
   320  				return nil
   321  			},
   322  			getMsg:       normalGetCreatePoolMsg,
   323  			verification: verification,
   324  			expectedErr: errors.New(
   325  				"insufficient coins: insufficient funds: insufficient account funds; 89900.000000000000000000aab,101.000000000000000000ammswap_aab_ccb,89900.000000000000000000ccb,100000.000000000000000000ddb,1000.000000000000000000fibo < 1.000000000000000000fff",
   326  			),
   327  		},
   328  	}
   329  	testCaseTest(t, tests)
   330  }
   331  
   332  func TestHandlerMsgDestroyPool(t *testing.T) {
   333  	common.InitConfig()
   334  	preExec := func(t *testing.T, tCtx *testContext) interface{} {
   335  		// create pool
   336  		createPoolMsg := createPool(t, tCtx)
   337  		return createPoolMsg
   338  	}
   339  	tests := []testCaseItem{
   340  		{
   341  			caseName:     "success",
   342  			preExec:      preExec,
   343  			getMsg:       normalGetDestroyPoolMsg,
   344  			verification: verification,
   345  			expectedErr:  nil,
   346  		},
   347  		{
   348  			caseName: "failed. Farm pool does not exist",
   349  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   350  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil)
   351  				return createPoolMsg
   352  			},
   353  			getMsg:       normalGetDestroyPoolMsg,
   354  			verification: verification,
   355  			expectedErr:  types.ErrNoFarmPoolFound("abc"),
   356  		},
   357  		{
   358  			caseName: "failed. the address isn't the owner of pool",
   359  			preExec:  preExec,
   360  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   361  				destroyPoolMsg := normalGetDestroyPoolMsg(tCtx, preData).(types.MsgDestroyPool)
   362  				destroyPoolMsg.Owner = tCtx.addrList[0]
   363  				return destroyPoolMsg
   364  			},
   365  			verification: verification,
   366  			expectedErr:  types.ErrInvalidPoolOwner("ex15ky9du8a2wlstz6fpx3p4mqpjyrm5cgp83ahy9", "abc"),
   367  		},
   368  		{
   369  			caseName: "failed. insufficient fee coins",
   370  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   371  				// create pool
   372  				createPoolMsg := createPool(t, tCtx)
   373  
   374  				// modify params
   375  				pools, found := tCtx.k.GetFarmPool(tCtx.ctx, createPoolMsg.PoolName)
   376  				require.True(t, found)
   377  				pools.DepositAmount = sdk.NewDecCoinFromDec(tCtx.nonExistTokenName[0], sdk.NewDec(1))
   378  				tCtx.k.SetFarmPool(tCtx.ctx, pools)
   379  				return createPoolMsg
   380  			},
   381  			getMsg:       normalGetDestroyPoolMsg,
   382  			verification: verification,
   383  			expectedErr:  errors.New("insufficient coins: insufficient funds: insufficient account funds; 10.000000000000000000fibo < 1.000000000000000000fff"),
   384  		},
   385  		{
   386  			caseName: "failed. the pool is not finished and can not be destroyed",
   387  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   388  				// create pool
   389  				createPoolMsg := createPool(t, tCtx)
   390  
   391  				// provide
   392  				provide(t, tCtx, createPoolMsg)
   393  
   394  				return createPoolMsg
   395  			},
   396  			getMsg:       normalGetDestroyPoolMsg,
   397  			verification: verification,
   398  			expectedErr:  types.ErrPoolNotFinished("abc"),
   399  		},
   400  		{
   401  			caseName: "success. destroy after providing",
   402  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   403  				// create pool
   404  				createPoolMsg := createPool(t, tCtx)
   405  
   406  				// provide
   407  				provide(t, tCtx, createPoolMsg)
   408  
   409  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   410  
   411  				return createPoolMsg
   412  			},
   413  			getMsg:       normalGetDestroyPoolMsg,
   414  			verification: verification,
   415  			expectedErr:  nil,
   416  		},
   417  		{
   418  			caseName: "success. destroy after claiming",
   419  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   420  				// create pool
   421  				createPoolMsg := createPool(t, tCtx)
   422  
   423  				// provide
   424  				provide(t, tCtx, createPoolMsg)
   425  
   426  				lock(t, tCtx, createPoolMsg)
   427  
   428  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   429  
   430  				claim(t, tCtx, createPoolMsg)
   431  
   432  				unlock(t, tCtx, createPoolMsg)
   433  
   434  				return createPoolMsg
   435  			},
   436  			getMsg:       normalGetDestroyPoolMsg,
   437  			verification: verification,
   438  			expectedErr:  nil,
   439  		},
   440  		{
   441  			caseName: "failed. insufficient rewards coins",
   442  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   443  				// create pool
   444  				createPoolMsg := createPool(t, tCtx)
   445  
   446  				// provide
   447  				provide(t, tCtx, createPoolMsg)
   448  
   449  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   450  
   451  				pool, found := tCtx.k.GetFarmPool(tCtx.ctx, createPoolMsg.PoolName)
   452  				require.True(t, found)
   453  				updatedPool, _ := tCtx.k.CalculateAmountYieldedBetween(tCtx.ctx, pool)
   454  
   455  				err := tCtx.k.SupplyKeeper().SendCoinsFromModuleToAccount(tCtx.ctx, YieldFarmingAccount, createPoolMsg.Owner, updatedPool.TotalAccumulatedRewards)
   456  				require.Nil(t, err)
   457  
   458  				return createPoolMsg
   459  			},
   460  			getMsg:       normalGetDestroyPoolMsg,
   461  			verification: verification,
   462  			expectedErr:  errors.New("insufficient coins: insufficient funds: insufficient account funds;  < 10.000000000000000000aab"),
   463  		},
   464  		{
   465  			caseName: "failed. the pool is not finished and can not be destroyed",
   466  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   467  				// create pool
   468  				createPoolMsg := createPool(t, tCtx)
   469  
   470  				// provide
   471  				provide(t, tCtx, createPoolMsg)
   472  
   473  				// lock
   474  				lock(t, tCtx, createPoolMsg)
   475  
   476  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   477  
   478  				return createPoolMsg
   479  			},
   480  			getMsg:       normalGetDestroyPoolMsg,
   481  			verification: verification,
   482  			expectedErr:  types.ErrPoolNotFinished("abc"),
   483  		},
   484  	}
   485  	testCaseTest(t, tests)
   486  }
   487  
   488  func TestHandlerMsgProvide(t *testing.T) {
   489  	var preExec preExecFunc = func(t *testing.T, tCtx *testContext) interface{} {
   490  		// create pool
   491  		createPoolMsg := createPool(t, tCtx)
   492  		return createPoolMsg
   493  	}
   494  	tests := []testCaseItem{
   495  		{
   496  			caseName:     "success",
   497  			preExec:      preExec,
   498  			getMsg:       normalGetProvideMsg,
   499  			verification: verification,
   500  			expectedErr:  nil,
   501  		},
   502  		{
   503  			caseName: "failed. The start height to yield is less than current height",
   504  			preExec:  preExec,
   505  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   506  				provideMsg := normalGetProvideMsg(tCtx, preData).(types.MsgProvide)
   507  				provideMsg.StartHeightToYield = 0
   508  				return provideMsg
   509  			},
   510  			verification: verification,
   511  			expectedErr:  types.ErrInvalidStartHeight(),
   512  		},
   513  		{
   514  			caseName: "failed. Farm pool does not exist",
   515  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   516  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil)
   517  				return createPoolMsg
   518  			},
   519  			getMsg:       normalGetProvideMsg,
   520  			verification: verification,
   521  			expectedErr:  types.ErrNoFarmPoolFound("abc"),
   522  		},
   523  		{
   524  			caseName: "failed. The coin name should be %s, not %s",
   525  			preExec:  preExec,
   526  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   527  				provideMsg := normalGetProvideMsg(tCtx, preData).(types.MsgProvide)
   528  				provideMsg.Amount = sdk.NewDecCoinFromDec(tCtx.nonExistTokenName[0], provideMsg.Amount.Amount)
   529  				return provideMsg
   530  			},
   531  			verification: verification,
   532  			expectedErr:  types.ErrInvalidDenom("aab", "fff"),
   533  		},
   534  		{
   535  			caseName: "failed. The remaining amount is %s, so it's not enable to provide token repeatedly util amount become zero",
   536  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   537  				// create pool
   538  				createPoolMsg := createPool(t, tCtx)
   539  
   540  				// provide
   541  				provide(t, tCtx, createPoolMsg)
   542  				return createPoolMsg
   543  			},
   544  			getMsg:       normalGetProvideMsg,
   545  			verification: verification,
   546  			expectedErr:  types.ErrRemainingAmountNotZero("10.000000000000000000aab"),
   547  		},
   548  		{
   549  			caseName: "insufficient amount",
   550  			preExec:  preExec,
   551  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   552  				provideMsg := normalGetProvideMsg(tCtx, preData).(types.MsgProvide)
   553  				provideMsg.Amount = sdk.NewDecCoinFromDec(provideMsg.Amount.Denom, sdk.NewDec(1000000000))
   554  				return provideMsg
   555  			},
   556  			verification: verification,
   557  			expectedErr: errors.New(fmt.Sprintf("failed. send coins from account to module failed insufficient funds: insufficient account funds; "+
   558  				"89900.000000000000000000aab,101.000000000000000000ammswap_aab_ccb,89900.000000000000000000ccb,"+
   559  				"100000.000000000000000000ddb,990.000000000000000000%s < 1000000000.000000000000000000aab", sdk.DefaultBondDenom)),
   560  		},
   561  	}
   562  
   563  	testCaseTest(t, tests)
   564  }
   565  
   566  func TestHandlerMsgLock(t *testing.T) {
   567  	var preExec preExecFunc = func(t *testing.T, tCtx *testContext) interface{} {
   568  		// create pool
   569  		createPoolMsg := createPool(t, tCtx)
   570  
   571  		// provide
   572  		provide(t, tCtx, createPoolMsg)
   573  
   574  		return createPoolMsg
   575  	}
   576  	tests := []testCaseItem{
   577  		{
   578  			caseName:     "success",
   579  			preExec:      preExec,
   580  			getMsg:       normalGetLockMsg,
   581  			verification: verification,
   582  			expectedErr:  nil,
   583  		},
   584  		{
   585  			caseName: "failed. Farm pool does not exist",
   586  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   587  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil)
   588  				return createPoolMsg
   589  			},
   590  			getMsg:       normalGetLockMsg,
   591  			verification: verification,
   592  			expectedErr:  types.ErrNoFarmPoolFound("abc"),
   593  		},
   594  		{
   595  			caseName: "failed. The coin name should be %s, not %s",
   596  			preExec:  preExec,
   597  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   598  				lockMsg := normalGetLockMsg(tCtx, preData).(types.MsgLock)
   599  				lockMsg.Amount.Denom = tCtx.nonExistTokenName[0]
   600  				return lockMsg
   601  			},
   602  			verification: verification,
   603  			expectedErr:  types.ErrInvalidDenom("ammswap_aab_ccb", "fff"),
   604  		},
   605  		{
   606  			caseName: "failed. lock amount %s must be greater than the pool`s min lock amount %s",
   607  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   608  				// create pool
   609  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil).(types.MsgCreatePool)
   610  				createPoolMsg.MinLockAmount.Amount = sdk.NewDec(math.MaxInt64)
   611  				_, err := tCtx.handler(tCtx.ctx, createPoolMsg)
   612  				require.Nil(t, err)
   613  
   614  				// provide
   615  				provide(t, tCtx, createPoolMsg)
   616  
   617  				return createPoolMsg
   618  			},
   619  			getMsg:       normalGetLockMsg,
   620  			verification: verification,
   621  			expectedErr:  types.ErrLockAmountBelowMinimum(sdk.MustNewDecFromStr("9223372036854775807.000000000000000000"), sdk.MustNewDecFromStr("1.000000000000000000")),
   622  		},
   623  		{
   624  			caseName: "success. has lockInfo",
   625  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   626  				// create pool
   627  				createPoolMsg := createPool(t, tCtx)
   628  
   629  				// provide
   630  				provide(t, tCtx, createPoolMsg)
   631  
   632  				// lock
   633  				lock(t, tCtx, createPoolMsg)
   634  
   635  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 2)
   636  
   637  				return createPoolMsg
   638  			},
   639  			getMsg: normalGetLockMsg,
   640  			verification: func(t *testing.T, tCtx *testContext, err sdk.Error, testCase testCaseItem, preCoins, afterCoins sdk.SysCoins, preData interface{}) {
   641  				verification(t, tCtx, err, testCase, preCoins, afterCoins, preData)
   642  				createPoolMsg := preData.(types.MsgCreatePool)
   643  
   644  				// claimed rewards
   645  				rewards := tCtx.mockKeeper.ObserverKeeper.ObserverData.ClaimedCoins.AmountOf(createPoolMsg.YieldedSymbol)
   646  				require.Equal(t, sdk.NewDec(1), rewards)
   647  			},
   648  			expectedErr: nil,
   649  		},
   650  		{
   651  			caseName: "failed. withdraw failed",
   652  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   653  				// create pool
   654  				createPoolMsg := createPool(t, tCtx)
   655  
   656  				// provide
   657  				provideMsg := provide(t, tCtx, createPoolMsg)
   658  
   659  				// lock
   660  				lock(t, tCtx, createPoolMsg)
   661  
   662  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   663  
   664  				err := tCtx.k.SupplyKeeper().SendCoinsFromModuleToAccount(tCtx.ctx, types.YieldFarmingAccount, provideMsg.Address, sdk.NewCoins(provideMsg.Amount))
   665  				require.Nil(t, err)
   666  				return createPoolMsg
   667  			},
   668  			getMsg:       normalGetLockMsg,
   669  			verification: verification,
   670  			expectedErr:  errors.New("insufficient funds: insufficient account funds;  < 10.000000000000000000aab"),
   671  		},
   672  		{
   673  			caseName: "failed. insufficient coins",
   674  			preExec:  preExec,
   675  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   676  				lockMsg := normalGetLockMsg(tCtx, preData).(types.MsgLock)
   677  				lockMsg.Amount.Amount = sdk.NewDec(1000000)
   678  				return lockMsg
   679  			},
   680  			verification: verification,
   681  			expectedErr: errors.New(fmt.Sprintf("failed. send coins from account to module failed insufficient funds: insufficient account funds; "+
   682  				"89890.000000000000000000aab,101.000000000000000000ammswap_aab_ccb,89900.000000000000000000ccb,"+
   683  				"100000.000000000000000000ddb,990.000000000000000000%s < 1000000.000000000000000000ammswap_aab_ccb", sdk.DefaultBondDenom)),
   684  		},
   685  	}
   686  
   687  	testCaseTest(t, tests)
   688  }
   689  
   690  func TestHandlerMsgUnlock(t *testing.T) {
   691  	common.InitConfig()
   692  	var preExec preExecFunc = func(t *testing.T, tCtx *testContext) interface{} {
   693  		// create pool
   694  		createPoolMsg := createPool(t, tCtx)
   695  
   696  		// provide
   697  		provide(t, tCtx, createPoolMsg)
   698  
   699  		// lock
   700  		lock(t, tCtx, createPoolMsg)
   701  
   702  		return createPoolMsg
   703  	}
   704  	tests := []testCaseItem{
   705  		{
   706  			caseName:     "success",
   707  			preExec:      preExec,
   708  			getMsg:       normalGetUnlockMsg,
   709  			verification: verification,
   710  			expectedErr:  nil,
   711  		},
   712  		{
   713  			caseName: "failed. the addr doesn't have any lock infos",
   714  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   715  				// create pool
   716  				createPoolMsg := createPool(t, tCtx)
   717  
   718  				// provide
   719  				provide(t, tCtx, createPoolMsg)
   720  				return createPoolMsg
   721  			},
   722  			getMsg:       normalGetUnlockMsg,
   723  			verification: verification,
   724  			expectedErr:  types.ErrNoLockInfoFound("ex15ky9du8a2wlstz6fpx3p4mqpjyrm5cgq68fzeh", "abc"),
   725  		},
   726  		{
   727  			caseName: "failed. The coin name should be %s, not %s",
   728  			preExec:  preExec,
   729  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   730  				unlockMsg := normalGetUnlockMsg(tCtx, preData).(types.MsgUnlock)
   731  				unlockMsg.Amount.Denom = tCtx.nonExistTokenName[0]
   732  				return unlockMsg
   733  			},
   734  			verification: verification,
   735  			expectedErr:  types.ErrInvalidDenom("ammswap_aab_ccb", "fff"),
   736  		},
   737  		{
   738  			caseName: "failed. The actual amount %s is less than %s",
   739  			preExec:  preExec,
   740  			getMsg: func(tCtx *testContext, preData interface{}) sdk.Msg {
   741  				unlockMsg := normalGetUnlockMsg(tCtx, preData).(types.MsgUnlock)
   742  				unlockMsg.Amount.Amount = unlockMsg.Amount.Amount.Add(sdk.NewDec(1))
   743  				return unlockMsg
   744  			},
   745  			verification: verification,
   746  			expectedErr:  types.ErrInsufficientAmount("1.000000000000000000ammswap_aab_ccb", "2.000000000000000000ammswap_aab_ccb"),
   747  		},
   748  		{
   749  			caseName: "failed. remain lock amount %s is less than pool`s min lock amount %s",
   750  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   751  				// create pool
   752  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil).(types.MsgCreatePool)
   753  				createPoolMsg.MinLockAmount.Amount = sdk.NewDec(2)
   754  				_, err := tCtx.handler(tCtx.ctx, createPoolMsg)
   755  				require.Nil(t, err)
   756  
   757  				// provide
   758  				provide(t, tCtx, createPoolMsg)
   759  
   760  				// lock
   761  				lockMsg := normalGetLockMsg(tCtx, createPoolMsg).(types.MsgLock)
   762  				lockMsg.Amount.Amount = sdk.NewDec(2)
   763  				_, err = tCtx.handler(tCtx.ctx, lockMsg)
   764  				require.Nil(t, err)
   765  
   766  				return createPoolMsg
   767  			},
   768  			getMsg:       normalGetUnlockMsg,
   769  			verification: verification,
   770  			expectedErr:  types.ErrLockAmountBelowMinimum(sdk.MustNewDecFromStr("2.000000000000000000"), sdk.MustNewDecFromStr("1.000000000000000000")),
   771  		},
   772  		{
   773  			caseName: "failed. Farm pool %s does not exist",
   774  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   775  				preData := preExec(t, tCtx).(types.MsgCreatePool)
   776  				tCtx.k.DeleteFarmPool(tCtx.ctx, preData.PoolName)
   777  				return preData
   778  			},
   779  			getMsg:       normalGetUnlockMsg,
   780  			verification: verification,
   781  			expectedErr:  types.ErrNoFarmPoolFound("abc"),
   782  		},
   783  		{
   784  			caseName: "failed. withdraw failed",
   785  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   786  				// create pool
   787  				createPoolMsg := createPool(t, tCtx)
   788  
   789  				// provide
   790  				provideMsg := provide(t, tCtx, createPoolMsg)
   791  
   792  				// lock
   793  				lock(t, tCtx, createPoolMsg)
   794  
   795  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   796  
   797  				err := tCtx.k.SupplyKeeper().SendCoinsFromModuleToAccount(tCtx.ctx, types.YieldFarmingAccount, provideMsg.Address, sdk.NewCoins(provideMsg.Amount))
   798  				require.Nil(t, err)
   799  				return createPoolMsg
   800  			},
   801  			getMsg:       normalGetUnlockMsg,
   802  			verification: verification,
   803  			expectedErr:  errors.New("insufficient funds: insufficient account funds;  < 10.000000000000000000aab"),
   804  		},
   805  		{
   806  			caseName: "failed. insufficient coins from module account",
   807  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   808  				// create pool
   809  				createPoolMsg := createPool(t, tCtx)
   810  
   811  				// provide
   812  				provide(t, tCtx, createPoolMsg)
   813  
   814  				// lock
   815  				lockMsg := lock(t, tCtx, createPoolMsg)
   816  
   817  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   818  
   819  				err := tCtx.k.SupplyKeeper().SendCoinsFromModuleToAccount(tCtx.ctx, ModuleName, lockMsg.Address, sdk.NewCoins(lockMsg.Amount))
   820  				require.Nil(t, err)
   821  				return createPoolMsg
   822  			},
   823  			getMsg:       normalGetUnlockMsg,
   824  			verification: verification,
   825  			expectedErr:  errors.New(fmt.Sprintf("failed. send coins from module to account failed insufficient funds: insufficient account funds; "+"10.000000000000000000%s < 1.000000000000000000ammswap_aab_ccb", sdk.DefaultBondDenom)),
   826  		},
   827  		{
   828  			caseName: "success. lock and unlock without provide before",
   829  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   830  				// create pool
   831  				createPoolMsg := createPool(t, tCtx)
   832  
   833  				// lock
   834  				lock(t, tCtx, createPoolMsg)
   835  
   836  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   837  				return createPoolMsg
   838  			},
   839  			getMsg:       normalGetUnlockMsg,
   840  			verification: verification,
   841  			expectedErr:  nil,
   842  		},
   843  		{
   844  			caseName: "success with rewards",
   845  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   846  				// create pool
   847  				createPoolMsg := createPool(t, tCtx)
   848  
   849  				// provide
   850  				provide(t, tCtx, createPoolMsg)
   851  
   852  				// lock
   853  				lock(t, tCtx, createPoolMsg)
   854  
   855  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 2)
   856  
   857  				return createPoolMsg
   858  			},
   859  			getMsg: normalGetUnlockMsg,
   860  			verification: func(t *testing.T, tCtx *testContext, err sdk.Error, testCase testCaseItem, preCoins, afterCoins sdk.SysCoins, preData interface{}) {
   861  				verification(t, tCtx, err, testCase, preCoins, afterCoins, preData)
   862  				createPoolMsg := preData.(types.MsgCreatePool)
   863  				diffCoins := afterCoins.Sub(preCoins)
   864  				actualDec := diffCoins.AmountOf(createPoolMsg.YieldedSymbol)
   865  				require.Equal(t, sdk.NewDec(1), actualDec)
   866  
   867  				// claimed rewards
   868  				rewards := tCtx.mockKeeper.ObserverKeeper.ObserverData.ClaimedCoins.AmountOf(createPoolMsg.YieldedSymbol)
   869  				require.Equal(t, sdk.NewDec(1), rewards)
   870  			},
   871  			expectedErr: nil,
   872  		},
   873  	}
   874  
   875  	testCaseTest(t, tests)
   876  }
   877  
   878  func TestHandlerMsgClaim(t *testing.T) {
   879  	var preExec preExecFunc = func(t *testing.T, tCtx *testContext) interface{} {
   880  		// create pool
   881  		createPoolMsg := createPool(t, tCtx)
   882  
   883  		// provide
   884  		provide(t, tCtx, createPoolMsg)
   885  
   886  		// lock
   887  		lock(t, tCtx, createPoolMsg)
   888  
   889  		return createPoolMsg
   890  	}
   891  	tests := []testCaseItem{
   892  		{
   893  			caseName:     "success. claim after providing at the same block height",
   894  			preExec:      preExec,
   895  			getMsg:       normalGetClaimMsg,
   896  			verification: verification,
   897  			expectedErr:  nil,
   898  		},
   899  		{
   900  			caseName: "success. claim after providing at the lower block height",
   901  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   902  				// create pool
   903  				createPoolMsg := createPool(t, tCtx)
   904  
   905  				// provide
   906  				provide(t, tCtx, createPoolMsg)
   907  
   908  				// lock
   909  				lock(t, tCtx, createPoolMsg)
   910  
   911  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 2)
   912  
   913  				return createPoolMsg
   914  			},
   915  			getMsg: normalGetClaimMsg,
   916  			verification: func(t *testing.T, tCtx *testContext, err sdk.Error, testCase testCaseItem, preCoins, afterCoins sdk.SysCoins, preData interface{}) {
   917  				verification(t, tCtx, err, testCase, preCoins, afterCoins, preData)
   918  				createPoolMsg := preData.(types.MsgCreatePool)
   919  				diffCoins := afterCoins.Sub(preCoins)
   920  				actualDec := diffCoins.AmountOf(createPoolMsg.YieldedSymbol)
   921  				require.Equal(t, sdk.NewDec(1), actualDec)
   922  
   923  				// claimed rewards
   924  				rewards := tCtx.mockKeeper.ObserverKeeper.ObserverData.ClaimedCoins.AmountOf(createPoolMsg.YieldedSymbol)
   925  				require.Equal(t, sdk.NewDec(1), rewards)
   926  			},
   927  			expectedErr: nil,
   928  		},
   929  		{
   930  			caseName: "failed. Farm pool %s does not exist",
   931  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   932  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil)
   933  				return createPoolMsg
   934  			},
   935  			getMsg:       normalGetClaimMsg,
   936  			verification: verification,
   937  			expectedErr:  types.ErrNoFarmPoolFound("abc"),
   938  		},
   939  		{
   940  			caseName: "failed. withdraw failed",
   941  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
   942  				// create pool
   943  				createPoolMsg := createPool(t, tCtx)
   944  
   945  				// provide
   946  				provideMsg := provide(t, tCtx, createPoolMsg)
   947  
   948  				// lock
   949  				lock(t, tCtx, createPoolMsg)
   950  
   951  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1000)
   952  
   953  				err := tCtx.k.SupplyKeeper().SendCoinsFromModuleToAccount(tCtx.ctx, types.YieldFarmingAccount, provideMsg.Address, sdk.NewCoins(provideMsg.Amount))
   954  				require.Nil(t, err)
   955  				return createPoolMsg
   956  			},
   957  			getMsg:       normalGetClaimMsg,
   958  			verification: verification,
   959  			expectedErr:  errors.New("insufficient funds: insufficient account funds;  < 10.000000000000000000aab"),
   960  		},
   961  	}
   962  
   963  	testCaseTest(t, tests)
   964  }
   965  
   966  func TestNewHandler(t *testing.T) {
   967  	// init
   968  	tCtx := initEnvironment(t)
   969  	msg := swaptypes.NewMsgCreateExchange(tCtx.swapTokenPairs[0].BasePooledCoin.Denom, tCtx.swapTokenPairs[0].QuotePooledCoin.Denom, tCtx.tokenOwner)
   970  	_, err := tCtx.handler(tCtx.ctx, msg)
   971  	require.Error(t, err)
   972  }
   973  
   974  func TestHandlerMultiLockAtOneBlockHeight(t *testing.T) {
   975  	tCtx := initEnvironment(t)
   976  
   977  	// create pool
   978  	createPoolMsg := createPool(t, tCtx)
   979  
   980  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 10)
   981  	// provide
   982  	provide(t, tCtx, createPoolMsg)
   983  
   984  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
   985  	// lock
   986  	lock(t, tCtx, createPoolMsg)
   987  
   988  	createPoolMsg.Owner = tCtx.addrList[0]
   989  	lock(t, tCtx, createPoolMsg)
   990  
   991  	createPoolMsg.Owner = tCtx.addrList[1]
   992  	lock(t, tCtx, createPoolMsg)
   993  
   994  	createPoolMsg.Owner = tCtx.addrList[2]
   995  	lock(t, tCtx, createPoolMsg)
   996  
   997  	createPoolMsg.Owner = tCtx.addrList[3]
   998  	lock(t, tCtx, createPoolMsg)
   999  
  1000  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1001  
  1002  	createPoolMsg.Owner = tCtx.addrList[4]
  1003  	lock(t, tCtx, createPoolMsg)
  1004  
  1005  	createPoolMsg.Owner = tCtx.addrList[5]
  1006  	lock(t, tCtx, createPoolMsg)
  1007  
  1008  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1009  
  1010  	createPoolMsg.Owner = tCtx.addrList[6]
  1011  	lock(t, tCtx, createPoolMsg)
  1012  
  1013  	createPoolMsg.Owner = tCtx.addrList[7]
  1014  	lock(t, tCtx, createPoolMsg)
  1015  
  1016  	createPoolMsg.Owner = tCtx.addrList[1]
  1017  	lock(t, tCtx, createPoolMsg)
  1018  
  1019  	createPoolMsg.Owner = tCtx.addrList[1]
  1020  	lock(t, tCtx, createPoolMsg)
  1021  
  1022  	createPoolMsg.Owner = tCtx.addrList[1]
  1023  	lock(t, tCtx, createPoolMsg)
  1024  
  1025  	createPoolMsg.Owner = tCtx.addrList[1]
  1026  	lock(t, tCtx, createPoolMsg)
  1027  
  1028  	//curPeriodRewards := tCtx.k.GetPoolCurrentRewards(tCtx.ctx, createPoolMsg.PoolName)
  1029  	//var period uint64
  1030  	//for period = 0;period < curPeriodRewards.Period;period++ {
  1031  	//	historyPeriodRewards := tCtx.k.GetPoolHistoricalRewards(tCtx.ctx, createPoolMsg.PoolName, period)
  1032  	//	fmt.Println("period:", period)
  1033  	//	fmt.Println(string(types.ModuleCdc.MustMarshalJSON(historyPeriodRewards)))
  1034  	//}
  1035  	tCtx.k.IterateAllLockInfos(tCtx.ctx, func(lockInfo types.LockInfo) (stop bool) {
  1036  		return false
  1037  	})
  1038  
  1039  }
  1040  
  1041  func TestHandlerMultiLockAtOneBlockHeight2(t *testing.T) {
  1042  	tCtx := initEnvironment(t)
  1043  
  1044  	// create pool
  1045  	createPoolMsg := createPool(t, tCtx)
  1046  
  1047  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 10)
  1048  	// provide
  1049  	provide(t, tCtx, createPoolMsg)
  1050  
  1051  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1052  	// lock
  1053  	lock(t, tCtx, createPoolMsg)
  1054  
  1055  	createPoolMsg.Owner = tCtx.addrList[0]
  1056  	lock(t, tCtx, createPoolMsg)
  1057  
  1058  	createPoolMsg.Owner = tCtx.addrList[0]
  1059  	lock(t, tCtx, createPoolMsg)
  1060  
  1061  	createPoolMsg.Owner = tCtx.addrList[0]
  1062  	lock(t, tCtx, createPoolMsg)
  1063  
  1064  	createPoolMsg.Owner = tCtx.addrList[0]
  1065  	lock(t, tCtx, createPoolMsg)
  1066  
  1067  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1068  
  1069  	createPoolMsg.Owner = tCtx.addrList[0]
  1070  	lock(t, tCtx, createPoolMsg)
  1071  
  1072  	createPoolMsg.Owner = tCtx.addrList[0]
  1073  	lock(t, tCtx, createPoolMsg)
  1074  
  1075  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1076  
  1077  	createPoolMsg.Owner = tCtx.addrList[0]
  1078  	lock(t, tCtx, createPoolMsg)
  1079  
  1080  	createPoolMsg.Owner = tCtx.addrList[0]
  1081  	lock(t, tCtx, createPoolMsg)
  1082  
  1083  	createPoolMsg.Owner = tCtx.addrList[0]
  1084  	lock(t, tCtx, createPoolMsg)
  1085  
  1086  	createPoolMsg.Owner = tCtx.addrList[0]
  1087  	lock(t, tCtx, createPoolMsg)
  1088  
  1089  	createPoolMsg.Owner = tCtx.addrList[0]
  1090  	lock(t, tCtx, createPoolMsg)
  1091  
  1092  	createPoolMsg.Owner = tCtx.addrList[0]
  1093  	lock(t, tCtx, createPoolMsg)
  1094  
  1095  	//curPeriodRewards := tCtx.k.GetPoolCurrentRewards(tCtx.ctx, createPoolMsg.PoolName)
  1096  	//var period uint64
  1097  	//for period = 0;period < curPeriodRewards.Period;period++ {
  1098  	//	historyPeriodRewards := tCtx.k.GetPoolHistoricalRewards(tCtx.ctx, createPoolMsg.PoolName, period)
  1099  	//	fmt.Println("period:", period)
  1100  	//	fmt.Println(string(types.ModuleCdc.MustMarshalJSON(historyPeriodRewards)))
  1101  	//}
  1102  	tCtx.k.IterateAllLockInfos(tCtx.ctx, func(lockInfo types.LockInfo) (stop bool) {
  1103  		return false
  1104  	})
  1105  
  1106  }
  1107  
  1108  func TestHandlerMultiLockAndUnlock(t *testing.T) {
  1109  	tCtx := initEnvironment(t)
  1110  
  1111  	// create pool
  1112  	createPoolMsg := createPool(t, tCtx)
  1113  
  1114  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 10)
  1115  	// provide
  1116  	provide(t, tCtx, createPoolMsg)
  1117  
  1118  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1119  	// lock
  1120  	lock(t, tCtx, createPoolMsg)
  1121  
  1122  	createPoolMsg.Owner = tCtx.addrList[1]
  1123  	lock(t, tCtx, createPoolMsg)
  1124  
  1125  	createPoolMsg.Owner = tCtx.addrList[2]
  1126  	lock(t, tCtx, createPoolMsg)
  1127  
  1128  	createPoolMsg.Owner = tCtx.addrList[3]
  1129  	lock(t, tCtx, createPoolMsg)
  1130  
  1131  	createPoolMsg.Owner = tCtx.addrList[4]
  1132  	lock(t, tCtx, createPoolMsg)
  1133  
  1134  	tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 4)
  1135  
  1136  	createPoolMsg.Owner = tCtx.tokenOwner
  1137  	unlock(t, tCtx, createPoolMsg)
  1138  
  1139  	createPoolMsg.Owner = tCtx.addrList[1]
  1140  	unlock(t, tCtx, createPoolMsg)
  1141  
  1142  	createPoolMsg.Owner = tCtx.addrList[2]
  1143  	unlock(t, tCtx, createPoolMsg)
  1144  
  1145  	createPoolMsg.Owner = tCtx.addrList[3]
  1146  	unlock(t, tCtx, createPoolMsg)
  1147  
  1148  	createPoolMsg.Owner = tCtx.addrList[4]
  1149  	unlock(t, tCtx, createPoolMsg)
  1150  
  1151  	//curPeriodRewards := tCtx.k.GetPoolCurrentRewards(tCtx.ctx, createPoolMsg.PoolName)
  1152  	numHistoricalRewards := 0
  1153  	tCtx.k.IteratePoolHistoricalRewards(tCtx.ctx, createPoolMsg.PoolName,
  1154  		func(store sdk.KVStore, key []byte, value []byte) (stop bool) {
  1155  			var rewards types.PoolHistoricalRewards
  1156  			types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(value, &rewards)
  1157  			numHistoricalRewards++
  1158  			return false
  1159  		})
  1160  	require.Equal(t, 1, numHistoricalRewards)
  1161  	numLockInfo := 0
  1162  	tCtx.k.IterateAllLockInfos(tCtx.ctx, func(lockInfo types.LockInfo) (stop bool) {
  1163  		numLockInfo++
  1164  		return false
  1165  	})
  1166  	require.Equal(t, 0, numLockInfo)
  1167  }
  1168  
  1169  func TestHandlerRandom(t *testing.T) {
  1170  	tCtx := initEnvironment(t)
  1171  
  1172  	// create pool
  1173  	createPoolMsg := createPool(t, tCtx)
  1174  	for i := 0; i < 10000; i++ {
  1175  		var msg sdk.Msg
  1176  		judge := rand.Intn(5)
  1177  		switch judge {
  1178  		case 0:
  1179  			msg = normalGetProvideMsg(tCtx, createPoolMsg)
  1180  		case 1:
  1181  			msg = normalGetCreatePoolMsg(tCtx, createPoolMsg)
  1182  		case 2:
  1183  			msg = normalGetLockMsg(tCtx, createPoolMsg)
  1184  		case 3:
  1185  			msg = normalGetUnlockMsg(tCtx, createPoolMsg)
  1186  		case 4:
  1187  			msg = normalGetClaimMsg(tCtx, createPoolMsg)
  1188  		case 5:
  1189  			msg = normalGetDestroyPoolMsg(tCtx, createPoolMsg)
  1190  		}
  1191  		ctx, writeCache := tCtx.ctx.CacheContext()
  1192  		_, err := tCtx.handler(ctx, msg)
  1193  		if err != nil {
  1194  			//fmt.Println(err.Error())
  1195  		} else {
  1196  			writeCache()
  1197  		}
  1198  		tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + int64(rand.Intn(2)))
  1199  	}
  1200  }
  1201  
  1202  func TestHandlerCheckCombination(t *testing.T) {
  1203  	var preExec preExecFunc = func(t *testing.T, tCtx *testContext) interface{} {
  1204  		return normalGetCreatePoolMsg(tCtx, nil)
  1205  	}
  1206  	tests := []testCaseItem{
  1207  		{
  1208  			caseName:     "success. create pool",
  1209  			preExec:      preExec,
  1210  			getMsg:       normalGetCreatePoolMsg,
  1211  			verification: verification,
  1212  			expectedErr:  nil,
  1213  		},
  1214  		{
  1215  			caseName: "success. provide",
  1216  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
  1217  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1)
  1218  				return normalGetCreatePoolMsg(tCtx, nil)
  1219  			},
  1220  			getMsg:       normalGetProvideMsg,
  1221  			verification: verification,
  1222  			expectedErr:  nil,
  1223  		},
  1224  		{
  1225  			caseName: "success. lock address 1",
  1226  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
  1227  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1)
  1228  				return normalGetCreatePoolMsg(tCtx, nil)
  1229  			},
  1230  			getMsg:       normalGetLockMsg,
  1231  			verification: verification,
  1232  			expectedErr:  nil,
  1233  		},
  1234  		{
  1235  			caseName: "success. lock address 2",
  1236  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
  1237  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1)
  1238  				createPoolMsg := normalGetCreatePoolMsg(tCtx, nil).(types.MsgCreatePool)
  1239  				createPoolMsg.Owner = tCtx.addrList[0]
  1240  				return createPoolMsg
  1241  			},
  1242  			getMsg:       normalGetLockMsg,
  1243  			verification: verification,
  1244  			expectedErr:  nil,
  1245  		},
  1246  		{
  1247  			caseName:     "success. claim address 1",
  1248  			preExec:      preExec,
  1249  			getMsg:       normalGetClaimMsg,
  1250  			verification: verification,
  1251  			expectedErr:  nil,
  1252  		},
  1253  		{
  1254  			caseName: "success. unlock address 1",
  1255  			preExec: func(t *testing.T, tCtx *testContext) interface{} {
  1256  				tCtx.ctx.SetBlockHeight(tCtx.ctx.BlockHeight() + 1)
  1257  				return normalGetCreatePoolMsg(tCtx, nil)
  1258  			},
  1259  			getMsg: normalGetUnlockMsg,
  1260  			verification: func(t *testing.T, tCtx *testContext, err sdk.Error, testCase testCaseItem, preCoins, afterCoins sdk.SysCoins, preData interface{}) {
  1261  				verification(t, tCtx, err, testCase, preCoins, afterCoins, preData)
  1262  				createPoolMsg := preData.(types.MsgCreatePool)
  1263  
  1264  				// check current rewards
  1265  				curPeriodRewards := tCtx.k.GetPoolCurrentRewards(tCtx.ctx, createPoolMsg.PoolName)
  1266  				var expectedCurrentPeriod uint64 = 6
  1267  				require.Equal(t, expectedCurrentPeriod, curPeriodRewards.Period)
  1268  				require.Equal(t, tCtx.ctx.BlockHeight(), curPeriodRewards.StartBlockHeight)
  1269  
  1270  				// check the number of historicalRewards
  1271  				numHistoricalRewards := 0
  1272  				tCtx.k.IteratePoolHistoricalRewards(tCtx.ctx, createPoolMsg.PoolName,
  1273  					func(store sdk.KVStore, key []byte, value []byte) (stop bool) {
  1274  						var rewards types.PoolHistoricalRewards
  1275  						types.ModuleCdc.MustUnmarshalBinaryLengthPrefixed(value, &rewards)
  1276  						numHistoricalRewards++
  1277  						return false
  1278  					})
  1279  				require.Equal(t, 2, numHistoricalRewards)
  1280  
  1281  				// check the number of lockInfo
  1282  				numLockInfo := 0
  1283  				tCtx.k.IterateAllLockInfos(tCtx.ctx, func(lockInfo types.LockInfo) (stop bool) {
  1284  					numLockInfo++
  1285  					return false
  1286  				})
  1287  				require.Equal(t, int(1), numLockInfo)
  1288  
  1289  				// check historical rewards of period 3
  1290  				expectedRatio := sdk.NewDecCoinsFromDec(createPoolMsg.YieldedSymbol, sdk.NewDec(1))
  1291  				rewards := tCtx.k.GetPoolHistoricalRewards(tCtx.ctx, createPoolMsg.PoolName, 3)
  1292  				require.Equal(t, uint16(1), rewards.ReferenceCount)
  1293  				require.Equal(t, expectedRatio.String(), rewards.CumulativeRewardRatio.String())
  1294  
  1295  				// check historical rewards of period 5
  1296  				expectedRatio = sdk.NewDecCoinsFromDec(createPoolMsg.YieldedSymbol, sdk.NewDecWithPrec(15, 1))
  1297  				rewards = tCtx.k.GetPoolHistoricalRewards(tCtx.ctx, createPoolMsg.PoolName, 5)
  1298  				require.Equal(t, uint16(1), rewards.ReferenceCount)
  1299  				require.Equal(t, expectedRatio.String(), rewards.CumulativeRewardRatio.String())
  1300  
  1301  				// check farm pool
  1302  				pool, found := tCtx.k.GetFarmPool(tCtx.ctx, createPoolMsg.PoolName)
  1303  				params := tCtx.k.GetParams(tCtx.ctx)
  1304  				require.True(t, found)
  1305  				require.Equal(t, params.CreatePoolDeposit.String(), pool.DepositAmount.String())
  1306  				expectedLockedValue := sdk.NewDecCoinFromDec(createPoolMsg.MinLockAmount.Denom, sdk.NewDec(1))
  1307  				require.Equal(t, expectedLockedValue.String(), pool.TotalValueLocked.String())
  1308  				require.Equal(t, 1, len(pool.YieldedTokenInfos))
  1309  				expectedRemainingAmount := sdk.NewDecCoinFromDec(createPoolMsg.YieldedSymbol, sdk.NewDec(8))
  1310  				require.Equal(t, expectedRemainingAmount.String(), pool.YieldedTokenInfos[0].RemainingAmount.String())
  1311  				expectedTotalAccumulatedRewards := sdk.NewDecCoinsFromDec(createPoolMsg.YieldedSymbol, sdk.NewDecWithPrec(5, 1))
  1312  				require.Equal(t, expectedTotalAccumulatedRewards.String(), pool.TotalAccumulatedRewards.String())
  1313  
  1314  			},
  1315  			expectedErr: nil,
  1316  		},
  1317  	}
  1318  
  1319  	testCaseCombinationTest(t, tests)
  1320  
  1321  }