# How to set allowance for icrc2\_transfer\_from?

**URL:** <https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821>\
**Category:** Developers\
**Created:** [November 26, 2024, 9:59am UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821 "2024-11-26T09:59:43Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![AliSci](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/alisci/32/33799_2.png) [@AliSci](https://forum.dfinity.org/u/AliSci)\
**Post date:** [November 26, 2024, 9:59am UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/1 "2024-11-26T09:59:43Z")

</div>

my backend code

```rs

  const depositCkusdt = async () => {
    const res = await backendActor.deposit_ckusdt();
}
async fn transfer_from(amount: Nat, from: Principal, to: Principal) -> Result<BlockIndex, Error> {
    let args = TransferFromArgs {
        spender_subaccount: None,
        from: Account {
            owner: from,
            subaccount: None,
        },
        to: Account {
            owner: to,
            subaccount: None,
        },
        amount,
        fee: None,
        memo: None,
        created_at_time: None,
    };
    let res = ic_cdk::call::<(TransferFromArgs, ), (Result<BlockIndex, TransferFromError>, )>(
        Principal::from_text("xevnm-gaaaa-aaaar-qafnq-cai").unwrap(),
        "icrc2_transfer_from",
        (args, ),
    )
        .await
        .map_err(|(_, message)| Error::IcCdkError { message })?
        .0
        .map_err(|e| Error::IcCdkError {
            message: format!("{:?}", e),
        });
    res
}

#[update]
async fn deposit_ckusdt() -> Result<Wallet, Error> {
    let mut wallet = Wallet::get(caller());
    let balance = get_user_balance().await;
    if balance.is_err() {
        return Err(Error::IcCdkError {
            message: format!("{:?}", balance),
        });
    }
    let balance = balance.unwrap();
    if balance > Nat::from(3000000 as u64) {
        let fee: Nat = get_fee().await;
        let _ = transfer_from(balance.clone() - fee, caller(), ic_cdk::id()).await?;
        wallet
            .deposit(
                nat_to_u64(balance.clone() / Nat::from(1000000 as u64)) as f64,
                "ExternalWallet".to_string(),
                ExchangeType::Deposit,
            )
            .map_err(|e| Error::IcCdkError {
                message: format!("{:?}", e),
            })?;
        let message = format!("You received {} CKUSD", balance);
        Notification::new(
            format!("{:?}", time::SystemTime::now()),
            caller(),
            NoteContent::ReceivedDeposit(message),
        )
            .save();
    }
    Ok(wallet.clone())
}

```

my frontend code

```tsx

const approveTransaction = async (balance, fee_value) => {
    const approveArg: ApproveArgs = {
      fee: [BigInt(fee_value)],
      memo: [],
      from_subaccount: [],
      created_at_time: [],
      amount: BigInt(Number(balance)),
      expected_allowance: [BigInt(Number(balance))],
      expires_at: [],
      spender: {
        owner: Principal.fromText(canisterId),
        subaccount: [],
      },
    };

    return await ckUSDCActor.icrc2_approve(approveArg);
  };

      const fee_value = await fetchFee();
      const account = { owner: Principal.fromText(profile.id), subaccount: [] };
      const balance = await fetchBalance(account);
      console.log({ balance });
      if (balance > BigInt(1000000)) {

        // -------------------- icrc2_approve --------------------
        let approve = await approveTransaction(balance, fee_value);
        console.log({ approve,fee_value });

        // -------------------- icrc2_allowance --------------------
        const allowance: AllowanceArgs = {
          account: {
            owner: Principal.fromText(canisterId),
            subaccount: [],
          },
          spender: {
            owner: Principal.fromText(canisterId),
            subaccount: [],
          },
        };
        let allowance_res: Allowance =
          await ckUSDCActor?.icrc2_allowance(allowance);
        console.log({ allowance_res });

        // -------------------- transfer from user to odoc wallet --------------------
        let deposit = await depositCkusdt();
        console.log({ deposit });
      }

```

 ![Screenshot 2024-11-26 at 6.00.44 PM](https://us1.discourse-cdn.com/flex023/uploads/dfn/original/3X/8/8/8823bc8458851bdbaf418e403a6a7315a1b21da7.png)

---

<div class="post-metadata">

**Author:** ![Vivienne](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/vivienne/32/29170_2.png) [@Vivienne](https://forum.dfinity.org/u/Vivienne)\
**Post date:** [November 26, 2024, 10:09am UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/2 "2024-11-26T10:09:19Z")

</div>

> [@AliSci](#):
>
> ```auto
> amount: BigInt(Number(balance)),
> expected_allowance: [BigInt(Number(balance))],
> 
> ```

This doesn’t make sense AFAIU. This basically means

```auto
if current_allowance = balance {
  allowance = balance;
}

```

I think this is why your allowance does not properly update (first object in the console screenshot). The full semantics are documented [here](https://github.com/dfinity/ICRC-1/blob/main/standards/ICRC-2/README.md#icrc2_approve)

---

<div class="post-metadata">

**Author:** ![AliSci](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/alisci/32/33799_2.png) [@AliSci](https://forum.dfinity.org/u/AliSci)\
**Post date:** [November 26, 2024, 3:58pm UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/3 "2024-11-26T15:58:16Z")

</div>

> [@AliSci](#):
>
> ` expected_allowance`

In summary I should just ` expected_allowance :[]`

---

<div class="post-metadata">

**Author:** ![Vivienne](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/vivienne/32/29170_2.png) [@Vivienne](https://forum.dfinity.org/u/Vivienne)\
**Post date:** [November 26, 2024, 4:28pm UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/4 "2024-11-26T16:28:37Z")

</div>

Yes, to get it working this should do it. But if you have high security expectations you probably should still use expected\_allowance

---

<div class="post-metadata">

**Author:** ![AliSci](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/alisci/32/33799_2.png) [@AliSci](https://forum.dfinity.org/u/AliSci)\
**Post date:** [November 26, 2024, 8:21pm UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/5 "2024-11-26T20:21:33Z")

</div>

> [@AliSci](#):
>
> ```auto
> const allowance: AllowanceArgs = {
> account: {
> owner: Principal.fromText(canisterId),
> subaccount: [],
> },
> spender: {
> owner: Principal.fromText(canisterId),
> subaccount: [],
> },
> };
> 
> ```

what about

````auto
const allowance: AllowanceArgs = {
          account: {
            owner: Principal.fromText(canisterId),
            subaccount: [],
          },
          spender: {
            owner: Principal.fromText(canisterId),
            subaccount: [],
          },
        };
``` the owner should be the `caller()` right ? should I call it from the backend ?
I also got error `"InsufficientAllowance { allowance: Nat(20000) }"` despite the transaction was actaully done
````

---

<div class="post-metadata">

**Author:** ![rem.codes](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/rem.codes/32/40260_2.png) [@rem.codes](https://forum.dfinity.org/u/rem.codes)\
**Post date:** [November 26, 2024, 8:38pm UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/6 "2024-11-26T20:38:11Z")

</div>

You should set the allowance (approve) through the frontend where the canister is the spender, also take into account that an approve is a transaction and a fee payed.

When fetching the allowance you need to specify the user principal where you set the allowance for as the “account” and the “spender” as the canister principal.

So if you want to transfer\_from in the user his behalf, make sure to also subtract the fee 10\_000 e8s for ICP

Here is an example in rust, do note that these are modified for a specific usecase (using a subaccount for example)

> <https://github.com/toolkit-development/ic-toolkit-utils/blob/a3c6c6afce5c2c2f1798eb107df95df825475587/src/helpers/transactions.rs#L290>

> <https://github.com/toolkit-development/ic-toolkit-utils/blob/a3c6c6afce5c2c2f1798eb107df95df825475587/src/helpers/transactions.rs#L311>

---

<div class="post-metadata">

**Author:** ![AliSci](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/alisci/32/33799_2.png) [@AliSci](https://forum.dfinity.org/u/AliSci)\
**Post date:** [November 26, 2024, 8:51pm UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/7 "2024-11-26T20:51:24Z")

</div>

> [@rem.codes](#):
>
> `Subaccount`

u siad we set allowance from the frontend but this is a backend code ?  
I tried this

```auto
let subaccount : Subaccount = Principal.fromText(profile.id).toUint8Array();
        // -------------------- icrc2_allowance --------------------
        const allowance: AllowanceArgs = {
          account: {
            owner: Principal.fromText(profile.id),
            subaccount: [],
          },
          spender: {
            owner: Principal.fromText(canisterId),
            subaccount: [subaccount],
            // subaccount: [],
          },
        };
        let allowance_res: Allowance =
          await ckUSDCActor?.icrc2_allowance(allowance);
        console.log({ allowance_res });

```

but I got issue with subaccount format rejected

---

<div class="post-metadata">

**Author:** ![rem.codes](https://sea1.discourse-cdn.com/flex023/user_avatar/forum.dfinity.org/rem.codes/32/40260_2.png) [@rem.codes](https://forum.dfinity.org/u/rem.codes)\
**Post date:** [November 26, 2024, 9:06pm UTC](https://forum.dfinity.org/t/how-to-set-allowance-for-icrc2-transfer-from/37821/8 "2024-11-26T21:06:22Z")

</div>

The subaccount isn’t required and I would only recommend starting to use it once you fully understand the flow because it brings extra complexity to what needs to be solved;

Usually a flow would go like this;

1. Frontend → icrc2\_approve  
(set spender (canister) and amount on behalf of the caller)

2. Backend → icrc2\_allowance  
(get allowance set for and account + spender (in the case the frontend caller is the account and the spender the backend canister)

3. Backend → icrc2\_transfer\_from  
(Transfer funds on behalf of the caller from the spender account)

I guess I should have included the transfer\_from example as well [ic-toolkit-utils/src/helpers/transactions.rs at a3c6c6afce5c2c2f1798eb107df95df825475587 · toolkit-development/ic-toolkit-utils · GitHub](https://github.com/toolkit-development/ic-toolkit-utils/blob/a3c6c6afce5c2c2f1798eb107df95df825475587/src/helpers/transactions.rs#L164)

Note that “2” is optional and can be called from both the frontend and backend because it’s public data as long as you know the account and spender. Just mentioned is as backend so the flow makes more sense
