Skip to content

Fatal coinIssue Bug in handleMsgIssue() #9

Description

@Jdkhnjggf

Describe The Bug
The crafted message of coin's issuance leads to an arbitrary coinIssue vulnerability of the asset handler located at /x/asset/handler.go. Specifically, the handleMsgIssue() routine is designed to handle the MsgIssueCoin message in order to issue a coin. However, the sanity checks on the input message are not thorough. As a result, a malicious MsgIssueCoin message which contains inconsistent creator , symbol and amount could lead to an arbitrary coinIssue behavior, causing huge asset losses to all users. In the following, we show the related code snippet.

Code Snippets (Optional)
handleMsgIssue() /x/asset/handler.go

// handleMsgIssue Handle Msg Issue coin
func handleMsgIssue(ctx chainTypes.Context, k keeper.AssetCoinsKeeper, msg *types.MsgIssueCoin) (*sdk.Result, error) {
	... ...
	ctx.RequireAccount(msgData.Creator)

	stat, err := k.GetCoinStat(ctx.Context(), msgData.Creator, msgData.Symbol)
	if err != nil {
		return nil, sdkerrors.Wrapf(err, "get coin stat from coin %s", msg.Amount.String())
	}

	// if coins cannot be issue, if there is 1000 blocks after coin created, no one can issue
	if !stat.CanIssue && (ctx.BlockHeight() > (stat.CreateHeight + 5)) { // FIXME: for test
		return nil, sdkerrors.Wrapf(types.ErrAssetCoinCannotBeLock, "coin %s cannot be issue after 1000 block from coin create", msg.Amount.String())
	}

	if err := k.Issue(ctx.Context(), msgData.Creator, msgData.Symbol, msgData.Amount); err != nil {
		return nil, sdkerrors.Wrapf(err, "msg issue coin %s", msgData.Symbol)
	}
        ... ...
}

Issue() /x/asset/keeper/keeper.go

func (a AssetKeeper) Issue(ctx sdk.Context, creator, symbol types.Name, amount types.Coin) error {
	if err := a.issueCoinStat(ctx, amount); err != nil {
		return err
	}

	creatorAccount := types.NewAccountIDFromName(creator)
	coins, err := a.getCoins(ctx, creatorAccount)
	if err != nil {
		return sdkerrors.Wrap(err, "get coins")
	}

	if err := a.setCoins(ctx, creatorAccount, coins.Add(amount)); err != nil {
		return sdkerrors.Wrap(err, "issue set coins")
	}

	return nil
}

Input/Output

  1. Craft a MsgIssueCoin : '{"creator": "kratos", "symbol": "kts", "amount": "100000kratos/kvs"}'
  2. Output : update state '{"newSupply": "100000kratos/kvs", "maxSupply": "1000000kratos/kvs", "limit": "1000000kratos/kvs"}'

To Reproduce
Steps to reproduce the behavior:

  1. Comment out that code in the client located at /x/asset/client/cli/issue.go (lines 52- 55)
  2. make
  3. sudo ./scripts/boot-testnet.sh
  4. sudo ./build/ktscli tx asset create kratos kvs 1000000kratos/kvs 1 1 10 1kratos/kvs "test" --
    keyring-backend test --chain-id testing --home /testing/cli/ --from kratos
  5. sudo ./build/ktscli tx asset issue kratos kts 100000kratos/kvs --keyring-backend test --chain-id
    testing --home /testing/cli/ --from kratos
  6. sudo ./build/ktscli query asset coins kratos

Expected Behavior
Returns an error "coin denom should equal %s != %s, chainTypes.CoinDenom(creator, symbol), amount.GetDenom()".

Screenshots
coinIssue

Desktop (please complete the following information):

  • OS: [macOS High Sierra 10.13.6]

Additional Context (Optional)
None

Contact Information

Email - ryzhang@peckshield.cn

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions