Multis has been building financial tools for web3 organizations for the past 3 years, and have come to our latest release - Fiat USD accounts.
This launch was a mix of exhilaration and massive challenges, so we wanted to share our approach and learnings to build a hybrid product at the crossroads of legacy banking infrastructure and Decentralized Finance.
Converting crypto-currencies to fiat currencies is a pain. It can take weeks, even months, to convert crypto to fiat. And that's when you're already approved by a bank or exchange.
Our team at Multis is lucky, we're USD-funded and have some fiat sitting on a bank account (which got frozen for no reason several times btw). However, the process is way more complicated for bootstrapped projects which generate revenue in crypto.
We’ve talked to many companies regarding the way in which they bridge their fiat and crypto funds, and some of them had very technical processes for crypto transactions, like writing custom API calls to (1) receive payments in crypto and (2) convert them. We love tech hacks, but when it comes to money we want it to be easy, straightforward and secure.
We wanted to share our approach to solve that problem:
Why?
We chose to help users secure their assets with multi-signature wallets. Simply put, multi-signature wallets are smart contracts locking crypto assets on-chain. Only a predefined majority of “owners” need to approve a transaction before it gets sent. Spending limits and other restrictions can be encoded into the approval rules of the wallet as well.
Our top priority when building our application was security and convenience, and we believe multi-signature wallets offer the best compromise out there:
They’re smart contract-based (this enables easy integration with Decentralized Finance)
They’re software-based (you only need bandwidth and a laptop to use them)
They can easily be embedded into a front-end
Most importantly, they’re self-custodial, which means users can have full shared ownership and control over a company’s funds
How?
Workflows and jargon like key management or gas fees can be intimidating. We strived to offer a simple and reassuring UX by abstracting complex concepts as much as possible. People should not need to be acquainted with network/chain, transactions submission, nonce management, multisig smart-contract deployment, etc. to simply manage their assets. Some examples:
In EVM based networks like Ethereum and Polygon, the gas fees are collected in its main currency – for example, Ethereum uses ETH. At Multis, we decided to handle network fees and enable users to pay in whatever cryptocurrency they’re transacting with
We’re relaying transactions with Infura ITX to ensure they don’t get stuck in the mempool forever
Getting data out of blockchains can be extremely painful and non-performant. We aggregate data across multiple networks in our databases to empower the discoverability of users’ funds
We use the CREATE2 opcode (deterministic smart contract addresses) to:
Give access to wallets but only deploy them when first deposits are made. This streamlines onboarding without costing us gas fees
Give users the same wallet address across different networks
We integrated multiple EVM networks in a single account. People don’t have to change their browser wallets (e.g. Metamask) settings to transact on these
We also strived to provide as much security as possible to our users with multi-signature wallets:
Users are protected against internal risk — outgoing transactions must be approved by several signing users to be processed (e.g. 2 out of 3 signatures required) to prevent misuse of funds
Users manage their private key to sign transactions and are protected against third-party risk. We can’t access their funds.
This multi-signature wallet is effectively a Gnosis Safe multisignature wallet. It’s open source, thoroughly audited, and currently secures over $175bn across Ethereum and other EVM networks
We faced multiple challenges in doing so, in particular:
There are no standards for signing methods in the web3 space. This means we have to support many different types of browser wallets to enable users to make or approve payments. Our integration with Wallet Connect only partly solved the issue.
Smart contract wallets like Gnosis Safe are open-source. This means users can transact not only from their Multis account but also from any other platforms supporting these smart contract wallets. While fantastic for users (money portability FTW), it makes nonce management (clashing) very complex and buggy. We still have to come up with better solutions here.
Why?
Our second main workstream was around data. We had to fuel data to our application from different sources, both on-chain (e.g. transactions status from multiple blockchain networks like Ethereum or Polygon) and off-chain (e.g. spot prices, metadata like labels or attachments added via our application). We wanted to ensure this data was easy to read and understood by crypto-fluent users and accountants alike. Most importantly, we wanted transactional data to be formatted and merged with USD transactions to offer a holistic experience.
How?
We built on 3 pillars:
We had to design a DB pattern that could handle many types of transactions from a debit card transaction to a complex DeFi transaction. Each atomic transaction has different information linked to it, including one or multiple incoming or outgoing transfers, different kinds of fees (to the blockchain network or to the providers, or us), different networks (blockchain or banking infrastructure for production/mainnet or sandbox/testnet), conversion price in USD and other information we want to store to offer as much transparency as we can
To do the above, we had to find the right partners that could allow us to aggregate the right level of information: For on-chain data - Infura to access nodes via RPC For on-chain information execution - Indexers such as Etherscan, TheGraph, Gnosis-Safe API and Covalent To obtain spot and historical prices, ethgas API’s and others - off-chain providers such as Coingecko
We dealt with wallet transaction rate limits - this was challenging because we retrieve a large amount of data from partners and third parties, which generally limit the number of requests to their APIs (e.g 5 calls/sec). We had to build a throttling mechanism to better manage the application’s throughput to downstream services and ensure we synchronize data in an efficient and resilient way.
Why?
Converting crypto-currencies into fiat is a hassle. The whole process can take up to a week:
Get approved to open a business account on an exchange (up to 6 months)
Send funds from company wallet to exchange wallet
Convert crypto into USD
Withdraw funds to an external bank account white-listed by the exchange compliance team (via ACH or wire transfers, usually takes 1-5 days to hit banking accounts)
Spend with corporate cards, ACH/wire transfers
Because we internalized wallets and exchange features, we’re able to streamline this as follows:
Get approved in less than 24h
Convert crypto into USD (directly from the multi-signature wallet, proceeds are instantly available)
Spend with corporate cards, ACH/wire transfers
How?
As an early-stage company, we needed help to build our banking infrastructure and get banking and money-service licenses. We had to outsource the bank stack to the right partner to allow us to focus on building the product.
We help mainly crypto companies. Finding a partner with high-security standards to fill the banking and brokerage gaps we were lacking was crucial to avoid the complexity of integrating with two core services
We use hexagonal architecture to build our service. Integrating a new data source to pull transactions to Multis was a no brainer. A new adapter and it was ready to roll.
Speed is a key market advantage to getting users verified and converting USD into crypto. As soon as these operations start at Multis, we subscribe to state changes in the bank to immediately react and keep the process in motion until it ends
Idempotence was taken to a higher level to avoid processing twice the same events. Without it, we could potentially have "double spending" issues, and we want those far away from our users' wallets
We have a robust state consistency mechanism to ensure the bank and Multis have a similar view of the world. Advanced fault tolerance and resilience techniques are in place to ensure we always persist state in distributed systems
We'd love to hear your feedback on the way we went about building Multis. What would you have done differently?
I hope this post is helpful and can inspire other builders to experiment with these hybrid infrastructures.