Skip to content

Add typed ERC-20 transfer encoding operation - #78

Merged
senamakel merged 7 commits into
mainfrom
wallet-erc20-encoding
Oct 11, 2026
Merged

senamakel merged 7 commits into
mainfrom
wallet-erc20-encoding

Conversation

@senamakel

Copy link
Copy Markdown
Member

Summary

Adds the typed EncodeErc20Transfer bus operation so OpenHuman can keep generic HTTP transport while ERC-20 calldata encoding remains in TinyWallet’s x402 implementation. The operation only adds serialized request/response vocabulary and a module dispatch; the existing calldata encoder remains the implementation source of truth.

The TinyWallet bus contract minor version advances to 1.13. Existing method names and arities remain unchanged.

Verification

  • cargo test -p tinywallet-bus --all-features (44 passed)
  • cargo test --all-features
  • cargo +stable clippy --all-targets --all-features -- -D warnings
  • cargo +stable build --all-targets --all-features
  • cargo fmt --all -- --check
  • Rust 1.88.0 scripts/test-e2e.sh: compiled TinyBus artifact loaded successfully; ERC-20 encoding and invalid-input behavior passed (2 module E2E tests, 1 lifecycle E2E test).

Local logs are in .migration-validation/wallet-erc20/ and are not part of the source diff.

senamakel and others added 7 commits October 11, 2026 20:38
Add a round-trip test asserting the explicit JSON shape of the ERC-20
transfer encode request and response, matching the existing wire-shape
tests for the other message types.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add a new bus method that encodes standard ERC-20 transfer calldata inside the module using the module-owned ABI implementation, exposing request and response wire types and bumping the contract version to 1.13.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Add an end-to-end case that calls EncodeErc20Transfer on the loaded
module and checks the calldata against the expected ABI encoding, so the
algorithm is proven to run inside the artifact rather than via host-linked
crypto. The same test asserts that an invalid recipient is rejected with
Web3OperationFailed, and the method is added to the expected manifest list.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Register the encode ERC20 transfer request and response types in the wire
module and expose the corresponding wallet service method, bringing the
dispatch table to 38 methods.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
ERC-20 transfer encoding failures now surface as InvalidInput instead of Web3OperationFailed, since malformed recipient or amount values are caller errors rather than upstream web3 faults. The end-to-end test was updated to expect the new error variant.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
Extend the lifecycle end-to-end test's expected method list to cover the
EncodeErc20Transfer RPC, keeping the assertion in sync with the module's
exposed interface.

Auto-committed-on: dragonfly
Co-authored-by: Medulla <medulla@tinyhumans.ai>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-11T18:00:38.494144Z d1d034d PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 11, 2026

Copy link
Copy Markdown

Review in Change Stack →

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c1021a8d-09b3-4582-aeac-d64b7a8bdea7

📥 Commits

Reviewing files that changed from the base of the PR and between fb33b3a and d1d034d.


📒 Files selected for processing (9)
  • crates/tinywallet-bus/src/lib_tests.rs
  • crates/tinywallet-bus/src/names/mod.rs
  • crates/tinywallet-bus/src/version/mod.rs
  • crates/tinywallet-bus/src/wire/mod.rs
  • crates/tinywallet-bus/src/wire/mod_tests.rs
  • crates/tinywallet-bus/src/wire/wallet.rs
  • crates/tinywallet-module/src/service/mod.rs
  • crates/tinywallet-module/tests/lifecycle_e2e.rs
  • crates/tinywallet-module/tests/module_e2e.rs

 ______________________________________________________
< GPU fans at max RPM: ready to blow away regressions. >
 ------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@senamakel
senamakel merged commit 3476626 into main Oct 11, 2026
28 of 29 checks passed
@tinysweeper

tinysweeper Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

Tiny Sweeper review

This pull request adds a new typed ERC-20 transfer encoding operation named `EncodeErc20Transfer` to the TinyWallet bus contract. It introduces request/response wire types, registers the method in the method-name list and contract version, implements the module-side handler delegating to `tinywallet_x402::abi::encode_erc20_transfer`, and updates unit and end-to-end tests. The contract version is bumped from (1, 12) to (1, 13). No review findings were reported across the critique, security, tests, and commits lanes; some reviewers did not produce usable responses for the module service file, the module e2e test file, and the PR description.

State: Incomplete
Priority: none
Reviewed head: d1d034d8a37a
Updated: 2026-10-12T02:38:25Z

