github.com/KiraCore/sekai@v0.3.43/x/layer2/keeper/abci.go (about)

     1  package keeper
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/KiraCore/sekai/x/layer2/types"
     7  	spendingtypes "github.com/KiraCore/sekai/x/spending/types"
     8  	sdk "github.com/cosmos/cosmos-sdk/types"
     9  )
    10  
    11  func (k Keeper) BeginBlocker(ctx sdk.Context) {
    12  
    13  }
    14  
    15  func (k Keeper) EndBlocker(ctx sdk.Context) {
    16  	dapps := k.GetAllDapps(ctx)
    17  	properties := k.gk.GetNetworkProperties(ctx)
    18  	currTimestamp := uint64(ctx.BlockTime().Unix())
    19  	for _, dapp := range dapps {
    20  		if dapp.Status == types.Bootstrap && dapp.CreationTime+properties.DappBondDuration <= currTimestamp {
    21  			k.FinishDappBootstrap(ctx, dapp)
    22  		}
    23  
    24  		if dapp.PremintTime+dapp.Pool.Drip < uint64(ctx.BlockTime().Unix()) &&
    25  			dapp.Issurance.Postmint.IsPositive() &&
    26  			dapp.Status == types.Active {
    27  			teamReserve := sdk.MustAccAddressFromBech32(dapp.TeamReserve)
    28  			dappBondLpToken := dapp.LpToken()
    29  			premintCoin := sdk.NewCoin(dappBondLpToken, dapp.Issurance.Premint)
    30  			err := k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, teamReserve, sdk.Coins{premintCoin})
    31  			if err != nil {
    32  				panic(err)
    33  			}
    34  			dapp.PostMintPaid = true
    35  			k.SetDapp(ctx, dapp)
    36  		}
    37  
    38  		if dapp.Status == types.Active {
    39  			session := k.GetDappSession(ctx, dapp.Name)
    40  			// session not started yet during denounce time
    41  			if session.NextSession != nil &&
    42  				session.NextSession.Start+properties.DappAutoDenounceTime <= currTimestamp &&
    43  				session.NextSession.Status == types.SessionScheduled {
    44  				operator := k.GetDappOperator(ctx, dapp.Name, session.NextSession.Leader)
    45  				operator.Status = types.OperatorJailed
    46  				k.SetDappOperator(ctx, operator)
    47  
    48  				// update next session with new info
    49  				k.ResetNewSession(ctx, dapp.Name, session.CurrSession.Leader)
    50  			}
    51  
    52  			// If the KEX collateral in the pool falls below dapp_liquidation_threshold (by default set to 100’000 KEX)
    53  			// then the dApp will enter a depreciation phase lasting dapp_liquidation_period (by default set to 2419200, that is ~28d)
    54  			// after which the execution will be stopped.
    55  			if dapp.LiquidationStart+properties.DappLiquidationPeriod < uint64(ctx.BlockTime().Unix()) {
    56  				dapp.Status = types.Halted
    57  				k.SetDapp(ctx, dapp)
    58  			}
    59  		}
    60  	}
    61  
    62  	// handle bridge xam time outs
    63  	for _, xam := range k.GetXAMs(ctx) {
    64  		if xam.Req.SourceDapp != 0 && xam.Res.Src == 0 {
    65  			account := k.GetBridgeAccount(ctx, xam.Req.SourceDapp)
    66  			dapp := k.GetDapp(ctx, account.DappName)
    67  			if xam.ReqTime+2*dapp.UpdateTimeMax < uint64(ctx.BlockTime().Unix()) {
    68  				xam.Res.Src = 498
    69  				k.SetXAM(ctx, xam)
    70  			}
    71  		}
    72  
    73  		if xam.Req.DestDapp != 0 && xam.Res.Drc == 0 {
    74  			account := k.GetBridgeAccount(ctx, xam.Req.DestDapp)
    75  			dapp := k.GetDapp(ctx, account.DappName)
    76  			if xam.ReqTime+2*dapp.UpdateTimeMax < uint64(ctx.BlockTime().Unix()) {
    77  				xam.Res.Drc = 498
    78  				k.SetXAM(ctx, xam)
    79  			}
    80  		}
    81  	}
    82  	// - **Deposit** funds from personal account (source application `src == 0`) to destination `dst` application beneficiary `ben` address.
    83  	//     - Deposit must be accepted by the `dst` application or funds returned back to the user kira account outside of ABR
    84  	//     - Max time for accepting deposit is `max(2 blocks,  2 * update_time_max<DstApp>)` after which transaction must fail (internal response `irc` code `522`)
    85  	// - **Transfer** funds from the source `src` application account `acc` address to another destination `dst` application beneficiary `ben` address
    86  	//     - Withdrawal from `src` application must be permissionless, the source `src` app does not need to confirm it but can speed it up by setting source response `src` code to `200`
    87  	//     - Deposit to destination `dst` app must be accepted by the `dst` app with destination app response code `drc` set to `200` or funds **returned through deposit like process**
    88  	//     - If Deposit fails to `dst` fails then `src` must accept the re-deposit otherwise if re-deposit fails the funds must be returned to the kira account outside of ABR
    89  	//     - Max time for accepting withdrawal by `src` app must be `max(2 blocks,  2 * update_time_max<SrcApp>)` otherwise the withdrawal must automatically succeed
    90  	//     - Max time for accepting deposit by `dst` app must be `max(2 blocks,  2 * update_time_max<DstApp>)` otherwise the deposit must automatically fail with internal response `irc` code set to `522`
    91  	//     - If redeposit must be executed the new transaction must be created with new `xid`. Rules for re-deposit are same as for the deposit (if re-deposit fails funds must be returned to kira address outside of ABR)
    92  	// - **Withdrawal** funds from the source `src` application account `acc` address to kira address outside the ABR (`dst == 0`) to beneficiary `ben` address
    93  	//     - Withdrawal from `src` application must be permissionless, the source `src` app does not need to confirm it but can speed it up by setting source response `src` code to `200`
    94  	//     - Max time for accepting withdrawal by `src` app must be `max(2 blocks,  2 * update_time_max<SrcApp>)` otherwise the withdrawal must automatically succeed
    95  
    96  }
    97  
    98  func (k Keeper) FinishDappBootstrap(ctx sdk.Context, dapp types.Dapp) {
    99  	properties := k.gk.GetNetworkProperties(ctx)
   100  	minDappBond := sdk.NewInt(int64(properties.MinDappBond)).Mul(sdk.NewInt(1000_000))
   101  	if dapp.TotalBond.Amount.LT(minDappBond) {
   102  		cacheCtx, write := ctx.CacheContext()
   103  		err := k.ExecuteDappRemove(cacheCtx, dapp)
   104  		if err == nil {
   105  			write()
   106  		}
   107  	} else {
   108  		userBonds := k.GetUserDappBonds(ctx, dapp.Name)
   109  		beneficiaries := []spendingtypes.WeightedAccount{}
   110  		for _, userBond := range userBonds {
   111  			beneficiaries = append(beneficiaries, spendingtypes.WeightedAccount{
   112  				Account: userBond.User,
   113  				Weight:  userBond.Bond.Amount.ToLegacyDec(),
   114  			})
   115  		}
   116  
   117  		dappBondLpToken := dapp.LpToken()
   118  		err := sdk.ValidateDenom(dappBondLpToken)
   119  		if err != nil {
   120  			return
   121  		}
   122  
   123  		spendingPoolDeposit := dapp.GetSpendingPoolLpDeposit()
   124  		totalSupply := dapp.GetLpTokenSupply()
   125  		drip := dapp.Pool.Drip
   126  		if drip == 0 {
   127  			drip = 1
   128  		}
   129  		rate := sdk.NewDecFromInt(spendingPoolDeposit).Quo(sdk.NewDec(int64(drip)))
   130  		err = k.bk.MintCoins(ctx, types.ModuleName, sdk.Coins{sdk.NewCoin(dappBondLpToken, totalSupply)})
   131  		if err != nil {
   132  			panic(err)
   133  		}
   134  
   135  		cacheCtx, write := ctx.CacheContext()
   136  		blockTime := uint64(ctx.BlockTime().Unix())
   137  		spendingPoolName := fmt.Sprintf("dp_%s", dapp.Name)
   138  		err = k.spk.CreateSpendingPool(cacheCtx, spendingtypes.SpendingPool{
   139  			Name:          spendingPoolName,
   140  			ClaimStart:    blockTime,
   141  			ClaimEnd:      blockTime + drip,
   142  			Rates:         sdk.NewDecCoins(sdk.NewDecCoinFromDec(dappBondLpToken, rate)),
   143  			VoteQuorum:    dapp.VoteQuorum,
   144  			VotePeriod:    dapp.VotePeriod,
   145  			VoteEnactment: dapp.VoteEnactment,
   146  			Owners: &spendingtypes.PermInfo{
   147  				OwnerRoles:    dapp.Controllers.Whitelist.Roles,
   148  				OwnerAccounts: dapp.Controllers.Whitelist.Addresses,
   149  			},
   150  			Beneficiaries: &spendingtypes.WeightedPermInfo{
   151  				Accounts: beneficiaries,
   152  			},
   153  			Balances:                []sdk.Coin{},
   154  			DynamicRate:             false,
   155  			DynamicRatePeriod:       0,
   156  			LastDynamicRateCalcTime: 0,
   157  		})
   158  		if err == nil {
   159  			write()
   160  		}
   161  
   162  		cacheCtx, write = ctx.CacheContext()
   163  		coin := sdk.NewCoin(dappBondLpToken, spendingPoolDeposit)
   164  		err = k.spk.DepositSpendingPoolFromModule(cacheCtx, types.ModuleName, spendingPoolName, sdk.Coins{coin})
   165  		if err == nil {
   166  			write()
   167  		}
   168  
   169  		dapp.Status = types.Halted
   170  		dapp.Pool.Deposit = spendingPoolName
   171  		dapp.PremintTime = blockTime
   172  		k.SetDapp(ctx, dapp)
   173  
   174  		// register bridge account for dapp
   175  		helper := k.GetBridgeRegistrarHelper(ctx)
   176  		k.SetBridgeAccount(ctx, types.BridgeAccount{
   177  			Index:    helper.NextUser,
   178  			Address:  dapp.GetAccount().String(),
   179  			DappName: dapp.Name,
   180  			Balances: []types.BridgeBalance{},
   181  		})
   182  		helper.NextUser += 1
   183  		k.SetBridgeRegistrarHelper(ctx, helper)
   184  
   185  		for _, userBond := range userBonds {
   186  			k.DeleteUserDappBond(ctx, dapp.Name, userBond.User)
   187  		}
   188  
   189  		// send premint amount to team reserve
   190  		if dapp.Issurance.Premint.IsPositive() {
   191  			teamReserve := sdk.MustAccAddressFromBech32(dapp.TeamReserve)
   192  			premintCoin := sdk.NewCoin(dappBondLpToken, dapp.Issurance.Premint)
   193  			err = k.bk.SendCoinsFromModuleToAccount(ctx, types.ModuleName, teamReserve, sdk.Coins{premintCoin})
   194  			if err != nil {
   195  				panic(err)
   196  			}
   197  		}
   198  	}
   199  }