Skip to content

Commit

Permalink
chore: Update cross-contract calls in documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
kpob committed Jul 30, 2024
1 parent c76f9ba commit 957dddb
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 21 deletions.
43 changes: 33 additions & 10 deletions docusaurus/docs/basics/10-cross-calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ description: Contracts calling contracts
To show how to handle calls between contracts, first, let's implement two of them:

```rust title="examples/src/features/cross_calls.rs"
use odra::prelude::*;
use odra::{Address, UnwrapOrRevert, Var};
use odra::{prelude::*, Address, External};

#[odra::module]
pub struct CrossContract {
pub math_engine: Var<Address>
pub math_engine: External<MathEngineContractRef>
}

#[odra::module]
Expand All @@ -23,8 +22,7 @@ impl CrossContract {
}

pub fn add_using_another(&self) -> u32 {
let math_engine_address = self.math_engine.get().unwrap_or_revert(&self.env());
MathEngineContractRef::new(self.env(), math_engine_address).add(3, 5)
self.math_engine.add(3, 5)
}
}

Expand All @@ -38,11 +36,26 @@ impl MathEngine {
}
}
```
`MathEngine` contract can add two numbers. `CrossContract` takes an `Address` in its init function and saves it in
`MathEngine` contract can add two numbers. `CrossContract` takes an `Address` in its `init` function and saves it in
storage for later use. If we deploy the `MathEngine` first and take note of its address, we can then deploy
`CrossContract` and use `MathEngine` to perform complicated calculations for us!

To perform a cross-contact call, we use the `{{ModuleName}}ContractRef` that was created for us by Odra:
To perform a cross-contact call, we use the `External` module component and wrap the `{{ModuleName}}ContractRef`
that was created for us by Odra:

```rust title="examples/src/features/cross_calls.rs"
pub struct CrossContract {
pub math_engine: External<MathEngineContractRef>
}
```

and then we use the `math_engine` like any other contract/module:

```rust title="examples/src/features/cross_calls.rs"
self.math_engine.add(3, 5)
```

Alternatively, we could store a raw `Address`, then use the `{{ModuleName}}ContractRef` directly:

```rust title="examples/src/features/cross_calls.rs"
MathEngineContractRef::new(self.env(), math_engine_address).add(3, 5)
Expand All @@ -53,11 +66,9 @@ We mentioned `HostRef` already in our [Testing](07-testing.md) article - a host

In the module context we use a `ContractRef` instead, to call other contracts.

Similarly to a `{{ModuleName}}HostRef`, the `{{ModuleName}}ContractRef` is generated automatically,
Similarly to the `{{ModuleName}}HostRef`, the `{{ModuleName}}ContractRef` is generated automatically,
by the `#[odra::module]` attribute.

To obtain an instance of a contract reference, we simply call the constructor - `{{ModuleName}}ContractRef::new(env: Rc<ContractEnv>, address: Address)`, as shown above.

The reference implements all the public endpoints to the contract (those marked as `pub` in `#[odra::module]`
impl), and the `{{ModuleName}}ContractRef::address()` function, which returns the address of the contract.

Expand All @@ -78,6 +89,18 @@ pub trait Adder {
Analogously to modules, Odra creates the `AdderContractRef` struct (and `AdderHostRef` to be used in tests, but do not implement the `Deployer` trait). Having an address, in the module context we can call:

```rust
struct Contract {
adder: External<AdderContractRef>
}
// in some function
self.adder.add(3, 5)

// or

struct Contract {
adder: Var<Address>
}
// in some function
AdderContractRef::new(self.env(), address).add(3, 5)
```

Expand Down
20 changes: 9 additions & 11 deletions docusaurus/docs/tutorials/odra-sol.md
Original file line number Diff line number Diff line change
Expand Up @@ -1497,11 +1497,11 @@ The key difference between the two is that in Solidity, the `keccak256` function
<TabItem value="rust" label="Odra">

```rust showLineNumbers
use odra::{module::Module, Address, ContractRef, Var};
use odra::{module::Module, Address, ContractRef, External, Var};

#[odra::module]
pub struct Example {
other_contract: Var<Address>,
other_contract: External<OtherContractContractRef>,
}

#[odra::module]
Expand All @@ -1511,15 +1511,13 @@ impl Example {
}

pub fn execute_external_call(&self) {
if let Some(addr) = self.other_contract.get() {
let result = OtherContractContractRef::new(self.env(), addr).some_function();
match result {
Ok(success) => {
// Code to execute if the external call was successful
}
Err(reason) => {
// Code to execute if the external call failed
}
let result = self.other_contract.some_function();
match result {
Ok(success) => {
// Code to execute if the external call was successful
}
Err(reason) => {
// Code to execute if the external call failed
}
}
}
Expand Down

0 comments on commit 957dddb

Please sign in to comment.