Assessment reports>Initia>High findings>Frozen module coin store can cause chain halt
Category: Coding Mistakes

Frozen module coin store can cause chain halt

High Severity
High Impact
High Likelihood

Description

The AllocateTokens function is called by the distributions module before each block in the BeginBlocker handler:

func (k Keeper) AllocateTokens(ctx context.Context, totalPreviousPower int64, bondedVotes []abci.VoteInfo) error {
    if err := k.beforeAllocateTokens(ctx); err != nil {
        return err
    }

    // fetch and clear the collected fees for distribution, since this is
    // called in BeginBlock, collected fees will be from the previous block
    // (and distributed to the previous proposer)
    feeCollector := k.authKeeper.GetModuleAccount(ctx, k.feeCollectorName)
    feesCollectedInt := k.bankKeeper.GetAllBalances(ctx, feeCollector.GetAddress())
    feesCollected := sdk.NewDecCoinsFromCoins(feesCollectedInt...)

    // transfer collected fees to the distribution module account
    err := k.bankKeeper.SendCoinsFromModuleToModule(ctx, k.feeCollectorName, types.ModuleName, feesCollectedInt)
    if err != nil {
        return err
    }

This will fetch the balance for any coins sent to the fee collector and send it to the distribution model, which ends up calling 0x1::coin::transfer in the Move VM.

The issue is that it is possible for someone to initialize a coin, freeze the distribution-module accounts store for that coin using the FreezeCapability, and then mint some coins to the fee module, causing the call to SendCoinsFromModuleToModule to fail.

Impact

A malicious user can cause the AllocateTokens method to return an error, and since it occurs in a BeginBlocker, it will cause a consensus failure and halt the chain.

Recommendations

The safest option to resolve this issue could be to have an allowlist of coins that the fee module can distribute instead of fetching all balances.

Remediation

Zellic © 2024Back to top ↑