The internal functions _balanceOf and totalSupply_ use the assembly return(offset, size) opcode. In the EVM, the RETURN opcode halts the execution of the entire transaction (or the current call context) and returns data to the caller. It does not return control to the calling Solidity function.
This means that any function calling _balanceOf or totalSupply_ will immediately terminate, and any code after the call will never be executed.
Real-world impact example:
In this example, _balanceOf returns the balance value but also terminates the entire function, causing the require check and _transfer call to be silently skipped. The Solidity compiler will warn about "unreachable code," but developers may overlook this, leading to critical security vulnerabilities.
Likelihood:
High. The project's README explicitly states: "User can use it as ERC20 token like openzeppelin implementation" (README.md:12), positioning this as a base implementation for developers to extend. Any developer using _balanceOf or totalSupply_ within their own logic (e.g., checking balance before an action, conditional minting, etc.) will encounter this broken control flow.
Impact:
Critical. It breaks the expected semantics of internal function calls. Logic placed after these calls will be silently skipped, potentially bypassing critical security checks, state updates, or logic flows. This is especially severe since the project markets itself as a reusable base like OpenZeppelin, meaning derived contracts will unknowingly inherit this dangerous behavior.
Analysis:
Expected result (if working correctly): 101 (bal + 1)
Actual result: 100 (just the balance)
This confirms that _balanceOf terminates the calling function immediately, preventing any subsequent code from executing. The compiler warning indicates that it recognizes the code path as unreachable, which developers might overlook when extending this base implementation.
Do not use the return opcode in assembly for internal functions. Instead, assign the value to the return variable or leave it on the stack (though in inline assembly within Solidity, assigning to the variable is the standard way).
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.