hero-org / herocast

herocast is Farcaster’s leading open-source client. Our goal is to decentralize power on the internet, faster.
https://app.herocast.xyz
GNU Affero General Public License v3.0
51 stars 21 forks source link

HatsFarcasterDelegator: better onboarding with recovery address flow #341

Open spengrah opened 2 weeks ago

spengrah commented 2 weeks ago

A significant drawback of the current onboarding flow is that migrating an existing account from Warpcast is really painful. Users need to export the seed phrase from Warpcast, find the private key of the fid custody account (derived from that seed phrase), and then import the private key into a browser wallet like metamask. This is high friction and also introduces bad op sec practices for users.

This issue describes an alternative and much improved flow that utilizes the Farcaster protocol's recovery functionality. Every fid has a recovery address, which is authorized to transfer the fid but nothing else. The key point is that Warpcast allows users to set the recovery address for their fid to any arbitrary address. For a user, this is much easier and more secure than exporting a seed phrase.

Below is what the new flow could look like. It has several key improvements:

Recommended Flow

  1. User connect wallets to herocast. This should be the wallet that wears or will wear the adminHat.
  2. Create hats using the 4-hat template from #218
  3. Mint adminHat to self (and casterHat to relevant addresses, but this could also happen later), as in #218
  4. Configure / deploy FD contract, as in #218
  5. Guide user to set their wallet address as the fid's recovery address in Warpcast. Optionally, herocast could listen for the ChangeRecoveryAddress event before guiding the user to the next step.
  6. Back in herocast, the user signs the receive signature on behalf of FD. Alternatively, the user could call HFD.prepareToReceive(). Note that only one of these (ECDSA signature or prepareToReceive) needs to be done.
  7. User executes the transfer by calling IdRegister.recover() with the signature from (6) as payload