Problems in creating a fully functional ICRC-1 token

That’s good to know with the dashboard - thanks!

Unfortunately, I don’t see a function in either of both github repository that implements the logo…

Hi @mindfulanon, the logo is not a a part of the token itself. You can add the logo by creating a pull request here:it will show up in the infinity wallet and infinityswap. token-lists/tokenlist.json at main · infinity-swap/token-lists · GitHub

for ICRC-1 tokens launched through SNS, the logo is stored by the root canisters.

2 Likes

Thank you for the reply Max! I have made the pull request. Hopefully I have done this correctly.

How can I make sure that my logo is not only displayed there but also in other decentralized exchanges / wallets?

Is there a reason why mint() and burn() are not prefaced by icrc_, like the other functions are?

There’re also not in the TokenInterface type: icrc1/Types.mo at 7af28bbfa7d41a20297ff6e349ee0374f9d1b576 · NatLabs/icrc1 · GitHub

Another thing I noticed is when calling burn() from another canister,

let icrc_canister = actor ("r7inp-6aaaa-aaaaa-aaabq-cai") : (ICRCTypes.TokenInterface and ICRCTypes.TokenInterfaceExtension);

(...)

    let burn_args : ICRCTypes.BurnArgs = {
      from_subaccount : ?Subaccount = null;
      amount : Balance = 12_000_000;
      memo : ?Blob = null;
      created_at_time : ?Nat64 = null;
    };

    let burn_receipt = await icrc_canister.burn(burn_args);
    Debug.print(debug_show (burn_receipt));

I get

#err(#GenericError({error_code = 0; message = "The sender cannot have the same account as the recipient."}))

What is burn() supposed to do? I wonder if the error has anything to do with the fact that the canister calling burn() is also the icrc canister’s minting_account as set on token deployment?

Right now mint and burn are not part of the spec. Maybe ICRC-4? These are left up to the implementation.

Typically you have a “minting” account that can mint by sending from and burn by sending to.

if (tx_req.from == tx_req.to) {
            return #err(
                #GenericError({
                    error_code = 0;
                    message = "The sender cannot have the same account as the recipient.";
                }),
            );
        };

The error you are seeing is from above. Basically you can’t send to yourself.

If your canister is the minting account owner then maybe use sub-accounts and send from the minting sub-account to another sub-account for a mint and then send back to the minting sub-account for burn. You really shouldn’t need mint and burn with this setup.

2 Likes

Thanks.

I just realised that when you icrc1_transfer() from the minting_account, it simply mints new tokens. It doesn’t transfer existing tokens, even if minting_account has enough. The balance of minting_account stays unchanged. It may be good to emphasise this in the code / docs. It seems odd behaviour for an action labelled “transfer”.

Though I still don’t understand the behaviour of burn(). I need burn because I need to be able to reduce the total supply, not just make some of it permanently inaccessible (is reducing the total supply possible another way?). In what sense is calling burn() sending to “the same account as the recipient”?

It would appear from

    public type BurnArgs = {
        from_subaccount : ?Subaccount;
        amount : Balance;
        memo : ?Blob;
        created_at_time : ?Nat64;
    };

that burn() is a function that any account could call, having to specify only an optional subaccount from which to subtract the to-be-burnt balance.

When someone wants to burn, just have them send tokens to the minting account. That’s the burn mechanism. If you look in the code, it will check with the Minting account and then it will burn those tokens if that is the to address.

I think your issue is that you’re trying to send from the meeting account to the meeting account and that just generally is it possible. Don’t give the minting account a balance. It’s balance should always be zero.

1 Like

Thanks again. That explains the logs and behaviour.

For tokens where the maximum supply is flexible, eg a stablecoin, is the only existing solution setting max_supply to a stupidly large number on deployment, or is there a way for max_supply to track total_supply or something like it?

I guess max_supply might be changed by an owner either with an upgrade or with an ad hoc function perhaps callable only by the mint_account, so that on mint / burn, max supply is increased / reduced together with total supply.

Would that be a good approach, or better just leave max_supply fixed at a very large number?