Forget everything you think you know about web3 and wallets. It all just changed for the better by 1,000x
No more passwords, passphrases, QR codes, copy and pasting secret keys, buying hardware wallets and all the other nonsense we’ve put up with over the past decade as blockchain has come of age. I want to show you how, with just two taps, you can generate an address and use it to sign transactions. It really can be just that simple.
- The demo site
- The code for the demo site
Today’s post will be a little less traditional as I don’t intend to get too deep into the weeds of walking through every single line of code for the above demo. Primarily I want you to experience it and then cover in sufficient detail what exactly is going on.
Let’s talk about the problem first though and then experience the future and finally detail what’s actually going on.
The Problem
Blockchain has a serious usability issue. The ecosystem is outrageously fractured and really tough to tie together. It’s tough for a lot of reasons; lack of protocol alignment, lack of coordination, regulatory inconsistencies, bad pr from rampant fraud, scams and dumb prominent utility, and the list goes on.
At the end of the day though the core of the issue as I see it is my inability to just pass over the benefits of blockchain contained within a sensible product. It’s never just the product. The app isn’t on the app store ‘cause Apple hates crypto. In order to use the app you first need to get some “native currency” which requires you to create an account on an “exchange” which requires you to KYC, connect your bank, wait 3-5 days, convert your fiat into the native currency, transfer those funds back to the app, don’t forget your “memo”, make sure to pick the right “network”. Dear lord it’s an absolute mess if you aren’t already in.
Fundamentally the power of blockchain isn’t its cryptocurrency it’s its cryptography. We’ve oriented our solutions around the wrong selling point. Math is the power of blockchain, not money. We’ve bundled up math into tidy APIs, databases and governing protocols for the purpose of solving difficult relational problems. It’s absolutely incredible, and it will absolutely die by the wayside if we don’t learn to move past cryptocurrency as the thing of blockchain.
Once we’ve done that it actually becomes much simpler to begin to utilize blockchain in meaningful ways that don’t create terrible user experiences that ultimately will just never catch on.
That’s what I want to talk about today. Namely using passkeys not as as permissions gateway for accounts but as the actual account itself. The passkey will do the signing of transactions.
There are a couple key pillars I require out of the tech I use and products I build.
- It has to be familiar
- It has to be secure
- It needs to work
- It needs to matter
This is more than just simple. There are apps out there that are simple that no one will use because they are foreign to them. Change takes time. Incremental minor tweaks over long periods of time. Traditional web3 is anything but that. It’s a radical break from the norms and thus will never catch on until we steer away from explaining things and actually wrap our radical improvements in familiar interfaces and experiences which are then easily digested and enjoyed.
Non-custodial, decentralized, these aren’t buzzwords, they’re essential for a future where the little guys can do big things. We can’t put the benefits of blockchain behind domain gates, master signing keys, or any other single points of failure. The worst thing for blockchain would be feigned success and that’s a lot of what is being touted out there in the web3 world right now. Centralized, custodial, breakable solutions that really aren’t any sort of improvement over traditional products and services.
Web3 breaks all of the time. Bad apps, bad errors, bad code, bad services, all taped together with last Saturday’s hackathon grant money. Of all the things I hate about web3 this may be chief among them. It’s just always a terrible experience. How can you honestly be selling that as a future anyone would actually care about? I understand the ecosystem is fragmented and a building will only be as good as the tools used to build it but open your eyes on what the software standards are out there. It’s a high bar at this point and web3 is complete trash way too much of the time.
Stop solving problems you don’t have. Stop building things you don’t care about. Build things you believe in! Build stuff you’re excited about, that means something to you. Care about someone, care about a lot of people, understand their issues and make them your own, and then help them. Any technology is only as useful as the people it’s helping. Blockchain isn’t a solution in search of a problem. That’s us, the builders, we’re the problem, way too often more interested in funky tech applied carelessly like kids with double sided tape and too much time on their hands.
Anywhere these pillars aren’t fundamental you will have pointless products that probably cost way too much money for way too few people to care. Where these things are paramount however you will be doing work that matters. That’s how Stellar’s smart contract protocol Soroban was built. It’s not perfect, but anywhere it’s not is an area for improvement not apathy because these are the key pillars for Soroban’s long term success.
For me this is nowhere more strong than in the first class support for account abstraction (more commonly known as passkey accounts or smart wallets) via the secp256r1 cryptographic curve added in protocol 21. That’s a lot of words, it’s very technical, and blockchain is and that’s the danger. What’s incredible about these technical words and features is that users can now utilize all the benefits of blockchain inside apps that require the pillars from above.
Clean user experiences are really hard to get right when requiring self custody of cryptographic accounts. That’s what’s given rise to the outrageous world of wallets we have today in web3. With the advent of passkeys and webauthn and the secp256r1 cryptographic curve a few years ago this problem was solved, it just came really late for blockchains already set in their ways. In that vein then Soroban is late, but right on time in every way that matters. We can access passkeys and webauthn and this secp256r1 curve right out of the gate together in tandem to create what I believe is blockchain’s best most obvious answer to the problem of wallets being the worst part of the blockchain UX.
So that’s the problem, let’s observe how it feels in practice. I’ll walk through it below but please do use the https://passkey.sorobanbyexample.org/ demo yourself in order to really understand how pleasantly boring this feels for a blockchain powered app.
Experience the Future
👉 Me walking through more of the code behind the demo 👈
What’s Actually Going On?
It’s really not terribly complex, it’s mainly just awesome. Essentially Soroban opens up access to a special function called __check_auth
which contract developers can configure with any number of special casing parameters and checks which will fire whenever this contract is being authenticated against for some type of authorization. This happens in the case of the require_auth
or require_auth_for_args
which Soroban utilizes for authenticating Address
es. Both for Stellar accounts and for Soroban contracts.
So think with me for a moment. You’ve likely used classic web3 accounts before which were bound to some sort of signing interface. A browser wallet, a hardware wallet, maybe even a fancy NFC wallet. The issue was however that the verification for the signatures these wallets created was part of the protocol, you could only control the device or user side of getting transactions signed.
With account abstraction, or more specifically with the __check_auth
special, reserved Soroban function a contract developer has the ability to add arbitrary logic to the verification of inbound signatures. This is a game changer for both blockchain protocols and their users because it unlocks the blockchain’s potential for innovation and the user’s experience of that innovation. In our case we allow the user to use familiar cryptographic signing tools like biometric bound passkeys to sign data which our blockchain smart contract can then successfully verify via a customized __check_auth
function which can handle the signatures created by these familiar interfaces.
The Stellar blockchain natively utilizes the Ed25519
elliptic curve signing algorithm. It’s awesome! It’s really fast and secure. However it’s not the only curve and it’s not as popular as the Secp256r1
. I’m no cryptographer and I don’t intend to dive into the differences here. The point here is that most passkeys default to Secp256r1
which isn’t compatible (for obvious reasons, this is cryptography after all) with Ed25519
. What this means is we can’t use signed data from a passkey natively with chains doing verification on any other curve. With the advent of Soroban however, and more specifically protocol 21 and most specifically CAP 51 we gained the ability to write our own native Secp256r1
verification logic for Soroban contracts.
And this then is ultimately what’s going on in the SoroPass demo. We create a Soroban account from a Secp256r1
public key generated by a passkey and then submit a transaction for this new account with data signed by the passkey and verified with a customized __check_auth
function. Here’s the code for that function. Untitled. You’ll notice it’s actually quite simple in our case. There’s certainly more we could do but if all we’re trying to do is verify Secp256r1
signature payloads in order to submit transactions to the blockchain which require the authentication of this account, this is all we need. Too cool!
To boil it down for the developers in the back let me break it down step by step in light of the contracts here and the functionality of the app as laid out here.
- We build 3 contracts
- The
chicken-v-egg
contract which contains the “protocol” we want to authenticate against when sending verified votes. - The
webauthn-factory
contract which will serve as the factory from which allwebauthn-secp256r1
contracts are deployed. A factory model allows us to ensure consistency of all theSecp256r1
passkey accounts. It behaves as a sort of cloning device printing out duplicates of ourwebauthn-secp256r1
contract with the only difference being what passkey public key that clone is associated with. No other funny business going on. - The
webauthn-secp256r1
contract is the actual meaty bit. The custom passkey account itself. The smart wallet if you will. This is where that custom__check_auth
function has been declared which will fire whenever contracts deployed with this code are invoked via arequire_auth
orrequire_auth_for_args
in another contract. (like what happens here in thechicken-v-egg
contract). - We deploy the
chicken-v-egg
contract and take note of its contract id. - We deploy the
webauthn-factory
contract and take note of its contract id. - We install the
webauthn-secp256r1
contract and take note of its wasm hash. - We invoke the
init
function on thewebauthn-factory
contract passing as its only argument thewasm_hash
from step 4.
Remember we won’t directly deploy webauthn-secp256r1
contracts. We prepare the webauthn-factory
contract with the wallet template we want to use (the wasm code which the wasm hash points to) and then whenever we call its deploy
function we’ll get a new clone of the Secp256r1
passkey account tied to the public key we pass in with the call. (in our case a passkey).
— At this point our contracts are ready and we can now begin deploying smart wallets from registered passkeys. —
- We create a passkey from within the https://passkey.sorobanbyexample.org service by clicking “Register”.
Clicking “Sign In” would attempt to link up to an existing passkey account. Which is awesome once you’ve got one to link to.
- Step 6 produces a webauthn create key response which contains the passkey’s public key which is what we need to pass to the
webauthn-factory
deploy
function. deploy
gives us the passkey account’s Soroban contract address. Yay! This is what we’ll use to interact with other Soroban services (like the chicken-v-egg contract). Whenever these other contracts requestrequire_auth
orrequire_auth_for_args
this newly created smart wallet (or passkey account) will have its__check_auth
method called to verify the passed in signature.
- This exact thing happens on the https://passkey.sorobanbyexample.org demo when we click to vote for either the chicken or the egg.
- Step 9 produces a webauthn get signature response which contains the passkey’s signature for the contract auth entry we sent it which the chicken-v-egg is requesting for its
vote
function. With that entry signed we just bundle up the transaction and submit it to the network. - The network receives our transaction and then runs the
__check_auth
function on our passkey account to verify everything validates and checks out. Assuming it does the submission succeeds and our vote is cryptographically approved and the votes are updated.
Am I too excited about this UX? No. I am perfectly, appropriately ecstatic. This is a flow anyone would be comfortable and familiar with. I don’t want to interact with web3 in any other way and neither should you.