Assessment reports>Initia>High findings>Move coins can be burned twice
Category: Coding Mistakes

Move coins can be burned twice

High Severity
Medium Impact
Medium Likelihood

Description

The BurnCoins method has special handling for Move coins not generated by 0x1 as they do not have the burn capability for them. Instead, they are sent to the community pool.

// BurnCoins burn coins or send to community pool.
func (k MoveBankKeeper) BurnCoins(
    ctx context.Context,
    accAddr sdk.AccAddress,
    coins sdk.Coins,
) error {
    for _, coin := range coins {
        // if a coin is not generated from 0x1, then send the coin to community pool
        // because we don't have burn capability.
        if types.IsMoveCoin(coin) {
            if err := k.communityPoolKeeper.FundCommunityPool(ctx, coins, accAddr); err != nil {
                return err
            }

            continue
        }
        // send tokens to 0x1
        err := k.SendCoin(ctx, accAddr, types.StdAddr, coin.Denom, coin.Amount)
        if err != nil {
            return err
        }
        // execute burn
        metadata, err := types.MetadataAddressFromDenom(coin.Denom)
        if err != nil {
            return err
        }

The issue is that the coins parameter is passed to FundCommunityPool, which contains every coin instead of only the coin that matched the condition.

Impact

If one of the coins returns true for types.IsMoveCoin(coin), then all the coins are sent to FundCommunityPool, not just the matching one. Then, the next iteration will send the coins again to 0x1 to be burned. If two Move coins are provided, then double of each will be sent to the fund. If one is Move and the other is not, then the other coin will be sent to the fund as well as burned.

Recommendations

Only the matching coin should be sent to the community pool.

Remediation

Zellic © 2024Back to top ↑