Hybrid Custody

Do you plan to introduce account abstraction in Flow blockchain design ?

It’s already available, hybrid custody would build on that


This has many benefits, I was a bit hesitant in the beginning about security side of things, but after reading about use cases and motivation, I think it can be implemented securely without losing any of the benefits.

Some benefits I see:

  • This will be great for developers: Capability model was too confusing to many of the newcomer developers, actually it was even complex for all ( me included )

  • Can provide great isolation between dapps.

  • Not requiring signing and allowing dapp to run action on behalf of the user without interaction is great UX. This can even make FCL obsolete.

  • it is great for onboarding but also makes dapps to have no excuse to have walled gardens anymore, so this has great benefit for users.

  • Wallets even auto create temp accounts when a dapp connected, link to main account, and add dapps public key ( so dapp and wallet can use the account at the same time )

  • Another good benefit is: now there is a misconception about each account is a user and each tx is user interacted, I think this will help to clear that misconception.

  • If we can somehow tag this child accounts to dapps, I think it can be a valuable metric about dapp usage etc.

I think here “Irrevocable access” can be also equally true. If dapp ( let’s say TopShot) will onboard me to a child account, I would like my parent account ( let’s say blocto ) should have irrevocable access to that child account ( unless I want to break the relation )

In general I am really excited about things we can do with this child accounts.

1 Like

All of the features called “Account Abstraction” in the Ethereum community were available from day 1 as part of Flow’s original design.

There is a FLIP currently being proposed that streamlines account delegation specifically to make it easier to use – and easier to audit – via AuthAccount Capabilities. This FLIP isn’t necessary for us to implement Hybrid Accounts, but I think it makes Hybrid Accounts much cleaner and would prefer we build Hybrid Accounts in this way before wallets and apps start supporting other methods. (It’d suck to have multiple competing mechanisms for Hybrid Accounts.)

1 Like

I don’t anticipate that it would make FCL entirely unnecessary.

For use-cases like marketplaces, you want to be able to access all of the assets in all connected accounts, and it totally makes sense to use the classic “app proposes and wallet approves” transaction flow that we are used to in web3.

I can totally imagine that applications like games could be built without ever interacting with a wallet via FCL, however!

I disagree. I mostly disagree because it adds complexity, but it doesn’t really add security, either.

If the controller of the child account becomes untrustworthy, they can always just move the assets out of the account; blocking them from revoking the delegation doesn’t really prevent malicious behaviour.

A new user, without a self-custody account, can sign up for a new account without having any wallet software. But when they are ready for self custody, they can delegate control of the app-custody account to their self-custody account.

Maybe I’m missing something, but does the app-custody account (aka the child account/new account) have an associated private key?

If the app-custody account has a private key, then who has access to it? The problem is premised on the idea that the new user can’t handle a private key yet, so does the application backend store it and not the user? If that’s the case, then it seems like a restricted child account in this use case doesn’t make sense, since the application has root access to the child account already through being able to create digital signatures for it. I understand that when the user “graduates”, they’ll have their own self-custody account with a separate private key that the application knows nothing about that will be the new parent of the app-custody account, but what’s happening with the app-custody account private key?

I imagined a bit different, app-custody account is dapp’s and created for user as a sandbox, later when I have my account, then I can move stuff from there (with authaccount capability)

Technically I can add my own key and remove dapp’s key from the account too. ( if I am adventurous )

This sub account model will resolve a number of plain point in web3 space. Although, app custody can provide a more seamless experience for the user. But it also means there is more work to do which was belonged to the wallet. For example, dApp how to generate and store private key is secure. And even they might need to create the flow account for the user. At the meantime, it could require high UX from both wallet side.

