You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/smart-accounts/1-overview.mdx
+22-6Lines changed: 22 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,8 +52,8 @@ Flare Smart Accounts support two complementary flows for turning an XRPL `Paymen
52
52
### Direct-minting (memo) flow
53
53
54
54
1. The XRPL user sends a `Payment` to an FAssets agent's XRPL address that mints FXRP directly to the smart account, with the [memo field](/smart-accounts/custom-instruction-comparison) carrying the instruction.
55
-
2. The FAssets `AssetManager` mints FXRP to the `MasterAccountController` and calls back into [`handleMintedFAssets`](/smart-accounts/reference/IMasterAccountController#handlemintedfassets) on `MemoInstructionsFacet`.
56
-
3. The facet routes the FAssets to the user's `PersonalAccount`, optionally pays an executor fee, and dispatches any memo instruction (`0xFF` execute UserOp, `0xE0` ignore memo, `0xE1` set nonce, `0xE2` replace fee, `0xD0`/`0xD1` set/remove executor).
55
+
2. The FAssets `AssetManager` mints FXRP to the `MasterAccountController` and calls back into [`handleMintedFAssets`](/smart-accounts/reference/IMasterAccountController#handlemintedfassets).
56
+
3. The `MasterAccountController` routes the FAssets to the user's `PersonalAccount`, optionally pays an executor fee, and dispatches any [memo instruction](#memo-opcodes-direct-minting-flow).
57
57
58
58
```mermaid
59
59
graph TB
@@ -106,7 +106,7 @@ The first nibble is the instruction type.
106
106
This is either `FXRP`, `Firelight`, or `Upshift` (with corresponding type IDS `0`, `1`, and `2`).
107
107
The second nibble is the instruction command; the available commands are different for each instruction type.
108
108
109
-
For the direct-minting flow, the memo carries a different layout - see the [Custom Instruction guide](/smart-accounts/custom-instruction) for the 0xFE variant, the [Raw Custom Instruction guide](/smart-accounts/raw-custom-instruction) for the `PackedUserOperation` format, or the [comparison](/smart-accounts/custom-instruction-comparison) of `0xFE`/`0xFF` and the executor-management codes `0xE0`/`0xE1`/`0xE2`/`0xD0`/`0xD1`.
109
+
For the direct-minting flow, the memo carries a different layout; the first byte selects one of the [memo opcodes](#memo-opcodes-direct-minting-flow) listed below.
110
110
111
111
<details>
112
112
<summary>Table of instruction IDs and corresponding actions.</summary>
@@ -151,12 +151,28 @@ Instructions for interacting with an Upshift-type vault.
151
151
152
152
</details>
153
153
154
+
### Memo opcodes (direct-minting flow)
155
+
156
+
The XRPL memo for the direct-minting flow selects one of the following opcodes in its first byte:
|`0xFE`| Custom Instruction | Carry `keccak256(PackedUserOperation)` in the memo; the bytes are delivered off-chain by an executor. See [Custom Instruction](/smart-accounts/custom-instruction). |
161
+
|`0xFF`| Raw Custom Instruction | Carry the full ABI-encoded `PackedUserOperation` inline in the memo. See [Raw Custom Instruction](/smart-accounts/raw-custom-instruction). |
162
+
|`0xE0`| Skip memo | Mark a target XRPL transaction's memo to be skipped on its next direct mint. |
163
+
|`0xE1`| Fast-forward nonce | Advance the personal account's memo-instruction nonce. |
164
+
|`0xE2`| Replace executor fee | Set a replacement executor fee for a stuck XRPL transaction. |
165
+
|`0xD0`| Pin executor | Pin a specific executor address to the personal account. |
166
+
|`0xD1`| Unpin executor | Unpin the executor from the personal account. |
167
+
168
+
The [Custom Instruction Comparison](/smart-accounts/custom-instruction-comparison) covers when to choose `0xFE` over `0xFF`.
169
+
154
170
## Dispatch on Flare
155
171
156
172
### Proof-based flow
157
173
158
174
The operator monitors incoming transactions to the specified XRPL address.
159
-
Upon receiving a payment, it requests a [`Payment` attestation](/fdc/attestation-types/payment) from the FDC and submits the proof together with the user's XRPL address to the appropriate facet on the `MasterAccountController`:
175
+
Upon receiving a payment, it requests a [`Payment` attestation](/fdc/attestation-types/payment) from the FDC and submits the proof together with the user's XRPL address to the appropriate function on the `MasterAccountController`:
160
176
161
177
-[`reserveCollateral`](/smart-accounts/reference/IMasterAccountController#reservecollateral) — for command `00` of any instruction type.
162
178
Takes the payment reference and XRPL transaction ID (no FDC proof needed at this stage, the user has only committed to mint).
@@ -173,8 +189,8 @@ The contract then resolves the XRPL user's `PersonalAccount` from the address ma
173
189
174
190
### Direct-minting flow
175
191
176
-
When the user mints FXRP directly to their smart account via [FAssets direct minting](/fassets/direct-minting), the FAssets `AssetManager` calls back into [`handleMintedFAssets`](/smart-accounts/reference/IMasterAccountController#handlemintedfassets) on `MemoInstructionsFacet`.
177
-
It enforces that the caller is the `AssetManager`, resolves (or deploys) the user's `PersonalAccount`, pays an executor fee out of the minted FAssets, forwards the remainder to the personal account, and dispatches any memo instruction (`0xFF`, `0xFE`, `0xE0`, `0xE1`, `0xE2`, `0xD0`, `0xD1`).
192
+
When the user mints FXRP directly to their smart account via [FAssets direct minting](/fassets/direct-minting), the FAssets `AssetManager` calls back into [`handleMintedFAssets`](/smart-accounts/reference/IMasterAccountController#handlemintedfassets) on the `MasterAccountController`.
193
+
It enforces that the caller is the `AssetManager`, resolves (or deploys) the user's `PersonalAccount`, pays an executor fee out of the minted FAssets, forwards the remainder to the personal account, and dispatches any [memo instruction](#memo-opcodes-direct-minting-flow).
Copy file name to clipboardExpand all lines: docs/smart-accounts/3-custom-instruction.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,7 +3,7 @@ sidebar_position: 1
3
3
slug: custom-instruction
4
4
title: Custom Instruction
5
5
authors: [nikerzetic]
6
-
description: Performing custom function calls in the Flare Smart Accounts by committing to a PackedUserOperation hash on XRPL and delivering the bytes via an executor (0xFE).
6
+
description: Performing custom function calls in Flare Smart Accounts via XRPL payments with an off-chain executor.
Copy file name to clipboardExpand all lines: docs/smart-accounts/4-raw-custom-instruction.mdx
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,7 +40,7 @@ The XRPL memo carries a 10-byte instruction header followed by the ABI-encoded `
40
40
|`0`|`instructionId`|`0xFF` - raw custom instruction |
41
41
|`1`|`walletId`| One-byte wallet identifier assigned by Flare; `0` if not registered |
42
42
|`2-9`|`executorFeeUBA`| Executor fee in the FAsset's smallest unit, big-endian `uint64`|
43
-
|`10+`|`userOpData`|`abi.encode(PackedUserOperation)` - the call payload the facet decodes |
43
+
|`10+`|`userOpData`|`abi.encode(PackedUserOperation)` - the call payload the controller decodes |
44
44
45
45
The total memo length is `10 + len(abi.encode(userOp))` bytes.
46
46
The XRPL caps each memo at `1024` bytes, so large or repetitive call batches must be split across multiple XRPL payments - each of which pays its own FAssets minting fee and executor fee - and a single call whose ABI-encoded calldata alone exceeds the budget cannot be expressed at all without deploying a shim contract on Flare to compress it.
The [Custom Instruction overview](/smart-accounts/custom-instruction) introduces the 0xFE memo opcode, which keeps the XRPL memo at a fixed 42 bytes by carrying only `keccak256(PackedUserOperation)` and delivers the user operation bytes to Flare through an off-chain executor.
23
+
The [Custom Instruction overview](/smart-accounts/custom-instruction) introduces the `0xFE` memo opcode, which keeps the XRPL memo at a fixed 42 bytes by carrying only `keccak256(PackedUserOperation)` and delivers the user operation bytes to Flare through an off-chain executor.
24
24
This guide walks through a TypeScript script that drives all three steps of the protocol with Viem and the [Flare Data Connector (FDC)](/fdc/overview).
25
25
26
26
A prerequisite for the user operation to be executed is that the personal account holds enough native tokens to cover the call values.
27
27
The script forwards a total of `2` C2FLR (Coston2 Flare native tokens), so fund the personal account from the [Flare faucet](https://faucet.flare.network/coston2) before running it.
28
28
The [State Lookup guide](/smart-accounts/guides/typescript-viem/state-lookup-ts#personal-account-of-an-xrpl-address) shows how to derive the personal account address.
29
29
30
+
The XRPL wallet that signs the `Payment` also needs enough XRP to cover the payment amount (net mint plus fees, computed below).
31
+
Before sending, the script reads the wallet's XRP balance with the `getXrpBalance` helper and aborts if it is below the required amount.
32
+
30
33
The full code is available on [GitHub](https://github.com/flare-foundation/flare-viem-starter/blob/main/src/custom-instructions.ts).
31
34
32
35
## Contracts
@@ -288,6 +291,52 @@ export async function computeDirectMintingPaymentAmountXrp({
288
291
289
292
The script also mints `10` FXRP as a side effect of the same payment, so the payment amount includes the net mint amount on top of the fees.
290
293
294
+
## Checking the XRPL Wallet Balance
295
+
296
+
The signer of the XRPL `Payment` must hold at least `paymentAmountXrp` XRP, otherwise the payment will fail when submitted to the network.
297
+
The `getXrpBalance` helper issues an [`account_info`](https://xrpl.org/account_info.html) request against the validated ledger and returns the wallet's balance in XRP.
298
+
It reuses the caller's `Client` when one is passed in, and otherwise opens and closes its own connection:
`Insufficient XRP balance on ${xrplWallet.address}: have ${xrpBalance} XRP, need ${paymentAmountXrp} XRP`,
333
+
);
334
+
}
335
+
```
336
+
337
+
This check covers only the payment amount; the XRPL network also requires the account to keep its base reserve, which is not subtracted here.
338
+
If the wallet's spendable balance is close to the reserve, the payment can still fail with `tecUNFUNDED_PAYMENT` even though this check passes.
339
+
291
340
## Step 1: Send the hash memo on XRPL
292
341
293
342
The user-side helper function computes the memo, sends the XRPL `Payment` to the FAssets direct-minting address, and returns everything the executor needs to drive Step 2:
@@ -503,6 +552,8 @@ Personal account address: 0xFd2f0eb6b9fA4FE5bb1F7B26fEE3c647ed103d9F
Copy file name to clipboardExpand all lines: docs/smart-accounts/guides/typescript-viem/03-raw-custom-instruction.mdx
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -38,6 +38,19 @@ The same cap is also why some calls - those whose calldata alone overruns the me
38
38
A prerequisite for the user operation to be executed is that the personal account holds enough native tokens to cover the call values.
39
39
The script calls forward a total of `2` C2FLR (Coston2 Flare native tokens), so fund the personal account from the [Flare faucet](https://faucet.flare.network/coston2) before running it.
40
40
41
+
The XRPL wallet must also cover the **sum** of both payments, `paymentAmountXrp + memoOnlyAmountXrp`, since the raw flow splits the batch into two XRPL `Payment` transactions.
42
+
The script reads the wallet's balance with the shared [`getXrpBalance`](/smart-accounts/guides/typescript-viem/custom-instruction-ts#checking-the-xrpl-wallet-balance) helper and aborts before sending either payment if the wallet is short, so neither half of the batch is submitted on partial funding:
0 commit comments