Hawk High

First Flight #39
Beginner FriendlySolidity
100 EXP
View results
Submission Details
Impact: high
Likelihood: high
Invalid

Lack of Access Control in the `initialize` Function Allows Unauthorized Calls

Summary


The initialize function of the contract lacks proper access control mechanisms, allowing any address to invoke it. While the initializer modifier prevents multiple invocations, it does not restrict who can call the function. This oversight can lead to unauthorized modification of critical contract state variables such as principal, schoolFees, and usdc, compromising the intended functionality of the contract.

Vulnerability Details


Affected Function:

  • initialize

  • Current Modifier:

    • The function uses the initializer modifier to ensure it is only called once.

  • Issue:

    • The initializer modifier does not restrict the caller of the function.

    • Any address can call the initialize function, which allows them to set arbitrary values for critical state variables:

      • principal: Address of the principal.

      • schoolFees: The school fees amount.

      • usdc: Address of the USDC token contract.


Code Reference:

function initialize(
address _principal,
uint256 _schoolFees,
address _usdcAddress
) public initializer {
if (_principal == address(0)) {
revert HH__ZeroAddress();
}
if (_schoolFees == 0) {
revert HH__ZeroValue();
}
if (_usdcAddress == address(0)) {
revert HH__ZeroAddress();
}
principal = _principal;
schoolFees = _schoolFees;
usdc = IERC20(_usdcAddress);
__UUPSUpgradeable_init();
}

Impact

Unauthorized Contract Initialization:
An attacker can invoke the initialize function and set malicious or incorrect values for the contract’s critical state variables.

  • System Functionality Compromised:
    Key functionalities relying on correctly initialized variables (such as principal and usdc) may break, leading to loss of trust or funds.


Tools Used

Manual review

Recommendations

Add Access Control

Restrict access to the initialize function by introducing a mechanism such as an onlyDeployer or onlyOwner modifier.

Example Implementation:

+ modifier onlyDeployer() {
+ require(msg.sender == deployer, "Caller is not the deployer");
+ _; }
+ address private deployer;
function initialize(
address _principal,
uint256 _schoolFees,
address _usdcAddress
+ ) public initializer onlyDeployer {
if (_principal == address(0)) {
revert HH__ZeroAddress();
}
if (_schoolFees == 0) {
revert HH__ZeroValue();
}
if (_usdcAddress == address(0)) {
revert HH__ZeroAddress();
}
principal = _principal;
schoolFees = _schoolFees;
usdc = IERC20(_usdcAddress);
__UUPSUpgradeable_init();
}
Updates

Lead Judging Commences

yeahchibyke Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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