Review snapshot

Change surface Files Review signal Count
Production 5 Active findings 0
Tests 4 Noted findings 0
Documentation 0 Resolved findings 0
Configuration 0 Pending checks/questions 4

Completeness: Incomplete
Test assessment: Test coverage is assessed from changed tests and lane evidence; execution is not claimed without trusted check data.

What changed

The wire contract gains `EncodeErc20TransferRequest` and `EncodeErc20TransferResponse` structs in `crates/tinywallet-bus/src/wire/wallet.rs`, both with `deny_unknown_fields`. The method name `EncodeErc20Transfer` is added to the `names::methods` constants and inserted into the sorted `METHODS` list, and the contract version is raised to (1, 13) in `crates/tinywallet-bus/src/version/mod.rs`. The re-export block in `crates/tinywallet-bus/src/wire/mod.rs` is reformatted to include the two new types. On the module side, `crates/tinywallet-module/src/service/mod.rs` adds an async `encode_erc20_transfer` handler that maps encoding errors to `invalid_input` and appends `EncodeErc20Transfer` to the exported method list. Test updates cover the wire shape and round trip, the cumulative method count, the module manifest expectations, and a new in-artifact encoding call with an invalid-address error path.

Features

  • Added — EncodeErc20Transfer wire types: Adds explicitly shaped, unknown-field-rejecting request and response structs carrying a recipient address plus decimal amount and hex calldata, re-exported from the bus wire module so hosts and the module share one typed contract. (crates/tinywallet-bus/src/wire/wallet.rs#use crate::Chain;, crates/tinywallet-bus/src/wire/mod.rs#pub use host::{)
  • Added — EncodeErc20Transfer method registration: Introduces the `EncodeErc20Transfer` method name constant and inserts it into the sorted `METHODS` list, so the operation becomes part of the dispatchable contract surface. (crates/tinywallet-bus/src/names/mod.rs#pub mod methods {, crates/tinywallet-bus/src/names/mod.rs#pub const METHODS: &[&str] = &[)
  • Modified — Contract version bump to (1, 13): Raises `CONTRACT_VERSION` from (1, 12) to (1, 13), signalling a minor contract change that hosts and modules use for compatibility binding. (crates/tinywallet-bus/src/version/mod.rs)
  • Added — Module-side ERC-20 transfer encoding handler: Implements `encode_erc20_transfer` inside the module, delegating calldata construction to the module-owned ABI implementation and converting encoding failures into `invalid_input`, and adds the method to the exported method list so it is advertised over the bus. (crates/tinywallet-module/src/service/mod.rs#mod exports {, crates/tinywallet-module/src/service/mod.rs#mod construction;)

Tests

  • unit — Verifies the ERC-20 encoding request and response wire shapes are explicit JSON objects and round-trip through serde, including a computed calldata string.: Covers serialization shape, `deny_unknown_fields` behavior indirectly, and deserialization round trip for both new wire types. (crates/tinywallet-bus/src/wire/mod_tests.rs)
  • unit — Updates the method-list assertions to expect 38 methods, checks the list is sorted and duplicate-free, and requires the new `EncodeErc20Transfer` member among native wallet members.: Keeps the canonical method-count and ordering invariants in sync with the added method. (crates/tinywallet-bus/src/lib_tests.rs#fn native_wallet_members_are_additive_and_use_one_typed_argument() {, crates/tinywallet-bus/src/lib_tests.rs#fn the_method_list_is_sorted_complete_and_free_of_duplicates() {)
  • unit — Asserts the contract version constant equals (1, 13) and that compatibility accepts the same or newer minor versions while rejecting a higher major version.: Locks the bumped version into the compatibility rule tests. (crates/tinywallet-bus/src/lib_tests.rs#fn network_request_keeps_legacy_json_and_omits_unset_endpoint_url() {)
  • e2e — Adds `encodes_erc20_transfers_inside_the_artifact` to the built-module broker test, calling `EncodeErc20Transfer` over a real broker, asserting exact selector-and-padded-arguments calldata, and asserting an invalid recipient yields an `InvalidInput` error string.: Exercises the operation through the actual bus boundary in the loaded artifact, including the error path; complements the added `EXPECTED_METHODS` entry asserting the manifest declares the method. (crates/tinywallet-module/tests/module_e2e.rs#async fn signs_an_evm_transfer_identically_to_the_library(proxy: &tinybus::Proxy, crates/tinywallet-module/tests/module_e2e.rs#async fn the_built_module_signs_every_chain_over_a_real_broker() {, crates/tinywallet-module/tests/module_e2e.rs#const EXPECTED_METHODS: &[&str] = &[, crates/tinywallet-module/tests/module_e2e.rs#use tinywallet::wire::{)
  • e2e — Updates the lifecycle end-to-end expected method list to include `EncodeErc20Transfer`.: Keeps the lifecycle manifest expectation aligned with the added method. (crates/tinywallet-module/tests/lifecycle_e2e.rs#const EXPECTED_METHODS: &[&str] = &[)
  • Unreviewed: tinysweeper/tests

Findings

No active actionable findings.

Could not review: crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/tests/module_e2e.rs, tinysweeper/description, tinysweeper/tests

Before merge

  • Complete the critique review for crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/tests/module_e2e.rs.
  • Complete the tests review for tinysweeper/tests.
  • Complete the description review for tinysweeper/description.

How this fits together

flowchart LR
  n0["...s_are_additive_and_use_one_typed_argument<br/>changed"]:::changed
  n1["...is_sorted_complete_and_free_of_duplicates<br/>changed"]:::changed
  n2["METHODS"]:::impacted
  n3["derive"]:::impacted
  n4["SecretMaterial"]:::impacted
  n5["...dule_signs_every_chain_over_a_real_broker"]:::impacted
  n6["NATIVE_WALLET_EXECUTE_PREPARED"]:::impacted
  n7["...ucts_evm_transactions_inside_the_artifact"]:::impacted
  n0 -->|uses| n6
  n1 -->|uses| n6
  n2 -->|uses| n6
  n5 -->|uses| n4
  n7 -->|calls| n3
  classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
  classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
  classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
  classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Loading
Agent review details

critique

  • Conclusion: Success
  • Scope reviewed: incomplete; unanswered: crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/tests/module_e2e.rs
  • Lane summary: Reviewed 7 files; 0 findings. 2 files could not be reviewed: crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/tests/module_e2e.rs. _The code index is behind this pull request (indexed at `35f2c9ec5706`), so retrieved context may be out of date._

security

  • Conclusion: Success
  • Scope reviewed: all assigned evidence
  • Lane summary: Reviewed 9 files; 0 findings. _The code index is behind this pull request (indexed at `35f2c9ec5706`), so retrieved context may be out of date._

tests

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: tinysweeper/tests
  • Lane summary: No reviewer produced a usable response.

commits

  • Conclusion: Neutral
  • Scope reviewed: all assigned evidence
  • Lane summary: Nothing sensitive found in what this pull request commits.

description

  • Conclusion: Neutral
  • Scope reviewed: incomplete; unanswered: tinysweeper/description
  • Lane summary: No reviewer produced a usable response.
Evidence and run details
  • Models: ladder/vectors-oai3, deepseek-v4.1-flash, glm-5.3-flash
  • Spend: $0.012824
  • Tokens: 892719 input · 66580 output · 224192 cached · 544 embedding
Head State Pass summary
d1d034d8a37a incomplete 0 active finding(s), 0 resolved finding(s) (at 2026-10-12T02:38:25Z)

tinysweeper 0.1.2

@tinysweeper tinysweeper Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

tinysweeper found nothing blocking, but could not review everything, so this is not an approval: crates/tinywallet-module/src/service/mod.rs, crates/tinywallet-module/tests/module_e2e.rs, tinysweeper/description, tinysweeper/tests.

             $0.0128 · 892,719 in / 66,580 out · 224,192 cached (25%) · ladder/vectors-oai3, deepseek-v4.1-flash, glm-5.3-flash · 544 embedded
critique:    $0.0026 · 401,367 in / 27,883 out · 93,440 cached (23%)  · deepseek-v4.1-flash
security:    $0.0096 · 425,839 in / 30,105 out · 109,248 cached (26%) · deepseek-v4.1-flash, glm-5.3-flash
tests:       $0.0003 · 39,436 in  / 3,763 out  · 15,360 cached (39%)  · deepseek-v4.1-flash
description: $0.0002 · 20,496 in  / 3,297 out  · 6,144 cached (30%)   · deepseek-v4.1-flash

@tinysweeper tinysweeper Bot added the priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect. label Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority: p3 Whenever. Cosmetic, a nicety, or a cleanup with no user visible effect.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant