Call response
You've probably noticed that you're often chaining .call().await.unwrap(). That's because:
- You have to choose between 
.call()and.simulate()(more on this in the next section); - Contract calls are asynchronous, so you can choose to either 
.awaitit or perform concurrent tasks, making full use of Rust's async; .unwrap()theResult<FuelCallResponse, Error>returned by the contract call.
Once you unwrap the FuelCallResponse, you have access to this struct:
pub struct FuelCallResponse<D> {
    pub value: D,
    pub receipts: Vec<Receipt>,
    pub gas_used: u64,
    pub log_decoder: LogDecoder,
}
Where value will hold the value returned by its respective contract method, represented by the exact type returned by the FuelVM, E.g., if your contract returns a FuelVM's u64, value's D will be a u64. If it's a FuelVM's tuple (u8,bool), then D will be a (u8,bool). If it's a custom type, for instance, a Sway struct MyStruct containing two components, a u64, and a b256, D will be a struct generated at compile-time, called MyStruct with u64 and a [u8; 32] (the equivalent of b256 in Rust-land).
receiptswill hold all receipts generated by that specific contract call.gas_usedis the amount of gas it consumed by the contract call.
Error handling
You can use the is_ok and is_err methods to check if a contract call Result is ok or contains an error. These methods will return either true or false.
let is_ok = response.is_ok();
let is_error = response.is_err();
If is_err returns true, you can use the unwrap_err method to unwrap the error message.
if response.is_err() {
    let err = response.unwrap_err();
    println!("ERROR: {:?}", err);
};