Skip to content

test: failing repros for confirmed v2-dev bugs (fixes to follow)#201

Open
MuncleUscles wants to merge 1 commit into
v2-devfrom
claude/new-dev-bug-hunting-eo2cic
Open

test: failing repros for confirmed v2-dev bugs (fixes to follow)#201
MuncleUscles wants to merge 1 commit into
v2-devfrom
claude/new-dev-bug-hunting-eo2cic

Conversation

@MuncleUscles

Copy link
Copy Markdown
Member

What

Adds tests/bug-hunt-v2dev.test.ts12 failing tests, each reproducing a distinct, confirmed defect on v2-dev (the v0.6 integration branch). This PR intentionally contains no fixes; the tests are the deliverable so a follow-up change can be validated against them. Every test documents the file:line and root cause inline.

All 114 pre-existing tests still pass; only these 12 new tests fail.

Wrong results

# Area File:line Bug
1 calldata toString() src/abi/calldata/string.ts:8-16 Map entries emitted with no separator{"a":1"b":2} (array branch adds ,; the map branch doesn't). Corrupts the readable field of decoded receipts.
2 calldata toString() src/abi/calldata/string.ts:48-52, 62-66 Per-byte hex uses b.toString(16) with no padStart(2,"0")[0x01,0x02] and [0x12] both render b#12; addresses render with <40 hex chars.
3 toJsonSafeDeep() src/utils/jsonifier.ts:~90-94 Cycle-guard seen.add(value) is never released, so a DAG (same object referenced twice) has its 2nd occurrence replaced with null. Reachable from readContract output.
4 createClient({endpoint}) src/client/client.ts:~132-135 chainConfig.rpcUrls.default.http = [endpoint] mutates the shared imported chain singleton in place; one client's endpoint override leaks into every other client (and later createClient() calls).
5 schema strictTypes src/contracts/schema.ts:101-113 Struct validation only runs if (isPlainObject(value)); a non-object scalar falls through to return true and is accepted as a struct.
6 schema strictTypes src/contracts/schema.ts:55 'int' accepts any typeof === "number", so 1.5/NaN pass validation and then crash later inside calldata.encode.
7 staking getValidatorInfo() src/staking/actions.ts:473 toHex(identityRaw.extraCid) double-encodes — viem already returns bytes as hex, so 0xdeadbeef becomes 0x30786465616462656566 (hex of the ASCII "0xdeadbeef"). Breaks the SDK's own setIdentitygetValidatorInfo round-trip.
8 vesting encodeExtraCid() src/vesting/actions.ts:95-99 Blind startsWith("0x") cast with no isHex/even-length check; an odd-length CID is silently right-padded by viem (0x1230x1230) and written on-chain with no error.
9 isSuccessful() src/transactions/actions.ts:68-86 Requires executionResultName === FINISHED_WITH_RETURN, derived only from txExecutionResult(Name) — fields the studio/localnet getTransaction path never populates. A finalized, successful studio tx is reported as unsuccessful.

Instability

# Area File:line Bug
10 calldata decode() src/abi/calldata/decoder.ts:52-73 TYPE_ARR/TYPE_MAP element counts are taken straight off the wire and drive a while/slice loop with no bound against remaining bytes. A tiny malformed payload forces multi-second allocation before erroring (a fixed impl should reject in O(1)). Relevant because decode() runs on consensus/validator-supplied bytes.
11 vesting exit src/vesting/actions.ts:310, 362 BigInt(options.shares) turns "" into 0n, silently signing & broadcasting a zero-share exit instead of rejecting the input.
12 staking API drift src/staking/actions.ts:550 Commit a338ad5 advertised the helper as isValidatorBelowMinStake, but it's implemented as isValidatorBelowMin, so the documented name is missing at runtime (caller gets is not a function). It is also absent from the StakingActions type.

Why

These were surfaced by a focused bug hunt across the recent v0.6 work (calldata, fees/transactions, staking, vesting, accounts/contracts, utils/client). Each one can produce silently wrong results or client instability. Landing the repros first lets the fix PR be verified objectively.

Testing done

  • vitest run → 114 pre-existing tests pass, the 12 new tests fail on their intended assertions (no harness errors).
  • vitest --typecheck → the new file typechecks clean (all reds are assertions).
  • Verified test isolation: the createClient singleton-mutation test restores localnet in a finally, so it does not pollute the rest of the run.

Decisions made

  • Tests only, no fixes — per the task, a separate change will implement the fixes and turn these green.
  • Where encodeExtraCid / the double-encode are internal, tests exercise them black-box through the public actions and decode the resulting calldata.
  • Not turned into a failing test (flagged for the fixer): accountActions.transfer (src/accounts/actions.ts:95) unconditionally calls waitForTransactionReceipt, but every other send lane returns early on chain.isStudio (see src/contracts/actions.ts:2363-2367). On a Studio localnet there is no EVM receipt, so a transfer would block ~180s then throw. No test is included because the correct fix is genuinely ambiguous (reject Studio early vs. synthesize a receipt — the method's return type is TransactionReceipt) and could not be reproduced against a live Studio backend.
  • Investigated and cleared (not bugs): the baseline Position 42 is out of bounds RLP stderr in transactions.test.ts (benign — decodeInputData catches it and returns null); fee/budget math vs. the studio reference; call-key derivation; v0.6 enum remaps; vesting ABI signatures vs. the on-chain contracts.

Checks

  • I have tested this code
  • I have reviewed my own PR
  • I have created an issue for this PR
  • I have set a descriptive PR title compliant with conventional commits

Reviewing tips

Read the inline comments in tests/bug-hunt-v2dev.test.ts — each describe block names the file:line and root cause, and each assertion notes the actual (buggy) value it observes today.

User facing release notes

None yet — this PR only adds failing regression tests. User-facing notes will accompany the fixes.

🤖 Generated with Claude Code


Generated by Claude Code

Adds tests/bug-hunt-v2dev.test.ts: 12 tests, each reproducing a distinct
confirmed defect on the v2-dev (v0.6) integration branch. Every test is
expected to FAIL against current code and should pass once the underlying
bug is fixed. File:line and root cause are documented inline per block.

Wrong results:
- calldata toString(): map entries emitted with no separator ({"a":1"b":2})
- calldata toString(): per-byte hex not zero-padded (distinct bytes collide)
- toJsonSafeDeep(): shared (non-cyclic) references replaced with null
- createClient({endpoint}): mutates the shared chain-config singleton
- schema strictTypes: non-object accepted for struct param; float/NaN for int
- staking getValidatorInfo(): toHex() double-encodes already-hex extraCid
- vesting encodeExtraCid(): odd-length hex silently corrupted (0x123 -> 0x1230)
- isSuccessful(): always false for finalized studio/localnet transactions

Instability:
- calldata decode(): trusts attacker-supplied array/map counts (unbounded work)
- vesting exit: BigInt("") coerces empty shares to 0n and broadcasts
- staking: advertised isValidatorBelowMinStake helper missing at runtime

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Xrmnk8SQeW3Aju4M7QHut
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bf7db6c7-da57-47a0-8a36-1a4d190cdc79

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/new-dev-bug-hunting-eo2cic

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.

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.

2 participants