fix(soroban): extract escrow_contract into its own crate to fix wasm build - #15
Merged
Meshmulla merged 1 commit intoJul 16, 2026
Conversation
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Second follow-up to #13 (alongside #14). With the
ethnumfix in #14 applied, the wasm build got further but then failed with:Root cause
soroban/src/lib.rs's own top-level contract andescrow_contract.rs'sTimeLockedEscrowContractboth export a wasm symbol namedinitialize. Since both compile into the samecdylib, their wasm export tables collide. There's already a comment inlib.rsexplaining thatgovernanceandinsurance_poolwere previously made test-only (#[cfg(test)]) for exactly this reason —escrow_contractjust 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:initializebetweenlib.rsandescrow_contract.rs.Fix
Extract
escrow_contractinto its own workspace crate (escrow_contract/), matching the existingtransfer_state_machine/layout — its ownCargo.toml, its own wasmcdyliboutput. The module had zerocrate::dependencies on the rest ofsoroban, so this was a straight relocation:soroban/src/lib.rs: droppub mod escrow_contract;soroban/Cargo.toml: drop theescrow_contract_test[[test]]entryCargo.toml: addescrow_contractto workspace membersCargo.lock: add theescrow-contractworkspace member entryREADME.md: document the new crate in the workspace tableescrow_contract/src/lib.rs: add#![no_std]at the crate root (it previously inherited this fromsoroban/src/lib.rsas a submodule; as its own crate root it needs the attribute itself, otherwise linking bothstd's andsoroban-sdk's panic handler duplicates thepanic_impllang item underwasm32-unknown-unknown—E0152)bridge_watch_contractsinstead of the currentescrow_contractTesting/validation performed
Pushed this change combined with #14's
ethnumbump to a disposable branch and confirmed via a real GitHub Actions run thatcargo build --release --target wasm32-unknown-unknownnow succeeds for the full workspace (soroban,transfer_state_machine, and the newescrow_contractcrate all compile). That disposable branch/run has been deleted — it was validation only, not a deliverable.Note:
cargo teststill fails onmainfor reasons unrelated to this PR or #14 (several pre-existing, independent issues: stalebridge_watch_sorobancrate-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 currentsoroban-sdkversion, and aformat!macro resolution issue underno_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
ethnumbump) — both are needed together forcargo build --release --target wasm32-unknown-unknownto succeed.