github.com/Finschia/finschia-sdk@v0.48.1/x/gov/keeper/deposit.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	sdk "github.com/Finschia/finschia-sdk/types"
     7  	sdkerrors "github.com/Finschia/finschia-sdk/types/errors"
     8  	"github.com/Finschia/finschia-sdk/x/gov/types"
     9  )
    10  
    11  // GetDeposit gets the deposit of a specific depositor on a specific proposal
    12  func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) (deposit types.Deposit, found bool) {
    13  	store := ctx.KVStore(keeper.storeKey)
    14  	bz := store.Get(types.DepositKey(proposalID, depositorAddr))
    15  	if bz == nil {
    16  		return deposit, false
    17  	}
    18  
    19  	keeper.cdc.MustUnmarshal(bz, &deposit)
    20  
    21  	return deposit, true
    22  }
    23  
    24  // SetDeposit sets a Deposit to the gov store
    25  func (keeper Keeper) SetDeposit(ctx sdk.Context, deposit types.Deposit) {
    26  	store := ctx.KVStore(keeper.storeKey)
    27  	bz := keeper.cdc.MustMarshal(&deposit)
    28  	depositor := sdk.MustAccAddressFromBech32(deposit.Depositor)
    29  
    30  	store.Set(types.DepositKey(deposit.ProposalId, depositor), bz)
    31  }
    32  
    33  // GetAllDeposits returns all the deposits from the store
    34  func (keeper Keeper) GetAllDeposits(ctx sdk.Context) (deposits types.Deposits) {
    35  	keeper.IterateAllDeposits(ctx, func(deposit types.Deposit) bool {
    36  		deposits = append(deposits, deposit)
    37  		return false
    38  	})
    39  
    40  	return
    41  }
    42  
    43  // GetDeposits returns all the deposits from a proposal
    44  func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) (deposits types.Deposits) {
    45  	keeper.IterateDeposits(ctx, proposalID, func(deposit types.Deposit) bool {
    46  		deposits = append(deposits, deposit)
    47  		return false
    48  	})
    49  
    50  	return
    51  }
    52  
    53  // DeleteDeposits deletes all the deposits on a specific proposal without refunding them
    54  func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID uint64) {
    55  	store := ctx.KVStore(keeper.storeKey)
    56  
    57  	keeper.IterateDeposits(ctx, proposalID, func(deposit types.Deposit) bool {
    58  		err := keeper.bankKeeper.BurnCoins(ctx, types.ModuleName, deposit.Amount)
    59  		if err != nil {
    60  			panic(err)
    61  		}
    62  
    63  		depositor := sdk.MustAccAddressFromBech32(deposit.Depositor)
    64  
    65  		store.Delete(types.DepositKey(proposalID, depositor))
    66  		return false
    67  	})
    68  }
    69  
    70  // IterateAllDeposits iterates over the all the stored deposits and performs a callback function
    71  func (keeper Keeper) IterateAllDeposits(ctx sdk.Context, cb func(deposit types.Deposit) (stop bool)) {
    72  	store := ctx.KVStore(keeper.storeKey)
    73  	iterator := sdk.KVStorePrefixIterator(store, types.DepositsKeyPrefix)
    74  
    75  	defer iterator.Close()
    76  
    77  	for ; iterator.Valid(); iterator.Next() {
    78  		var deposit types.Deposit
    79  
    80  		keeper.cdc.MustUnmarshal(iterator.Value(), &deposit)
    81  
    82  		if cb(deposit) {
    83  			break
    84  		}
    85  	}
    86  }
    87  
    88  // IterateDeposits iterates over the all the proposals deposits and performs a callback function
    89  func (keeper Keeper) IterateDeposits(ctx sdk.Context, proposalID uint64, cb func(deposit types.Deposit) (stop bool)) {
    90  	store := ctx.KVStore(keeper.storeKey)
    91  	iterator := sdk.KVStorePrefixIterator(store, types.DepositsKey(proposalID))
    92  
    93  	defer iterator.Close()
    94  
    95  	for ; iterator.Valid(); iterator.Next() {
    96  		var deposit types.Deposit
    97  
    98  		keeper.cdc.MustUnmarshal(iterator.Value(), &deposit)
    99  
   100  		if cb(deposit) {
   101  			break
   102  		}
   103  	}
   104  }
   105  
   106  // AddDeposit adds or updates a deposit of a specific depositor on a specific proposal
   107  // Activates voting period when appropriate
   108  func (keeper Keeper) AddDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.Coins) (bool, error) {
   109  	// Checks to see if proposal exists
   110  	proposal, ok := keeper.GetProposal(ctx, proposalID)
   111  	if !ok {
   112  		return false, sdkerrors.Wrapf(types.ErrUnknownProposal, "%d", proposalID)
   113  	}
   114  
   115  	// Check if proposal is still depositable
   116  	if (proposal.Status != types.StatusDepositPeriod) && (proposal.Status != types.StatusVotingPeriod) {
   117  		return false, sdkerrors.Wrapf(types.ErrInactiveProposal, "%d", proposalID)
   118  	}
   119  
   120  	// update the governance module's account coins pool
   121  	err := keeper.bankKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositAmount)
   122  	if err != nil {
   123  		return false, err
   124  	}
   125  
   126  	// Update proposal
   127  	proposal.TotalDeposit = proposal.TotalDeposit.Add(depositAmount...)
   128  	keeper.SetProposal(ctx, proposal)
   129  
   130  	// Check if deposit has provided sufficient total funds to transition the proposal into the voting period
   131  	activatedVotingPeriod := false
   132  
   133  	if proposal.Status == types.StatusDepositPeriod && proposal.TotalDeposit.IsAllGTE(keeper.GetDepositParams(ctx).MinDeposit) {
   134  		keeper.ActivateVotingPeriod(ctx, proposal)
   135  
   136  		activatedVotingPeriod = true
   137  	}
   138  
   139  	// Add or update deposit object
   140  	deposit, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
   141  
   142  	if found {
   143  		deposit.Amount = deposit.Amount.Add(depositAmount...)
   144  	} else {
   145  		deposit = types.NewDeposit(proposalID, depositorAddr, depositAmount)
   146  	}
   147  
   148  	// called when deposit has been added to a proposal, however the proposal may not be active
   149  	keeper.AfterProposalDeposit(ctx, proposalID, depositorAddr)
   150  
   151  	ctx.EventManager().EmitEvent(
   152  		sdk.NewEvent(
   153  			types.EventTypeProposalDeposit,
   154  			sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.String()),
   155  			sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
   156  		),
   157  	)
   158  
   159  	keeper.SetDeposit(ctx, deposit)
   160  
   161  	return activatedVotingPeriod, nil
   162  }
   163  
   164  // RefundDeposits refunds and deletes all the deposits on a specific proposal
   165  func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID uint64) {
   166  	store := ctx.KVStore(keeper.storeKey)
   167  
   168  	keeper.IterateDeposits(ctx, proposalID, func(deposit types.Deposit) bool {
   169  		depositor := sdk.MustAccAddressFromBech32(deposit.Depositor)
   170  
   171  		err := keeper.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, depositor, deposit.Amount)
   172  		if err != nil {
   173  			panic(err)
   174  		}
   175  
   176  		store.Delete(types.DepositKey(proposalID, depositor))
   177  		return false
   178  	})
   179  }