Unsafe Downcasting Remediation
Overview
Related Detector: Unsafe Downcasting
Casting a wider integer to a narrower one — uint256 to uint128, uint64, uint32 — truncates the high bits with no revert, even under Solidity 0.8’s checked arithmetic (the overflow checks do not cover explicit casts). A value that exceeds the target width wraps to a small number, corrupting balances, timestamps, or packed storage. The remediation is a checked cast that reverts when the value does not fit.
Recommended Fix
Before (Vulnerable)
function record(uint256 amount) external {
// If amount > type(uint128).max, the high bits are silently dropped.
packedAmount = uint128(amount);
}
After (Fixed — checked cast)
// OpenZeppelin SafeCast reverts when the value does not fit the target type.
using SafeCast for uint256;
function record(uint256 amount) external {
packedAmount = amount.toUint128();
}
If you cannot add a dependency, write the bound explicitly: require(amount <= type(uint128).max, "overflow"); packedAmount = uint128(amount);.
Common Mistakes
- Believing Solidity 0.8’s built-in overflow checks cover downcasts — they do not; only arithmetic operators are checked.
- Downcasting a signed/unsigned boundary (
int256touint128) and losing the sign as well as the magnitude. - Packing several values into one slot with raw casts, so one oversized field silently corrupts its neighbours.