Discrepancy in value: `getBalance` and `balance_of`

There’s a discrepancy in the values returned by getBalance in the TS SDK, and balance_of fn in Sway.

To reproduce:

use std::{context::*, asset::*, call_frames::contract_id};
abi Fungible {
    fn get_asset_id() -> AssetId;
	fn mint(recipient: Identity, amount: u64) ;
    fn transfer(to: Identity, amount: u64);

impl Fungible for Contract {
    fn get_asset_id() -> AssetId {
        AssetId::new(contract_id(), ZERO_B256)

	#[storage(read, write)]
    fn mint(recipient: Identity, amount: u64) {
        let asset_id = AssetId::new(contract_id(), ZERO_B256);

        let supply = storage.total_supply.get(asset_id);

            .insert(asset_id, supply.try_read().unwrap_or(0) + amount);

        mint_to(recipient, ZERO_B256, amount);

    fn transfer(to: Identity, amount: u64) {
        let asset_id = AssetId::new(contract_id(), ZERO_B256);

        transfer(to, asset_id, amount);
use std::{context::*, asset::*, call_frames::contract_id};
abi BalanceChecker {
	fn get_balance_for(asset_id: AssetId) -> u64;

impl BalanceChecker for Contract {
	/// Get the internal balance of a specific coin at a specific contract.
	fn get_balance_for(asset_id: AssetId) -> u64 {
		balance_of(contract_id(), asset_id)

deploy both contracts via local node

// BTC = Fungible
// BALANCE_CHECKER = BalanceChecker

// Balance before: { contr: '0', balan: '0' }
console.log("Balance before:", {
    contr: (await BALANCE_CHECKER.functions.get_balance_for(toAsset(BTC)).call()).value.toString(),
    balan: (await BALANCE_CHECKER.getBalance(getAssetId(BTC))).toString()

await BTC.functions.mint(addrToIdentity(deployer), "2_000_000_000").call()
await BTC.functions
    .transfer(contrToIdentity(BALANCE_CHECKER), "1_000_000_000")
    .callParams({ forward: ["1_000_000_000", getAssetId(BTC)] })

// Balance after: { contr: '0', balan: '1000000000' }
console.log("Balance after:", {
    contr: (await BALANCE_CHECKER.functions.get_balance_for(toAsset(BTC)).call()).value.toString(),
    balan: (await BALANCE_CHECKER.getBalance(getAssetId(BTC))).toString()

import { getAssetId as getAssetIdFuels, } from "fuels"

// getAssetId:
export function getAssetId(
    fungibleContract: any,
    sub_id: string = "0x0000000000000000000000000000000000000000000000000000000000000000",
): string {
    return getAssetIdFuels(fungibleContract.id.toHexString(), sub_id)

// Verify assetids
const asset_id_from_contract = (await BTC.functions.get_asset_id().call()).value.value
const asset_id_from_fuels = getAssetId(BTC)

assert asset_id_from_contract == asset_id_from_fuels // this doesn't throw

according to the above, the native asset “BTC” is transferred successfully to the contract BALANCE_CHECKER, and can be verified with the getBalance function in the TS SDK. However, from the contract’s perspective, there was no native asset forwarded to it. Am I doing something wrong here?

I’ve also verified that the asset id’s match (see the assert statement above).

nvm: this was an error on my part. The implementation of toAsset didn’t not use the getAssetIdFuels fn, and simply used the .id of the contract which wasn’t the asset id.

1 Like

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.