Icon LinkBeta 4 Migration

This guide focuses on the transition from the end of tool support for beta 3 to the start of beta 4.

Icon LinkFuelup Toolchain

Update to the latest version of fuelup:

fuelup self update

Install the beta-4 toolchain:

fuelup toolchain install beta-4

Set the beta-4 toolchain as your default:

fuelup default beta-4

You will get this output if everything went as intended:

default toolchain set to 'beta-4-aarch64-apple-darwin'

Icon LinkWallet

Fuel Wallet version 0.11.0 is not compatible with beta 4. For compatibility with beta-4, please download the non-backwards compatible Fuel Wallet version 0.12.3.

pnpm install @fuel-wallet@0.12.3

We have already submitted the beta-4 compatible version to the Chrome Web Store, and it is currently under review. Once your users update to this version, they will no longer be able to interact with the contracts you currently have deployed on the beta-3 testnet.

Please follow the instructions provided below:

  1. Download FuelWallet zip file Icon Link
  2. Inside Chrome or Brave;
  3. Open the extensions page; it can be done by:
    • Clicking on settings -> extensions or;
  4. Accessing brave://extensions/ or chrome://extensions/.
  5. Enable the "Developer mode" switch on the top right
  6. Load fuel-wallet.zip by:
    • Dragging your downloaded Fuel wallet file and dropping it in the extensions page or;
    • Clicking on Load unpacked and selecting the file.
  7. If all goes right, an onboarding page will instantly open.

Icon LinkSway

Integer types no longer implicitly cast to each other. Here are some examples of the changes:

// BEFORE - BETA 3
let y1: u16 = 4u8
 
// AFTER - BETA 4
let y1: u16 = 4u8.as_u16()
// BEFORE - BETA 3
let y3: u16 = 4u32
 
// AFTER - BETA 4
let y3: u16 = 4u32.try_as_u16().unwrap()

The standard library introduced read(), write(), and try_read() methods to contract storage. Use try_read() when possible to avoid potential issues with accessing uninitialized storage:

// BEFORE - BETA 3
let owner = storage.owner;
 
// AFTER - BETA 4
let owner = storage.owner.try_read().unwrap();
// BEFORE - BETA 3
storage.item_counter += 1;
 
// AFTER - BETA 4
storage.item_counter.write(storage.item_counter.read() + 1);

Function signatures in the standard library have changed:

// BEFORE - BETA 3
mint_to(amount, recipient);
 
// AFTER - BETA 4
mint_to(recipient, ZERO_B256, 1_000_000_000);
// BEFORE - BETA 3
transfer(amount, asset_id, recipient);
 
// AFTER - BETA 4
transfer(recipient, asset_id, amount);

Multi-token support, akin to Ethereum's ERC-1155, has now been natively introduced. This advancement enables the creation and destruction of unique subsidiary tokens within a single contract. These modifications will be incorporated into the standard library as std::token. Actions involving burning and minting now necessitate the sub_id of the token. Function signatures in the standard library have changed:

pub fn construct_asset_id(contract_id: ContractId, sub_id: SubId) -> AssetId {
    sha256((contract_id, sub_id))
}

Additionally, AssetId doesn't equate to ContractId. Instead, it's calculated in alignment with the aforementioned changes:

// BEFORE - BETA 3
IncorrectAssetId: ContractId;
 
// AFTER - BETA 4
IncorrectAssetId: AssetId;

Changes disable_panic_on_overflow() function to return the flags set prior to calling the function:

// BEFORE - BETA 3
pub fn disable_panic_on_overflow() 
 
// AFTER - BETA 4
pub fn disable_panic_on_overflow() -> u64

Icon LinkTS SDK

The rawPayload property has been deprecated from the Receipt struct.

For more details on the schema modification, please refer to the schema here Icon Link.

// BEFORE - BETA 3
const receipt = new ReceiptCoder().decode(arrayify(gqlReceipt.rawPayload), 0)[0];
 
// AFTER - BETA 4
const receipt = assembleReceiptByType(gqlReceipt);

