Core Contracts

Regnum Aurum Acquisition Corp
HardhatReal World AssetsNFT
77,280 USDC
View results
Submission Details
Severity: medium
Valid

Inconsistent Fee Collector Address Validation in RAACMinter: Denial of Service for Disabling Fee Collection

Summary

The RAACMinter contract manages token minting and fee-related configurations by interfacing with the RAACToken contract. One such function, setFeeCollector, is used to update the fee collector address. In RAACMinter, the function rejects a zero address (to prevent accidental misconfiguration), while the RAACToken’s setFeeCollector function explicitly allows setting the fee collector to the zero address to disable fee collection. This discrepancy creates an inconsistency: RAACMinter prevents an owner or administrator from disabling fee collection via setting the fee collector to the zero address, thereby potentially blocking a legitimate administrative action. This misalignment in access control, while seemingly low risk by design, could lead to a denial of service for fee collection disablement, hampering the protocol’s flexibility in emergency or maintenance scenarios.

Vulnerability Details

How It Begins

  1. RAACMinter Implementation:
    The setFeeCollector function in RAACMinter is implemented as follows:

    function setFeeCollector(address _feeCollector) external onlyRole(UPDATER_ROLE) {
    if (_feeCollector == address(0)) revert FeeCollectorCannotBeZeroAddress();
    raacToken.setFeeCollector(_feeCollector);
    emit ParameterUpdated("feeCollector", uint256(uint160(_feeCollector)));
    }
    • Issue: It explicitly reverts if _feeCollector is the zero address. This prevents the RAACMinter from disabling fee collection.

  2. RAACToken Implementation:
    Conversely, the RAACToken contract allows setting the fee collector to the zero address as a means to disable fee collection:

    function setFeeCollector(address _feeCollector) external onlyOwner {
    // Fee collector can be set to zero address to disable fee collection
    if (feeCollector == address(0) && _feeCollector != address(0)) {
    emit FeeCollectionEnabled(_feeCollector);
    }
    if (_feeCollector == address(0)) {
    emit FeeCollectionDisabled();
    }
    feeCollector = _feeCollector;
    emit FeeCollectorSet(_feeCollector);
    }
    • Intended Behavior: Allowing a zero address to be set provides a mechanism to disable fee collection when needed.

  3. Discrepancy and Impact:

    • The RAACMinter’s restriction prevents an administrator from taking the action to disable fee collection via setting the fee collector to the zero address, which is an allowed and sometimes necessary administrative operation in the RAACToken design.

    • This misalignment in validations can lead to a denial of service for disabling fee collection—an important control for managing protocol fees under certain circumstances.

Proof of Concept

Scenario Walkthrough

  1. Setup:

    • The RAACMinter contract is deployed with proper dependencies.

    • The RAACToken contract is deployed and configured accordingly.

  2. Faulty Operation:

    • An administrator with the appropriate UPDATER_ROLE attempts to call setFeeCollector(address(0)) via the RAACMinter interface in order to disable fee collection.

    • Due to the check in RAACMinter, the call reverts with FeeCollectorCannotBeZeroAddress(), even though the RAACToken is designed to accept a zero address for disabling fees.

