#!/usr/bin/env bash # test_transpiler_clamping.sh — Tests transpiler validation of output register values. # Verifies that: # - negative literal outputs for ci, anchorShare, anchorWidth, discoveryDepth produce # a transpiler-level error with a clear message (not a silent Solidity compile failure). # - an anchorWidth literal outside [0, 16777215] produces a transpiler-level error. # - a valid anchorWidth literal within range is accepted and still uses % (2**24). # Exit: 0 if all tests pass, 1 if any fail. set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PASS=0 FAIL=0 assert_contains() { local name="$1" local output="$2" local expected="$3" if echo "$output" | grep -qF "$expected"; then echo " PASS: $name" PASS=$((PASS + 1)) else echo " FAIL: $name" echo " expected to contain: $expected" echo " actual output:" echo "$output" | sed 's/^/ /' FAIL=$((FAIL + 1)) fi } assert_not_contains() { local name="$1" local output="$2" local pattern="$3" if echo "$output" | grep -qF "$pattern"; then echo " FAIL: $name" echo " expected NOT to contain: $pattern" echo " actual output:" echo "$output" | sed 's/^/ /' FAIL=$((FAIL + 1)) else echo " PASS: $name" PASS=$((PASS + 1)) fi } assert_exits_nonzero() { local name="$1" local stderr_output="$2" local expected_fragment="$3" # stderr_output is non-empty only if the command failed (captured separately) if echo "$stderr_output" | grep -qF "$expected_fragment"; then echo " PASS: $name" PASS=$((PASS + 1)) else echo " FAIL: $name" echo " expected stderr to contain: $expected_fragment" echo " actual stderr:" echo "$stderr_output" | sed 's/^/ /' FAIL=$((FAIL + 1)) fi } # ── Ensure node_modules exist ──────────────────────────────────────────────── if [ ! -d "$SCRIPT_DIR/node_modules" ]; then (cd "$SCRIPT_DIR" && npm install --silent) fi TMPDIR_T=$(mktemp -d) trap 'rm -rf "$TMPDIR_T"' EXIT run_transpiler() { local push3_content="$1" local input_file="$TMPDIR_T/test_input.push3" local output_file="$TMPDIR_T/test_output.sol" printf '%s\n' "$push3_content" > "$input_file" rm -f "$output_file" local stderr_out # Capture stderr; allow non-zero exit without aborting if stderr_out=$(cd "$SCRIPT_DIR" && npx tsx src/index.ts "$input_file" "$output_file" 2>&1 >/dev/null); then echo "OK" else printf '%s' "$stderr_out" fi } # ── Test 6: anchorWidth literal > uint24 max → transpiler error ────────────── echo "Test 6: anchorWidth = 1e18 (literal) → transpiler error, not silent Solidity failure" # Push3 program: push 4 values (discoveryDepth, anchorWidth=1e18, anchorShare, ci). # The transpiler pops top-4 from DYADIC stack; these literals sit on top of the # primed input slots, so they become the 4 output vars. STDERR=$(run_transpiler "( 300000000000000000 1000000000000000000 300000000000000000 0 )") assert_contains \ "anchorWidth 1e18: transpiler emits range error message" \ "$STDERR" \ "anchorWidth literal (1000000000000000000) is outside uint24 range [0, 16777215]" # ── Test 7: valid anchorWidth literal (in range) → accepted, wraps with % (2**24) ─ echo "Test 7: anchorWidth = 100 (valid literal) → accepted, output uses % (2**24)" INPUT_6="$TMPDIR_T/valid_aw.push3" OUTPUT_6="$TMPDIR_T/valid_aw.sol" cat > "$INPUT_6" <<'PUSH3EOF' ( 300000000000000000 100 300000000000000000 0 ) PUSH3EOF (cd "$SCRIPT_DIR" && npx tsx src/index.ts "$INPUT_6" "$OUTPUT_6" 2>/dev/null) SOL_6=$(cat "$OUTPUT_6") assert_contains \ "anchorWidth 100: output uses % (2**24)" \ "$SOL_6" \ "uint24(100 % (2**24))" # ── Test 8: negative ci literal → transpiler error ─────────────────────────── echo "Test 8: ci = -1 (negative literal) → transpiler error" STDERR=$(run_transpiler "( 300000000000000000 100 300000000000000000 -1 )") assert_contains \ "negative ci: transpiler emits error message" \ "$STDERR" \ "ci is a negative literal (-1)" # ── Test 9: negative anchorShare literal → transpiler error ────────────────── echo "Test 9: anchorShare = -5 (negative literal) → transpiler error" STDERR=$(run_transpiler "( 300000000000000000 100 -5 0 )") assert_contains \ "negative anchorShare: transpiler emits error message" \ "$STDERR" \ "anchorShare is a negative literal (-5)" # ── Test 10: negative discoveryDepth literal → transpiler error ─────────────── echo "Test 10: discoveryDepth = -99 (negative literal) → transpiler error" STDERR=$(run_transpiler "( -99 100 300000000000000000 0 )") assert_contains \ "negative discoveryDepth: transpiler emits error message" \ "$STDERR" \ "discoveryDepth is a negative literal (-99)" # ── Test 11: negative anchorWidth literal → transpiler error ───────────────── echo "Test 11: anchorWidth = -1 (negative literal) → transpiler error" STDERR=$(run_transpiler "( 300000000000000000 -1 300000000000000000 0 )") assert_contains \ "negative anchorWidth: transpiler emits range error message" \ "$STDERR" \ "anchorWidth literal (-1) is outside uint24 range [0, 16777215]" # ── Test 12: forge build — transpiler output compiles (regression for #900) ── echo "Test 12: forge build on valid transpiler output (regression for #900)" REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" FORGE_BIN="$(command -v forge 2>/dev/null || true)" if [ -z "$FORGE_BIN" ] && [ -x /root/.foundry/bin/forge ]; then FORGE_BIN=/root/.foundry/bin/forge fi if [ -z "$FORGE_BIN" ]; then echo " SKIP: forge not found — add foundry bin to PATH to enable compile verification" else FORGE_DIR="$TMPDIR_T/forge_verify" mkdir -p "$FORGE_DIR/src" printf '[profile.default]\nsrc = "src"\nout = "out"\nlibs = []\nvia_ir = true\n' > "$FORGE_DIR/foundry.toml" cp "$REPO_ROOT/onchain/src/IOptimizer.sol" "$FORGE_DIR/src/" cp "$OUTPUT_6" "$FORGE_DIR/src/OptimizerV3Push3.sol" FORGE_OUT="" FORGE_RC=0 FORGE_OUT=$(cd "$FORGE_DIR" && "$FORGE_BIN" build 2>&1) || FORGE_RC=$? if [ "$FORGE_RC" -eq 0 ]; then echo " PASS: forge build succeeded on transpiled contract" PASS=$((PASS + 1)) else echo " FAIL: forge build failed — transpiled contract does not compile" echo "$FORGE_OUT" | sed 's/^/ /' FAIL=$((FAIL + 1)) fi fi # ── Test 13: ci literal > 1e18 → transpiler error ──────────────────────────── echo "Test 13: ci = 2e18 (literal) → transpiler error" STDERR=$(run_transpiler "( 300000000000000000 100 300000000000000000 2000000000000000000 )") assert_contains \ "ci 2e18: transpiler emits max1e18 error message" \ "$STDERR" \ "ci literal (2000000000000000000) exceeds 1e18 (max allowed)" # ── Test 14: anchorShare literal > 1e18 → transpiler error ─────────────────── echo "Test 14: anchorShare = 2e18 (literal) → transpiler error" STDERR=$(run_transpiler "( 300000000000000000 100 2000000000000000000 0 )") assert_contains \ "anchorShare 2e18: transpiler emits max1e18 error message" \ "$STDERR" \ "anchorShare literal (2000000000000000000) exceeds 1e18 (max allowed)" # ── Test 15: discoveryDepth literal > 1e18 → transpiler error ──────────────── echo "Test 15: discoveryDepth = 2e18 (literal) → transpiler error" STDERR=$(run_transpiler "( 2000000000000000000 100 300000000000000000 0 )") assert_contains \ "discoveryDepth 2e18: transpiler emits max1e18 error message" \ "$STDERR" \ "discoveryDepth literal (2000000000000000000) exceeds 1e18 (max allowed)" # ── Summary ────────────────────────────────────────────────────────────────── echo "" echo "Results: $PASS passed, $FAIL failed" [ "$FAIL" -eq 0 ]