DEV Community

yuzurush
yuzurush

Posted on • Updated on

Soroban Quest : Cross Contract

Hi there! Welcome to my "Soroban Quest" blog post series. Soroban Quest is a gamified educational course where you’ll learn Soroban (new smart contract platform by Stellar Foundation) and earn badge rewards!. In this series, i will explain steps to complete every soroban quest and help you understand more about soroban smart contract itself.

The 4th quest is called "Cross Contract". This quest will give you lesson how cross contract call works in Soroban.

Joining The Quest

To join the quest and get a Quest Account, use this command:

sq play 4
Enter fullscreen mode Exit fullscreen mode

And dont forget to fund the quest account right away.

Examining README.md

After examining README.md, I found that the tasks for the 4th quest is to:

  • Deploy DataStore contract from the 2nd quest using 4th quest account
  • Invoke put function from the deployed contract to store some data
  • Build CrossContractCallcontract, and deploy it
  • Invoke inv_get function from the deployed CrossContractCall contract to retrieve the data that you previously stored on the deployed DataStore contract

Lets read the contract code to get some more knowledge to do all that.

The Contract Code

#![no_std]
use soroban_sdk::{contractimpl, Address, Bytes, BytesN, Env};

/// We import the compiled binary from our auth store contract in Quest 2,
/// allowing us to use that contract's types and client in this contract.
mod storage_contract {
    // We do this inside a `mod{}` block to avoid collisions between type names
    soroban_sdk::contractimport!(file = "./soroban_auth_store_contract.wasm");
}

/// We define a `trait` which can be used to create shared behavior between
/// types, and can be used to group together signatures for related functions.
pub trait StorageCallTrait {
    // We define in this trait that the `inv_get()` function will accept:
    // - `store_id`: the other contract we are going to invoke
    // - `owner`: the `Address` that was used to `put` data to that contract
    // This funtion will return the data that was stored, in `Bytes`
    fn inv_get(env: Env, store_id: BytesN<32>, owner: Address) -> Bytes;
}

pub struct CrossContractCallContract;

/// The `CrossContractCall` contract implements the trait we defined earlier,
/// and fleshes out what the `inv_get()` function should do with it arguments
/// and how it should create the value to return.
#[contractimpl]
impl StorageCallTrait for CrossContractCallContract {
    /// The `inv_get()` function will create a new client to the auth store
    /// contract, and cross-invoke the `get` function, supplying the `owner`
    /// argument we provide when we invoked `inv_get`.
    fn inv_get(env: Env, store_id: BytesN<32>, owner: Address) -> Bytes {
        let storage_client = storage_contract::Client::new(&env, &store_id);
        storage_client.get(&owner)
    }
}

mod test;

Enter fullscreen mode Exit fullscreen mode

The contract is located in lib.rs and contains one function:

  • inv_get() - Retrieves data by calling get function on an instance of the auth_store_contract, passing in an owner address

The contract also imports the compiled code of another contract (auth_store_contract) using contractimport. This allows it to use that other contract's types and client within this contract.So in summary, this contract can be used to invoke the get method on an instance of the auth_store_contract, passing in an owner address. It will return the data stored for that owner in the other contract.
This allows contracts to build on and compose other contracts, reusing their functionality. Contracts don't have to be self-contained, but can interact with and use other contracts.

Building The Contract

To build the contract, use the following command:

cd quests/4-cross-contract
cargo build --target wasm32-unknown-unknown --release
Enter fullscreen mode Exit fullscreen mode

This should output a .wasm file in the ../target directory:

../target/wasm32-unknown-unknown/release/soroban_cross_contract_call_contract.wasm
Enter fullscreen mode Exit fullscreen mode

Deploying The Contracts

We need to deploy DataStoreContract contract and CrossContractCall contract, to deploy DataStoreContract contract use this following command :

soroban contract deploy --wasm /workspace/soroban-quest/quests/4-cross-contract/soroban_auth_store_contract.wasm
Enter fullscreen mode Exit fullscreen mode

Save the contract ID for later.
Next is to deploy DataStoreContract contract, usig this command :

soroban contract deploy --wasm /workspace/soroban-quest/target/wasm32-unknown-unknown/release/soroban_cross_contract_call_contract.wasm
Enter fullscreen mode Exit fullscreen mode

Save the contract ID for later.

Storing Data using Deployed DataStoreContract Contract

To store data we will invoke put function from the deployed DataStoreContract, using this command format :

soroban contract invoke --id <DeployedDataStoreContractID> -- put --user <QuestPublicKey> --value '<StoredDataInHex>'
Enter fullscreen mode Exit fullscreen mode

Note : To convert string to hex use echo "YourString" | xxd -p

StoreData

Retrieving Stored Data using deployed CrossContractCall Contract

To retrieve the data that we stored earlier, we will invoke inv_get function from the deployed CrossContractCall, using this command format :

soroban contract invoke --id <DeployedCrossContractCallContractID> -- inv_get --store_id '<DeployedDataStoreContractID>' --owner <QuestPublicKey>   
Enter fullscreen mode Exit fullscreen mode

Cross Contract Call

Checking the Quest

We already completed every step to complete the quest and this is the last thing you need to do. Check your quest and claim your badge reward. To check use the following command :

sq check 4
Enter fullscreen mode Exit fullscreen mode

Congratulations! You have already completed 4 out of 6 quests. You have 2 more to go.

Top comments (0)