Skip to content

feat(withdrawal): add canonical Base-to-Nockchain codec - #8

Open
ryjm wants to merge 12 commits into
nockbox:mainfrom
ryjm:ryjm/withdrawal-codec
Open

ryjm wants to merge 12 commits into
nockbox:mainfrom
ryjm:ryjm/withdrawal-codec

Conversation

@ryjm

@ryjm ryjm commented Sep 1, 2026 •

Copy link
Copy Markdown

Summary

This PR adds the canonical Iris codec for withdrawals from Base to Nockchain.

The codec resolves a Nockchain destination. It also checks withdrawal-policy-v1 and creates the exact contract calldata.

Changes

  • The codec encodes, decodes, and checks WithdrawalWireV1 data.
  • The SDK resolves v1_pkh and lock-root destinations.
  • The SDK calculates the TIP-5 limbs and the destination commitment.
  • The policy checks the 100,000-NOCK minimum, exact divisibility, addresses, and stale data.
  • The SDK returns a WithdrawalWireError code for each malformed input or policy error.
  • The package exports the codec from the main entry point and the withdrawal entry point.
  • The package includes the canonical Rust vectors.
  • These vectors check byte-for-byte compatibility.
  • The package includes a deterministic Node 22 test driver.
  • The driver metadata contains the Git revision and the package hashes.
  • The package version is 0.3.3.

Safety

  • A client must use the returned calldata without a change for simulation, gas estimation, and submission.
  • A client must create new calldata after a change to the account, chain, token, amount, or destination.
  • The burn(uint256,bytes32) call omits part of the destination.
  • A client must not use this call for a withdrawal.

Tests

  • npm test passed 20 tests.
  • npm run typecheck passed.
  • npm run format:check passed.
  • npm run test:pack-readiness passed 15 tests.
  • The full withdrawal test used Iris revision 34f00b991e5050d877d9691c185883c409c5755f.
  • The full withdrawal test passed.

Related changes

  • NockSwap uses this exact Iris revision.
  • The Nockchain test used stacked head fc7d912cb5ee22e57137dc0eb7f1a93007132626.

Nockchain PR stack

Review and merge the Nockchain PRs in this order:

  1. PR #169: Define the canonical withdrawal protocol
  2. PR #170: Make withdrawal state recoverable and queryable
  3. PR #171: Enforce reorg-safe single-flight settlement
  4. PR #172: Add the deterministic withdrawal harness
  5. PR #173: Prove final withdrawal settlement
  6. PR #174: Model and replay withdrawal failures
  7. PR #175: Add the production browser path

@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds the canonical Base-to-Nockchain withdrawal codec, destination resolution, policy validation, deterministic E2E packaging, and protocol vectors. It also updates the package exports, dependencies, version, and CI runtime.

  • Encodes, decodes, and validates the 116-byte WithdrawalWireV1 calldata format.
  • Resolves lock-root and v1_pkh destinations and calculates withdrawal commitments and fees.
  • Adds a bundled Node 22 E2E driver, deterministic package metadata, and canonical compatibility tests.
  • Removes the existing public WASM guard namespace while changing upstream WASM import specifiers.

Confidence Score: 4/5

The public WASM guard API needs to be restored before merging so existing consumers do not break.

The withdrawal implementation is extensively validated, but the wrapper now omits the previously exported guard namespace that remains reachable through the package’s public wasm API.

Files Needing Attention: src/wasm.ts

Important Files Changed

Filename Overview
src/withdrawal.ts Adds destination resolution, amount-policy enforcement, commitment calculation, and canonical calldata encoding and validation.
src/wasm.ts Changes upstream module specifiers but also removes the established public guard namespace, breaking existing root-package consumers.
scripts/encode-withdrawal-e2e.ts Adds a strict JSON E2E driver that resolves destinations, encodes withdrawals, and returns deterministic success or error responses.
scripts/prepare-withdrawal-e2e-package.ts Adds clean-checkout validation, deterministic npm packaging, package-content checks, and integrity metadata generation.
package.json Publishes the withdrawal subpath, includes fixtures, adds the E2E build and test lifecycle, and bumps the package version.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Client withdrawal request] --> B[Resolve destination]
  B --> C[Validate amount policy]
  C --> D[Calculate commitment]
  D --> E[Encode 116-byte calldata]
  E --> F[Decode and self-validate]
  F --> G[Simulation and submission]
Loading
Prompt To Fix All With AI
### Issue 1
src/wasm.ts:5-6
**WASM guard namespace removed**

When an existing consumer accesses `wasm.guard` through the root SDK export, the wrapper no longer provides the previously exported guard namespace, causing compile-time failures or an `undefined` runtime value in validation paths.

```suggestion
export * from '@nockbox/iris-wasm/iris_wasm.js';
export { default } from '@nockbox/iris-wasm/iris_wasm.js';
export * as guard from '@nockbox/iris-wasm/iris_wasm.guard';
```

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "chore: drop unused e2e driver plumbing" | Re-trigger Greptile

Comment thread src/wasm.ts
Comment on lines +5 to +6
export * from '@nockbox/iris-wasm/iris_wasm.js';
export { default } from '@nockbox/iris-wasm/iris_wasm.js';

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 WASM guard namespace removed

When an existing consumer accesses wasm.guard through the root SDK export, the wrapper no longer provides the previously exported guard namespace, causing compile-time failures or an undefined runtime value in validation paths.

Suggested change
export * from '@nockbox/iris-wasm/iris_wasm.js';
export { default } from '@nockbox/iris-wasm/iris_wasm.js';
export * from '@nockbox/iris-wasm/iris_wasm.js';
export { default } from '@nockbox/iris-wasm/iris_wasm.js';
export * as guard from '@nockbox/iris-wasm/iris_wasm.guard';

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/wasm.ts
Line: 5-6

Comment:
**WASM guard namespace removed**

When an existing consumer accesses `wasm.guard` through the root SDK export, the wrapper no longer provides the previously exported guard namespace, causing compile-time failures or an `undefined` runtime value in validation paths.

```suggestion
export * from '@nockbox/iris-wasm/iris_wasm.js';
export { default } from '@nockbox/iris-wasm/iris_wasm.js';
export * as guard from '@nockbox/iris-wasm/iris_wasm.guard';
```

**Knowledge Base Used:**
- [WASM cryptographic integration](https://app.greptile.com/nockbox/-/custom-context/knowledge-base/nockbox/iris-sdk/-/docs/wasm-cryptographic-integration.md)
- [WASM wrapper and declarations](https://app.greptile.com/nockbox/-/custom-context/knowledge-base/nockbox/iris-sdk/-/docs/wasm-wrapper-and-declarations.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

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