The .simulate() method replacing .get() is tailored for read-only calls and testing potential blockchain changes without committing them, while .call() should be used for actions that modify the blockchain's state, keeping in mind that state-altering methods using .call() will consume resources.

// BEFORE - BETA 3
let { value } = await contract.functions.get_count().get();
 
// AFTER - BETA 4
let { value } = await contract.functions.get_count().simulate();

Icon LinkRust SDK

When providing contract IDs or addresses to contract functions, .into() is not longer needed:

// BEFORE - BETA 3
let response = contract_methods
    .transfer_coins_to_output(1_000_000, contract_id.into(), address.into())
    .append_variable_outputs(1)
    .call()
    .await?;
 
// AFTER - BETA 4
let response = contract_methods
    .transfer_coins_to_output(1_000_000, contract_id, address)
    .append_variable_outputs(1)
    .call()
    .await?;

setup_contract_test has been changed to setup_program_test.

The command to generate bindings with Abigen has been modified; previously, it was Abigen(name="..."), but now it requires the program type and should be written as Abigen(Program_Type(name="...")):

// BEFORE - BETA 3
setup_contract_test!(
    Wallets("wallet"),
    Abigen(name="MyContract", abi="some_folder")
);
 
// AFTER - BETA 4
setup_program_test!(
    Wallets("wallet"),
    Abigen(Contract(name = "MyContract", project = "some_folder")
// Other Program Types 
// Abigen(Script(name = "MyScript", project = "some_folder"))
// Abigen(Predicate(name = "MyPredicate", project = "some_folder"))
    )
);

Now supporting String types, there have been slight modifications if you directly use ParamTypes:

// BEFORE - BETA 3
ParamType::String(len) => Self::decode_string_array(bytes, *len),
 
ParamType::StdString => Self::decode_std_string(bytes),
 
// AFTER - BETA 4
ParamType::StringArray(len) => Self::decode_string_array(bytes, *len),
 
ParamType::String => Self::decode_std_string(bytes),

Contract deployment no longer takes contract binary and deploy configurations as a parameter but is instead loaded in:

// BEFORE - BETA 3
let id = Contract::deploy(
    "./out/debug/contract.bin",
    &wallet,
    DeployConfiguration::default(),
)
.await?;
 
// AFTER - BETA 4
let storage_config =
StorageConfiguration::load_from("out/debug/contract-storage_slots.json").unwrap();
 
let load_config = LoadConfiguration::default().set_storage_configuration(storage_config);
 
let id = Contract::load_from(
    "./out/debug/contract.bin", load_config
)?
.deploy(&wallet, TxParameters::default())
.await?;

Now, send_transaction(&tx) immediately returns the transaction ID, which is used to retrieve the receipts:

// BEFORE - BETA 3
let receipts = self.try_provider()?.send_transaction(&tx).await?;
 
// AFTER - BETA 4
let tx_id = self.try_provider()?.send_transaction(&tx).await?;
let receipts = provider.get_receipts(&tx_id).await?;

The produce_blocks function has been updated to no longer need time parameters:

// BEFORE - BETA 3
provider
    .produce_blocks(100, Some(Utc.timestamp_opt(100, 0).unwrap()))
    .await?;
 
// AFTER - BETA 4
provider
    .produce_blocks(blocks_to_produce.into(), None)

AssetId and ContractId are no longer under the tx package and has since been moved to the prelude:

// BEFORE - BETA 3
use fuels::{prelude::*, tx::AssetId, tx::ContractId};
 
// AFTER - BETA 4
use fuels::{prelude::*}

Default parameter functions now start with with_* instead of set_*:

/* BEFORE - BETA 3 */
let call_params = CallParameters::default().set_storage_configuration(price);
 
let call_params = CallParameters::default().set_amount(price);
 
/* AFTER - BETA 4 */
let call_params = CallParameters::default().with_storage_configuration(price);
 
let call_params = CallParameters::default().with_amount(price);

Was this page helpful?

Icon ListDetailsOn this page