Use case: We want to call Contract B through Contract A.
The contract call of Contract B emits an log.
Now when indexing, we want that to be part of a transaction of Contract B, not Contract A.
We’ve tried something similar to what is documented in fuels-rs:
//get the first 4 bytes
let hash: b256 = sha256("register(ContractId,Identity)");
let bytes = Bytes::from(hash);
let mut function_selector = Bytes::new();
function_selector.push(bytes.get(0).unwrap());
function_selector.push(bytes.get(1).unwrap());
function_selector.push(bytes.get(2).unwrap());
function_selector.push(bytes.get(3).unwrap());
let this_contract = ContractId::this();
let call_data = Bytes::from(encode((this_contract, owner)));
let call_params = CallParams {
coins: 0,
asset_id: AssetId::base(),
gas: 10_000_000, //placeholder
};
call_with_function_selector(
registry_id,
function_selector,
call_data,
call_params,
);
Is this possible in sway?
If not: Is there a way to have the log come from Contract B rather than Contract A)
Yes, it is possible to call Contract B from Contract A in Sway and have the log come from Contract B. This can be achieved by using the ABI system in Sway to make the contract call. Here is an example of how you can do this:
Contract A
contract;
use contract_b::ContractB;
abi ContractA {
fn call_contract_b();
}
const CONTRACT_B_ID: ContractId = 0x79fa8779bed2f36c3581d01c79df8da45eee09fac1fd76a5a656e16326317ef0;
impl ContractA for Contract {
fn call_contract_b() {
let contract_b = abi(ContractB, CONTRACT_B_ID);
contract_b.some_function();
}
}
Contract B
contract;
abi ContractB {
fn some_function();
}
impl ContractB for Contract {
fn some_function() {
// Emit a log here
log("Log from Contract B");
}
}
Explanation
- Contract A:
- Defines an ABI
ContractA
with a function call_contract_b
.
- Uses the ABI of
ContractB
to call some_function
on Contract B.
- The
CONTRACT_B_ID
is the address of Contract B.
- Contract B:
- Defines an ABI
ContractB
with a function some_function
.
- Implements the
some_function
which emits a log.
When call_contract_b
is called on Contract A, it will call some_function
on Contract B, and the log will be emitted from Contract B.
Low-Level Call Example
If you prefer to use a low-level call, you can follow the example provided in the context:
fn call_low_level_call(
target: ContractId,
function_selector: Bytes,
calldata: Bytes,
) {
let call_params = CallParams {
coins: 0,
asset_id: AssetId::from(ZERO_B256),
gas: 10_000,
};
call_with_function_selector(target, function_selector, calldata, call_params);
}
You can construct the function selector and calldata as shown in the example and call call_with_function_selector
to make the call to Contract B.
For more details, you can refer to the Fuel Network documentation on low-level calls.
lmk if you still want help