Deployment Graph
In modern dApps, smart contracts rarely exist in isolation. A Liquidity Pool contract depends on Token contracts; a Governance Vault depends on Staking and Token contracts.
Caatinga handles multi-contract dependencies natively using a Topological Deployment Graph.
Defining Dependencies
Dependencies are declared in caatinga.config.ts using the dependsOn property:
export default defineConfig({
project: "defi-dapp",
defaultNetwork: "testnet",
contracts: {
token: {
path: "./contracts/token",
wasm: "./contracts/token/target/wasm32v1-none/release/token.wasm",
},
vault: {
path: "./contracts/vault",
wasm: "./contracts/vault/target/wasm32v1-none/release/vault.wasm",
dependsOn: ["token"],
deployArgs: { token: "${contracts.token.contractId}" },
},
market: {
path: "./contracts/market",
wasm: "./contracts/market/target/wasm32v1-none/release/market.wasm",
dependsOn: ["token", "vault"],
deployArgs: {
token: "${contracts.token.contractId}",
vault: "${contracts.vault.contractId}",
},
},
},
networks: {
testnet: {
rpcUrl: "https://soroban-testnet.stellar.org",
networkPassphrase: "Test SDF Network ; September 2015",
},
},
});
Graph Resolution & Order
When you execute npx ctg deploy, Caatinga resolves the graph:
token
│
├──────→ vault
│ │
└──────→ market
tokenhas 0 dependencies → Deployed first. Its Contract ID is recorded.vaultdepends ontoken→ Deployed second. Caatinga resolves the${contracts.token.contractId}placeholder invault’sdeployArgsfrom the artifacts. A placeholder must reference a contract listed independsOn; this is validated when the config loads.marketdepends ontokenandvault→ Deployed third once both prerequisites are confirmed on-chain.
Cycle Validation
Caatinga validates the DAG during config loading. If a cycle is detected (e.g. A depends on B and B depends on A), deployment halts immediately with error code CAATINGA_CONTRACT_DEPENDENCY_CYCLE.