github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/cosmos-sdk/x/bank/internal/keeper/keeper_test.go (about)

     1  package keeper_test
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	abci "github.com/fibonacci-chain/fbc/libs/tendermint/abci/types"
     8  	tmkv "github.com/fibonacci-chain/fbc/libs/tendermint/libs/kv"
     9  	tmtime "github.com/fibonacci-chain/fbc/libs/tendermint/types/time"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/simapp"
    13  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    14  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth"
    15  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/vesting"
    16  	keep "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/bank/internal/keeper"
    17  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/bank/internal/types"
    18  	"github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/supply"
    19  )
    20  
    21  const (
    22  	fooDenom = "foo"
    23  	barDenom = "bar"
    24  )
    25  
    26  func TestKeeper(t *testing.T) {
    27  	app, ctx := createTestApp(false)
    28  
    29  	addr := sdk.AccAddress([]byte("addr1"))
    30  	addr2 := sdk.AccAddress([]byte("addr2"))
    31  	addr3 := sdk.AccAddress([]byte("addr3"))
    32  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
    33  
    34  	// Test GetCoins/SetCoins
    35  	app.AccountKeeper.SetAccount(ctx, acc)
    36  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
    37  
    38  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
    39  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
    40  
    41  	// Test HasCoins
    42  	require.True(t, app.BankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
    43  	require.True(t, app.BankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
    44  	require.False(t, app.BankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
    45  	require.False(t, app.BankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5))))
    46  
    47  	// Test AddCoins
    48  	app.BankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15)))
    49  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 25))))
    50  
    51  	app.BankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 15)))
    52  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 15), sdk.NewInt64Coin("foocoin", 25))))
    53  
    54  	// Test SubtractCoins
    55  	app.BankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
    56  	app.BankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5)))
    57  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15))))
    58  
    59  	app.BankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 11)))
    60  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15))))
    61  
    62  	app.BankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10)))
    63  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
    64  	require.False(t, app.BankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 1))))
    65  
    66  	// Test SendCoins
    67  	app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))
    68  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
    69  	require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
    70  
    71  	app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
    72  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
    73  	require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
    74  
    75  	app.BankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 30)))
    76  	app.BankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)))
    77  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5))))
    78  	require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10))))
    79  
    80  	// Test InputOutputCoins
    81  	input1 := types.NewInput(addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 2)))
    82  	output1 := types.NewOutput(addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 2)))
    83  	app.BankKeeper.InputOutputCoins(ctx, []types.Input{input1}, []types.Output{output1})
    84  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 7))))
    85  	require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 8))))
    86  
    87  	inputs := []types.Input{
    88  		types.NewInput(addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 3))),
    89  		types.NewInput(addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 3), sdk.NewInt64Coin("foocoin", 2))),
    90  	}
    91  
    92  	outputs := []types.Output{
    93  		types.NewOutput(addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 1))),
    94  		types.NewOutput(addr3, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5))),
    95  	}
    96  	app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)
    97  	require.True(t, app.BankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 21), sdk.NewInt64Coin("foocoin", 4))))
    98  	require.True(t, app.BankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 7), sdk.NewInt64Coin("foocoin", 6))))
    99  	require.True(t, app.BankKeeper.GetCoins(ctx, addr3).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5))))
   100  
   101  	// Test retrieving black listed accounts
   102  	for acc := range simapp.GetMaccPerms() {
   103  		addr := supply.NewModuleAddress(acc)
   104  		require.Equal(t, app.BlacklistedAccAddrs()[addr.String()], app.BankKeeper.BlacklistedAddr(addr))
   105  	}
   106  }
   107  
   108  func TestSendKeeper(t *testing.T) {
   109  	app, ctx := createTestApp(false)
   110  
   111  	blacklistedAddrs := make(map[string]bool)
   112  
   113  	paramSpace := app.ParamsKeeper.Subspace("newspace")
   114  	sendKeeper := keep.NewBaseSendKeeper(app.AccountKeeper, paramSpace, blacklistedAddrs)
   115  	app.BankKeeper.SetSendEnabled(ctx, true)
   116  
   117  	addr := sdk.AccAddress([]byte("addr1"))
   118  	addr2 := sdk.AccAddress([]byte("addr2"))
   119  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   120  
   121  	// Test GetCoins/SetCoins
   122  	app.AccountKeeper.SetAccount(ctx, acc)
   123  	require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
   124  
   125  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
   126  	require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
   127  
   128  	// Test HasCoins
   129  	require.True(t, sendKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
   130  	require.True(t, sendKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
   131  	require.False(t, sendKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
   132  	require.False(t, sendKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5))))
   133  
   134  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15)))
   135  
   136  	// Test SendCoins
   137  	sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))
   138  	require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
   139  	require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
   140  
   141  	sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
   142  	require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
   143  	require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
   144  
   145  	app.BankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 30)))
   146  	sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)))
   147  	require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5))))
   148  	require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10))))
   149  
   150  	// validate coins with invalid denoms or negative values cannot be sent
   151  	// NOTE: We must use the Coin literal as the constructor does not allow
   152  	// negative values.
   153  	err := sendKeeper.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: sdk.NewDec(-5)}})
   154  	require.Error(t, err)
   155  }
   156  
   157  func TestInputOutputNewAccount(t *testing.T) {
   158  	app, ctx := createTestApp(false)
   159  	balances := sdk.NewCoins(sdk.NewInt64Coin("foo", 100), sdk.NewInt64Coin("bar", 50))
   160  	addr1 := sdk.AccAddress([]byte("addr1"))
   161  	acc1 := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   162  
   163  	app.AccountKeeper.SetAccount(ctx, acc1)
   164  	require.NoError(t, app.BankKeeper.SetCoins(ctx, addr1, balances))
   165  
   166  	acc1Balances := app.BankKeeper.GetCoins(ctx, addr1)
   167  	require.Equal(t, balances, acc1Balances)
   168  
   169  	addr2 := sdk.AccAddress([]byte("addr2"))
   170  
   171  	require.Nil(t, app.AccountKeeper.GetAccount(ctx, addr2))
   172  	require.Empty(t, app.BankKeeper.GetCoins(ctx, addr2))
   173  
   174  	inputs := []types.Input{
   175  		{Address: addr1, Coins: sdk.NewCoins(sdk.NewInt64Coin("foo", 30), sdk.NewInt64Coin("bar", 10))},
   176  	}
   177  	outputs := []types.Output{
   178  		{Address: addr2, Coins: sdk.NewCoins(sdk.NewInt64Coin("foo", 30), sdk.NewInt64Coin("bar", 10))},
   179  	}
   180  
   181  	require.NoError(t, app.BankKeeper.InputOutputCoins(ctx, inputs, outputs))
   182  
   183  	expected := sdk.NewCoins(sdk.NewInt64Coin("foo", 30), sdk.NewInt64Coin("bar", 10))
   184  	acc2Balances := app.BankKeeper.GetCoins(ctx, addr2)
   185  	require.Equal(t, expected, acc2Balances)
   186  	require.NotNil(t, app.AccountKeeper.GetAccount(ctx, addr2))
   187  }
   188  
   189  func TestMsgSendEvents(t *testing.T) {
   190  	app, ctx := createTestApp(false)
   191  
   192  	app.BankKeeper.SetSendEnabled(ctx, true)
   193  
   194  	addr := sdk.AccAddress([]byte("addr1"))
   195  	addr2 := sdk.AccAddress([]byte("addr2"))
   196  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   197  
   198  	app.AccountKeeper.SetAccount(ctx, acc)
   199  	newCoins := sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))
   200  	err := app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)
   201  	require.Error(t, err)
   202  	events := ctx.EventManager().Events()
   203  	require.Equal(t, 2, len(events))
   204  	event1 := sdk.Event{
   205  		Type:       types.EventTypeTransfer,
   206  		Attributes: []tmkv.Pair{},
   207  	}
   208  	event1.Attributes = append(
   209  		event1.Attributes,
   210  		tmkv.Pair{Key: []byte(types.AttributeKeyRecipient), Value: []byte(addr2.String())},
   211  		tmkv.Pair{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())},
   212  		tmkv.Pair{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins.String())})
   213  	event2 := sdk.Event{
   214  		Type:       sdk.EventTypeMessage,
   215  		Attributes: []tmkv.Pair{},
   216  	}
   217  	event2.Attributes = append(
   218  		event2.Attributes,
   219  		tmkv.Pair{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())})
   220  	require.Equal(t, event1, events[0])
   221  	require.Equal(t, event2, events[1])
   222  
   223  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
   224  	newCoins = sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))
   225  	err = app.BankKeeper.SendCoins(ctx, addr, addr2, newCoins)
   226  	require.NoError(t, err)
   227  	events = ctx.EventManager().Events()
   228  	require.Equal(t, 4, len(events))
   229  	require.Equal(t, event1, events[2])
   230  	require.Equal(t, event2, events[3])
   231  }
   232  
   233  func TestMsgMultiSendEvents(t *testing.T) {
   234  	app, ctx := createTestApp(false)
   235  
   236  	app.BankKeeper.SetSendEnabled(ctx, true)
   237  
   238  	addr := sdk.AccAddress([]byte("addr1"))
   239  	addr2 := sdk.AccAddress([]byte("addr2"))
   240  	addr3 := sdk.AccAddress([]byte("addr3"))
   241  	addr4 := sdk.AccAddress([]byte("addr4"))
   242  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   243  	acc2 := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   244  
   245  	app.AccountKeeper.SetAccount(ctx, acc)
   246  	app.AccountKeeper.SetAccount(ctx, acc2)
   247  	newCoins := sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))
   248  	newCoins2 := sdk.NewCoins(sdk.NewInt64Coin("barcoin", 100))
   249  	inputs := []types.Input{
   250  		{Address: addr, Coins: newCoins},
   251  		{Address: addr2, Coins: newCoins2},
   252  	}
   253  	outputs := []types.Output{
   254  		{Address: addr3, Coins: newCoins},
   255  		{Address: addr4, Coins: newCoins2},
   256  	}
   257  	err := app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)
   258  	require.Error(t, err)
   259  	events := ctx.EventManager().Events()
   260  	require.Equal(t, 0, len(events))
   261  
   262  	// Set addr's coins but not addr2's coins
   263  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
   264  
   265  	err = app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)
   266  	require.Error(t, err)
   267  	events = ctx.EventManager().Events()
   268  	require.Equal(t, 1, len(events))
   269  	event1 := sdk.Event{
   270  		Type:       sdk.EventTypeMessage,
   271  		Attributes: []tmkv.Pair{},
   272  	}
   273  	event1.Attributes = append(
   274  		event1.Attributes,
   275  		tmkv.Pair{Key: []byte(types.AttributeKeySender), Value: []byte(addr.String())})
   276  	require.Equal(t, event1, events[0])
   277  
   278  	// Set addr's coins and addr2's coins
   279  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
   280  	newCoins = sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50))
   281  	app.BankKeeper.SetCoins(ctx, addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 100)))
   282  	newCoins2 = sdk.NewCoins(sdk.NewInt64Coin("barcoin", 100))
   283  
   284  	err = app.BankKeeper.InputOutputCoins(ctx, inputs, outputs)
   285  	require.NoError(t, err)
   286  	events = ctx.EventManager().Events()
   287  	require.Equal(t, 5, len(events))
   288  	event2 := sdk.Event{
   289  		Type:       sdk.EventTypeMessage,
   290  		Attributes: []tmkv.Pair{},
   291  	}
   292  	event2.Attributes = append(
   293  		event2.Attributes,
   294  		tmkv.Pair{Key: []byte(types.AttributeKeySender), Value: []byte(addr2.String())})
   295  	event3 := sdk.Event{
   296  		Type:       types.EventTypeTransfer,
   297  		Attributes: []tmkv.Pair{},
   298  	}
   299  	event3.Attributes = append(
   300  		event3.Attributes,
   301  		tmkv.Pair{Key: []byte(types.AttributeKeyRecipient), Value: []byte(addr3.String())})
   302  	event3.Attributes = append(
   303  		event3.Attributes,
   304  		tmkv.Pair{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins.String())})
   305  	event4 := sdk.Event{
   306  		Type:       types.EventTypeTransfer,
   307  		Attributes: []tmkv.Pair{},
   308  	}
   309  	event4.Attributes = append(
   310  		event4.Attributes,
   311  		tmkv.Pair{Key: []byte(types.AttributeKeyRecipient), Value: []byte(addr4.String())})
   312  	event4.Attributes = append(
   313  		event4.Attributes,
   314  		tmkv.Pair{Key: []byte(sdk.AttributeKeyAmount), Value: []byte(newCoins2.String())})
   315  	require.Equal(t, event1, events[1])
   316  	require.Equal(t, event2, events[2])
   317  	require.Equal(t, event3, events[3])
   318  	require.Equal(t, event4, events[4])
   319  }
   320  
   321  func TestViewKeeper(t *testing.T) {
   322  	app, ctx := createTestApp(false)
   323  
   324  	//paramSpace := app.ParamsKeeper.Subspace(types.DefaultParamspace)
   325  	viewKeeper := keep.NewBaseViewKeeper(app.AccountKeeper)
   326  
   327  	addr := sdk.AccAddress([]byte("addr1"))
   328  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr)
   329  
   330  	// Test GetCoins/SetCoins
   331  	app.AccountKeeper.SetAccount(ctx, acc)
   332  	require.True(t, viewKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
   333  
   334  	app.BankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
   335  	require.True(t, viewKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
   336  
   337  	// Test HasCoins
   338  	require.True(t, viewKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
   339  	require.True(t, viewKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
   340  	require.False(t, viewKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
   341  	require.False(t, viewKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5))))
   342  }
   343  
   344  func TestVestingAccountSend(t *testing.T) {
   345  	app, ctx := createTestApp(false)
   346  	now := tmtime.Now()
   347  	ctx.SetBlockHeader(abci.Header{Time: now})
   348  	endTime := now.Add(24 * time.Hour)
   349  
   350  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   351  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   352  
   353  	addr1 := sdk.AccAddress([]byte("addr1"))
   354  	addr2 := sdk.AccAddress([]byte("addr2"))
   355  	bacc := auth.NewBaseAccountWithAddress(addr1)
   356  	bacc.SetCoins(origCoins)
   357  	vacc := vesting.NewContinuousVestingAccount(&bacc, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   358  	app.AccountKeeper.SetAccount(ctx, vacc)
   359  
   360  	// require that no coins be sendable at the beginning of the vesting schedule
   361  	err := app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)
   362  	require.Error(t, err)
   363  
   364  	// receive some coins
   365  	vacc.SetCoins(origCoins.Add(sendCoins...))
   366  	app.AccountKeeper.SetAccount(ctx, vacc)
   367  
   368  	// require that all vested coins are spendable plus any received
   369  	ctx.SetBlockTime(now.Add(12 * time.Hour))
   370  	err = app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)
   371  	vacc = app.AccountKeeper.GetAccount(ctx, addr1).(*vesting.ContinuousVestingAccount)
   372  	require.NoError(t, err)
   373  	require.Equal(t, origCoins, vacc.GetCoins())
   374  }
   375  
   376  func TestPeriodicVestingAccountSend(t *testing.T) {
   377  	app, ctx := createTestApp(false)
   378  	now := tmtime.Now()
   379  	ctx.SetBlockHeader(abci.Header{Time: now})
   380  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   381  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   382  
   383  	addr1 := sdk.AccAddress([]byte("addr1"))
   384  	addr2 := sdk.AccAddress([]byte("addr2"))
   385  	bacc := auth.NewBaseAccountWithAddress(addr1)
   386  	bacc.SetCoins(origCoins)
   387  	periods := vesting.Periods{
   388  		vesting.Period{Length: int64(12 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 50)}},
   389  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   390  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   391  	}
   392  	vacc := vesting.NewPeriodicVestingAccount(&bacc, ctx.BlockHeader().Time.Unix(), periods)
   393  	app.AccountKeeper.SetAccount(ctx, vacc)
   394  
   395  	// require that no coins be sendable at the beginning of the vesting schedule
   396  	err := app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)
   397  	require.Error(t, err)
   398  
   399  	// receive some coins
   400  	vacc.SetCoins(origCoins.Add(sendCoins...))
   401  	app.AccountKeeper.SetAccount(ctx, vacc)
   402  
   403  	// require that all vested coins are spendable plus any received
   404  	ctx.SetBlockTime(now.Add(12 * time.Hour))
   405  	err = app.BankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)
   406  	vacc = app.AccountKeeper.GetAccount(ctx, addr1).(*vesting.PeriodicVestingAccount)
   407  	require.NoError(t, err)
   408  	require.Equal(t, origCoins, vacc.GetCoins())
   409  }
   410  
   411  func TestVestingAccountReceive(t *testing.T) {
   412  	app, ctx := createTestApp(false)
   413  	now := tmtime.Now()
   414  	ctx.SetBlockHeader(abci.Header{Time: now})
   415  	endTime := now.Add(24 * time.Hour)
   416  
   417  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   418  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   419  
   420  	addr1 := sdk.AccAddress([]byte("addr1"))
   421  	addr2 := sdk.AccAddress([]byte("addr2"))
   422  
   423  	bacc := auth.NewBaseAccountWithAddress(addr1)
   424  	bacc.SetCoins(origCoins)
   425  	vacc := vesting.NewContinuousVestingAccount(&bacc, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   426  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   427  	app.AccountKeeper.SetAccount(ctx, vacc)
   428  	app.AccountKeeper.SetAccount(ctx, acc)
   429  	app.BankKeeper.SetCoins(ctx, addr2, origCoins)
   430  
   431  	// send some coins to the vesting account
   432  	app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)
   433  
   434  	// require the coins are spendable
   435  	vacc = app.AccountKeeper.GetAccount(ctx, addr1).(*vesting.ContinuousVestingAccount)
   436  	require.Equal(t, origCoins.Add(sendCoins...), vacc.GetCoins())
   437  	require.Equal(t, vacc.SpendableCoins(now), sendCoins)
   438  
   439  	// require coins are spendable plus any that have vested
   440  	require.Equal(t, vacc.SpendableCoins(now.Add(12*time.Hour)), origCoins)
   441  }
   442  
   443  func TestPeriodicVestingAccountReceive(t *testing.T) {
   444  	app, ctx := createTestApp(false)
   445  	now := tmtime.Now()
   446  	ctx.SetBlockHeader(abci.Header{Time: now})
   447  
   448  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   449  	sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   450  
   451  	addr1 := sdk.AccAddress([]byte("addr1"))
   452  	addr2 := sdk.AccAddress([]byte("addr2"))
   453  
   454  	bacc := auth.NewBaseAccountWithAddress(addr1)
   455  	bacc.SetCoins(origCoins)
   456  	periods := vesting.Periods{
   457  		vesting.Period{Length: int64(12 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 50)}},
   458  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   459  		vesting.Period{Length: int64(6 * 60 * 60), Amount: sdk.Coins{sdk.NewInt64Coin("stake", 25)}},
   460  	}
   461  	vacc := vesting.NewPeriodicVestingAccount(&bacc, ctx.BlockHeader().Time.Unix(), periods)
   462  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr2)
   463  	app.AccountKeeper.SetAccount(ctx, vacc)
   464  	app.AccountKeeper.SetAccount(ctx, acc)
   465  	app.BankKeeper.SetCoins(ctx, addr2, origCoins)
   466  
   467  	// send some coins to the vesting account
   468  	app.BankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)
   469  
   470  	// require the coins are spendable
   471  	vacc = app.AccountKeeper.GetAccount(ctx, addr1).(*vesting.PeriodicVestingAccount)
   472  	require.Equal(t, origCoins.Add(sendCoins...), vacc.GetCoins())
   473  	require.Equal(t, vacc.SpendableCoins(now), sendCoins)
   474  
   475  	// require coins are spendable plus any that have vested
   476  	require.Equal(t, vacc.SpendableCoins(now.Add(12*time.Hour)), origCoins)
   477  }
   478  
   479  func TestDelegateCoins(t *testing.T) {
   480  	app, ctx := createTestApp(false)
   481  	now := tmtime.Now()
   482  	ctx.SetBlockHeader(abci.Header{Time: now})
   483  	endTime := now.Add(24 * time.Hour)
   484  	ak := app.AccountKeeper
   485  
   486  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   487  	delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   488  
   489  	addr1 := sdk.AccAddress([]byte("addr1"))
   490  	addr2 := sdk.AccAddress([]byte("addr2"))
   491  	addrModule := sdk.AccAddress([]byte("moduleAcc"))
   492  
   493  	bacc := auth.NewBaseAccountWithAddress(addr1)
   494  	bacc.SetCoins(origCoins)
   495  	macc := ak.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   496  	vacc := vesting.NewContinuousVestingAccount(&bacc, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   497  	acc := ak.NewAccountWithAddress(ctx, addr2)
   498  	ak.SetAccount(ctx, vacc)
   499  	ak.SetAccount(ctx, acc)
   500  	ak.SetAccount(ctx, macc)
   501  	app.BankKeeper.SetCoins(ctx, addr2, origCoins)
   502  
   503  	ctx.SetBlockTime(now.Add(12 * time.Hour))
   504  
   505  	// require the ability for a non-vesting account to delegate
   506  	err := app.BankKeeper.DelegateCoins(ctx, addr2, addrModule, delCoins)
   507  	acc = ak.GetAccount(ctx, addr2)
   508  	macc = ak.GetAccount(ctx, addrModule)
   509  	require.NoError(t, err)
   510  	require.Equal(t, origCoins.Sub(delCoins), acc.GetCoins())
   511  	require.Equal(t, delCoins, macc.GetCoins())
   512  
   513  	// require the ability for a vesting account to delegate
   514  	err = app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins)
   515  	vacc = ak.GetAccount(ctx, addr1).(*vesting.ContinuousVestingAccount)
   516  	require.NoError(t, err)
   517  	require.Equal(t, delCoins, vacc.GetCoins())
   518  }
   519  
   520  func TestUndelegateCoins(t *testing.T) {
   521  	app, ctx := createTestApp(false)
   522  	now := tmtime.Now()
   523  	ctx.SetBlockHeader(abci.Header{Time: now})
   524  	endTime := now.Add(24 * time.Hour)
   525  	ak := app.AccountKeeper
   526  
   527  	origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
   528  	delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
   529  
   530  	addr1 := sdk.AccAddress([]byte("addr1"))
   531  	addr2 := sdk.AccAddress([]byte("addr2"))
   532  	addrModule := sdk.AccAddress([]byte("moduleAcc"))
   533  
   534  	bacc := auth.NewBaseAccountWithAddress(addr1)
   535  	bacc.SetCoins(origCoins)
   536  	macc := ak.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   537  	vacc := vesting.NewContinuousVestingAccount(&bacc, ctx.BlockHeader().Time.Unix(), endTime.Unix())
   538  	acc := ak.NewAccountWithAddress(ctx, addr2)
   539  	ak.SetAccount(ctx, vacc)
   540  	ak.SetAccount(ctx, acc)
   541  	ak.SetAccount(ctx, macc)
   542  	app.BankKeeper.SetCoins(ctx, addr2, origCoins)
   543  
   544  	ctx.SetBlockTime(now.Add(12 * time.Hour))
   545  
   546  	// require the ability for a non-vesting account to delegate
   547  	err := app.BankKeeper.DelegateCoins(ctx, addr2, addrModule, delCoins)
   548  	require.NoError(t, err)
   549  
   550  	acc = ak.GetAccount(ctx, addr2)
   551  	macc = ak.GetAccount(ctx, addrModule)
   552  	require.Equal(t, origCoins.Sub(delCoins), acc.GetCoins())
   553  	require.Equal(t, delCoins, macc.GetCoins())
   554  
   555  	// require the ability for a non-vesting account to undelegate
   556  	err = app.BankKeeper.UndelegateCoins(ctx, addrModule, addr2, delCoins)
   557  	require.NoError(t, err)
   558  
   559  	acc = ak.GetAccount(ctx, addr2)
   560  	macc = ak.GetAccount(ctx, addrModule)
   561  	require.Equal(t, origCoins, acc.GetCoins())
   562  	require.True(t, macc.GetCoins().Empty())
   563  
   564  	// require the ability for a vesting account to delegate
   565  	err = app.BankKeeper.DelegateCoins(ctx, addr1, addrModule, delCoins)
   566  	require.NoError(t, err)
   567  
   568  	vacc = ak.GetAccount(ctx, addr1).(*vesting.ContinuousVestingAccount)
   569  	macc = ak.GetAccount(ctx, addrModule)
   570  	require.Equal(t, origCoins.Sub(delCoins), vacc.GetCoins())
   571  	require.Equal(t, delCoins, macc.GetCoins())
   572  
   573  	// require the ability for a vesting account to undelegate
   574  	err = app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins)
   575  	require.NoError(t, err)
   576  
   577  	vacc = ak.GetAccount(ctx, addr1).(*vesting.ContinuousVestingAccount)
   578  	macc = ak.GetAccount(ctx, addrModule)
   579  	require.Equal(t, origCoins, vacc.GetCoins())
   580  	require.True(t, macc.GetCoins().Empty())
   581  }
   582  
   583  func newFooCoin(amt int64) sdk.Coin {
   584  	return sdk.NewInt64Coin(fooDenom, amt)
   585  }
   586  
   587  func newBarCoin(amt int64) sdk.Coin {
   588  	return sdk.NewInt64Coin(barDenom, amt)
   589  }
   590  
   591  func TestUndelegateCoins_Invalid(t *testing.T) {
   592  	app, ctx := createTestApp(false)
   593  	now := tmtime.Now()
   594  	ctx.SetBlockHeader(abci.Header{Time: now})
   595  	delCoins := sdk.NewCoins(newFooCoin(50))
   596  
   597  	addr1 := sdk.AccAddress([]byte("addr1_______________"))
   598  	addrModule := sdk.AccAddress([]byte("moduleAcc___________"))
   599  	macc := app.AccountKeeper.NewAccountWithAddress(ctx, addrModule) // we don't need to define an actual module account bc we just need the address for testing
   600  	acc := app.AccountKeeper.NewAccountWithAddress(ctx, addr1)
   601  
   602  	require.Error(t, app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   603  
   604  	app.AccountKeeper.SetAccount(ctx, macc)
   605  
   606  	require.Error(t, app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   607  	app.AccountKeeper.SetAccount(ctx, acc)
   608  
   609  	require.Error(t, app.BankKeeper.UndelegateCoins(ctx, addrModule, addr1, delCoins))
   610  }