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.