Skip to content

fix(onchain): remove SorobanOnchainAdapter stub that fabricated success - #449

Merged
kilodesodiq-arch merged 1 commit into
ChainForgee:mainfrom
lovesmilesmall-hue:fix/issue-426-remove-fake-onchain-adapter
Aug 20, 2026
Merged

fix(onchain): remove SorobanOnchainAdapter stub that fabricated success#449
kilodesodiq-arch merged 1 commit into
ChainForgee:mainfrom
lovesmilesmall-hue:fix/issue-426-remove-fake-onchain-adapter

Conversation

@lovesmilesmall-hue

Copy link
Copy Markdown
Contributor

Summary

Closes #426

SorobanOnchainAdapter implemented OnchainAdapter but could never drive the aid_escrow contract: its invokeContract posted a hand-rolled {contractId, method, args} JSON blob to simulateTransaction/sendTransaction (no XDR envelope, signature, or fee), called non-existent contract methods (initialize, claim_package, disburse_package, a 6-arg create_package), and returned status: 'success' with an empty transactionHash for every mutation regardless of what the RPC returned. It was superseded by SorobanAdapter but never deleted — exported dead code that reads as a working adapter and silently corrupts the audit trail if selected. This PR deletes it entirely and locks the canonical SorobanAdapter to the correct behavior with a regression spec.

The single most important design decision: delete, don't repair. The class is unreferenced (its only importers are its own file and the coverage baseline), the module already registers MockOnchainAdapter/SorobanAdapter only, and the issue's proposed design explicitly names removal as the fix. Keeping two *soroban*.adapter.ts files invites re-wiring; the guardrail is now a test that fails if any adapter submits a JSON blob instead of a real envelope.

Why

The OnchainAdapter interface masks the gap — every method returns status: 'success' | 'failed' and a string transactionHash, so a stub satisfies the type system while doing nothing. The old class exploited exactly that: createAidPackage/claimAidPackage/disburseAidPackage returned status: 'success' and transactionHash: '' unconditionally, and amountClaimed/amountDisbursed were hardcoded '0'. Because onchain.module.ts never registered it, the damage was latent — but any ONCHAIN_ADAPTER=soroban-onchain-style config (or a future contributor "fixing" the wiring) would have observed success for every operation while nothing was written on-chain. The existing onchain.module.spec.ts asserted only that an adapter instance was created, not that calls produce real transactions — the regression spec closes that hole.

What was built

Deleted:

  • app/backend/src/onchain/soroban-onchain.adapter.ts — the fabricated adapter. Fully superseded by soroban.adapter.ts (SorobanAdapter), which builds real envelopes via TransactionBuilder, signs with the admin keypair, simulates, submits, and polls for confirmation. Deleting it also removes the duplicate export { ONCHAIN_ADAPTER_TOKEN } re-export.

Modified:

  • app/backend/test/coverage-baseline.json — removed the stale per-file coverage entry for the deleted adapter (regenerating the baseline would produce the same; the entry referenced a file that no longer exists).

Added (matching test file):

  • app/backend/src/onchain/soroban.adapter.spec.ts — 5 regression tests that mock @stellar/stellar-sdk's RPC boundary (rpc.Server with simulateTransaction/sendTransaction/getTransaction, TransactionBuilder, Contract, Keypair) and assert:
    1. createAidPackage passes a real TransactionBuilder-built envelope (an object with toEnvelope/toXDR) to simulateTransaction and sendTransaction — the JSON-blob payload from the deleted class would fail these assertions (JSON.stringify of the payload must not contain contractId/method/args).
    2. A failed simulation rejects with Contract simulation error instead of returning status: 'success'.
    3. A submission that is not PENDING/DUPLICATE rejects.
    4. A confirmed-but-FAILED transaction rejects.
    5. The envelope targets the contract's real create_package entrypoint with a real Contract.call operation (the stub used a 6-arg JSON blob).

Acceptance criteria coverage

  • soroban-onchain.adapter.ts is deleted or reimplemented to sign and submit real Soroban envelopes, and exactly one canonical Soroban adapter remains for the soroban config value. (File deleted; onchain.module.ts registers only SorobanAdapter for soroban, asserted by the existing createOnchainAdapter module spec.)
  • No adapter returns status: 'success' with an empty transactionHash after a failed or never-sent transaction. (soroban.adapter.spec.ts — success is only returned with a 64-char confirmed hash; simulation failure, non-PENDING submission, and FAILED receipt all reject.)
  • A test fails if an adapter's simulateTransaction payload is not a valid Soroban envelope (no {contractId, method, args} JSON blob), and passes for SorobanAdapter. (soroban.adapter.spec.ts — first test asserts the payload is an envelope object with toEnvelope/toXDR and that JSON.stringify(payload) contains no contractId/method/args keys; the deleted class's payload shape fails this assertion by construction.)

Test plan

  • jest src/onchain src/onchain/utils — 26/26 passing (5 new)
  • jest (full backend unit suite) — 557 passed, 10 skipped, 0 failed (5 new tests for this feature)
  • jest --config ./test/jest-coverage.js --coverage src/onchain/soroban.adapter.spec.ts — 5/5 passing under the CI coverage config
  • eslint (backend eslint.config.mjs) — 0 errors on changed files
  • prettier --check — clean
  • nest build — succeeds

Env vars / Notes

No new environment variables; no config values change (soroban was and remains the only Soroban adapter value). The deleted class's SOROBAN_RPC_URL/SOROBAN_CONTRACT_ID/SOROBAN_SECRET_KEY/STELLAR_NETWORK env vars were never read by anything else — SorobanAdapter uses AID_ESCROW_CONTRACT_ID, STELLAR_RPC_URL, STELLAR_NETWORK_PASSPHRASE, SOROBAN_NETWORK, and SOROBAN_ADMIN_SECRET_KEY — so no deployment config needs to change.

SorobanOnchainAdapter posted a hand-rolled {contractId, method, args}
JSON blob to simulateTransaction/sendTransaction — not a Soroban
envelope — and returned status 'success' with an empty transactionHash
for every mutation, silently corrupting the audit trail. Delete it and
its stale coverage-baseline entry, keeping SorobanAdapter as the single
canonical adapter, and add a regression spec proving the adapter
submits real TransactionBuilder-built envelopes and only reports
success with a confirmed non-empty hash.

@kilodesodiq-arch kilodesodiq-arch left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@kilodesodiq-arch
kilodesodiq-arch merged commit 32b73a5 into ChainForgee:main Aug 20, 2026
5 checks passed
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.

SorobanOnchainAdapter fabricates success from a fake RPC payload: it cannot drive aid_escrow and is not registered

2 participants