github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/gov/keeper/deposit.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     6  	"github.com/fibonacci-chain/fbc/x/gov/types"
     7  )
     8  
     9  // SetDeposit sets the deposit of a specific depositor on a specific proposal
    10  func (keeper Keeper) SetDeposit(ctx sdk.Context, deposit types.Deposit) {
    11  	store := ctx.KVStore(keeper.storeKey)
    12  	bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
    13  	store.Set(types.DepositKey(deposit.ProposalID, deposit.Depositor), bz)
    14  }
    15  
    16  func tryEnterVotingPeriod(
    17  	ctx sdk.Context, keeper Keeper, proposal *types.Proposal, depositAmount sdk.SysCoins, eventType string,
    18  ) {
    19  	// Update proposal
    20  	proposal.TotalDeposit = proposal.TotalDeposit.Add(depositAmount...)
    21  	// Check if deposit has provided sufficient total funds to transition the proposal into the voting period
    22  	activatedVotingPeriod := false
    23  	var minDeposit sdk.SysCoins
    24  	if !keeper.proposalHandlerRouter.HasRoute(proposal.ProposalRoute()) {
    25  		minDeposit = keeper.GetDepositParams(ctx).MinDeposit
    26  	} else {
    27  		phr := keeper.proposalHandlerRouter.GetRoute(proposal.ProposalRoute())
    28  		minDeposit = phr.GetMinDeposit(ctx, proposal.Content)
    29  	}
    30  
    31  	if proposal.Status == types.StatusDepositPeriod && proposal.TotalDeposit.IsAllGTE(minDeposit) {
    32  		keeper.activateVotingPeriod(ctx, proposal)
    33  		activatedVotingPeriod = true
    34  		proposal.DepositEndTime = ctx.BlockHeader().Time
    35  	}
    36  	keeper.SetProposal(ctx, *proposal)
    37  
    38  	if activatedVotingPeriod {
    39  		// execute the logic when the deposit period is passed
    40  		if !keeper.ProposalHandlerRouter().HasRoute(proposal.Content.ProposalRoute()) {
    41  			keeper.AfterDepositPeriodPassed(ctx, *proposal)
    42  		} else {
    43  			proposalHandler := keeper.ProposalHandlerRouter().GetRoute(proposal.Content.ProposalRoute())
    44  			proposalHandler.AfterDepositPeriodPassed(ctx, *proposal)
    45  		}
    46  
    47  		ctx.EventManager().EmitEvent(
    48  			sdk.NewEvent(
    49  				eventType,
    50  				sdk.NewAttribute(types.AttributeKeyVotingPeriodStart, fmt.Sprintf("%d", proposal.ProposalID)),
    51  			),
    52  		)
    53  	}
    54  }
    55  
    56  func updateDeposit(
    57  	ctx sdk.Context, keeper Keeper, proposalID uint64, depositorAddr sdk.AccAddress, depositAmount sdk.SysCoins,
    58  ) {
    59  	deposit, found := keeper.GetDeposit(ctx, proposalID, depositorAddr)
    60  	if found {
    61  		deposit.Amount = deposit.Amount.Add(depositAmount...)
    62  	} else {
    63  		deposit = types.Deposit{
    64  			ProposalID: proposalID,
    65  			Depositor:  depositorAddr,
    66  			Amount:     depositAmount,
    67  		}
    68  	}
    69  	keeper.SetDeposit(ctx, deposit)
    70  }
    71  
    72  // AddDeposit adds or updates a deposit of a specific depositor on a specific proposal
    73  // Activates voting period when appropriate
    74  func (keeper Keeper) AddDeposit(
    75  	ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress,
    76  	depositAmount sdk.SysCoins, eventType string,
    77  ) sdk.Error {
    78  	// Checks to see if proposal exists
    79  	proposal, ok := keeper.GetProposal(ctx, proposalID)
    80  	if !ok {
    81  		return types.ErrUnknownProposal(proposalID)
    82  	}
    83  
    84  	// Check if proposal is still depositable
    85  	if proposal.Status != types.StatusDepositPeriod {
    86  		return types.ErrInvalidateProposalStatus()
    87  	}
    88  	depositCoinsAmount := depositAmount
    89  	// update the governance module's account coins pool
    90  	err := keeper.supplyKeeper.SendCoinsFromAccountToModule(ctx, depositorAddr, types.ModuleName, depositCoinsAmount)
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	// try enter voting period according to proposal's total deposit
    96  	tryEnterVotingPeriod(ctx, keeper, &proposal, depositAmount, eventType)
    97  
    98  	// Add or update deposit object
    99  	updateDeposit(ctx, keeper, proposalID, depositorAddr, depositAmount)
   100  
   101  	ctx.EventManager().EmitEvent(
   102  		sdk.NewEvent(
   103  			types.EventTypeProposalDeposit,
   104  			sdk.NewAttribute(sdk.AttributeKeyAmount, depositAmount.String()),
   105  			sdk.NewAttribute(types.AttributeKeyProposalID, fmt.Sprintf("%d", proposalID)),
   106  		),
   107  	)
   108  
   109  	return nil
   110  }
   111  
   112  // RefundDeposits refunds and deletes all the deposits on a specific proposal
   113  func (keeper Keeper) RefundDeposits(ctx sdk.Context, proposalID uint64) {
   114  	deposits := keeper.GetDeposits(ctx, proposalID)
   115  	for i := 0; i < len(deposits); i++ {
   116  		deposit := deposits[i]
   117  		err := keeper.supplyKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, deposit.Depositor,
   118  			deposit.Amount)
   119  		if err != nil {
   120  			panic(err)
   121  		}
   122  		keeper.deleteDeposit(ctx, proposalID, deposit.Depositor)
   123  	}
   124  }
   125  
   126  // DistributeDeposits distributes and deletes all the deposits on a specific proposal
   127  func (keeper Keeper) DistributeDeposits(ctx sdk.Context, proposalID uint64) {
   128  	deposits := keeper.GetDeposits(ctx, proposalID)
   129  	for i := 0; i < len(deposits); i++ {
   130  		deposit := deposits[i]
   131  		err := keeper.supplyKeeper.SendCoinsFromModuleToModule(ctx, types.ModuleName, keeper.feeCollectorName,
   132  			deposit.Amount)
   133  		if err != nil {
   134  			panic(err)
   135  		}
   136  		keeper.deleteDeposit(ctx, proposalID, deposit.Depositor)
   137  	}
   138  }
   139  
   140  func (keeper Keeper) deleteDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) {
   141  	store := ctx.KVStore(keeper.storeKey)
   142  	store.Delete(types.DepositKey(proposalID, depositorAddr))
   143  }
   144  
   145  // GetDeposit gets the deposit of a specific depositor on a specific proposal
   146  func (keeper Keeper) GetDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress) (deposit types.Deposit, found bool) {
   147  	store := ctx.KVStore(keeper.storeKey)
   148  	bz := store.Get(types.DepositKey(proposalID, depositorAddr))
   149  	if bz == nil {
   150  		return deposit, false
   151  	}
   152  
   153  	keeper.cdc.MustUnmarshalBinaryLengthPrefixed(bz, &deposit)
   154  	return deposit, true
   155  }
   156  
   157  func (keeper Keeper) setDeposit(ctx sdk.Context, proposalID uint64, depositorAddr sdk.AccAddress, deposit types.Deposit) {
   158  	store := ctx.KVStore(keeper.storeKey)
   159  	bz := keeper.cdc.MustMarshalBinaryLengthPrefixed(deposit)
   160  	store.Set(types.DepositKey(proposalID, depositorAddr), bz)
   161  }
   162  
   163  // GetAllDeposits returns all the deposits from the store
   164  func (keeper Keeper) GetAllDeposits(ctx sdk.Context) (deposits types.Deposits) {
   165  	keeper.IterateAllDeposits(ctx, func(deposit types.Deposit) bool {
   166  		deposits = append(deposits, deposit)
   167  		return false
   168  	})
   169  	return
   170  }
   171  
   172  // GetDeposits returns all the deposits from a proposal
   173  func (keeper Keeper) GetDeposits(ctx sdk.Context, proposalID uint64) (deposits types.Deposits) {
   174  	keeper.IterateDeposits(ctx, proposalID, func(deposit types.Deposit) bool {
   175  		deposits = append(deposits, deposit)
   176  		return false
   177  	})
   178  	return
   179  }
   180  
   181  // GetDepositsIterator gets all the deposits on a specific proposal as an sdk.Iterator
   182  func (keeper Keeper) GetDepositsIterator(ctx sdk.Context, proposalID uint64) sdk.Iterator {
   183  	store := ctx.KVStore(keeper.storeKey)
   184  	return sdk.KVStorePrefixIterator(store, types.DepositsKey(proposalID))
   185  }
   186  
   187  // DeleteDeposits deletes all the deposits on a specific proposal without refunding them
   188  func (keeper Keeper) DeleteDeposits(ctx sdk.Context, proposalID uint64) {
   189  	store := ctx.KVStore(keeper.storeKey)
   190  
   191  	keeper.IterateDeposits(ctx, proposalID, func(deposit types.Deposit) bool {
   192  		err := keeper.supplyKeeper.BurnCoins(ctx, types.ModuleName, deposit.Amount)
   193  		if err != nil {
   194  			panic(err)
   195  		}
   196  
   197  		store.Delete(types.DepositKey(proposalID, deposit.Depositor))
   198  		return false
   199  	})
   200  }