Replace ts-node with tsx across all push3-transpiler scripts: - inject.sh: npx ts-node → npx tsx - test_inject_extraction.sh: node --loader ts-node/esm → npx tsx - test_transpiler_clamping.sh: node --loader ts-node/esm → npx tsx - package.json: ts-node devDep → tsx, transpile script updated - tsconfig.json: removed ts-node config block - src/index.ts: updated usage comments Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
268 lines
8.1 KiB
Bash
Executable file
268 lines
8.1 KiB
Bash
Executable file
#!/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 5: anchorWidth literal > uint24 max → transpiler error ──────────────
|
|
echo "Test 5: 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 6: valid anchorWidth literal (in range) → accepted, wraps with % (2**24) ─
|
|
echo "Test 6: 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 7: negative ci literal → transpiler error ───────────────────────────
|
|
echo "Test 7: 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 8: negative anchorShare literal → transpiler error ──────────────────
|
|
echo "Test 8: 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 9: negative discoveryDepth literal → transpiler error ───────────────
|
|
echo "Test 9: 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 10: negative anchorWidth literal → transpiler error ─────────────────
|
|
echo "Test 10: 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 11: forge build — transpiler output compiles (regression for #900) ──
|
|
echo "Test 11: 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 12: ci literal > 1e18 → transpiler error ────────────────────────────
|
|
echo "Test 12: 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 13: anchorShare literal > 1e18 → transpiler error ───────────────────
|
|
echo "Test 13: 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 14: discoveryDepth literal > 1e18 → transpiler error ────────────────
|
|
echo "Test 14: 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 ]
|