Multi-Contract dApp
Multi-contract architecture is a normal pattern in Xian. You do not need to force all business logic into one contract.
A Practical Split
A common split is:
- one contract for token or accounting state
- one contract for domain logic
- one contract for governance, registry, or upgrade coordination
This keeps each contract smaller and makes permission boundaries easier to reason about.
The Main Building Blocks
Xian supports several composition tools:
- static imports for fixed dependencies
importlib.import_module(...)for runtime-selected contractsimportlib.exists(...)andimportlib.has_export(...)for safe probingimportlib.call(...)for dynamic exported-function dispatchimportlib.enforce_interface(...)for contract-shape checksForeignVariableandForeignHashfor read-only state accessimportlib.contract_info(...)andimportlib.code_hash(...)for metadata and artifact verification
Security Rules
The biggest design trap is confusing the immediate caller with the original signer.
Across a contract-to-contract call:
ctx.callerbecomes the calling contractctx.signerstays the original external user
Use that split deliberately when designing permission checks.
Recommended Workflow
- define the stable contract interfaces first
- keep cross-contract writes explicit and minimal
- use interface checks for anything that can be swapped or chosen dynamically
- test the contracts together with
ContractingClient - if you need allowlists, persist contract names or code hashes explicitly
When Dynamic Dispatch Makes Sense
Dynamic dispatch is useful for:
- plugin registries
- governance-selected modules
- factory-driven integrations
- adapter patterns
If the dependency is fixed forever, prefer static imports instead.