Some Questions:

  1. Does wallet need query ( all children accounts ) under parent account to find all assets belong the to user or only parent account is enough ?

  2. Let’s say a children parent is a game dApp account, I wanna purchase some game item but child account has insufficient balance, it possible to auto-delegate this payment to parent account or it still need transfer funds from parent account to child account first then proceed the payment.

  3. It will be nice to see some best practice examples to educate dApp developers how to manage App custody private key for their projects, such as like the Google KMS, Mobile Secure Enclave. Or I like Bluesign’s idea even wallet can provide temporary account generate function to the dApp.

  4. On flow account creation need submit a transaction to the chain. For now, there is no public RPC to create a main net account easily (Since, there is actually cost on it). Hence, even dApp know how to create the private key, they might still need build their own service for account creation.

  5. Is it possible to use account delegation to transfer an parent account to an new parent account ? Or by adding new key is more recommended ? For example, I wanna transfer my one wallet account (eg. Blocto) to my new wallet account (eg. Dapper self-custody).

And yes, I’m also really excited about child account is coming on flow !!

The best way to think about the child account is being subject to “joint custody”. The user (through the delegation) and the app (through the key) both have unrestricted access the contents of the child account.

Of course, if you don’t trust the app, then you should move the assets out of the child account and into the parent account (where only the user has access). The app can still see those assets in the parent account (through FCL), and can still propose transactions that need to be signed by the wallet managing the parent account in order to use them. This lets each user optimize between security and convenience.

You could do this, but as per Kate’s point just above, remember that the app has unrestricted access to the child account. If the child account has some kind of capability in it that can draw funds from the parent account, there’s a chance the app could steal those funds.

Again, I would suggest that the right tradeoff for most people would be to have some small amount of funds that they are willing to trust to the app developer in the child account, and then the app can use wallet authorization to refill the child account when it gets below a threshold.

Absolutely! The responsibility for managing the on-chain account falls to the app developer in this case. Fortunately, there’s already an open source project that makes this quite easy, complete with support for GCP and AWS key-management services. (It’s marked as “not maintained”, but I believe it works as expected, and is used by several live projects.)

I would expect that a wallet would want to show a user all assets in all accounts available.

This certainly feels like a solid iterative step in order to bridge app level custody and self custody. However, it doesn’t really take you to a long-term place where the user no longer has to see and sign for transactions, because it’s making the assumption that the parent app can have unlimited access into the child. That’s not really a state that I’d ever want to be in, even if I trusted the parent app. Maybe I’m misunderstanding things here, but it seems like this will be what happens for most apps and accounts:

  1. I sign up for a new app - let’s call it “Hybrid App A”. They give me a child account (“Child Account A”).

  2. I take over custody of the account “Child Account A”, but “Hybrid App A” retains access to this account since it’s under hybrid custody. Note: I understand that I can remove the access for “Hybrid App A”.

  3. Now, “Hybrid App A” can sign for anything on this account, even collections that are not from the original app or anything. I can query things, transfer them, and really anything.

To compare this to Web2, this would be like if I signed up with Google, the app I signed up to had full access to look at information I signed up for other apps with. And the way to get out of that is to remove Google-Sign in and use standard username/password (which is metaphorically going to full self-custody, with no delegated access).

That doesn’t seem great - let’s assume the parent app (“Hybrid App A”) is well-intentioned, still even simple bugs can transfer the wrong assets out of the accounts. I’d rather be in a world where I can onboard with app custody, add in a self-custody wallet later and then move items from app custody into self-custody.

@anir-niftory I can appreciate the concern around custodial risk, though I think something about the construction isn’t clear. When you assume control of the child account, both you and the app maintain control of the account, yes. However, your main account is still partitioned such that only you maintain access to it. Hybrid App A in your example only ever has access to that which is in Child Account A which would be used for actions you take within the Hybrid App A. So the flow would be this:

  1. I sign up for a new app and the app creates an account - ChildAccountA
  2. After some time, I connect my wallet, assuming shared control of ChildAccountA. Note - you now have two accounts: the main account you connected and ChildAccountA which your main account maintains a capability on
  3. Yes, Hybrid App A can sign for anything on the account. The point being that only that which is pertinent to the app is ever in the account, but you can also transfer assets from that account to your self-custody account which the app doesn’t have access to.

