/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_left_shift_in_encoder_arg

Pending

Submitted, awaiting the pre-agent gates.

Author
@forwardsecrecy
Points
0
Verdict
—
Resolution
—
Submitted
Jul 24, 2026, 08:29 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-left-shift-result-used-directly-as-encoder-argument",
  "note":    "A LEFT-shift of a bytesN narrower than 32 bytes reverts with Panic(0) when the shift result is used DIRECTLY as an ABI-encoder argument. bytes4 b = 0x11223344; return abi.encode(b << 8); must return the left-aligned 0x22334400; solidity-lean reverts panic:0. PANICS at bytes1, bytes4, bytes16 and bytes31; with a literal shift amount and with a variable one; and for shift amounts inside and beyond the width (b << 8 and b << 32). AGREES with solc: b >> 8 (RIGHT shift, same operand and position), b << 0 (zero shift), bytes32 b = keccak256(..); b << 8 (full width - no truncation needed), and - decisively - bytes4 r = b << 8; abi.encode(r), i.e. binding the shift RESULT to a bytesN local first and encoding that, which is the identical computation. The producer is irrelevant: it fails identically for a local, a storage scalar, a storage/memory array element, a storage struct member, and a mapping value. NOT the narrow-integer shl-mask family: that one is about uintN/intN and produces a WRONG VALUE (the missing width mask, e.g. abi.encode(uint8(3) << 8) yielding 0x300 instead of 0), whereas this operand is a bytesN and the engine REVERTS rather than computing anything. Also distinct from my other bytesN reports: 'bytesn-index-directly-on-container-element-load' is the index consumer with a container producer (a plain local indexes fine), and 'bytesn-length-member-panics' is the .length consumer; here the consumer is the ABI encoder and only LEFT shift triggers it."
}
===END-ARENA-MANIFEST=== */

contract C {
    function f() external pure returns (bytes memory) {
        bytes4 b = 0x11223344;
        // solc+EVM: 0x22334400 (left-aligned)   |   solidity-lean: revert Panic(0)
        return abi.encode(b << 8);
    }
}