-
Notifications
You must be signed in to change notification settings - Fork 337
/
deposit.go
127 lines (107 loc) · 3.86 KB
/
deposit.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/kava-labs/kava/x/earn/types"
)
// Deposit adds the provided amount from a depositor to a vault. The vault is
// specified by the denom in the amount.
func (k *Keeper) Deposit(
ctx sdk.Context,
depositor sdk.AccAddress,
amount sdk.Coin,
depositStrategy types.StrategyType,
) error {
// Get AllowedVault, if not found (not a valid vault), return error
allowedVault, found := k.GetAllowedVault(ctx, amount.Denom)
if !found {
return types.ErrInvalidVaultDenom
}
if amount.IsZero() {
return types.ErrInsufficientAmount
}
// Check if deposit strategy is supported by vault
if !allowedVault.IsStrategyAllowed(depositStrategy) {
return types.ErrInvalidVaultStrategy
}
// Check if account can deposit -- this checks if the vault is private
// and if so, if the depositor is in the AllowedDepositors list
if !allowedVault.IsAccountAllowed(depositor) {
return types.ErrAccountDepositNotAllowed
}
// Check if VaultRecord exists, create if not exist
vaultRecord, found := k.GetVaultRecord(ctx, amount.Denom)
if !found {
// Create a new VaultRecord with 0 supply
vaultRecord = types.NewVaultRecord(amount.Denom, sdk.ZeroDec())
}
// Get the strategy for the vault
// NOTE: Currently always uses the first one, AllowedVaults are currently
// only valid with 1 and only 1 strategy so this is safe.
// If/When multiple strategies are supported and users can specify specific
// strategies, shares should be issued per-strategy instead of per-vault.
strategy, err := k.GetStrategy(allowedVault.Strategies[0])
if err != nil {
return err
}
// Transfer amount to module account
if err := k.bankKeeper.SendCoinsFromAccountToModule(
ctx,
depositor,
types.ModuleName,
sdk.NewCoins(amount),
); err != nil {
return err
}
// Get VaultShareRecord for account, create if account has no deposits.
// This can still be found if the account has deposits for other vaults.
vaultShareRecord, found := k.GetVaultShareRecord(ctx, depositor)
if !found {
// Create a new empty VaultShareRecord with 0 supply
vaultShareRecord = types.NewVaultShareRecord(depositor, types.NewVaultShares())
}
shares, err := k.ConvertToShares(ctx, amount)
if err != nil {
return fmt.Errorf("failed to convert assets to shares: %w", err)
}
isNew := vaultShareRecord.Shares.AmountOf(amount.Denom).IsZero()
if !isNew {
// If deposits for this vault already exists, call hook with user's existing shares
k.BeforeVaultDepositModified(ctx, amount.Denom, depositor, vaultShareRecord.Shares.AmountOf(amount.Denom))
}
// Increment VaultRecord total shares and account shares
vaultRecord.TotalShares = vaultRecord.TotalShares.Add(shares)
vaultShareRecord.Shares = vaultShareRecord.Shares.Add(shares)
// Update VaultRecord and VaultShareRecord
k.SetVaultRecord(ctx, vaultRecord)
k.SetVaultShareRecord(ctx, vaultShareRecord)
if isNew {
// If first deposit in this vault
k.AfterVaultDepositCreated(ctx, amount.Denom, depositor, shares.Amount)
}
// Deposit to the strategy
if err := strategy.Deposit(ctx, amount); err != nil {
return err
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
types.EventTypeVaultDeposit,
sdk.NewAttribute(types.AttributeKeyVaultDenom, amount.Denom),
sdk.NewAttribute(types.AttributeKeyDepositor, depositor.String()),
sdk.NewAttribute(types.AttributeKeyShares, shares.Amount.String()),
sdk.NewAttribute(sdk.AttributeKeyAmount, amount.Amount.String()),
),
)
return nil
}
// DepositFromModuleAccount adds the provided amount from a depositor module
// account to a vault. The vault is specified by the denom in the amount.
func (k *Keeper) DepositFromModuleAccount(
ctx sdk.Context,
from string,
wantAmount sdk.Coin,
withdrawStrategy types.StrategyType,
) error {
addr := k.accountKeeper.GetModuleAddress(from)
return k.Deposit(ctx, addr, wantAmount, withdrawStrategy)
}