github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/staking/handler_shares.go (about)

     1  package staking
     2  
     3  import (
     4  	"time"
     5  
     6  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
     7  	"github.com/fibonacci-chain/fbc/x/staking/keeper"
     8  	"github.com/fibonacci-chain/fbc/x/staking/types"
     9  )
    10  
    11  func handleMsgBindProxy(ctx sdk.Context, msg types.MsgBindProxy, k keeper.Keeper) (*sdk.Result, error) {
    12  	delegator, found := k.GetDelegator(ctx, msg.DelAddr)
    13  
    14  	if !found || delegator.Tokens.IsZero() {
    15  		return types.ErrNoDelegationToAddShares(msg.DelAddr.String()).Result()
    16  	}
    17  
    18  	if !delegator.Shares.Equal(sdk.ZeroDec()) {
    19  		return types.ErrAlreadyAddedShares(delegator.DelegatorAddress.String()).Result()
    20  	}
    21  
    22  	// proxy must delegated
    23  	proxyDelegator, found := k.GetDelegator(ctx, msg.ProxyAddress)
    24  	if !found || proxyDelegator.Tokens.IsZero() {
    25  		return types.ErrProxyNotFound(msg.ProxyAddress.String()).Result()
    26  	}
    27  
    28  	// target delegator must reg as a proxy
    29  	if !proxyDelegator.IsProxy {
    30  		return types.ErrProxyNotFound(msg.ProxyAddress.String()).Result()
    31  	}
    32  
    33  	// double proxy is denied on fbchain
    34  	if delegator.IsProxy {
    35  		return types.ErrDoubleProxy(delegator.DelegatorAddress.String()).Result()
    36  	}
    37  
    38  	// same proxy, only update shares
    39  	if delegator.HasProxy() && delegator.ProxyAddress.Equals(proxyDelegator.DelegatorAddress) {
    40  		updateTokens := proxyDelegator.TotalDelegatedTokens.Add(proxyDelegator.Tokens)
    41  		if err := k.UpdateShares(ctx, proxyDelegator.DelegatorAddress, updateTokens); err != nil {
    42  			return types.ErrInvalidDelegation(proxyDelegator.DelegatorAddress.String()).Result()
    43  		}
    44  		return &sdk.Result{Events: ctx.EventManager().Events()}, nil
    45  	}
    46  
    47  	// unbind from the original proxy
    48  	if len(delegator.ProxyAddress) != 0 {
    49  		if sdkErr := unbindProxy(ctx, delegator.DelegatorAddress, k); sdkErr != nil {
    50  			return nil, sdkErr
    51  		}
    52  	}
    53  
    54  	// bind proxy relationship
    55  	delegator.BindProxy(msg.ProxyAddress)
    56  
    57  	// update proxy's shares weight
    58  	proxyDelegator.TotalDelegatedTokens = proxyDelegator.TotalDelegatedTokens.Add(delegator.Tokens)
    59  
    60  	k.SetDelegator(ctx, delegator)
    61  	k.SetDelegator(ctx, proxyDelegator)
    62  	k.SetProxyBinding(ctx, proxyDelegator.DelegatorAddress, delegator.DelegatorAddress, false)
    63  
    64  	finalTokens := proxyDelegator.TotalDelegatedTokens.Add(proxyDelegator.Tokens)
    65  
    66  	if err := k.UpdateShares(ctx, proxyDelegator.DelegatorAddress, finalTokens); err != nil {
    67  		return types.ErrInvalidDelegation(proxyDelegator.DelegatorAddress.String()).Result()
    68  	}
    69  
    70  	return &sdk.Result{Events: ctx.EventManager().Events()}, nil
    71  }
    72  
    73  func unbindProxy(ctx sdk.Context, delAddr sdk.AccAddress, k keeper.Keeper) error {
    74  	delegator, found := k.GetDelegator(ctx, delAddr)
    75  	if !found {
    76  		return types.ErrNoDelegationToAddShares(delAddr.String())
    77  	}
    78  
    79  	proxyDelegator, found := k.GetDelegator(ctx, delegator.ProxyAddress)
    80  	if !found {
    81  		return types.ErrProxyNotFound(delAddr.String())
    82  	}
    83  
    84  	// update proxy's shares weight
    85  	if k.UpdateProxy(ctx, delegator, delegator.Tokens.Mul(sdk.NewDec(-1))) != nil {
    86  		return types.ErrInvalidDelegation(delAddr.String())
    87  	}
    88  	// unbind proxy relationship
    89  	delegator.UnbindProxy()
    90  	k.SetDelegator(ctx, delegator)
    91  	k.SetProxyBinding(ctx, proxyDelegator.DelegatorAddress, delegator.DelegatorAddress, true)
    92  
    93  	return nil
    94  }
    95  
    96  func handleMsgUnbindProxy(ctx sdk.Context, msg types.MsgUnbindProxy, k keeper.Keeper) (*sdk.Result, error) {
    97  	if sdkErr := unbindProxy(ctx, msg.DelAddr, k); sdkErr != nil {
    98  		return nil, sdkErr
    99  	}
   100  
   101  	return &sdk.Result{Events: ctx.EventManager().Events()}, nil
   102  }
   103  
   104  func regProxy(ctx sdk.Context, proxyAddr sdk.AccAddress, k keeper.Keeper) (*sdk.Result, error) {
   105  	// check status
   106  	proxy, found := k.GetDelegator(ctx, proxyAddr)
   107  	if !found {
   108  		return types.ErrNoDelegationToAddShares(proxyAddr.String()).Result()
   109  	}
   110  	if proxy.IsProxy {
   111  		return types.ErrProxyAlreadyExist(proxyAddr.String()).Result()
   112  	}
   113  	if len(proxy.ProxyAddress) != 0 {
   114  		return types.ErrAlreadyBound(proxyAddr.String()).Result()
   115  	}
   116  
   117  	proxy.RegProxy(true)
   118  	k.SetDelegator(ctx, proxy)
   119  
   120  	if k.UpdateShares(ctx, proxy.DelegatorAddress, proxy.Tokens) != nil {
   121  		return types.ErrInvalidDelegation(proxy.DelegatorAddress.String()).Result()
   122  	}
   123  
   124  	return &sdk.Result{Events: ctx.EventManager().Events()}, nil
   125  
   126  }
   127  
   128  func unregProxy(ctx sdk.Context, proxyAddr sdk.AccAddress, k keeper.Keeper) (*sdk.Result, error) {
   129  	// check status
   130  	proxy, found := k.GetDelegator(ctx, proxyAddr)
   131  	if !found {
   132  		return types.ErrProxyNotFound(proxyAddr.String()).Result()
   133  	}
   134  
   135  	if !proxy.IsProxy {
   136  		return types.ErrProxyNotFound(proxyAddr.String()).Result()
   137  	}
   138  
   139  	proxy.RegProxy(false)
   140  	// unreg action, we need to erase all proxy relationship
   141  	proxy.TotalDelegatedTokens = sdk.ZeroDec()
   142  	k.ClearProxy(ctx, proxy.DelegatorAddress)
   143  	k.SetDelegator(ctx, proxy)
   144  
   145  	if k.UpdateShares(ctx, proxy.DelegatorAddress, proxy.Tokens) != nil {
   146  		return types.ErrInvalidDelegation(proxy.DelegatorAddress.String()).Result()
   147  	}
   148  
   149  	return &sdk.Result{Events: ctx.EventManager().Events()}, nil
   150  
   151  }
   152  
   153  func handleRegProxy(ctx sdk.Context, msg types.MsgRegProxy, k keeper.Keeper) (*sdk.Result, error) {
   154  	if msg.Reg {
   155  		return regProxy(ctx, msg.ProxyAddress, k)
   156  	}
   157  
   158  	return unregProxy(ctx, msg.ProxyAddress, k)
   159  }
   160  
   161  func handleMsgAddShares(ctx sdk.Context, msg types.MsgAddShares, k keeper.Keeper) (*sdk.Result, error) {
   162  	maxValsToAddShares := int(k.ParamsMaxValsToAddShares(ctx))
   163  	if len(msg.ValAddrs) == 0 {
   164  		return nil, types.ErrEmptyValidators()
   165  	} else if len(msg.ValAddrs) > maxValsToAddShares {
   166  		return types.ErrExceedValidatorAddrs(maxValsToAddShares).Result()
   167  	}
   168  
   169  	// 0. check whether the delegator has delegation
   170  	delegator, found := k.GetDelegator(ctx, msg.DelAddr)
   171  	if !found || delegator.Tokens.IsZero() {
   172  		return types.ErrNoDelegationToAddShares(msg.DelAddr.String()).Result()
   173  	}
   174  	if delegator.HasProxy() {
   175  		return types.ErrAddSharesDuringProxy(delegator.DelegatorAddress.String(),
   176  			delegator.ProxyAddress.String()).Result()
   177  	}
   178  
   179  	// 1. get last validators which were added shares to and existing in the store
   180  	lastVals, lastShares := k.GetLastValsAddedSharesExisted(ctx, msg.DelAddr)
   181  
   182  	// 2. withdraw the shares last time
   183  	k.WithdrawLastShares(ctx, msg.DelAddr, lastVals, lastShares)
   184  
   185  	// 3. get validators to add shares this time (if the validator doesn't exist, return error)
   186  	vals, sdkErr := k.GetValidatorsToAddShares(ctx, msg.ValAddrs)
   187  	if sdkErr != nil {
   188  		return nil, sdkErr
   189  	}
   190  	if sdkErr = validateSharesAdding(vals); sdkErr != nil {
   191  		return nil, sdkErr
   192  	}
   193  
   194  	// 4. get the total amount of self token and delegated token
   195  	totalTokens := delegator.Tokens.Add(delegator.TotalDelegatedTokens)
   196  
   197  	// 4.1 increment validators period
   198  	delegatorValAddresses := getValsAddrs(vals)
   199  	k.BeforeDelegationCreated(ctx, msg.DelAddr, delegatorValAddresses)
   200  
   201  	// 5. add shares to the vals this time
   202  	shares, sdkErr := k.AddSharesToValidators(ctx, msg.DelAddr, vals, totalTokens)
   203  	if sdkErr != nil {
   204  		return nil, sdkErr
   205  	}
   206  
   207  	// 6. update the delegator entity for this time
   208  	delegator.ValidatorAddresses = delegatorValAddresses
   209  	delegator.Shares = shares
   210  	k.SetDelegator(ctx, delegator)
   211  
   212  	// 7. create new delegator starting info
   213  	k.AfterDelegationModified(ctx, msg.DelAddr, delegator.ValidatorAddresses)
   214  
   215  	ctx.EventManager().EmitEvent(buildEventForHandlerAddShares(delegator))
   216  	return &sdk.Result{Events: ctx.EventManager().Events()}, nil
   217  }
   218  
   219  // validateSharesAdding gives a quick validity of target validators before shares adding
   220  func validateSharesAdding(vals types.Validators) error {
   221  	if len(vals) == 0 {
   222  		return types.ErrEmptyValidators()
   223  	}
   224  
   225  	if valAddr, ok := isDismissed(vals); ok {
   226  		return types.ErrAddSharesToDismission(valAddr.String())
   227  	}
   228  
   229  	return nil
   230  }
   231  
   232  // isDismissed tells whether validator with zero-msd is among the shares adding targets and returns the first dismissed
   233  // validator address
   234  func isDismissed(vals types.Validators) (sdk.ValAddress, bool) {
   235  	valsLen := len(vals)
   236  	for i := 0; i < valsLen; i++ {
   237  		if vals[i].MinSelfDelegation.IsZero() {
   238  			return vals[i].OperatorAddress, true
   239  		}
   240  	}
   241  
   242  	return nil, false
   243  }
   244  
   245  // getValsAddrs gets validator addresses from a set of validator's entities
   246  func getValsAddrs(vals types.Validators) []sdk.ValAddress {
   247  	lenVals := len(vals)
   248  	valAddrs := make([]sdk.ValAddress, lenVals)
   249  	for i := 0; i < lenVals; i++ {
   250  		valAddrs[i] = vals[i].OperatorAddress
   251  	}
   252  	return valAddrs
   253  }
   254  
   255  func buildEventForHandlerAddShares(delegator types.Delegator) sdk.Event {
   256  	lenAttributes := len(delegator.ValidatorAddresses) + 2
   257  	attributes := make([]sdk.Attribute, lenAttributes)
   258  	attributes[0] = sdk.NewAttribute(types.AttributeKeyDelegator, delegator.DelegatorAddress.String())
   259  	attributes[1] = sdk.NewAttribute(types.AttributeKeyShares, delegator.Shares.String())
   260  	for i := 2; i < lenAttributes; i++ {
   261  		attributes[i] = sdk.NewAttribute(types.AttributeKeyValidatorToAddShares, delegator.ValidatorAddresses[i-2].String())
   262  	}
   263  
   264  	return sdk.NewEvent(types.EventTypeAddShares, attributes...)
   265  }
   266  
   267  func handleMsgDeposit(ctx sdk.Context, msg types.MsgDeposit, k keeper.Keeper) (*sdk.Result, error) {
   268  	if msg.Amount.Denom != k.BondDenom(ctx) {
   269  		return ErrBadDenom().Result()
   270  	}
   271  
   272  	err := k.Delegate(ctx, msg.DelegatorAddress, msg.Amount)
   273  	if err != nil {
   274  		return nil, err
   275  	}
   276  
   277  	ctx.EventManager().EmitEvents(sdk.Events{
   278  		sdk.NewEvent(
   279  			types.EventTypeDelegate,
   280  			sdk.NewAttribute(types.AttributeKeyValidator, msg.DelegatorAddress.String()),
   281  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
   282  		),
   283  	})
   284  	return &sdk.Result{Events: ctx.EventManager().Events()}, nil
   285  }
   286  
   287  func handleMsgWithdraw(ctx sdk.Context, msg types.MsgWithdraw, k keeper.Keeper) (*sdk.Result, error) {
   288  	if msg.Amount.Denom != k.BondDenom(ctx) {
   289  		return ErrBadDenom().Result()
   290  	}
   291  
   292  	completionTime, err := k.Withdraw(ctx, msg.DelegatorAddress, msg.Amount)
   293  	if err != nil {
   294  		return nil, err
   295  	}
   296  
   297  	ctx.EventManager().EmitEvents(sdk.Events{
   298  		sdk.NewEvent(
   299  			types.EventTypeUnbond,
   300  			sdk.NewAttribute(sdk.AttributeKeySender, msg.DelegatorAddress.String()),
   301  			sdk.NewAttribute(sdk.AttributeKeyAmount, msg.Amount.String()),
   302  			sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
   303  		),
   304  	})
   305  	completionTimeBz := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime)
   306  	return &sdk.Result{Data: completionTimeBz, Events: ctx.EventManager().Events()}, nil
   307  }
   308  
   309  func handleMsgDestroyValidator(ctx sdk.Context, msg types.MsgDestroyValidator, k keeper.Keeper) (*sdk.Result, error) {
   310  	valAddr := sdk.ValAddress(msg.DelAddr)
   311  	// 0.check to see if the validator which belongs to the delegator exists
   312  	validator, found := k.GetValidator(ctx, valAddr)
   313  	if !found {
   314  		return ErrNoValidatorFound(valAddr.String()).Result()
   315  	}
   316  
   317  	completionTime, sdkErr := k.WithdrawMinSelfDelegation(ctx, msg.DelAddr, validator)
   318  	if sdkErr != nil {
   319  		return nil, sdkErr
   320  	}
   321  
   322  	ctx.EventManager().EmitEvents(sdk.Events{
   323  		sdk.NewEvent(
   324  			types.EventTypeUnbond,
   325  			sdk.NewAttribute(sdk.AttributeKeySender, msg.DelAddr.String()),
   326  			sdk.NewAttribute(sdk.AttributeKeyAmount, validator.GetMinSelfDelegation().String()),
   327  			sdk.NewAttribute(types.AttributeKeyCompletionTime, completionTime.Format(time.RFC3339)),
   328  		),
   329  	})
   330  
   331  	completionTimeBytes := types.ModuleCdc.MustMarshalBinaryLengthPrefixed(completionTime)
   332  	return &sdk.Result{Data: completionTimeBytes, Events: ctx.EventManager().Events()}, nil
   333  
   334  }