This allows for the situation where you onboard with app custody, as you mentioned. Once you connect your wallet & create the parent-child link, you can transfer those assets from the hybrid account to your self custody account even without needing to interface with the app if you choose to do so. Again because your main account now has a capability to Child Account A

Now imagine a world without hybrid custody where you have any number of apps that custody your assets and there’s no notion of linking them. It’s entirely up to you to manage them, remember which apps hold your assets, transfer them from the app account to your self-custody account, etc. because there’s no notion of on-chain relationships between your main and app accounts for a wallet to allow you to manage. That’s entirely unmanageable for any of us let alone a mainstream user.

With hybrid custody, you could leave the app-related assets in their respective hybrid app accounts, partitioned by where they’re useful (yes, with some custodial risk). But because of the on-chain relationship between your main (AKA parent) account and each child account, you can move assets among your network of accounts as you see fit and any wallet or dapp would be able to present you with a dashboard of that network of accounts and collective assets.

Does that make sense?


Is there a reason why we would need key-management services? I could be confused, but I’m still thinking that the child account shouldn’t have their own keys because all the control is coming from another account at every point.

Screenshot 2023-01-27 at 3.37.38 PM

I’m imagining that the flow is:

  1. app admin account exists
  2. new user starts using the app, app admin creates a new child account (with no keys associated) and makes its own account a parent
  3. The user “graduates” and decides to create a self-custody account.
  4. They make this self-custody account another parent of the child account. At this point, there are two parents. Both the app and the user have complete control of the child account.
  5. The user might optionally decide to revoke all access from the application.

@kate_sills there are a few advantages for an account to sign as its own:

  • you can see the transactions for an account; as every state modification will be a transaction.

  • normally dapp doesn’t need AuthAccount capability as they have the key. So transactions will not need capabilities. ( you can have a multisign transaction for multi-player transactions )
    Otherwise, you need to keep those capabilities and make a big map for User->Capability. It can be problematic.
    This means if dapp is hacked, all resources are gone. ( with this User->Capability map )

  • If dapp lets you to graduate, you can revoke dapp key later. ( or re-add when you want to use it again )

PS: Bigger problem is dapps will be wallet providers ( crypto asset holders on behalf of clients )

1 Like

I took a shot at visualizing this concept. I think this hybrid model solves a couple point points I’ve experienced multiple times. Can anyone comment if this looks right?

(The users’ full names are Mainstream Maddie and Early Market Earl)


this is very helpful.

i feel like for Maddie’s account, there would be a multiple party, multiple signer scenario (two keys, 1000 weight each)

the 2 keys for Maddie where the app uses Key #1 to sign and Key #2 is an escape hatch for Maddie to revoke which can take the form of an emailed “recovery kit”

1 Like

Thanks, updated to “app key mgmt” to reflect it’s whatever the app decides.

Also wrote a short post on how it solves challenges I’ve faced trying to grow within this ecosystem: The Custody Chasm - by Brian Astrove - Brian’s Bulletin

1 Like

This is a great full-context diagram, and a solid read. The “Custody Chasm” is the perfect way to put the problem Hybrid Custody solves.

In your diagram, it looks like account access to Earl’s app account is delegated via keys, and this does enable shared access to the app-custody wallet. The downside here is that dApps would have to rely on wallet providers to maintain and provide knowledge of an authenticated user’s linked accounts - the 3rd party marketplace in this example. Additionally, re-keying the main account would require re-keying all linked accounts. Relying on wallet providers to enable linked-account management poses the risk of a lack of interoperability, fragmented user experience, and a requirement that they buy in to the business case for this feature to begin with.

