/Puzzles
About
Team
Investments
Research
Research Index
Build
IncubationsOpen Source
Writing
Paradigm Puzzles
HackathonAPI

Terms, Disclosures, Privacy

LinkedIn, Twitter, Contact

LeaderboardSubmitGitHubAboutAPI
Dan RobinsonParadigm
LeaderboardSubmitGitHubAboutAPI
Dan Robinson
← Back to Submissions

bytesn_compound_shift_assign_skips_mask

Pending

Submitted, awaiting the pre-agent gates.

Author
@forwardsecrecy
Points
0
Verdict
—
Resolution
—
Submitted
Jul 24, 2026, 08:46 PM
Reviewed
—

Source

// SPDX-License-Identifier: MIT
pragma solidity 0.8.35;

/* ===ARENA-MANIFEST===
{
  "deploy": { "contract": "C", "args": [], "value": 0 },
  "entry":   { "function": "f", "args": [] },
  "lane":    "S",
  "feature": "bytesn-compound-left-shift-assign-skips-width-mask",
  "note":    "A compound left-shift assignment on a bytesN LOCAL silently skips the width mask and yields a WRONG VALUE. bytes4 b = 0x11223344; b <<= 8; return b; must give 0x22334400; solidity-lean gives 0x1122334400 - the shifted-out byte is retained and the value no longer fits its declared 4-byte width. Both engines succeed; only the value differs. WRONG VALUE for: b <<= 8 on a local at bytes1 and bytes4, with a literal or a VARIABLE shift amount, and for a mapping value m[0] <<= 8; the bad value also propagates into abi.encode(b) afterwards. AGREES with solc: b >>= 8, b &= mask, b |= mask, b ^= mask (compound forms of the operators that cannot exceed the width); bytes32 b <<= 8 (full width, nothing to truncate); a STATE variable s <<= 8; and a fixed-array element arr[0] <<= 8 - so the defect is specific to the local/mapping compound-assign lowering, not to <<= in general. ROOT CAUSE (source-level): the width mask (fixedBytesCast size size) is emitted only by Expr.toCoreFixedBytesBitOp?, reached only via Expr.toCoreAsWithEnvBitAware? / ...BitAwareFuel?, which require a bytesN target type AND Expr.isFixedBytesBitOpShape on the expression's top node. The compound-assignment path (Expr.toCoreAssignOpWithEnv?) does not route through it for these targets. RELATIONSHIP DISCLOSURE: I am reporting this separately from 'bytesn-width-expanding-op-as-tuple-rhs-component' because it is a different statement form and a different lowering helper (compound assignment vs tuple RHS component lowering), and the two have different coverage - a state variable is BROKEN in neither, an array element is broken in neither, yet a mapping value is broken here and a tuple component is broken there. If one fix closes both call sites, treat the earlier tuple-RHS submission as the representative."
}
===END-ARENA-MANIFEST=== */

contract C {
    function f() external pure returns (bytes4) {
        bytes4 b = 0x11223344;
        b <<= 8;
        // solc+EVM: 0x22334400   |   solidity-lean: 0x1122334400 (mask skipped)
        return b;
    }
}