diff --git a/tools/push3-transpiler/package.json b/tools/push3-transpiler/package.json index 5bd95b5..80c939f 100644 --- a/tools/push3-transpiler/package.json +++ b/tools/push3-transpiler/package.json @@ -7,7 +7,7 @@ "scripts": { "build": "tsc", "transpile": "ts-node src/index.ts", - "test": "bash test_inject_extraction.sh" + "test": "bash test_inject_extraction.sh && bash test_transpiler_clamping.sh" }, "dependencies": {}, "devDependencies": { diff --git a/tools/push3-transpiler/src/index.ts b/tools/push3-transpiler/src/index.ts index 654a83d..2cce36e 100644 --- a/tools/push3-transpiler/src/index.ts +++ b/tools/push3-transpiler/src/index.ts @@ -79,7 +79,7 @@ function main(): void { ...functionBody, ` ci = uint256(${ciVar});`, ` anchorShare = uint256(${anchorShareVar});`, - ` anchorWidth = uint24(${anchorWidthVar});`, + ` anchorWidth = uint24(${anchorWidthVar} % (2**24));`, ` discoveryDepth = uint256(${discoveryDepthVar});`, ' }', ' }', diff --git a/tools/push3-transpiler/test_transpiler_clamping.sh b/tools/push3-transpiler/test_transpiler_clamping.sh new file mode 100755 index 0000000..2010fd4 --- /dev/null +++ b/tools/push3-transpiler/test_transpiler_clamping.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# test_transpiler_clamping.sh — Tests that the transpiler clamps anchorWidth to uint24 bounds. +# Verifies that a Push3 program producing 1e18 for anchorWidth generates +# `uint24(... % (2**24))` rather than a raw overflowing literal. +# 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 +} + +# ── Ensure node_modules exist ──────────────────────────────────────────────── +if [ ! -d "$SCRIPT_DIR/node_modules" ]; then + (cd "$SCRIPT_DIR" && npm install --silent) +fi + +# ── Test 5: anchorWidth = 1e18 is clamped to uint24 range ─────────────────── +echo "Test 5: anchorWidth overflow clamped via % (2**24)" + +TMPDIR_T=$(mktemp -d) +trap 'rm -rf "$TMPDIR_T"' EXIT + +INPUT_PUSH3="$TMPDIR_T/overflow.push3" +OUTPUT_SOL="$TMPDIR_T/overflow.sol" + +# 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. +cat > "$INPUT_PUSH3" <<'PUSH3EOF' +( + 300000000000000000 + 1000000000000000000 + 300000000000000000 + 0 +) +PUSH3EOF + +(cd "$SCRIPT_DIR" && node --loader ts-node/esm src/index.ts "$INPUT_PUSH3" "$OUTPUT_SOL" 2>/dev/null) + +SOL_CONTENT=$(cat "$OUTPUT_SOL") + +assert_not_contains \ + "anchorWidth: no raw uint24(1000000000000000000) literal" \ + "$SOL_CONTENT" \ + "uint24(1000000000000000000)" + +assert_contains \ + "anchorWidth: output uses % (2**24) clamping" \ + "$SOL_CONTENT" \ + "uint24(1000000000000000000 % (2**24))" + +# ── Summary ────────────────────────────────────────────────────────────────── +echo "" +echo "Results: $PASS passed, $FAIL failed" +[ "$FAIL" -eq 0 ]