52669 sc low token minting is blocked for whitelisted addresses when transfersallowed is false

Submitted on Aug 12th 2025 at 11:04:26 UTC by @magtentic for Attackathon | Plume Network

  • Report ID: #52669

  • Report Type: Smart Contract

  • Report severity: Low

  • Target: https://github.com/immunefi-team/attackathon-plume-network/blob/main/arc/src/ArcToken.sol

  • Impacts: Contract fails to deliver promised returns, but doesn't lose value

Description

Brief / Intro

When transfersAllowed is disabled, the whitelist restriction module still allows whitelisted users to transfer tokens. However, minting new tokens to those same whitelisted users fails.

This occurs because address(0) (used as the source address for minting) is not and cannot be whitelisted, which causes the transfer validation to fail even if the recipient is whitelisted and the caller has the MINTER_ROLE.

Vulnerability Details

Whitelisted users cannot have tokens minted to them because address(0) will never be whitelisted. Within the ArcToken contract, _update checks whether a specificRestrictionModules is configured and uses it to validate the transfer:

function _update(address from, address to, uint256 amount) internal virtual override {
    ...
    address specificTransferModule = $.specificRestrictionModules[RestrictionTypes.TRANSFER_RESTRICTION_TYPE];
    if (specificTransferModule != address(0)) {
        transferAllowed =
            transferAllowed && ITransferRestrictions(specificTransferModule).isTransferAllowed(from, to, amount);
    }
    ...
    if (!transferAllowed) {
        revert TransferRestricted();
    }
    ...
}

If transfersAllowed is false, a transfer will only be allowed if the restriction module explicitly approves it.

In the WhitelistRestrictions module, approval is based on whether both from and to are whitelisted. Attempts to whitelist address(0) are blocked:

And batchAddToWhitelist explicitly skips zero address:

Because address(0) will never be whitelisted, isTransferAllowed(address(0), to, amount) returns false even when to is whitelisted and the caller has MINTER_ROLE. That causes mint operations to revert with TransferRestricted().

Impact Details

  • Minting tokens to whitelisted addresses fails when transfersAllowed is disabled, even when the caller has the MINTER_ROLE.

  • This unintentionally blocks minting in scenarios where the restriction system is otherwise configured to allow it.

  • It creates inconsistency between transfer and mint semantics for whitelisted users.

References

This is a resubmission of #49716 with an updated PoC and explanation. The project's own tests show expectations that minting/burning will work with temporary whitelist toggles (see the ArcToken test suite referenced below):

  • Test suite reference: https://github.com/plumenetwork/contracts/blob/main/arc/test/ArcToken.t.sol

An example comment from tests:

This implies tests expect temporary whitelisting or disabled transfer restrictions to allow minting — inconsistent with the observed behavior when transfersAllowed is false.

Proof of Concept

1

Steps to reproduce (summary)

  • Attempt to add address(0) to the whitelist using addToWhitelist — this reverts with InvalidAddress().

  • Add a user (Alice) to the whitelist and validate isWhitelisted(alice).

  • Disable transfers via the whitelist module (setTransfersAllowed(false)), confirming transfers are restricted.

  • Attempt to mint tokens to Alice — mint reverts with TransferRestricted() because isTransferAllowed(address(0), alice, amount) is false.

Proof-of-Concept test (Solidity/Foundry)

Was this helpful?