Skip to content

fix(soroban): extract escrow_contract into its own crate to fix wasm build - #15

Merged
Meshmulla merged 1 commit into
stellar-kracken:mainfrom
Meshmulla:feature/1-split-escrow-contract-crate
Jul 16, 2026
Merged

fix(soroban): extract escrow_contract into its own crate to fix wasm build#15
Meshmulla merged 1 commit into
stellar-kracken:mainfrom
Meshmulla:feature/1-split-escrow-contract-crate

Conversation

@Meshmulla

Copy link
Copy Markdown
Contributor

Summary

Second follow-up to #13 (alongside #14). With the ethnum fix in #14 applied, the wasm build got further but then failed with:

error: symbol `initialize` is already defined
   --> soroban/src/escrow_contract.rs:112:1

Root cause

soroban/src/lib.rs's own top-level contract and escrow_contract.rs's TimeLockedEscrowContract both export a wasm symbol named initialize. Since both compile into the same cdylib, their wasm export tables collide. There's already a comment in lib.rs explaining that governance and insurance_pool were previously made test-only (#[cfg(test)]) for exactly this reason — escrow_contract just never got the same treatment and was still being compiled unconditionally into the release wasm artifact.

I checked all 18 #[contract]-bearing modules in the crate for method-name collisions; restricting to the ones that are actually compiled unconditionally (i.e. not already behind #[cfg(test)]), the only collision is this one: initialize between lib.rs and escrow_contract.rs.

Fix

Extract escrow_contract into its own workspace crate (escrow_contract/), matching the existing transfer_state_machine/ layout — its own Cargo.toml, its own wasm cdylib output. The module had zero crate:: dependencies on the rest of soroban, so this was a straight relocation:

  • soroban/src/lib.rs: drop pub mod escrow_contract;
  • soroban/Cargo.toml: drop the escrow_contract_test [[test]] entry
  • root Cargo.toml: add escrow_contract to workspace members
  • Cargo.lock: add the escrow-contract workspace member entry
  • README.md: document the new crate in the workspace table
  • escrow_contract/src/lib.rs: add #![no_std] at the crate root (it previously inherited this from soroban/src/lib.rs as a submodule; as its own crate root it needs the attribute itself, otherwise linking both std's and soroban-sdk's panic handler duplicates the panic_impl lang item under wasm32-unknown-unknownE0152)
  • Fixed a stale import in the moved test file that referenced the crate's pre-rename name bridge_watch_contracts instead of the current escrow_contract

Testing/validation performed

Pushed this change combined with #14's ethnum bump to a disposable branch and confirmed via a real GitHub Actions run that cargo build --release --target wasm32-unknown-unknown now succeeds for the full workspace (soroban, transfer_state_machine, and the new escrow_contract crate all compile). That disposable branch/run has been deleted — it was validation only, not a deliverable.

Note: cargo test still fails on main for reasons unrelated to this PR or #14 (several pre-existing, independent issues: stale bridge_watch_soroban crate-name references in a couple of test files, a test file missing a [[test]] entry causing an invalid auto-discovered target name, a field/method mismatch against the current soroban-sdk version, and a format! macro resolution issue under no_std). Those are out of scope here since they're unrelated to the wasm build collision this PR fixes — flagging for a separate follow-up.

Related

Building the workspace for wasm32-unknown-unknown failed with:

  error: symbol `initialize` is already defined
     --> soroban/src/escrow_contract.rs:112:1

The soroban crate's own top-level contract (in lib.rs) and
TimeLockedEscrowContract both export a wasm symbol named `initialize`.
Since they compiled into the same cdylib, the wasm export tables
collided. A comment already in lib.rs notes that governance and
insurance_pool were previously handled the same way (test-only via
#[cfg(test)]) for this exact reason, but escrow_contract had never
gotten that treatment and was still compiled unconditionally.

Fix: move escrow_contract.rs out of the soroban crate into its own
workspace member, `escrow_contract/`, matching the existing
transfer_state_machine crate layout (its own Cargo.toml, its own
wasm cdylib output). It has no dependency on any other soroban
module, so the move is a straight file relocation plus:

- soroban/src/lib.rs: drop `pub mod escrow_contract;`
- soroban/Cargo.toml: drop the escrow_contract_test [[test]] entry
- root Cargo.toml: add escrow_contract to workspace members
- Cargo.lock: add the escrow-contract workspace member entry
- README.md: document the new crate in the workspace table
- escrow_contract/src/lib.rs: add `#![no_std]` at the crate root.
  It previously inherited this from soroban/src/lib.rs as a submodule;
  as its own crate root it needs the attribute itself, otherwise it
  links libstd's panic_impl alongside soroban-sdk's own, which
  duplicates the lang item (E0152) under the wasm32 target.

Also fixed a stale import in the moved test file
(escrow_contract/tests/escrow_contract.test.rs) that referenced the
crate's pre-rename name `bridge_watch_contracts` instead of the
current `escrow_contract`.

Verified via a real GitHub Actions run (on a disposable branch,
combined with the ethnum bump from the companion PR) that
`cargo build --release --target wasm32-unknown-unknown` now succeeds
for the full workspace with these two changes together.
@Meshmulla
Meshmulla merged commit 7119be6 into stellar-kracken:main Jul 16, 2026
1 check failed
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