Skip to content
On this page

S2C6: uint8 Overflow + Reentrancy

1. Problem

The contract has a points and level system, where mintFlag checks uint8(points << levels) == 32. It is necessary to find a combination of points and levels such that points << levels equals exactly 32 after uint8 overflow.

2. Cause

The contract uses uint8 casting to truncate the shift result. Since uint8 only has 8 bits (0-255), the left-shifted value wraps around if it exceeds 255. At the same time, the contract has a reentrancy vulnerability that allows unlimited points acquisition.

3. Solution

  1. Exploit the reentrancy vulnerability to obtain 59 points (59 claimPoints calls)
  2. Upgrade 5 times (consuming 50 points, leaving 9 points, level 5)
  3. Verify: uint8(9 << 5) = uint8(288) = 288 - 256 = 32 ✓
  4. points(9) < 10 ✓ and points × levels(45) >= 30 ✓
solidity
function solve() public {
    counter = 0;
    challenge.resetPoints();
    challenge.claimPoints(); // reenters 58 more times → total 59
    // 5 x upgradeLevel: points=9, levels=5
    for (uint i = 0; i < 5; i++) challenge.upgradeLevel();
    challenge.mintFlag(); // uint8(9<<5)=32 ✓
}

receive() external payable {
    if (counter < 58) { counter++; challenge.claimPoints(); }
}

4. Pitfalls Encountered

Reentrancy Count and Overflow Parameter Matching: The number of reentrancy calls and upgrade operations must be precisely calculated so that the final parameters satisfy all checks. Incorrect initial calculations can lead to unsatisfied conditions.

5. Pitfall Causes

Three conditions constrain each other:

  1. points < 10 → final points must be < 10
  2. points * levels >= 30 → points × level ≥ 30
  3. uint8(points << levels) == 32 → after shifting, uint8 truncation = 32

It is necessary to find a (points, levels) combination that satisfies all three conditions simultaneously, along with a path to reach that combination.

6. How to Resolve

Mathematical Analysis:

  • 9 << 5 = 288, uint8(288) = 288 % 256 = 32
  • points=9 < 10 ✓, 9*5=45 >= 30 ✓
  • Path to reach: 59 claimPoints → points=59, 5 upgradeLevel → points=59-50=9
  • Key: find the optimal combination where points << levels equals 32 under uint8

uint8 Shift Overflow Lookup Table:

pointslevelsp<<luint8(p<<l)
9528832 ✓
153232 ✓
243232 ✓

Choose 9 and 5 because: points * levels = 45 >= 30 and points = 9 < 10.

7. Key Technical Points

PointDescription
uint8 overflowLeft-shift results exceeding 255 are automatically truncated: uint8(x) == x % 256
Reentrancy vulnerabilityExternal call before state update → unlimited reentry
Parameter space searchExhaustively enumerate points(1-255) × levels(0-255) to find combinations satisfying uint8(p<<l)==32

Core code: solutions/season2/Challenge6SolutionV2.sol (59 reentrancy calls + 5 upgrades)

Built with AiAda