IMHO the smoothest road to Flow-wide portable hybrid custody is with an agreed upon contract-level standard that relies on AuthAccount Capability linking over key-based delegation. Full-disclosure, I have a smart contract engineer’s bias so no surprise I think the contract hammer can fix the problem. I believe a standardized set of contract defined resources solves the problem of portable linked accounts and relying on AuthAccount Capablities over keys means that users can re-key their main account without risking loss of their linked accounts. It also means that interoperability across wallets & dApps is as simple as leveraging scripts & transactions against the standardized resource, preventing wallet lock-in for the sake of this powerful feature.

I’ll take this opportunity to call out the recently submitted FLIP going over this construction - would really appreciate feedback on this idea and prototype!

Just to try to drive home the idea, it’s really a small change to the diagram you posted (forgive the quick hand drawing!). The difference is that the app maintains the key for Earl’s child account & Earl accesses the account via a stored AuthAccount Capability - more on that linking process here

As a sidenote, you mentioned the problem of airdrops in your article - this model could be useful as a new airdrop mechanism. You create and custody keys for accounts users can access with their Web2 identities. When they want to migrate outside of your airdrop app, they can link their wallet-custodied account and either transfer or simply maintain access for later use. You can still airdrop additional tokens to the account your app created & custodied knowing they can access assets as they wish.


@brianastrove that was a great read, I envy people like you can write in such flow.

I think situation is a bit different in reality though, nobody wants to give up custody voluntarily, neither brands nor market places or dapps. So I think situation is more like: how to convince Maddie to give us control despite Earl working at IT at Maddie’s company defending ‘not your keys not your money’

I mean maybe we are sugar coating it a bit, we are saying she doesn’t want to, instead of she isn’t capable of etc. or we are saying you can move your stuff anytime, but we will punish you for it :slight_smile:

Anyway I stopped myself for writing next fight club manifesto :slight_smile:


Wouldn’t it be preferable to restrict app custody to certain permissions only? Or to make app custody and transactions conditional on the users authorizing use of their account (“just-in-time” access without a web3 wallet)?

As it may sound abstract, I’ll provide an example I have in mind. LocalCryptos has provided non-custodial wallets with web2 on-boarding starting in 2017. The user would sign in to the app with a password and 2FA, and then the user could execute blockchain transactions on the web2 app with the app as a relay. For example, funding an escrow for a sale of crypto required no web3 wallet interaction, only clicking on a button. In summary, the app utilized the Web Cryptography API to enable cryptographic operations in the browser (web3 wallet interactions as frontend interactions) and had some centralized components (e.g., the relay). The app never had custody of funds or knowledge of user keys, but had an encrypted “AccountKeyMaster” key which was stored in the browser after user authentication.

I’m not familiar with Flow’s technical architecture to provide more insight, but I just wanted to throw this here and advocate for apps to be as non-custodial as practicable.

The unrestricted access to the child account is still the toughest struggle for me with Hybrid Custody. Although it’s great in practice, the app custody model is now responsible for a lot more in a hybrid system. In the past, the app could, like Dapper Wallet, restrict certain transactions from running. This means that I can prevent someone from having real usable Flow, FUSD, etc in this app wallet and have it be a limited, app-only wallet.

With unrestricted access, this child wallet can now literally be used for anything the main account wants to do. I can move Flow into it, out of it, etc. One thing we do is top off Flow for users - now the parent account can just use this as a way to accumulate flow by withdrawing this topped off Flow. In the world of running an app wallet, my life actually just got a lot more complicated. Really, the parent account could just use these app wallets as ways to move money around, etc and now my app wallets would also be at risk for usage in all of this.

Again, we’d absolutely love a limited way to hybrid link, but an unlimited way still feels challenging to use in practice, where the app now takes on a lot more risk for how these wallets can be used. If it was limited in some way, i.e. to a storage path, a set of capabilities, etc we’d be able to control the risk much more easily.