Hawk High

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

[M-7] USDC Token Operational Risks Not Mitigated

Severity

Medium

Impact

The protocol relies entirely on USDC for payments without implementing any safeguards against USDC's administrative features. This creates serious operational risks where:

  1. Blacklisted addresses would be unable to enroll, receive payments, or participate in the protocol

  2. If USDC is paused, the entire school system would become non-functional

  3. Users could lose funds or be unable to interact with the contract during USDC operational issues

Description

Unlike regular ERC20 tokens, USDC has additional features controlled by Circle, including:

  1. Blacklisting functionality: Circle can blacklist addresses, preventing them from sending or receiving USDC

  2. Pause mechanism: Circle can pause all USDC transfers globally

  3. Upgradeable contract: Circle can upgrade the USDC contract, potentially changing its behavior

The Hawk High School relies solely on USDC with no contingency plans for these scenarios:

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();
}

Additionally, if Circle ever blacklists the contract address itself, the entire protocol would be permanently locked, with no way to recover funds.

Tools Used

Manual code review

Recommended Mitigation

  1. Add chain-specific hardcoded USDC addresses for production environments:

function initialize(address _principal, uint256 _schoolFees, address _usdcAddress) public initializer {
// ... existing validation ...
+ // Validate USDC address based on chain ID
+ if (block.chainid == 1) {
+ // Ethereum Mainnet
+ require(_usdcAddress == 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, "Invalid USDC address");
+ } else if (block.chainid == 137) {
+ // Polygon Mainnet
+ require(_usdcAddress == 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174, "Invalid USDC address");
+ }
// ... rest of function ...
}
  1. Add emergency recovery mechanism for blacklisted contract scenarios:

function emergencyTokenRecovery(address token, address recipient) external onlyPrincipal {
require(recipient != address(0), "Zero address recipient");
require(!inSession, "School in session");
// Get balance of tokens in contract
uint256 balance = IERC20(token).balanceOf(address(this));
// Transfer tokens to recipient
IERC20(token).safeTransfer(recipient, balance);
emit EmergencyRecovery(token, recipient, balance);
}
  1. Consider adding support for alternative stablecoins as a fallback:

// Add multiple stablecoin support
mapping(address => bool) public supportedStablecoins;
Updates

Lead Judging Commences

yeahchibyke Lead Judge about 2 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

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