Reject text: IC0503: Canister b4q7m-7iaaa-aaaaa-aaerq-cai trapped explicitly: IDL error: unexpected IDL type when parsing Nat

I’m trying to transfer ICP but am getting the following error:

Reject text: IC0503: Canister b4q7m-7iaaa-aaaaa-aaerq-cai trapped explicitly: IDL error: unexpected IDL type when parsing Nat

below is the relevant code snippet. Does anyone see any apparent reason for the error?

 public shared(msg) func transferICP(amount: Nat, canisterAccountId: Account.AccountIdentifier) : async Result.Result<(), Error> {

        let callerId = msg.caller;

        let userProfile = Trie.find(
            profiles,
            key(callerId), //Key
            Principal.equal 
        );

        switch(userProfile) {
            case null{
                #err(#NotFound)
            }; 
            case (? profile){
                let userJournal = profile.journal;

                let status = await userJournal.transferICP(Nat64.fromNat(amount), canisterAccountId);
                if(status == true){
                    #ok(());
                } else {
                    #err(#TxFailed)
                }

            };
        };
    };

the userJournal.transferICP() function that is used in the above code snippet is defined below :point_down:t5:

public func transferICP(amount: Nat64, recipientAccountId: Account.AccountIdentifier) : async Bool {

        let res = await Ledger.transfer({
          memo = Nat64.fromNat(10);
          from_subaccount = null;
          to = recipientAccountId;
          amount = { e8s = amount };
          fee = { e8s = 10_000 };
          created_at_time = ?{ timestamp_nanos = Nat64.fromNat(Int.abs(Time.now())) };
        });

        switch (res) {
          case (#Ok(blockIndex)) {
            Debug.print("Paid reward to " # debug_show principal # " in block " # debug_show blockIndex);
            return true;
          };
          case (#Err(#InsufficientFunds { balance })) {
            throw Error.reject("Top me up! The balance is only " # debug_show balance # " e8s");
            return false;
          };
          case (#Err(other)) {
            throw Error.reject("Unexpected error: " # debug_show other);
            return false;
          };
        };
    };

edit: I think it may be something wrong with the way I’m sending the recipientAccountId to the backend, but I’m not quite sure what exactly the issue is. below is the front end code when I convert the address from a text to a byte array then send the request to the backend:

const onSendConfirm = async () => {
        console.log(fromHexString(recipientAddress));
        const status = await actor.transferICP(parseInt(amountToSend), fromHexString(recipientAddress));
        console.log(status);
    };

here is the definition of the fromHexString() function:

export const fromHexString = (hex) => {
    if (hex.substr(0,2) === "0x") hex = hex.substr(2);
    for (var bytes = [], c = 0; c < hex.length; c += 2)
    bytes.push(parseInt(hex.substr(c, 2), 16));
    return bytes;
};

I don’t know motoko, but are Nat and Nat64 interchangeable? You seem to be using both, and the error hints at expecting Nat and receiving something else.

Nat and Nat64 are distinct and cannot be used interchangeably. On the line where i define status I convert the Nat To a Nat64, which is the data type that the Ledger.transfer() function is ultimately expecting.

I ended up having to stop and restart my local replicas and redeploy my app and after that, the error disappeared and it working. So, for anyone reading this in the future, trying restarting your local replica and redeploying you app and see where that gets you.

1 Like