Core Contracts

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

Lack of Initialization Protection

Summary

The stabilityPool address can remain unset after deployment, potentially leading to a blocked contract state.

Vulnerability Details

The contract doesn't enforce setting the stabilityPool address during construction, and there's no check for zero address in core functions.

POC

const { expect } = require("chai");
const { ethers } = require("hardhat");
describe("DEToken Initialization Vulnerability", function () {
let deToken;
let owner;
let user;
beforeEach(async function () {
[owner, user] = await ethers.getSigners();
const DEToken = await ethers.getContractFactory("DEToken");
deToken = await DEToken.deploy(
"Debitum Emptor",
"DE",
owner.address,
"0x1234567890123456789012345678901234567890" // rToken address
);
await deToken.deployed();
});
it("should fail all operations when stabilityPool is not set", async function () {
// Try to mint tokens
await expect(
deToken.mint(user.address, ethers.utils.parseEther("1"))
).to.be.revertedWith("OnlyStabilityPool");
// Verify stabilityPool is zero address
expect(await deToken.getStabilityPool()).to.equal(
ethers.constants.AddressZero
);
});
});

Impact

Severity: Medium

  • Contract becomes unusable until stabilityPool is set

  • No explicit checks preventing operations with unset stabilityPool

  • Could lead to locked funds if tokens are sent before setup

Tools Used

  • Hardhat testing framework

  • Manual code review

Recommendations

  1. Add initialization status tracking:

contract DEToken is ERC20, ERC20Permit, IDEToken, Ownable {
bool private _initialized;
event Initialized();
error NotInitialized();
modifier whenInitialized() {
if (!_initialized) revert NotInitialized();
_;
}
function setStabilityPool(address newStabilityPool) external onlyOwner {
if (newStabilityPool == address(0)) revert InvalidAddress();
address oldStabilityPool = stabilityPool;
stabilityPool = newStabilityPool;
if (!_initialized) {
_initialized = true;
emit Initialized();
}
emit StabilityPoolUpdated(oldStabilityPool, newStabilityPool);
}
function mint(address to, uint256 amount) external override
onlyStabilityPool
whenInitialized
{
// ...existing code...
}
}
  1. Add initialization check to core functions:

function transfer(address recipient, uint256 amount) public override(ERC20,IERC20)
onlyStabilityPool
whenInitialized
returns (bool)
{
return super.transfer(recipient, amount);
}
function transferFrom(address sender, address recipient, uint256 amount) public override(ERC20,IERC20)
onlyStabilityPool
whenInitialized
returns (bool)
{
return super.transferFrom(sender, recipient, amount);
}
  1. Add recovery mechanism for stuck tokens:

function rescueTokens(address token, address to, uint256 amount) external onlyOwner {
if (token == rTokenAddress) revert CannotRescueRToken();
if (token == address(this)) revert CannotRescueDEToken();
IERC20(token).safeTransfer(to, amount);
emit TokensRescued(token, to, amount);
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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

Give us feedback!