Skip to content

Chapter 4

This chapter introduces the use of the use_contract macro to interact with other contracts. We have ContractProxy that serves as a middle-man to another contract MyLittlePony, the contract that we implemented in the last chapter. We are going to explore the interaction between the two contracts by calling entrypoint methods and sending tokens from the balance of one contract to another contract.


Firstly, use the macro use_contract to specify the contract entrypoint methods in a trait. The address is hard-coded when using this macro. It is recommended to remove or comment out the methods that are not intended to be used.

Recall that we have a deployed contract called MyLittlePony that consists of three methods, self_introduction(), grow_up(), and change_person(). We are going to use grow_up() in ContractProxy, so we can comment out the rest of them.

lib.rs: define a trait

use pchain_sdk::{
    use_contract, call, contract, contract_methods
};

#[use_contract("-jUt6jrEfMRD1JM9n6_yAASl2cwsc4tg1Bqp07gvQpU")]
pub trait MyLittlePony {
    //fn self_introduction() -> String;
    fn grow_up();
    //fn change_person(name: String, age: u32, gender_name: String, description: String);
}

After preparing the trait MyLittlePony, we start implementing the functionalities of ContractProxy.

The trait will be transformed to mod by using the macro use_contract, Calling the contract MyLittlePony can be simply calling associate methods according to the defined method in the trait. One way of calling grow_up() is to simply do my_little_pony::grow_up(0).

lib.rs: use_contract macro

#[contract]
pub struct ContractProxy {}

#[contract_methods]
impl ContractProxy {

    #[call]
    fn grow_up() {
        my_little_pony::grow_up(0);
    }
}

The above example has shown how we can use the use_contract macro to do cross-contract calls. It is also possible to use pchain_sdk::call_untyped() to do so. We pass the contract address as an argument so that the contract address does not need to be hard-coded in the contract.

lib.rs: pchain_sdk::call_untyped()

#[call]
fn grow_up_2(address: String) {
    let contract_address = base64url::decode(address).unwrap().try_into().unwrap();
    pchain_sdk::call_untyped(
        contract_address,
        "grow_up", 
        Vec::new(),
        0
    );
}

lib.rs: transfer contract balance

Except by calling the entrypoint methods from MyLittlePony, we can also transfer the balance from the contract to a specific address by pchain_sdk::transfer().

#[call]
fn send_tokens(to_address: String, value :u64){
    let contract_address = base64url::decode(to_address).unwrap().try_into().unwrap();
    pchain_sdk::transfer(
        contract_address,
        value
    );
}