Potential generalizable solutions for recovering funds that users accidentally send to their II app principal?

The problem

Developers constantly get bombarded with - “I accidentally sent token X to my principal with your app”, can you help me recover it?

This problem applies generally to any app that has Internet Identity login, including the NNS.

What to do?

The NNS team ended up building out a solution that allows anyone to import any token, but developers shouldn’t be required to build out recovery pages to support tokens sent accidentally from users.

At the same time, crypto users new to ICP are unaccustomed to how delegates and per-app principals work - so the fact that this keeps happening shows that there is a certain amount of confusion.

We then end up in a situation with repeated work and time spent by developers, and a poor experience for end-users who made the mistake (and hopefully will be more careful in the future).

Potential Resources?

  • A terminal script - allowing the user to open up their console, and paste in the the script, and edit the token ledger and principal args, as well as the amount to send
  • An open source recovery page and standard where that anyone can copy/paste into their app and put at a path like …ic0.app/recovery or …com/recovery
  • A protocol enabled recovery mechanism and site allowing II users to recover their funds on domain X even if the domain or canister id no longer exists! (My favorite for long-term security of user funds in app-wallets, but requires the most work & security consideration)

I’d be curious to hear what the NNS team and @chepreghy think about what the right solution for both developers and users might be. The goal here would be to save both users and developers the time and frustration associated with lost funds - especially as more and more people learn about and use ICP in 2025!

4 Likes

I absolutely agree there need to be improvements in this regard.
Btw the example url you provided links to a site with explicit content.

1 Like

Oops, thanks for the correction forgot that xxx does that :sweat_smile:, meant it as an example :man_facepalming:

Just to share because it touches this subject;

We had a similar issue a while back where SNS neurons were distributed to a principal that wasn’t supporting interaction with neurons them so we wanted to transfer them, with the help of @peterparker we developed a solution for that, but it came in handy a couple of times so a couple of days ago somebody had the issue as described above for WTN tokens so a transfer function was added.

For now it only support internet identity for token transfers but others can be added easily;

How it works:
open up your chrome console and paste the following in (with the replaced params to fit your need)

const { transferToken } = await import("https://unpkg.com/yolosns-2@1.1.8/dist/esm/index.js")
await transferToken("LEDGER_CANISTER_ID", "SEND_TO_PRINCIPAL", BigInt(AMOUNT - FEE))

This is the method you are calling

So basically how it works,

  • you login with internet identity which sets a global identity on the dapp where your assets are sent to
  • the script uses that identity to run not-ui enabled methods (in this case a hardcoded icrc1_transfer)

This is based on “trust me bro” but everything is verifiable, so this might be something that comes in handy when developing a more generic solution.

4 Likes