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

There are two intended ways to deploy a contract

  • deploy
  • deploy_with_parameters

If you are only interested in a single instance of your contract, then use deploy

        // 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!(
            MyContract,
            // This path is relative to the workspace (repository) root
            "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;

        // Optional: Configure deployment parameters or use `TxParameters::default()`
        let gas_price = 0;
        let gas_limit = 1_000_000;
        let maturity = 0;

        // 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,
            TxParameters::new(Some(gas_price), Some(gas_limit), Some(maturity)),
            StorageConfiguration::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, if you want multiple instances of the same contract then use deploy_with_parameters and set the salt parameter.

        use fuels::prelude::*;
        use rand::prelude::{Rng, SeedableRng, StdRng};

        abigen!(
            MyContract,
            "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,
            TxParameters::default(),
            StorageConfiguration::default(),
        )
        .await?;

        println!("Contract deployed @ {contract_id_1}");

        let rng = &mut StdRng::seed_from_u64(2322u64);
        let salt: [u8; 32] = rng.gen();

        let contract_id_2 = Contract::deploy_with_parameters(
            "../../packages/fuels/tests/contracts/contract_test/out/debug/contract_test.bin",
            &wallet,
            TxParameters::default(),
            StorageConfiguration::default(),
            Salt::from(salt),
        )
        .await?;

        println!("Contract deployed @ {contract_id_2}");

        assert_ne!(contract_id_1, contract_id_2);