Core Contracts

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

Critical Functions Become Unusable After Ownership Transfer to RAACMinter

Summary

The RAACToken contract contains a vulnerability where critical functions become unusable after the ownership is transferred to the RAACMinter contract. This issue arises because the RAACMinter contract does not implement the necessary functions to manage the RAACToken contract, leading to a situation where administrative functions cannot be performed. RAACMinter needs to be owner of RAACToken so it can perform normal operations.

Vulnerability Details

The vulnerability is found in the RAACToken contract when the ownership is transferred to the RAACMinter contract. The RAACMinter contract does not implement the necessary functions such as setFeeCollector, manageWhitelist, setMinter, and setTaxRateIncrementLimit. As a result, these functions become unusable, and critical administrative tasks cannot be performed. RAACMinter needs to be owner of RAACToken so it can perform normal operations.

Impact

The impact of this vulnerability is significant as it causes critical functions of the RAACToken contract to become unusable after the ownership is transferred to the RAACMinter contract. This can lead to a situation where administrative tasks cannot be performed like manageWhitelist(), setFeeCollector(), setTaxRateIncrementLimit(), setMinter() , potentially affecting the operation and governance of the token.

Tools Used

Solidity: The programming language used to write the smart contracts.
Manual Code Review: Reviewing the code to identify potential issues.
Foundry Tests: For PoC

Recommendations

Access Control: Implement a more flexible access control mechanism that allows multiple addresses to perform administrative functions without transferring ownership.

POC

Commands to run in the terminal

mkdir ../raacFoundry
cd ../raacFoundry
forge init
rm src/Counter.sol test/Counter.t.sol script/Counter.s.sol
cp -r ../2025-02-raac/contracts src
touch test/Test.sol
npm install @openzeppelin/contracts
npm install @openzeppelin/contracts
npm install @openzeppelin/contracts-upgradeable
npm install @chainlink/contracts
forge test

Add this to the forge.toml file

[profile.default]
src = "src"
out = "out"
libs = ['lib', 'node_modules']
remappings = [
"@openzeppelin/=node_modules/@openzeppelin/",
"@chainlink/=node_modules/@chainlink/"
]

Add this to the test/Test.sol file

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "forge-std/Test.sol";
import "../src/contracts/core/pools/LendingPool/LendingPool.sol";
import "../src/contracts/mocks/core/tokens/crvUSDToken.sol";
import "../src/contracts/core/primitives/RAACHousePrices.sol";
import "../src/contracts/core/tokens/RAACNFT.sol";
import "../src/contracts/core/tokens/RToken.sol";
import "../src/contracts/core/tokens/DebtToken.sol";
import "../src/contracts/core/pools/StabilityPool/StabilityPool.sol";
import "../src/contracts/core/tokens/RAACToken.sol";
import "../src/contracts/core/minters/RAACMinter/RAACMinter.sol";
import "../src/contracts/core/tokens/DeToken.sol";
contract StabilityPoolTest is Test {
address owner;
address user1;
address user2;
address user3;
address treasury;
StabilityPool stabilityPool;
LendingPool lendingPool;
RAACMinter raacMinter;
RToken rToken;
DebtToken debtToken;
DEToken deToken;
RAACToken raacToken;
crvUSDToken crvusd;
RAACNFT raacNFT;
RAACHousePrices raacHousePrices;
uint256 currentTime = 1672531200; // Example timestamp (January 1, 2023)
uint256 constant WAD = 1e18;
uint256 constant RAY = 1e27;
function setUp() public {
owner = address(this);
user1 = address(0x1);
user2 = address(0x2);
user3 = address(0x3);
treasury = address(0x4);
crvusd = new crvUSDToken(owner);
crvusd.setMinter(owner);
raacToken = new RAACToken(owner, 100, 50);
raacToken.setMinter(owner);
raacHousePrices = new RAACHousePrices(owner);
raacHousePrices.setOracle(owner);
raacNFT = new RAACNFT(address(crvusd), address(raacHousePrices), owner);
rToken = new RToken("RToken", "RToken", owner, address(crvusd));
deToken = new DEToken("DEToken", "DEToken", owner, address(rToken));
debtToken = new DebtToken("DebtToken", "DT", owner);
uint256 initialPrimeRate = 5e27;
lendingPool = new LendingPool(
address(crvusd),
address(rToken),
address(debtToken),
address(raacNFT),
address(raacHousePrices),
initialPrimeRate
);
raacHousePrices.setOracle(owner);
stabilityPool = new StabilityPool(owner);
vm.warp(currentTime);
raacMinter = new RAACMinter(
address(raacToken),
address(stabilityPool),
address(lendingPool),
owner
);
}
function testFunctionsUnusable() public {
// Set the owner of the RAAC token to the RAACMinter contract
// This transfers ownership from the current owner to the RAACMinter contract
vm.prank(owner);
raacToken.transferOwnership(address(raacMinter));
// Attempt to call setFeeCollector through the RAACMinter
// This should fail because RAACMinter does not implement setFeeCollector
vm.prank(owner);
// Uncomment the line below to expect a specific revert message
// vm.expectRevert("OwnableUnauthorizedAccount");
raacMinter.setFeeCollector(user1);
// Attempt to call manageWhitelist through the RAACMinter
// This should fail because RAACMinter does not implement manageWhitelist
vm.prank(owner);
vm.expectRevert();
raacToken.manageWhitelist(user2, true);
// Attempt to call setMinter through the RAACMinter
// This should fail because RAACMinter does not implement setMinter
vm.prank(owner);
vm.expectRevert();
raacToken.setMinter(user1);
// Attempt to call setTaxRateIncrementLimit through the RAACMinter
// This should fail because RAACMinter does not implement setTaxRateIncrementLimit
vm.prank(owner);
vm.expectRevert();
raacToken.setTaxRateIncrementLimit(100);
}
}
Updates

Lead Judging Commences

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

RAACMinter lacks critical ownership transfer functionality and parameter management after receiving RAACToken ownership, causing permanent protocol rigidity

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

RAACMinter lacks critical ownership transfer functionality and parameter management after receiving RAACToken ownership, causing permanent protocol rigidity

Support

FAQs

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

Give us feedback!