Compilation breaks when switching from actor to actor class

I was playing around with the ICRC-1 in motoko: GitHub - NatLabs/icrc1: A full implementation of the ICRC-1 fungible token standard that I imported through mops.

Everything was working fine until I decided to make the token an actor class instead of an actor: somehow when I use an actor class, my other canister complains that the subaccount shall be a [Nat8] instead of a blob. What would it have anything to do with switchting from an actor to an actor class ? This is puzzling me.

I recreated a simple example here: GitHub - sardariuss/icrc1_airdrop. As is the compilation fails. Switch from actor class to actor in token/main.mo (and uncomment the hardcoded args) and it builds.

1 Like

Thanks for the report and repro! I’ll try to take a look later today. Do you know which version of dfx/moc you were using?

1 Like

Thank you for having a look.

I use dfx 0.14.1:

The command ‘“/home/tanguy/.cache/dfinity/versions/0.14.1/moc” “/home/tanguy/airdrop_test/src/airdrop/main.mo” “-o” “/home/tanguy/airdrop_test/.dfx/local/canisters/airdrop/airdrop.wasm” “-c” “–debug” “–idl” “–stable-types” “–public-metadata” “candid:service” “–public-metadata” “candid:args” “–actor-idl” “/home/tanguy/airdrop_test/.dfx/local/canisters/idl/” “–actor-alias” “airdrop” “bkyz2-fmaaa-aaaaa-qaaaq-cai” “–actor-alias” “token” “bd3sg-teaaa-aaaaa-qaaba-cai” “–package” “base” “.mops/base@0.8.8/src” “–package” “map” “.mops/map@8.1.0/src” “–package” “icrc1” “.mops/_github/icrc1@main/src” “–package” “array” “.mops/_github/array@v0.2.0/src” “–package” “StableTrieMap” “.mops/_github/StableTrieMap@main/src” “–package” “StableBuffer” “.mops/_github/StableBuffer@v0.2.0/src” “–package” “itertools” “.mops/_github/itertools@main/src”’ failed with exit status ‘exit status: 1’.

Odd.

I cloned your repo and it failed to build with the same error using a class.
Commenting out the class header, to make it an actor (with suitable definitions for the arguments as locals) produces the same error at line 100.

However, changing line 100 to add a conversion compiles with both variant:

        subaccount = ?Blob.toArray(toSubaccount(principal));

Note that a candid [vec nat8] can be imported as Motoko [Nat8] or Blob so maybe there is some confusion between these going on elsewhere.

1 Like

Yeah I’m not so sure if I should just do the conversion into a [Nat8] everywhere in my code right away or wait first to find the root cause. It’s especially strange to do this change because the ICRC1 Subaccount type defined in Types.mo is a Blob, not a [Nat8].

Something I just saw is that in the .dfx/local/canisters/token, in token.did I have: type Subaccount = blob;
whereas in service.did there is : type Subaccount = vec nat8;

In Candid, ‘blob’ is just an abbreviation for ‘vec nat8’, so it shouldn’t make a difference.

The issue is that Motoko ‘Blob’ and ‘[Nat8]’, which are distinct types, with different representations, both map to Candid ‘vec nat8’ so a Motoko author has to choose which interpretation they want when they implement a Candid function using ‘vec nat’.

It’s confusing.

Although it’s been a while, I remember encountering a related issue with both the official Motoko implementation and Natlabs’ version as constructor args involving a subaccount (adding a subaccount to either the minting account or any of the original deposits) would cause it to trap while deploying. Could be the same source?

While [nat8] and blob are similar in candid, [nat8] takes more memory. I think @quint was working on some improvements to blob, but I don’t know the status.

Status is: postponed :smiling_face_with_tear: I have not had the time to do a read-through of compile.ml, and won’t have any time soon… I wish I’d have some more time to learn about the Motoko compiler.

Candid [nat8] and blob are not only similar but literally the same:

blob is just a short-hand for [nat8].

In Motoko, Blob and [Nat8] are distinct types, though you can convert between them.

So the same but different

Blobs take 1/4 of the space and, by not containing references to Motoko objects, place less stress on the GC (in the current implementation).

2 Likes