Like many others in the community, we're incredibly excited about the recent launch of the dYdX v4 testnet. Unlike previous versions of the dYdX protocol, which were built on top of StarkEx, the latest version is built using the Cosmos SDK. This has the potential to solve a long-standing security weakness in dYdX, namely the handling of private dYdX keys in the browser instead of the wallet.
At first glance, it appears that the newly launched dYdX testnet hasn't fulfilled its promise. dYdX still only supports the same less-secure flow as before, and users cannot use their Cosmos wallet to manage their dYdX private keys.
Yet a closer look at the newly launched dYdX testnet and its code reveals that dYdX already has support for Cosmos wallets under the hood. By making a few modifications to the dYdX client-side code, we enable Keplr support in the user interface and connect the dYdX DApp to Keplr. We demonstrate an end-to-end signature flow on the dYdX testnet using Keplr (see video below). The Keplr-based flow avoids the insecure in-browser key derivation, as it uses the wallet for key management. In the remainder of this blog, we discuss our findings in details.
Previously, dYdX was unable to rely on the user's wallet for private key management and signing. This was due to the fact that dYdX was built on top of StarkEx, which used a non-standard digital signature scheme (specifically, ECDSA over the Stark elliptic curve) that was unsupported by most mainstream wallets. Instead, dYdX developed a custom key management solution which generated the user's dYdX private key within the dYdX application in the user's browser. This approach introduced a degree of risk for users, especially for institutional users of MPC wallets. For more details on this problem and the solutions developed by our team at Fordefi, please refer to our previous blog post.
The move to Cosmos, which uses a standard signature scheme and has many supporting wallets opens up the possibility for dYdX to benefit from standard wallet interfaces and allow users to store their dYdX private keys in Cosmos wallets like Keplr, instead of in their browsers.
A couple of weeks ago, dYdX released their public testnet. However, we were slightly disappointed that it did not yet include a wallet integration with any Cosmos wallet. As in previous versions, the dYdX v4 testnet DApp retains the same flow, where the user signs an onboarding message with their Ethereum wallet, and the DApp derives the dYdX private key from the message signature. The only difference is that the type of the key is ECDSA secp256k1 instead of Stark.
Based on some of dYdX’s twitter announcements, we assume this is temporary, and future versions of the DApp would soon support native wallet key management, for example using Keplr. And yet, we were too excited to wait!
A Closer Look at the Code
What’s interesting in this code snippet is the last element in the list —
CosmosSigner. Whereas the dYdX user interface or documentation have no visible support for Cosmos wallets, under the hood there is already some support for a Cosmos Signer.
Looking a bit further, we see the following:
This list of wallets contains exactly those wallets that the user can choose from, when they click “Connect Wallet” in the app.
What does the app do when the user chooses any of those wallet? A bit further down in the code. we see the following:
Each wallet in the
DISPLAYED_WALLETS list has a corresponding entry in the
wallets map, which specified its name, icon, and connection type. Note that the connection types in the
wallets map match the connection types in the
walletConnectionTypes enum (e.g.,
injectedEip1193, etc.) However, none of the wallets on the list specify the
CosmosSigner connection type.
This got us thinking: what happens if we modify this list and try using the
CosmosSigner connection type?
Modifying the Code
This rule adds another entry to the list of wallets in the dYdX client-side application:
The important part is that our new entry specifies the
CosmosSigner connection type.
Let’s see how the “Connect Wallet” modal looks like with our change:
Nice! We now see a Keplr option in the list. Clicking it, we see something very interesting: our Keplr wallet shows the following popup:
It seems that the
CosmosSigner is not merely a placeholder — there is actually code in the application that handles this type of signer and interacts with the Keplr wallet when the user chooses this type of wallet — a choice that our patch makes possible. Moreover, it seems that the Cosmos wallet adapter within the dYdX app uses Keplr’s
experimentalSuggestChain feature, which allows a DApp to request Keplr adds a custom Cosmos chain, even if that chain is not one of the chains that Keplr supports out of the box. We see that the dYdX app uses this feature to request Keplr adds the dYdX testnet chain
This looks promising, so we eagerly click “Approve” to add the chain to Keplr. However, the application then shows an error: “failed to fetch”. OK, so maybe the Cosmos wallet support is not fully built yet. But let’s not give up yet: looking at Chrome Developer Tools to see any hints about the error, we see there is some problem with the node communication. Moreover it seems that the chain id that the dYdX app has added to Keplr (
dydxprotocol-testnet) does not match the chain id that appears in some of the documentation that has already been released about the new dYdX Cosmos chain (
dydx-testnet-1). So it seems like the chain config that the app contains is not up to date.
Searching GitHub reveals the correct configuration: dYdX already have a pending pull request to Keplr with the correct chain configuration:
Note that the RPC endpoints and the chain id are different than what the dYdX app currently suggests.
When looking in the frontend code of the dYdX DApp, we see the chain info:
This is different than the official chain info published by dYdX:
We therefore add a second patch to the application by modifying our Requestly rule as follows:
We now have two modifications:
- The first modification is the one we already had - it adds Keplr to the list of displayed wallets.
- The second modification replaces the chain configuration to the one we have found on GitHub.
We then reload the app and try to connect Keplr again. First, as before, we see the application requests Keplr to add the dYdX testnet chain — only this time, thanks to our hook, the requests specifies the correct chain parameters. We again click approve to add the chain, and this time we get no error from the DApp. Furthermore, the wallet indicator in top right corner looks connected. Interestingly, the bech32 address that it shows matches the address of our Keplr wallet. This means that using the
CosmosSigner flow sidesteps the in-browser key derivation, and instead just uses the wallet’s actual address. This is exactly what we have been interested in — since with this flow the user’s keys are stored safely in the wallet.
Moving forward, let’s see what happens when we try sending an order. We enter our order in the application and click “Place Limit Order”. A Keplr transaction-approval popup appears, asking us to sign a Cosmos transaction on the dYdX chain.
The transaction’s type is
dydxprotocol.clob.MsgPlaceOrder. This is again very exciting and different from the existing flow. As a reminder, in the existing dYdX flow, keys are derived and stored in the browser, so when the user wants to sign an order, the app can just sign the order without an additional consent from the user’s wallet. This can be problematic for institutional users, who might want to require a wallet-based approval for certain order. With this new Cosmos-based flow which we have discovered, keys are stored in the wallet, and so signing every order requires interacting with the wallet, which enables the wallet to enforce a security policy before signing the order.
To continue, we approve the transaction in the Keplr popup. The dYdX application shows the new order, and after a few seconds, our order is filled. It seems that the Cosmos Signer-based flow indeed works end to end!
Our research shows that dYdX already have the building blocks ready to support native Cosmos wallets like Keplr. It further shows that the the native Cosmos flow offers significant security benefits compared to the existing flow which is based on Ethereum wallets. Specifically, it allows the user to keep their private keys in their wallet and require wallet approval before every order. We are excited to see this flow launch on dYdX (first on the testnet and then on mainnet) and we look forward to utilizing it to provide secure access to dYdX to our institutional users.
Dima Kogan is Chief Technology Officer and co-founder of Fordefi. Dima’s career in cryptography and cybersecurity spans more than 15 years in academia, industry and government. Dima’s research has been published by top-tier academic conferences, and he was awarded the “Best Young Researcher” prize at both the Eurocrypt 2018, Theory of Cryptography Conference 2019 and Eurocrypt 2020. Dima holds a PhD in computer science from Stanford University and is a graduate of the IDF’s elite Talpiot program.