Skip to content

fix(encode): validate string format before BigInt conversion#178

Open
6figpsolseeker wants to merge 1 commit intodcccrypto:mainfrom
6figpsolseeker:fix/encode-validate-string-before-bigint
Open

fix(encode): validate string format before BigInt conversion#178
6figpsolseeker wants to merge 1 commit intodcccrypto:mainfrom
6figpsolseeker:fix/encode-validate-string-before-bigint

Conversation

@6figpsolseeker
Copy link
Copy Markdown

@6figpsolseeker 6figpsolseeker commented Apr 9, 2026

Summary

The encode helpers (encU64, encI64, encU128, encI128) and encodePushOraclePrice all accepted bigint | string but converted strings via raw BigInt(val) without format validation. This throws an unhelpful SyntaxError: Cannot convert X to a BigInt on inputs containing whitespace, scientific notation (1e6), decimal points (1.5), hex prefixes (0x1A), or other non-decimal-integer strings.

Since over 60 instruction arg fields across the SDK accept bigint | string, this is a systemic boundary issue affecting any consumer that passes user-supplied strings.

Changes

  • src/abi/encode.ts — Added safeBigInt(val, caller) helper that validates strings against /^-?(0|[1-9]\d*)$/ (same regex as validation.ts) before calling BigInt(). Replaced the raw BigInt(val) call in encU64, encI64, encU128, and encI128.
  • src/abi/instructions.ts:567encodePushOraclePrice had a direct BigInt(args.priceE6) that bypassed the encode helpers. Now inline-validated with the same regex.

Error messages are now clear and actionable:

encU64: string must be a decimal integer (got "1.5e6").
Example valid inputs: "0", "123", "-456"

This is a non-breaking change — all previously-valid inputs (bigint values and correctly-formatted decimal strings) produce identical results.

Test plan

  • npm run lint (tsc --noEmit) clean
  • npx vitest run test/encode.test.ts — all 54 tests pass
  • Full vitest run: same 14 pre-existing failures as main, zero new failures

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Enhanced validation for numeric encoding operations to enforce strict decimal integer formatting.
    • Improved error handling with more descriptive messages when invalid number formats are detected, replacing generic parsing errors with clear, context-specific feedback to help users identify and correct formatting issues.

The encode helpers (encU64, encI64, encU128, encI128) and
encodePushOraclePrice all accepted `bigint | string` but converted
strings via raw `BigInt(val)` without format validation. This throws
an unhelpful `SyntaxError: Cannot convert X to a BigInt` on inputs
containing whitespace, scientific notation (1e6), decimal points (1.5),
hex prefixes (0x1A), or other non-decimal-integer strings.

Since many instruction arg interfaces accept `bigint | string` (over
60 fields across the SDK), this is a systemic boundary issue. The fix
adds a shared `safeBigInt()` helper in encode.ts that validates the
string matches a strict decimal integer pattern before calling BigInt().
The regex is identical to the one already used in validation.ts for
input validators, ensuring consistency.

The helper produces a clear, actionable error message:
  encU64: string must be a decimal integer (got "1.5e6").
  Example valid inputs: "0", "123", "-456"

encodePushOraclePrice also had a direct `BigInt(args.priceE6)` call
that bypassed the encode helpers. This is now inline-validated with
the same regex pattern.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Added a safeBigInt helper function to validate string-to-bigint conversion using strict decimal-integer regex validation in src/abi/encode.ts, and applied similar pre-validation in src/abi/instructions.ts. Both changes replace raw BigInt() calls with controlled validation that rejects hex, octal, binary, scientific notation, and other non-decimal formats before conversion.

Changes

Cohort / File(s) Summary
String-to-BigInt Validation Helper
src/abi/encode.ts
Added safeBigInt helper with strict decimal-integer regex validation (optional leading -, digits without leading zeros). Updated encU64, encI64, encU128, encI128 to use the helper for string inputs, replacing raw BigInt() calls with caller-specific error handling.
Oracle Price Validation
src/abi/instructions.ts
Added pre-validation for string priceE6 in encodePushOraclePrice using the same decimal-integer regex pattern before BigInt conversion. Non-string inputs bypass validation; downstream range checks remain unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A regex guard stands firm and true,
Protecting BigInt from what's askew,
No hex, no octal, no tricks in disguise—
Just decimal digits before our eyes! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding string format validation before BigInt conversion in encode helpers.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/abi/instructions.ts (1)

567-579: Consider de-duplicating decimal-integer validation logic.

Line 572-Line 577 reimplements the same string-to-bigint guard already present in src/abi/encode.ts. Centralizing this parser would keep regex and error semantics aligned across entry points.

♻️ Proposed refactor
-  const price = typeof args.priceE6 === "string"
-    ? (() => {
-        if (!/^-?(0|[1-9]\d*)$/.test(args.priceE6)) {
-          throw new Error(
-            `encodePushOraclePrice: priceE6 must be a decimal integer string (got ${JSON.stringify(args.priceE6)})`,
-          );
-        }
-        return BigInt(args.priceE6);
-      })()
-    : args.priceE6;
+  const price = typeof args.priceE6 === "string"
+    ? safeBigInt(args.priceE6, "encodePushOraclePrice")
+    : args.priceE6;
// Additional change outside this segment:
// src/abi/encode.ts
export function safeBigInt(val: string, caller: string): bigint { ... }

// src/abi/instructions.ts import list
import { ..., safeBigInt } from "./encode.js";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/abi/instructions.ts` around lines 567 - 579, Extract the string-to-BigInt
validation into a shared helper (e.g., export function safeBigInt(val: string,
caller: string): bigint) in src/abi/encode.ts and import it into
src/abi/instructions.ts; then replace the inline regex + BigInt block in the
encodePushOraclePrice path with a call to safeBigInt(args.priceE6,
"encodePushOraclePrice") (keeping the existing branch: if typeof args.priceE6
=== "string" then call safeBigInt else use args.priceE6) and add safeBigInt to
the import list from "./encode.js" so regex and error messages are centralized
and consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/abi/instructions.ts`:
- Around line 567-579: Extract the string-to-BigInt validation into a shared
helper (e.g., export function safeBigInt(val: string, caller: string): bigint)
in src/abi/encode.ts and import it into src/abi/instructions.ts; then replace
the inline regex + BigInt block in the encodePushOraclePrice path with a call to
safeBigInt(args.priceE6, "encodePushOraclePrice") (keeping the existing branch:
if typeof args.priceE6 === "string" then call safeBigInt else use args.priceE6)
and add safeBigInt to the import list from "./encode.js" so regex and error
messages are centralized and consistent.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3d14626b-1478-4940-9702-00f1ffecb720

📥 Commits

Reviewing files that changed from the base of the PR and between 2f80d79 and dbcccf4.

📒 Files selected for processing (2)
  • src/abi/encode.ts
  • src/abi/instructions.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant