Skip to content

Share checking of ValidateUnbondAmount has bug #6063

Open
@wangkui0508

Description

Summary of Bug

The checking logic in ValidateUnbondAmount is strange. It requires sharesTruncated <= delShares <= shares. At some corner cases, this requirement prevents me from unbonding all my shares.

Version

f1fdde5

Steps to Reproduce

Use the following Unit Test file:

package staking_test

import (
	"fmt"
	"testing"

	sdk "github.com/cosmos/cosmos-sdk/types"
	"github.com/cosmos/cosmos-sdk/x/staking/types"
)

func TestTokenAndShareCalc(t *testing.T) {
	validator := types.NewValidator(nil, PKs[0], types.Description{})
	// Due to slashing, this validator's DelegatorShares is 10000 but has only 5000 Tokens remained
	validator.DelegatorShares = sdk.NewDec(10000)
	validator.Tokens = sdk.NewInt(5000)

	//Suppose a delegator's share is 7 and she wants to unbond all of her share
	del := types.Delegation{Shares: sdk.NewDec(7)}

	//But no matter she sets the unbonding amount to 3 or 4, she has no way to successfully unbonds 7:
	shares, err := calcShares(validator, del, sdk.NewInt(3))
	fmt.Printf("%#v %#v\n", shares, err)
	//6.000000000000000000 <nil>
	shares, err = calcShares(validator, del, sdk.NewInt(4))
	fmt.Printf("%#v %#v\n", shares, err)
	//8.000000000000000000 &errors.Error{codespace:"staking", code:0x1e, desc:"invalid shares amount"}
}

// following lines are copied from ValidateUnbondAmount
func calcShares(validator types.Validator, del types.Delegation, amt sdk.Int) (shares sdk.Dec, err error) {
	shares, err = validator.SharesFromTokens(amt)
	if err != nil {
		return shares, err
	}

	sharesTruncated, err := validator.SharesFromTokensTruncated(amt)
	if err != nil {
		return shares, err
	}

	delShares := del.GetShares()
	if sharesTruncated.GT(delShares) {
		return shares, types.ErrBadSharesAmount
	}

	// Cap the shares at the delegation's shares. Shares being greater could occur
	// due to rounding, however we don't want to truncate the shares or take the
	// minimum because we want to allow for the full withdraw of shares from a
	// delegation.
	if shares.GT(delShares) {
		shares = delShares
	}

	return shares, nil
}

For Admin Use

  • Not duplicate issue
  • Appropriate labels applied
  • Appropriate contributors tagged
  • Contributor assigned/self-assigned

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    • Status

      📋 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions