Skip to content

Safety and trust

Keys and security

How signing works for passkey and email users, what Floatless can and can’t do with your money, and the known risks.

On this page

This page explains how keys work for each way of signing in, what Floatless can and can't do with your money, the checks that run before anything is signed, and the risks we already know about.

Two ways to sign in

Your dollars sit in your own wallet address on Monad, and your Floatless Savings are vault shares held by that same wallet. How you sign in decides who can sign for that wallet.

Passkey Email
How you sign in Create account or Sign in with your passkey, then your phone's passkey prompt Your email address, then a 6-digit code
Where the key comes from Your passkey, on your phone An embedded wallet held by Privy
Who signs Your phone The Floatless API, through Privy, after you confirm in the app
Can Floatless sign for you? No Yes

Passkey

When you tap Create account, the app creates a passkey for floatless.xyz named with your name. Sign in with your passkey, and I already have an account on the welcome screen, use the one you already have and never create a new wallet. Each time you sign, the app rebuilds your wallet key from the passkey on your phone. The key isn't saved on your phone, and it's never sent to Floatless's servers. They get your wallet address and the signatures you make. To start a session, your phone signs a one-time challenge from the API.

If your passkey manager can't create a Floatless wallet, the app tells you and suggests iCloud Keychain on iOS 18 or later, or Google Password Manager on Android.

Floatless has no copy of your key, so it can't restore your wallet if you lose your passkey. In Profile, Recovery under Security explains that your passkey syncs to a new phone through your password manager, and that guardian recovery isn't available yet. Passkey under Security shows where yours is saved.

Payment sessions

On the review screen, a passkey account can turn on Skip Face ID for 10 minutes before tapping Send. That payment is still approved with Face ID. Once it's signed, the app keeps the Mera signing session from that unlock open, so the payments after it don't ask for Face ID again, within these limits that the app checks before it signs:

  • Up to 10 minutes from the approval.
  • Only stablecoin payments, meaning a transfer on one of the stablecoin contracts the app has built in. It can't approve a token, call any other contract or send MON.
  • Up to $25 in total across the session, counting each stablecoin at $1. The payment you approved with Face ID to start it doesn't count toward this.
  • Only on this network, and only from the wallet that opened it.

Every payment still gets the full check against your onchain spending rules and balance. While a session is open, Home shows "Payments unlocked" with the time and the amount left, and End. The session ends, and the app zeroes the key in memory, when the 10 minutes run out, when you tap End, when the app goes to the background, or when you sign out. A payment that's outside the limits asks for Face ID as usual. The limits are enforced by the app on your phone, not onchain, so a payment session trusts the app the same way an unlocked phone does.

Email

Privy, the wallet provider Floatless uses for email accounts, sends you a 6-digit code. The first time, the Floatless API creates an embedded wallet for you with Privy and links it to your account. When you confirm something in the app, the app asks the Floatless API to sign, and the API asks Privy to sign with your wallet.

The API signs only structured requests for an email wallet, through two routes:

  • /v1/wallet/sign-transaction signs only the transactions the app builds: a stablecoin transfer, an approve to the savings vault or SafeLock, or a call to the savings vault, SafeLock or the spending-rules registry. It must be on this network, from your wallet, and send no MON. It also runs the same regulated-transfer check as every payment, and the app checks that the signed transaction matches what you reviewed before sending it.
  • /v1/wallet/sign-typed-data signs only Floatless spending rules: the FundingMandate type for this network's registry, for your own wallet, with no extra fields. A token permit or an exchange order is refused.

There's no route that signs a raw hash or a message, or that signs and sends in one step.

You don't have to manage a key, but your wallet depends on the Floatless API and on Privy. On testnet, the signing service also refuses to sign a regulated-dollar transfer unless Cleanverse approves it at that moment. See Regulated dollars.

What Floatless can and can't do

With either sign-in, Floatless can decline a payment check. That stops the app from sending the payment, and it doesn't move any money. Floatless also controls the savings vault's settings through team-held keys, within the limits in Who controls the savings vault.

If you sign in with a passkey, Floatless can't sign anything for your wallet. It can't send your money, register spending rules for you, or approve anyone to spend from your wallet. Each of those needs your passkey.

If you sign in with email, the Floatless API can sign for your wallet through Privy. The app only asks it to after you confirm, and it checks every signed payment before sending it. Even so, anyone who controlled the API or its Privy access could sign other transactions for email wallets. That's the trade-off for not managing a key yourself.

Checks before you sign

Here's what happens between tapping Send and your payment reaching Monad.

  1. Payment check. The Floatless API checks the payment against your spending rules, today's total, your goal floors and your balance on Monad, and confirms your rules are the active version in the registry. For regulated dollars on testnet, it also asks Cleanverse about both wallets.
  2. Review. On the review screen, Send $X only turns on when the check allowed this exact amount, currency and recipient, and the screen shows the maximum network fee.
  3. Second check. When you tap Send $X, the app runs the check again. It stops if the payment is now declined, the fee went up, the API and the app are on different networks, the sender isn't your wallet, the token address doesn't match the one built into the app, or the amount or recipient changed. A check is good for up to one minute.
  4. The app builds the transaction on your phone, a plain token transfer of your amount to your recipient.
  5. Your phone signs it with your passkey. For email sign-in, Privy signs it through the Floatless API.
  6. Signed-transaction check. Before anything is broadcast, the app reads the signed transaction back and checks that the network, token, recipient, amount, sequence number and fee settings are exactly what it built, and that your wallet signed it. If anything differs, it stops before broadcasting, for example with "The signed transaction does not match the reviewed transfer."
  7. The app saves the transaction's ID on your phone, then broadcasts it. If the network is slow, Check status looks up that same transaction instead of sending a second payment.
  8. After the payment settles, the API reads it back from Monad and checks the sender, recipient, token and amount before adding it to your history.

