⌘K

Icon SunFilledIcon MoonStars
Inter Contract Calls

Icon LinkInter-Contract Calls with the SDK

This guide explains how to use the SDK to execute a contract call where one contract interacts with another contract. We will use a simple scenario involving a SimpleToken contract and a TokenDepositor contract.

Icon LinkSimpleToken and TokenDepositor Contracts

In this example, we have a SimpleToken contract representing a basic token contract capable of holding balances for different addresses. We also have a TokenDepositor contract that deposits tokens into the SimpleToken contract.

Icon LinkContract: SimpleToken

Here's a simple token contract that allows holding balances:

contract;
 
use ::simple_token_abi::SimpleToken;
 
use std::hash::*;
storage {
balances: StorageMap<b256, u64> = StorageMap {},
}
impl SimpleToken for Contract {
#[storage(read, write)]
fn deposit(address: b256, amount: u64) {
	let current_balance = storage.balances.get(address).try_read().unwrap_or(0);
	storage.balances.insert(address, current_balance + amount);
}
#[storage(read)]
fn get_balance(address: b256) -> u64 {
	let balance = storage.balances.get(address).try_read().unwrap_or(0);
	balance
}
}

Icon LinkContract: TokenDepositor

The TokenDepositor contract imports the SimpleToken contract and calls its deposit function to deposit tokens:

contract;
 
use std::auth::msg_sender;
 
use ::simple_token_abi::SimpleToken;
 
abi TokenDepositor {
fn deposit_to_simple_token(contract_id: b256, amount: u64);
}
 
impl TokenDepositor for Contract {
fn deposit_to_simple_token(contract_id: b256, amount: u64) {
	let simple_token_contract = abi(SimpleToken, contract_id);
 
	let sender = msg_sender().unwrap();
 
	let address: b256 = match sender {
	Identity::Address(sender_param) => sender_param.into(),
	_ => revert(0),
	};
 
	simple_token_contract.deposit(address, amount);
}
}

Icon LinkInter-contract calls using the SDK

Once both contracts are deployed, we can use the SDK to make the TokenDepositor contract to call the SimpleToken contract.

const amountToDeposit = 70;
const { minGasPrice } = provider.getGasConfig();
const { value: initialBalance } = await simpleToken.functions
	.get_balance(wallet.address.toB256())
	.txParams({ gasPrice: minGasPrice, gasLimit: 10_000 })
	.call();
 
expect(new BN(initialBalance).toNumber()).toBe(0);
 
await tokenDepositor.functions
	.deposit_to_simple_token(simpleToken.id.toB256(), amountToDeposit)
	.addContracts([simpleToken])
	.txParams({ gasPrice: minGasPrice, gasLimit: 10_000 })
	.call();
 
const { value: finalBalance } = await simpleToken.functions
	.get_balance(wallet.address.toB256())
	.txParams({ gasPrice: minGasPrice, gasLimit: 10_000 })
	.call();
 
expect(new BN(finalBalance).toNumber()).toBe(amountToDeposit);

Pay attention to the method addContracts called by the TokenDepositor contract. This method accepts an array of instances of deployed contracts. Without calling this method, the inter-contract call will not work.