In this example there are two contracts that are compiled separately, deployed separately, and then tested together. There are a variety of ways to develop and test contracts with dependencies on other contracts, and the Soroban SDK and tooling is still building out the tools to support these workflows. Feedback appreciated here.
Run the Example
First go through the Setup process to get your development environment configured, then clone thev23.0.0 tag of soroban-examples repository:
cargo test from Contract B’s directory. Build Contract A by navigating to the cross_contract/contract_a directory and use the stellar contract build build command:
cross_contract/contract_b directory, and use cargo test.
Code
cross_contract/contract_a/src/lib.rs
cross_contract/contract_b/src/lib.rs
How it Works
Cross contract calls are made by invoking another contract by its contract ID. Contracts to invoke can be imported into your contract with the use ofcontractimport!(file = "..."). The import will code generate:
- A
ContractClienttype that can be used to invoke functions on the contract. - Any types in the contract that were annotated with
#[contracttype].
Contract A: The Contract to be Called
The contract to be called is Contract A. It is a simple contract that acceptsx and y parameters, adds them together and returns the result.
cross_contract/contract_a/src/lib.rs
Contract B: The Contract doing the Calling
The contract that does the calling is Contract B. It accepts a contract ID that it will call, as well as the same parameters to pass through. In many contracts the contract to call might have been stored as contract data and be retrieved, but in this simple example it is being passed in as a parameter each time. The contract imports Contract A into thecontract_a module.
The contract_a::Client is constructed pointing at the contract ID passed in.
The client is used to execute the add function with the x and y parameters on Contract A.
cross_contract/contract_b/src/lib.rs
Tests
Open thecross_contract/contract_b/src/test.rs file to follow along.
cross_contract/contract_b/src/test.rs
Env, which is the Soroban environment that the contract will run in.
impl block that is annotated with the #[contractimpl] attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with Client appended. For example, in our contract the contract type is ContractB, and the client is named ContractBClient. The client can be constructed and used in the same way that client generated for Contract A can be.
add_with function on Contract B. Contract B will invoke Contract A, and the result will be returned.
Build the Contracts
To build the contract into a.wasm file, use the stellar contract build command. Both contract_call/contract_a and contract_call/contract_b must be built, with contract_a being built first.
.wasm files should be found in both contract target directories after building both contracts:
Run the Contract
If you havestellar-cli installed, you can invoke contract functions. Both contracts must be deployed.
- macOS/Linux
- Windows (PowerShell)
add_with function, passing in values for x and y (e.g. as 5 and 7), and then pass in the contract ID or alias of Contract A.
- macOS/Linux
- Windows (PowerShell)
add_with function invoked Contract A’s add function to do the addition.