Test Suite Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test, console} from "forge-std/Test.sol";
import {RAACMinter} from "../src/core/minters/RAACMinter/RAACMinter.sol";
import {RAACToken} from "../src/core/tokens/RAACToken.sol";
contract RAACMinterTest is Test {
RAACToken raacToken;
RAACMinter raacMinter;
address RAAC_OWNER = makeAddr("RAAC_OWNER");
address RAAC_MINTER_OWNER = makeAddr("RAAC_MINTER_OWNER");
uint256 initialRaacSwapTaxRateInBps = 200; // 2%
uint256 initialRaacBurnTaxRateInBps = 150; // 1.5%
address ALICE = makeAddr("ALICE");
address BOB = makeAddr("BOB");
address CHARLIE = makeAddr("CHARLIE");
address DEVIL = makeAddr("DEVIL");
address stabilityPool = makeAddr("STABILITY_POOL");
address lendingPool = makeAddr("LENDING_POOL");
function setUp() public {
raacToken = new RAACToken(RAAC_OWNER, initialRaacSwapTaxRateInBps, initialRaacBurnTaxRateInBps);
vm.warp(block.timestamp + 1 days);
raacMinter = new RAACMinter(address(raacToken), stabilityPool, lendingPool, RAAC_MINTER_OWNER);
}
function testRAACMinterCannotDisableFeeCollection() public {
vm.startPrank(RAAC_OWNER);
raacToken.transferOwnership(address(raacMinter));
vm.stopPrank();
vm.startPrank(RAAC_MINTER_OWNER);
// Attempting to set the fee collector to the zero address should revert.
vm.expectRevert(bytes4(keccak256("FeeCollectorCannotBeZeroAddress()")));
raacMinter.setFeeCollector(address(0));
vm.stopPrank();
}
}

How to Run the Test

  1. Initialize a Foundry Project:

    forge init my-foundry-project
  2. Place Contract Files:
    Ensure that RAACMinter.sol and RAACToken.sol are in the src directory.

  3. Create Test Directory:
    Create a test directory adjacent to src and add the above test file (e.g., RAACMinterTest.t.sol).

  4. Run the Test:

    forge test --mt testRAACMinterCannotDisableFeeCollection -vv
  5. Expected Outcome:
    The test should revert with the FeeCollectorCannotBeZeroAddress() error, confirming that RAACMinter currently does not allow the fee collector to be set to zero—even though RAACToken supports it.

Impact

  • Operational Inflexibility:
    The inability to disable fee collection by setting the fee collector to the zero address can hinder administrative responses during emergencies or maintenance periods.

  • Denial of Service for Fee Management:
    Administrators are blocked from executing a valid operation (disabling fee collection) when it is needed, potentially exposing the protocol to further issues.

  • Misalignment Between Contracts:
    The inconsistency between RAACMinter and RAACToken in handling zero addresses for fee collection undermines the integrated design, leading to confusion and potential misconfiguration.

Tools Used

  • Manual Review

  • Foundry

Recommendations

Proposed Diff for RAACMinter::setFeeCollector

Modify the RAACMinter setFeeCollector function to allow a zero address, aligning it with RAACToken’s behavior.

function setFeeCollector(address _feeCollector) external onlyRole(UPDATER_ROLE) {
- if (_feeCollector == address(0)) revert FeeCollectorCannotBeZeroAddress();
+ // Allow zero address to disable fee collection as per RAACToken design.
raacToken.setFeeCollector(_feeCollector);
emit ParameterUpdated("feeCollector", uint256(uint160(_feeCollector)));
}

Benefits of This Update

  • Consistency:
    Aligns RAACMinter with RAACToken, ensuring that the ability to disable fee collection (by setting the fee collector to zero) is uniformly available.

  • Operational Flexibility:
    Enables administrators to disable fee collection when necessary, which can be crucial during maintenance or emergency situations.

  • Simplified Administration:
    Removing the unnecessary check reduces confusion and potential misconfiguration, allowing for a more intuitive management process.

  • Improved Protocol Integration:
    Consistent behavior across contracts helps maintain system integrity and reduces the risk of unexpected behavior in fee management.

Implementing these changes will resolve the inconsistency between RAACMinter and RAACToken regarding fee collector settings. This update will enable administrators to disable fee collection as intended, ensuring that the protocol's fee management functions operate reliably and flexibly.

Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RAACMinter::setFeeCollector prevents disabling fees by blocking zero address assignment

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Validated
Assigned finding tags:

RAACMinter::setFeeCollector prevents disabling fees by blocking zero address assignment

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.

Give us feedback!