frXRP
frXRP is live: the signer group sweeps deposit addresses, mints frXRP on Bitcoin and pays burns out on the XRP Ledger. The first full cycle ran on 13 October 2026 (see Mainnet lifecycle). Start with a small amount.
Gateway: https://fr1q4mgjev2fnzp2z2p0hwv89q59pxnq8r07px97rcrfkptdhlw6vyqcwkl7e.fr.style. The same service also answers on .subdns.to and .asilos.ltd in place of .fr.style. GET /v1/info returns the group key, the group address and the minimum deposit.
frXRP is XRP held by the signer group on the XRP Ledger, and represented on Bitcoin as an alkane. 1 frXRP unit = 1 drop: frXRP has the same 6 decimals as XRP (1 XRP = 1,000,000 drops).
Contracts and ids
| chain | id | what it is | |
|---|---|---|---|
| frXRP | Bitcoin | 4:50051 | the alkane, plus its burn queue. Deployed in 1ad68572…19d4 |
| frXRP-AUTH | Bitcoin | 2:103066 | mint authority, held by the signer group |
| frXRP-SIGIL | Bitcoin | 2:103067 | limits and upgrade authority, held by SUBFROST's operator address, never the signer group |
group account G | XRP Ledger | rD86YcZ35wxoTJEhrtmascwW932h2Qa7yE | holds the XRP. Never send XRP to it directly; use a deposit address |
Why there is no vault contract
The XRP Ledger mainnet has no smart contracts: Hooks and the ledger's native vault and bridge amendments are not enabled. So frXRP uses a group account instead of a contract vault:
- The group account
Gis the classic address of the signer group's Ed25519 key,7a06eebf8e040b065e9b7022f2c5acbe4441ed65cea9d7e3ed7eae881287a095, with no other key. Check: RIPEMD-160(SHA-256(0xED‖ key)) =8c4612af82f72c2094c1cee150a3cb6a8f9a748e, which encodes torD86YcZ35wxoTJEhrtmascwW932h2Qa7yE. - Deposit addresses. Each deposit intent gets its own address
D(intent), derived from the group key and the intent bytes. Anyone can deriveDfrom the intent; only the group can sign for it.
The trade-off is plain: nothing on the ledger limits what the group account can do. The payout cap and the pause are enforced by the signer group's programs, not by the ledger. SUBFROST keeps the balance held in G low, close to what one payout window needs.
Depositing XRP
- Build your deposit intent, with a refund account. The intent names the Bitcoin script that receives the frXRP and, in version 2, an XRP Ledger refund account (and optional destination tag) where your XRP goes back if the deposit address can never be swept. Version 1 has no refund account and is still accepted, but a blocked v1 deposit can only be held for the operator to settle (below), so use version 2. frFB's own intents are not accepted, and XRP sent to an address derived from a refused intent is never swept or minted. The exact bytes are in the developer reference.
- Get the deposit address. Register the intent with the frXRP gateway (
POST /v1/intent), which returnsD(intent). The refund account is part of whatDcommits to: a different refund account, or tag, is a different address. RecomputeDyourself from the group key and your intent before you send anything, and pass your address asexpected_addressso the gateway refuses a mismatch. The formula, the API and test vectors are in the developer reference. - Pay at least 2 XRP to
Dwith a plain XRPPayment. The payment creates the account. A smaller balance waits atDuntil it is topped up to the minimum. - The group sweeps it. Once
Dis at least 256 ledgers old (the XRP Ledger's rule for deleting an account), the group deletesDintoGwith anAccountDeletethat carries your intent as a memo. The deletion fee, the ledger's owner reserve (0.2 XRP at the time of writing), comes out of the deposit. - The group mints frXRP to your recipient script on Bitcoin: the amount the sweep delivered, less the mint fee.
A gateway that lies about an intent can't redirect a deposit: every seat re-derives D from the intent bytes before it signs a sweep, and a sweep whose memo doesn't re-derive to its own address is never minted.
Blocked deposit addresses: refunds and held deposits
Anyone can attach an object to an XRP Ledger account, such as an incoming Check, Escrow or payment channel, or a trust line. While one is attached, D can't be deleted, so it can't be swept. Only send plain XRP payments to a deposit address. If D is blocked anyway and holds at least the minimum deposit, the group pays out its spendable balance once, less a 12-drop fee:
- Refund (version-2 intents). The XRP goes to your refund account, with your tag. Nothing is minted.
- Held (version-1 intents, or a refund account that can't receive it). The XRP goes to the group account
G, marked as held. It is not minted. It stays inGas a refundable liability, recorded inG's own history, until SUBFROST's operator approves a refund payment fromG. A refund account can't receive the payment if it doesn't exist and the amount is below the base reserve, if it requires a destination tag your intent lacks, if it has deposit authorization enabled, or if it isGorDitself.
Either way, the reserve stays on the blocked address: the base reserve (1 XRP today) plus the owner reserve for each object attached to it can't be recovered.
Redeeming: burn frXRP for XRP
Burn frXRP on Bitcoin with a release intent naming an XRP Ledger account and, optionally, a destination tag:
cellpack [4, 50051, 88, len, w0, …, w(n-1)]
receives exactly the frXRP to burn, and no other alkane
release intent v1 = 0x02 ‖ AccountID (20 bytes) ‖ has_tag (0 or 1) ‖ tag u32 LE (only if has_tag = 1) ‖ action (empty = plain)
A plain untagged intent is 22 bytes; a plain tagged one is 26; the limit is 256. A tag of 0 is a real destination tag 0, not "no tag". The intent carries the raw 20-byte AccountID, never the address text; how to get it from an r… or X… address, with a worked example, is in the developer reference.
An edict in the burn protostone does not limit it. Spend a UTXO holding exactly the frXRP to burn and no other alkane, or put an edict-only protostone before the burn that sends it the exact amount. See Getting the amount right, which has a worked frXRP example.
The burn reverts, and you keep your frXRP, on:
- a zero amount, or one above the max burn;
- a version byte other than
0x02; - an intent too short for its tag flag, or a tag flag other than 0 or 1;
- the special accounts ACCOUNT_ZERO (
rrrrrrrrrrrrrrrrrrrrrhoLvTp) and ACCOUNT_ONE (rrrrrrrrrrrrrrrrrrrrBZbvji); - an intent over 256 bytes, or non-zero words after the intent;
- a second burn in the same protostone.
Payout
After the burn has 3 Bitcoin confirmations, the group pays one XRP Payment per burn from G, burns strictly in Bitcoin order. The payment's frxrp/payout memo carries the burn id.
paid = burned − flat payout fee (12 drops by default, the XRP network fee the group pays)
Check the destination before you burn
The alkane does not know the XRP Ledger. A burn it accepts but the group can't pay is voided: an AccountSet from G with an frxrp/void memo that records the burn id and pays nothing. The frXRP is already burned, and its XRP stays in G for SUBFROST's operator to settle by hand. A burn is voided when:
- the release intent doesn't decode;
- the destination is the group account
G; - the destination requires a destination tag and the intent has none;
- the destination has deposit authorization enabled;
- the destination account doesn't exist and the payout is below the base reserve (a payment that small can't create it);
- the payout is above the payout program's per-payment maximum.
So, before burning, check the destination in a validated ledger (account_info, server_state).
Fees, limits and confirmations
| value | where it comes from | |
|---|---|---|
| minimum deposit | 2 XRP | the sweep program's default; never below the base reserve plus the owner reserve |
| sweep fee | the owner reserve (0.2 XRP at the time of writing), from the deposit | XRP Ledger rule |
| refund or hold of a blocked deposit address | 12 drops, and the reserve stays on the address | the sweep program's default |
| deposit address age before a sweep | 256 ledgers | XRP Ledger rule |
| mint fee | 0.10% of the delivered amount | launch setting (same as frSOL) |
| payout fee | 12 drops, flat | the payout program's default; never below the network fee |
| alkane mint cap | 500,000 XRP per 144 blocks | compiled default (GetLimits) |
| alkane max burn | 500,000 XRP | compiled default (GetLimits, word 4) |
| alkane hard ceilings | mint cap 2,000,000 XRP, max burn 2,000,000 XRP | compiled |
| payout per payment, and per window | 500,000 XRP per payment and per 144 Bitcoin blocks | launch setting; equal to the alkane max burn |
| burn confirmations | 3 Bitcoin blocks | the payout program's default |
What can go wrong
| situation | what happens |
|---|---|
| your intent isn't a valid frXRP version-1 or version-2 intent | its deposit address is never swept: don't send XRP to it |
| you paid less than 2 XRP | the deposit waits at D; top it up |
D holds a Check, Escrow, payment channel or trust line | not swept; with a version-2 intent the balance (less the reserve and 12 drops) is refunded to your refund account, otherwise it is held at G for an operator-approved refund. Nothing is minted |
| the burn is zero, above max burn, malformed, or to ACCOUNT_ZERO / ACCOUNT_ONE | the burn reverts; you keep the frXRP |
| the destination can't be paid (see above) | voided; the XRP stays in G for the operator to settle |
the payout window is used up, or G's spendable balance is too low | the payout waits |
| the signers are paused | nothing is swept or paid until they resume |
Security, as designed
frXRP follows the model in What you trust, with less enforced on the foreign chain than frSOL or frADA:
- At-most-once payout from the ledger's own sequence numbers. Each payment from
Gconsumes the account's next sequence number, and the group proposes burn k only whenG's validated history shows burn k−1 paid or voided and k unpaid. - The pause is off-ledger. SUBFROST's operator can pause the group's programs with a signed instruction, but there is no ledger-enforced operator power over
G. A compromised signer group could moveG's balance; the exposure is bounded by keeping that balance small. - Reads come from three XRP Ledger providers run by different operators, validated ledgers only, which must agree. Every sweep and payout is simulated on all of them before it is signed.
Mainnet lifecycle
The deployment and the first full cycle (deposit, sweep, mint, burn and payout) on 13 October 2026:
| step | chain | transaction | what happened |
|---|---|---|---|
| frXRP deployed | Bitcoin | 1ad68572…19d4 | 4:50051, frXRP-AUTH 2:103066 and frXRP-SIGIL 2:103067 created (block 971,276) |
| AUTH to the group | Bitcoin | 83bfb4a1…bc8d | frXRP-AUTH sent to the signer group; frXRP-SIGIL kept by SUBFROST's operator (block 971,278) |
| group account funded | XRP Ledger | 1A98DBD0… | G created |
| group bootstrap | XRP Ledger | 0B6A5144… | AccountSet signed by the group, memo frxrp/bootstrap: destination tags required on G |
| 1. deposit | XRP Ledger | DF87970C… | 5.250108 XRP paid to the deposit address rnUipjNNkYF3QRueU8hwZYdB66acY5YiW5 |
| 2. sweep | XRP Ledger | 7932D4C2… | AccountDelete into G, memo frxrp/intent: 5,050,118 drops delivered after the 0.2 XRP deletion fee |
| 3. mint | Bitcoin | 0fb543ca…4860 | signed by the group: 5,045,068 frXRP (5,050,118 less 0.10%) to the intent's script (block 971,298) |
| 4. burn | Bitcoin | 21ed3782…3a33 | 5,045,068 frXRP burned to a new XRP Ledger account (block 971,299), burn id 971299:0 |
| 5. payout | XRP Ledger | 8C6437CF… | Payment from G, memo frxrp/payout = burn id 971299:0: 5,045,056 drops paid (5,045,068 − 12), creating the destination account |