Icon HelpCircleForumIcon Link

⌘K

Icon HelpCircleForumIcon Link
Deploying Contracts

Icon LinkDeploying Contracts

To deploy a contract using the SDK, you can use the ContractFactory. This process involves collecting the contract artifacts, initializing the contract factory, and deploying the contract.

The SDK utilizes two different deployment processes, depending on the contract's size. The threshold for the contract size is dictated by the chain and can be queried:

// #import { Provider, TESTNET_NETWORK_URL };
 
const provider = await Provider.create(TESTNET_NETWORK_URL);
const { consensusParameters } = provider.getChain();
const contractSizeLimit = consensusParameters.contractParameters.contractMaxSize;

It either uses a single create transaction to deploy the entire contract bytecode, or it splits the contract bytecode into multiple chunks, deploys them as blobs (on chain data accessible to the VM), and then generates a contract from the associated blob IDs. That generated contract is then deployed as a create transaction.

The ContractFactory offers the following methods for the different processes:

  • deploy for deploying contacts of any size (will automatically choose the appropriate deployment process).
  • deployAsCreateTx for deploying the entire contract bytecode in a single create transaction.
  • deployAsBlobTx for deploying the contract in chunks as blobs, and then deploying the contract as a create transaction.
Icon InfoCircle

Note: If the contract is deployed via blob deployments, multiple transactions will be required to deploy the contract.

Icon LinkDeploying a Contract Guide

This guide will cover the process of deploying a contract using the deploy method, however all these methods can be used interchangeably dependent on the contract size. In the guide we use a contract factory that has been built using Typegen . This tool provided by the Fuels CLI provides a better developer experience and end to end type support for your smart contracts.

Icon Link1. Setup

After writing a contract in Sway you can build the necessary deployment artifacts either by running forc build (read more Icon Link on how to work with Sway) or by using the Fuels CLI and running fuels build using your chosen package manager. We recommend using the Fuels CLI as it provides a more comprehensive usage including end to end type support.

Once you have the contract artifacts, it can be passed to the ContractFactory for deployment, like so:

// #import { Provider, TESTNET_NETWORK_URL, Wallet };
import { WALLET_PVT_KEY } from 'path/to/my/env/file';
import { TypegenFactory } from 'path/to/typegen/outputs';
 
const provider = await Provider.create(TESTNET_NETWORK_URL);
const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider);
const factory = new TypegenFactory(wallet);

Icon Link2. Contract Deployment

As mentioned earlier, there are two different processes for contract deployment handled by the ContractFactory. These can be used interchangeably, however, the deploy method is recommended as it will automatically choose the appropriate deployment process based on the contract size.

This call resolves as soon as the transaction to deploy the contract is submitted and returns three items: the contractId, a waitForTransactionId function and a waitForResult function.

// Deploy the contract
const { waitForResult, contractId, waitForTransactionId } = await factory.deploy();
// Retrieve the transactionId
const transactionId = await waitForTransactionId();
// Await it's deployment
const { contract, transactionResult } = await waitForResult();

The contract instance will be returned only after calling waitForResult and waiting for it to resolve. To avoid blocking the rest of your code, you can attach this promise to a hook or listener that will use the contract only after it is fully deployed. Similarly, the transaction ID is only available once the underlying transaction has been funded. To avoid blocking the code until the ID is ready, you can use the waitForTransactionId function to await it's retrieval.

Icon Link3. Executing a Contract Call

Now that the contract is deployed, you can interact with it by submitting a contract call:

// Call the contract
const { waitForResult: waitForCallResult } = await contract.functions.echo_u8(10).call();
// Await the result of the call
const { value } = await waitForCallResult();

Icon LinkDeploying a Large Contract as Blobs

In the above guide we use the recommended deploy method. If you are working with a contract that is too large to be deployed in a single transaction, then the SDK will chunk the contract for you and submit it as blobs, to then be accessed later by a create transaction. This process is handled by the deployAsBlobTx method, also available on the ContractFactory should you want to use that directly.

// #import { Provider, TESTNET_NETWORK_URL, Wallet, ContractFactory };
import { WALLET_PVT_KEY } from 'path/to/my/env/file';
import { bytecode, abi } from 'path/to/typegen/outputs';
 
const provider = await Provider.create(TESTNET_NETWORK_URL);
const wallet = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider);
const factory = new ContractFactory(bytecode, abi, wallet);
 
// Deploy the contract as blobs
const { waitForResult, contractId, waitForTransactionId } = await factory.deployAsBlobTx({
  // Increasing chunk size multiplier to be 90% of the max chunk size
  chunkSizeMultiplier: 0.9,
});
// Await it's deployment
const { contract, transactionResult } = await waitForResult();

In the above example, we also pass a chunkSizeMultiplier option to the deployment method. The SDK will attempt to chunk the contract to the most optimal about, however the transaction size can fluctuate and you can also be limited by request size limits against the node. By default we set a multiplier of 0.95, meaning the chunk size will be 95% of the potential maximum size, however you can adjust this to suit your needs and ensure the transaction passes. It must be set to a value between 0 and 1.

Icon InfoCircle

Note: Deploying large contracts using blob transactions will take more time. Each transaction is dependent and has to wait for a block to be produced before it gets mined. Then a create transaction is submitted as normal. So you will need to wait longer than usual for the contract to be fully deployed and can be interacted with.