Deploying contracts
There are two main ways of working with contracts in the SDK: deploying a contract with SDK or using the SDK to interact with existing contracts.
Deploying a contract binary
Once you've written a contract in Sway and compiled it with forc build
(read here for more on how to work with Sway), you'll have in your hands two important artifacts: the compiled binary file and the JSON ABI file.
Below is how you can deploy your contracts using the SDK. For more details about each component in this process, read The abigen macro, The FuelVM binary file, and The JSON ABI file.
The deploy functions
The Contract::deploy
function is used to deploy a contract binary to the blockhain. To configure the deployment you can use the DeployConfiguration
struct.
If you are only interested in a single instance of your contract, use the default configuration: DeployConfiguration::default()
// This will generate your contract's methods onto `MyContract`.
// This means an instance of `MyContract` will have access to all
// your contract's methods that are running on-chain!
abigen!(Contract(
name = "MyContract",
// This path is relative to the workspace (repository) root
abi = "packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json"
));
// This helper will launch a local node and provide a test wallet linked to it
let wallet = launch_provider_and_get_wallet().await;
// This will deploy your contract binary onto the chain so that its ID can
// be used to initialize the instance
let contract_id = Contract::deploy(
// This path is relative to the current crate (examples/contracts)
"../../packages/fuels/tests/contracts/contract_test/out/debug/contract_test.bin",
&wallet,
DeployConfiguration::default(),
)
.await?;
println!("Contract deployed @ {contract_id}");
You can then use the contract methods very simply:
// This is an instance of your contract which you can use to make calls to your functions
let contract_instance = MyContract::new(contract_id, wallet);
let response = contract_instance
.methods()
.initialize_counter(42) // Build the ABI call
.call() // Perform the network call
.await?;
assert_eq!(42, response.value);
let response = contract_instance
.methods()
.increment_counter(10)
.call()
.await?;
assert_eq!(52, response.value);
Alternatively, you can use DeployConfiguration
to configure the deployment. You can, for example, deploy multiple instances of the same contract, change the storage or tx_parameters
or update the binary using configurables
.
use fuels::{
prelude::*,
tx::{Bytes32, StorageSlot},
};
use rand::prelude::{Rng, SeedableRng, StdRng};
abigen!(Contract(
name = "MyContract",
abi = "packages/fuels/tests/contracts/contract_test/out/debug/contract_test-abi.json"
));
let wallet = launch_provider_and_get_wallet().await;
let contract_id_1 = Contract::deploy(
"../../packages/fuels/tests/contracts/contract_test/out/debug/contract_test.bin",
&wallet,
DeployConfiguration::default(),
)
.await?;
println!("Contract deployed @ {contract_id_1}");
// Optional: Configure deployment parameters or use `TxParameters::default()`
let tx_parameters = TxParameters::default()
.set_gas_price(0)
.set_gas_limit(1_000_000)
.set_maturity(0);
// Optional: Configure storage
let key = Bytes32::from([1u8; 32]);
let value = Bytes32::from([2u8; 32]);
let storage_slot = StorageSlot::new(key, value);
let storage_configuration =
StorageConfiguration::default().set_manual_storage(vec![storage_slot]);
let rng = &mut StdRng::seed_from_u64(2322u64);
let salt: [u8; 32] = rng.gen();
let contract_id_2 = Contract::deploy(
"../../packages/fuels/tests/contracts/contract_test/out/debug/contract_test.bin",
&wallet,
DeployConfiguration::default()
.set_storage_configuration(storage_configuration)
.set_salt(salt)
.set_tx_parameters(tx_parameters),
)
.await?;
println!("Contract deployed @ {contract_id_2}");
assert_ne!(contract_id_1, contract_id_2);
Note: The next section will give more information on how
configurables
can be used.