Core Contracts

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

DebtToken Uninitialized ReservePool

Summary

The DebtToken contract deploys with an uninitialized _reservePool address, causing all balance and supply queries to revert since they depend on the ReservePool's getNormalizedDebt() function.

Vulnerability Details

_reservePool is not set in the constructor. Calls to balanceOf/totalSupply will revert until set, rendering the contract unusable.

In DebtToken.sol#L97-L99, balanceOf()#L223-225, totalSupply()#L232-L234

// Constructor lacks ReservePool initialization
constructor(string memory name, string memory symbol, address initialOwner)
ERC20(name, symbol)
ERC20Permit(name)
Ownable(initialOwner) {
if (initialOwner == address(0)) revert InvalidAddress();
_usageIndex = uint128(WadRayMath.RAY);
// Missing: _reservePool initialization
}
// These core functions will revert with uninitialized _reservePool
function balanceOf(address account) public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledBalance = super.balanceOf(account);
return scaledBalance.rayMul(ILendingPool(_reservePool).getNormalizedDebt());
}
function totalSupply() public view override(ERC20, IERC20) returns (uint256) {
uint256 scaledSupply = super.totalSupply();
return scaledSupply.rayDiv(ILendingPool(_reservePool).getNormalizedDebt());
}

Impact

Contract functionality is blocked until resolved.

Tools Used

manual

Recommendations

Initialize _reservePool during construction or enforce it via initial setup.

Constructor Initialization

constructor(
string memory name,
string memory symbol,
address initialOwner,
address reservePool
) ERC20(name, symbol) ERC20Permit(name) Ownable(initialOwner) {
if (initialOwner == address(0)) revert InvalidAddress();
if (reservePool == address(0)) revert InvalidAddress();
_usageIndex = uint128(WadRayMath.RAY);
_reservePool = reservePool;
}

Two-Step Initialization

function initialize(address reservePool) external onlyOwner {
if (_reservePool != address(0)) revert AlreadyInitialized();
if (reservePool == address(0)) revert InvalidAddress();
_reservePool = reservePool;
emit ReservePoolSet(reservePool);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 month ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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