Spending rules get a similar check. Before you sign them, the app confirms that the rules the API prepared match the ones you reviewed, for your wallet, this network and the registry built into the app, and it recomputes the fingerprint your wallet signs from those rules.

The savings vault is pinned in the app

The mainnet app has the Floatless Savings vault address, 0x35277466836C6cdb426F50DDF79db0e043e6bbFe, and the vault's AUSD address built in.

  • Before each deposit or withdrawal, the app compares both with what the API reports. If they differ, it stops with "The savings vault reported by the server does not match this app. Nothing was signed."
  • The app builds the transactions itself: an approval for exactly the amount you're depositing when one is needed, then the deposit, or a withdrawal paid to your own wallet.
  • After each one, the API checks the vault's own deposit or withdrawal record for your wallet on Monad before adding it to your history.

A server that's been tampered with can't point your deposits at another vault through the app. For email sign-in, the API still signs these transactions, so the trust described above applies.

Mainnet and testnet stay apart

  • The mainnet app uses api-mainnet.floatless.xyz on chain 143, and the testnet app uses api.floatless.xyz on chain 10143. Each API has its own database.
  • Every API response names its network, and the app refuses a server on the other one.
  • Before signing a payment, the app checks that the API and its own connection to Monad are on the app's network.
  • Spending-rule signatures name the network, so they can't be reused on the other one.
  • Pending payments and passkey sessions on your phone are kept separately for each network.

Mainnet and testnet covers what works on each.

Who controls the savings vault

Floatless Savings is a Morpho Vault V2 on Monad mainnet. The code that holds the money is Morpho's audited contracts, and Floatless configured them. Three separate keys, all held by the Floatless team, can change its settings.

Role Address What it can do
Owner, also the backup allocator and fee recipient 0x024Db1faC265D471C2a5eca95AD00C19e3394A07 Right away: replace the curator, cancel any pending change, lower the deposit cap, and undo a bad allocator move. It receives the 10% fee on interest.
Curator 0x7830200a9D5a4BB821B1C2327B8953f991E8F9C9 Propose changes to the vault's adapters, caps, fees, gates or allocators. Each change waits 3 days.
Allocator, the operations key 0xE1E55cB254feB8CBEA730AAe987777f12d8C5B25 Move money between the vault and its one Morpho adapter, and set the path deposits and withdrawals use and the maximum interest rate.

In plain words:

  • An adapter is the vault's connection to a Morpho vault that lends the money out. A gate can limit who deposits or withdraws.
  • Any curator change that could affect savers waits 3 days. All 17 Vault V2 functions that can be delayed are set to this wait. You can see a change coming onchain and withdraw first, and the owner can cancel it during the wait.
  • The vault can only use adapters from Morpho's own registry, and that setting is locked for good.
  • If a leaked allocator key broke the withdrawal path, the owner could restore it right away. The app also offers Withdraw straight from Morpho for a 0.01% fee.
  • None of these keys can move the vault shares in your wallet.

Floatless Savings and Contracts and verification have the full setup.

Known risks

  • Team-held keys. The vault's owner, curator and allocator are separate keys held by the Floatless team. They aren't a multisig yet, which is a wallet that needs several people to approve each action. The 3-day wait and the owner's power to cancel limit what one leaked key could do.
  • Morpho liquidity. Withdrawals depend on Morpho having unborrowed AUSD. When its markets are heavily borrowed, only part of your savings may be withdrawable until borrowers repay.
  • Morpho bad debt. If a Morpho market takes a loss, the underlying Morpho Vault V1.1 doesn't show it in its share price, so the last savers to leave could absorb it.
  • Email wallets. The Floatless API signs for email wallets through Privy, so a problem with the API or with Privy could put them at risk. Passkey wallets don't depend on the API to sign.
  • Spending rules and goal floors. Floatless checks them before you sign, and they don't stop transfers made outside Floatless.
  • Lost passkeys. Floatless can't restore a passkey wallet, and guardian recovery isn't set up.
  • Stablecoin issuers. Your balances are stablecoins, and each one depends on its issuer. Floatless Savings holds only AUSD, issued by Agora.

Report a vulnerability

Please don't open a public issue for a security problem. Report it privately instead.

Say what you found, how to reproduce it and the impact you expect. Describe any private keys, seed phrases, API keys or user data instead of including them. Floatless will acknowledge your report, keep you updated, and credit you when the fix ships if you'd like.

Don't test against the live mainnet vault, real users on the hosted APIs, or anyone else's funds. Use a local API, the testnet API or the mainnet fork tests:

MONAD_MAINNET_RPC_URL=https://rpc.monad.xyz forge test --match-contract FloatlessSavingsFork -vv

Bugs inside third-party services such as Privy, Mera, Cleanverse and Morpho belong with those providers, but how Floatless configures and uses them is in scope. The risks above are already known, so please don't file them as new findings. The full scope and policy are in SECURITY.md.