Flap Apps (Draft Spec)
From a token launchpad to an app launchpad.
Flap will not only be a launchpad for tokens — with Flap Apps, it becomes a launchpad for apps. Ship your contract; Flap hosts your UI and backend and keeps your app running. Your app, unstoppable.
Vision
Today, everything built on Flap starts with a token. Flap Apps remove that requirement. Any project with a smart contract — a game, a tool, a launchpad, or a Vault — can launch on Flap and get the same guarantees mechanism tokens get today:
- Audited contracts, reviewed by Flap and its partner security firms.
- Flap-hosted UI, so the app doesn't disappear when its creator walks away.
- Flap-hosted backend, through shared infrastructure instead of servers the developer has to keep alive.
Roadmap
| Stage | What it covers | Status |
|---|---|---|
| 1. Vaults + Vault UI | Token tax flows into a custom contract; Flap hosts its UI on the token page | Live |
| 2. Flap App v2 developer preview | Standalone apps with no token, built with the template's Flap App v2 mode | Developer preview |
| 3. Flap Shared Indexer (FSI) | Flap-hosted backend: index and query any contract's events | Beta — BNB Chain Testnet → BNB Chain Mainnet → Robinhood Chain |
| 4. Flap Apps launch | Audited Flap Apps published at flap.sh/apps/{slug} and listed in the Flap Apps catalog | Coming |
| 5. More shared infrastructure | New backend capabilities driven by what Flap App developers need | Ongoing — tell us what you need |
Draft. This page describes the direction and the draft specification of Flap Apps. The boundaries are intentionally open: during the draft phase we review every Flap App case by case, and details on this page may change before the final release.
Table of Contents
- Vision
- Roadmap
- From token launchpad to app launchpad
- Why Flap hosts mechanisms
- What is a Flap App?
- Vault vs Flap App
- Architecture
- The three layers
- Flap Shared Indexer (FSI)
- Building a Flap App, step by step
- Open questions
From token launchpad to app launchpad
Flap started as a launchpad for tokens. With Vaults, a token's tax flows into a smart contract where the developer implements custom logic, and with a Vault UI that logic gets its own interface — hosted by Flap.
But the Vault model has a structural limitation: you need a token first. A token is launched, then it has a Vault, then the Vault gets a UI. Many applications don't fit that shape:
- a tool (a dashboard, a calculator, a batch utility) that has no token of its own;
- a launchpad built on top of Flap that launches other people's tokens but has no token itself;
- a game whose contract people play with directly;
- any other app that simply has a smart contract users want to interact with.
These apps still have a contract, still need a backend, and still need a UI that users can trust to keep working. Flap Apps widen the Vault + Vault UI model to cover them. Our goal is for Flap to be a launchpad of apps, not just a launchpad of tokens — and for Flap's infrastructure to make your app unstoppable.
Why Flap hosts mechanisms
Almost every token that uses a Vault has some mechanism built into that Vault — dividends, buybacks, games, social-proof routing. We call these mechanism tokens. Their biggest pain point is durability:
- If the UI is hosted on the creator's own server, the mechanism dies when the creator rugs, loses interest, or stops paying for hosting.
- If the mechanism needs a custom backend (an indexer, a database, a keeper), it dies when that backend goes down.
- Users can't tell whether the contract behind a third-party UI is safe.
Flap removes these failure points:
| Risk | How Flap addresses it |
|---|---|
| The contract is unsafe or centralized | Flap and its partner security firms review and audit the contract before it is listed |
| The UI disappears | The UI is reviewed, built, and hosted by Flap |
| The backend disappears | Backend needs are served by shared Flap infrastructure (indexing, scheduling, oracles, verifiers), not a server the developer has to run |
Developers only have to care about the contract itself, and integrate Flap's infrastructure into it so the app is as decentralized as possible. Users don't have to worry that the mechanism will break because of a dead server or an unmaintained contract: the contract has been checked by Flap and its audit partners, and the UI and backend are run by Flap.
What is a Flap App?
In this draft, a Flap App is:
- An app whose UI and backend are both hosted by Flap. It is published at its own URL on Flap (
https://flap.sh/apps/{slug}) and does not need a token, a Vault, or a factory to exist. - Backed by any smart contract. The contract can be a Vault, but it doesn't have to be. A game contract, a tool's helper contract, or a launchpad contract are all valid.
- Audited. The contract must pass an audit. We work with partner security companies who will audit your code.
That's it. We don't draw a hard boundary around what a Flap App may do — during the draft phase we keep the definition open and review submissions case by case.
Vault vs Flap App
| Vault + Vault UI | Flap App | |
|---|---|---|
| Requires a token | Yes — the Vault receives a token's tax | No |
| Contract | Must implement the Vault spec | Any contract (a Vault is allowed) |
| Audit | Optional; required for the low-risk badge | Required |
| UI hosting | Flap-hosted on the token's Vault panel | Flap-hosted at flap.sh/apps/{slug} |
| UI identity | Bound to a factory / Vault / token (match.bindings) | Stable artifact ID + immutable slug; no bindings |
| Backend | Flap shared infrastructure | Flap shared infrastructure, including the Flap Shared Indexer |
| Product entry | The token's page | The Flap Apps catalog |
A project can ship both: a Vault UI for its token and a standalone Flap App. They are reviewed and published separately but can reuse the same contracts and most of the same UI code.
Architecture
flowchart LR
U[User] -->|flap.sh/apps/slug| UI
subgraph Flap["Hosted by Flap"]
UI[Flap App UI<br/>reviewed and built by Flap Workbench]
FSI[Flap Shared Indexer<br/>indexes and serves your contract's events]
INFRA[Other shared infrastructure<br/>Trigger Service, AI Oracle,<br/>X General Verifier, FlapVaultEx]
end
subgraph Chain["On-chain"]
C[Your audited contract]
end
UI -->|reads, simulates, writes<br/>through the Flap SDK| C
C -->|emits FSI events| FSI
UI -->|queries leaderboards,<br/>feeds, activity| FSI
C <-->|callbacks / proofs| INFRA
All business state and every rule that moves funds live in your contract. Flap hosts everything around it.
The three layers
1. Contract — any audited contract
Your contract can implement any logic. The only hard requirement in this draft is that it passes an audit by one of Flap's partner security companies before the Flap App is published. Reach out to the Flap team to schedule one.
Keep in mind when you design the contract:
- Put everything that matters on-chain. Anything involving funds must be enforced and readable on-chain. Off-chain data (including FSI) is a cache for display, never a settlement source.
- Prefer Flap's shared infrastructure over your own servers. If you need a scheduler, an AI decision, or a social-proof check, use the existing services — see Quick start for Vault Developers § 3. They work for any contract, not just Vaults.
- Emit FSI events for anything your UI needs to list, sort, or page through (see below), so you never have to run your own indexer.
2. Backend — hosted by Flap
Most apps need a backend for one reason: to turn on-chain events into data a UI can query (leaderboards, user histories, feeds, activity logs). Instead of running your own indexer, database, and API, your contract emits a small set of standard events and Flap indexes them for you — this is the Flap Shared Indexer (FSI).
Other backend needs are covered by existing Flap services:
| If you need to... | Use... |
|---|---|
| Query lists, rankings, and histories of your contract's data | Flap Shared Indexer |
| Schedule a delayed or MEV-protected callback | Flap Trigger Service |
| Get a verifiable LLM/AI decision on-chain | Flap AI Oracle |
| Verify that an X account posted a given text | X General Verifier |
| Swap any token into another without writing DEX routing | FlapVaultEx |
| Generate AI video on-chain | Flap Video Generator |
If your app needs a backend capability that none of these cover, tell us — that is exactly the kind of infrastructure we want to add.
3. UI — hosted by Flap
Flap App UIs are built with the flap-vault-component-template, the same template used for Vault UIs, in its standalone Flap App v2 mode. The developer preview lives on the template's feat/mini-app-v2 branch — start with its Flap App v2 quickstart and the step-by-step walkthrough.
The essentials:
-
A controlled business component, not a free-form website. Like a Vault UI, the App is a React component under
src/vaults/{slug}/(Component.tsx,manifest.json,VaultABI.ts,i18n.json). The same safety boundaries apply: no direct wallet provider access, no undeclared endpoints, no hidden transaction targets. -
Independent identity. The manifest declares the standalone model and an immutable
slug, with no token/factory/Vault bindings:{ "schemaVersion": 2, "mode": "mini-app", "appModel": "standalone", "slug": "my-app", "artifactId": "vaultui_my-app_01ARZ3NDEKTSV4RRFFQ69G5FAV", "name": "My App", "displayTitle": { "en": "My App", "zh": "我的应用" }, "match": { "bindings": [] }, "i18n": ["en", "zh"] } -
Reviewed wallet permissions. Instead of binding to a token, an App declares exactly which chains (
walletChains) and which contracts and function signatures (walletContracts) it may call, with bounded native value and ERC20 approval caps. Dynamic per-token targets go through on-chain resolvers. The host refuses any transaction outside the declared policy. -
One SDK, host-owned wallet. The App calls
useFlapSdk({ chainId })for reads, simulations, writes, and receipts, using the user's wallet already connected to Flap. Apps never implement their own wallet connection. -
Check, test, package, review.
yarn app:scaffold→yarn app:check→yarn app:e2e→yarn app:package→yarn app:verify-package, then submit the generated ZIP to the Flap App Workbench. Flap reviews, builds, and publishes it athttps://flap.sh/apps/{slug}. No on-chain registration is required for the UI.
The earlier token-bound Flap App mode (bound to an 8888 token) is deprecated for new development. New Flap Apps use the standalone v2 model described here.
Flap Shared Indexer (FSI)
Beta. FSI is in beta. The event signatures below are the fsi-v1 templates. Rollout order is BNB Chain Testnet (97) → BNB Chain Mainnet (56) → Robinhood Chain (4663). We are not publishing the FSI endpoint yet — if you want access or to join the test, please reach out to us.
Once a contract emits events that follow FSI's fixed templates, its data becomes queryable and sortable off-chain — leaderboards, claimed amounts, epoch statistics, post timelines, claim / compound / burn logs — without the developer running an indexer, a database, or a query API. Flap runs one indexer per chain that listens for these templates, stores each row, and serves it over HTTP to your Flap App UI, Vault UI, or any third party.
FSI works for any contract — a Vault, a factory, or a Flap App's business contract — under exactly the same rules. No registration is required.
Templates
| Need | Template | Event | Primary key | What is stored |
|---|---|---|---|---|
| Current balance, points, claimed amount, or share for an address | A | FlapSharedIndexerAddrUint | (emitter, ns, key) | One latest value per address |
| The same, scoped to a round / epoch | B | FlapSharedIndexerUintAddrUint | (emitter, ns, round, account) | One latest value per round and account |
| An ordered history you must keep: a post plus updates, announcements, buyback records | L | FlapSharedIndexerFeed | (emitter, ns, id, seq) | Every record, with a contract-assigned sequence number |
| A low-cost activity log: claim, compound, burn, auto-claim, a single trade | G | FlapSharedIndexerLog | (emitter, txHash, logIndex) | Every log, keyed by its on-chain position; the contract stores no state for it |
event FlapSharedIndexerAddrUint(bytes32 ns, address key, uint256 value, string data); // A
event FlapSharedIndexerUintAddrUint(bytes32 ns, uint256 round, address account, uint256 value, string data); // B
event FlapSharedIndexerFeed(bytes32 ns, uint256 id, uint256 seq, address actor, address related, uint256 value, string data); // L
event FlapSharedIndexerLog(bytes32 ns, uint256 id, address actor, address related, uint256 amount, uint256 extra); // G| Template | topic0 |
|---|---|
| A | 0x6d92bb4f14ee2a433bdba0d337dc697cf6017066878befb1a42edf326092dba3 |
| B | 0x9cdf0eeb5c96afc4a86997e5b946603d187dfc2f1119862ad053c413de36dd28 |
| L | 0x262063c773bcbfa80d8648888e2f288454339e80d08c1c8f78aa6e55c2db75cb |
| G | 0x0483a030f7f57a91177910ed00ae51f19170eb9db2129394c858e7e3bc188aed |
No parameter is indexed (this saves gas). The indexer filters on topic0 only and decodes the rest. Events that match none of the templates are ignored.
| Field | Meaning |
|---|---|
ns | Namespace (bytes32). One contract uses different ns values as separate logical tables, e.g. "points" and "claimed". Use bytes32(0) if you only need one. |
key (A) | Row key (an address). |
round, account (B) | Round / epoch / ID, and the user address. Use account = address(0) for pure round stats (round total, global counter). |
id, seq (L) | The object the record belongs to (e.g. a post ID) and its sequence number within that object — assigned by the contract: 0 for the first record, then 1, 2, … |
id (G) | The object or a type code, used for filtering (a pool, an epoch, 0 = claim / 1 = compound). |
actor, related (L, G) | The submitter / operator, and another bound address (e.g. a beneficiary). Use address(0) when unused. |
value (A, B, L) | A, B: the row's current absolute value, sortable. L: the sort field, usually block.timestamp. |
amount, extra (G) | Values of this action (not cumulative). amount is sortable and filterable; extra is returned as-is. |
data (A, B, L) | Optional string, not sortable, returned as-is. Truncated past 1024 bytes; keep it under 256 bytes. For L it is usually the CID of a content JSON. |
Two rules that always apply
- The event must be emitted by your contract itself. The indexer takes
emitterfromlog.address, so only your contract can write your contract's rows. - FSI is an off-chain cache, never a settlement source. Logic that involves funds (e.g. how much a user can claim) must read on-chain state. Never settle based on an FSI response.
Base contract
Flap provides a dependency-free abstract contract, FlapSharedIndexerV1. Inherit it and use the helpers — they make "emit the absolute value" the default:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
abstract contract FlapSharedIndexerV1 {
event FlapSharedIndexerAddrUint(bytes32 ns, address key, uint256 value, string data);
event FlapSharedIndexerUintAddrUint(bytes32 ns, uint256 round, address account, uint256 value, string data);
event FlapSharedIndexerFeed(
bytes32 ns, uint256 id, uint256 seq, address actor, address related, uint256 value, string data
);
event FlapSharedIndexerLog(
bytes32 ns, uint256 id, address actor, address related, uint256 amount, uint256 extra
);
function flapSharedIndexerSpecVersion() public pure virtual returns (string memory) {
return "fsi-v1";
}
/// Template A: absolute value for one address.
function _fsiSetAddr(bytes32 ns, address key, uint256 absoluteValue) internal {
emit FlapSharedIndexerAddrUint(ns, key, absoluteValue, "");
}
/// Template B: absolute value for one user in one round. Pass account = address(0) for pure round stats.
function _fsiSetRound(bytes32 ns, uint256 round, address account, uint256 absoluteValue) internal {
emit FlapSharedIndexerUintAddrUint(ns, round, account, absoluteValue, "");
}
/// Template L: seq is unique under the same (ns, id). 0 is the first record. value is block.timestamp.
function _fsiAppend(bytes32 ns, uint256 id, uint256 seq, address actor, address related, string memory data)
internal
{
emit FlapSharedIndexerFeed(ns, id, seq, actor, related, block.timestamp, data);
}
/// Template G: no sequence number required; the contract stores no counter.
function _fsiLog(bytes32 ns, uint256 id, address actor, address related, uint256 amount, uint256 extra)
internal
{
emit FlapSharedIndexerLog(ns, id, actor, related, amount, extra);
}
}flapSharedIndexerSpecVersion() declares which FSI version your contract is built on. Before development, confirm the target chain already supports the templates you use (GET /fsi/versions, see Querying FSI).
Write semantics
Templates A and B — latest absolute value. For each primary key the indexer keeps only the latest value. It does not accumulate deltas and does not keep history.
valuemust be the current value after your state update. Update storage first, then emit the value read back from storage.- A stored value is overwritten only by an event at a strictly later
(block, logIndex). Older or duplicate deliveries never roll data back. Within one block, the greatestlogIndexwins. - To fix a wrong value, just emit the correct current value again — no migration needed.
- There is no delete event: emitting
value = 0clears a row (it still counts toward the quota; filter it out withminValue=1).
| Wrong (delta) | Right (absolute value) |
|---|---|
_fsiSetAddr("points", user, 50) where 50 is this increment | _fsiSetAddr("points", user, points[user]) |
Re-emitting an ERC20 Transfer(from, to, amount) | One event each for from and to, with each balance after the transfer |
Claimed(user, amount) | _fsiSetAddr("claimed", user, claimed[user]) — the cumulative amount |
Template L — append only. Each (emitter, ns, id, seq) is an independent record; the original and every update are kept. If a primary key repeats, the earliest on-chain occurrence wins and later duplicates are dropped — so always use a new seq. There is no delete; to hide an object, keep a flag with template B (e.g. ns = "hidden", round = id, account = address(0), value = 1). Permission to create or append is enforced by your contract, not by the indexer.
Template G — append only, no sequence number. Each log is stored once per (txHash, logIndex); one transaction may emit several. A G event writes no on-chain state and costs roughly 2,000–3,000 gas. Records can't be edited or deleted — emit a correcting record under a convention you define. On a chain reorganization, logs from rolled-back blocks are removed and re-added from the canonical chain; your contract doesn't need to handle this. Use A/B for cumulative totals; G is for per-action values.
Example: a Flap App contract using all four templates
A small game that tracks lifetime points (A), per-round scores and a round total (B), posts with author-only updates (L), and claim logs (G):
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {FlapSharedIndexerV1} from "./FlapSharedIndexerV1.sol";
contract MiniGame is FlapSharedIndexerV1 {
bytes32 constant NS_POINTS = "points";
bytes32 constant NS_SCORE = "score";
bytes32 constant NS_POST = "post";
bytes32 constant NS_CLAIM = "claim";
mapping(address => uint256) public points;
mapping(uint256 => mapping(address => uint256)) public score;
mapping(uint256 => uint256) public totalScore;
uint256 public postCount;
mapping(uint256 => uint256) public updateCount;
mapping(uint256 => address) public authorOf;
function play(uint256 round, uint256 delta) external {
// A: lifetime points — absolute value after the update
points[msg.sender] += delta;
_fsiSetAddr(NS_POINTS, msg.sender, points[msg.sender]);
// B: this user's score this round, plus a pure round stat (account = address(0))
score[round][msg.sender] += delta;
totalScore[round] += delta;
_fsiSetRound(NS_SCORE, round, msg.sender, score[round][msg.sender]);
_fsiSetRound("roundTotal", round, address(0), totalScore[round]);
}
// L: a post (seq 0) followed by ordered updates (seq 1, 2, 3...)
function createPost(string calldata cid) external returns (uint256 postId) {
postId = ++postCount;
authorOf[postId] = msg.sender;
_fsiAppend(NS_POST, postId, 0, msg.sender, address(0), cid);
}
function appendUpdate(uint256 postId, string calldata cid) external {
require(authorOf[postId] == msg.sender, "not author"); // permissions are enforced by the contract
_fsiAppend(NS_POST, postId, ++updateCount[postId], msg.sender, address(0), cid);
}
// G: one activity log per claim — the value of this action, not a cumulative total
function claim(uint256 poolId) external {
uint256 amount = _payout(msg.sender, poolId);
_fsiLog(NS_CLAIM, poolId, msg.sender, address(0), amount, 0);
}
function _payout(address, uint256) internal virtual returns (uint256) {
return 0; // your payout logic
}
}With just these events, the Flap App UI can show a global points leaderboard, a per-round leaderboard, a post feed with full update history, and a "my claims" list — without any developer-run backend.
Querying FSI
There is one FSI instance per chain; the path carries no chain ID (the instance's chain is reported by GET /fsi/versions). Addresses are lowercase hex.
GET /fsi/versions
GET /fsi/v1/{emitter}/A/{ns}?sort=value_desc&limit=100&cursor=&minValue=&maxValue=
GET /fsi/v1/{emitter}/A/{ns}/{key}
GET /fsi/v1/{emitter}/B/{ns}?round=7&sort=value_desc&limit=100&cursor=
GET /fsi/v1/{emitter}/B/{ns}/{round}/{account}
GET /fsi/v1/{emitter}/L/{ns}?seq=0&actor=&related=&sort=value_desc&limit=100&cursor=
GET /fsi/v1/{emitter}/L/{ns}/{id}?limit=100&cursor=
GET /fsi/v1/{emitter}/G/{ns}?id=&actor=&related=&minValue=&maxValue=&sort=time_desc&limit=100&cursor=
GET /fsi/v1/{emitter}/G/{ns}/{id}?limit=100&cursor=
GET /fsi/v1/{emitter}/G?ns=&id=&actor=&related=&sort=time_desc&limit=100&cursor=
GET /fsi/v1/by-key/{address}?templateId=A|B|L|G
Key behaviors:
{ns}is either a readable string (e.g.points, encoded as a left-aligned zero-paddedbytes32) or a0x-prefixed 64-hexbytes32.limitdefaults to 100, max 1000. Page with the returnednextCursor. Lists may be cached for a few seconds.- A / B sort by
value_desc(default),value_asc,updated_desc, orkey.rankis returned only on value-sorted lists (B must includeround); equal values share a rank. A single-key query returns404 {"error":"not_found"}if the key was never written. - L lists support
seq=0(only the first record of each object, e.g. a post list), andactor/relatedfilters. The detail endpoint returns every record of one object in ascendingseq. - G lists filter by
id/actor/related, filteramountwithminValue/maxValue, and sort bytime_desc(default),time_asc,value_desc, orvalue_asc.GET /fsi/v1/{emitter}/Gmerges everynsof one contract into a single activity stream. - by-key returns one address's rows across all emitters (with
role=actor|related|bothfor L and G). - Numeric values (
value,amount,extra,id,round) are returned as decimal strings to preserveuint256precision. Every row carriesblockNumber,logIndex,txHash, andupdatedAtso callers can judge freshness. - REST returns only confirmed data (
confirmed: true). During a short reorg, results may briefly show the pre-fork value and then recover.
Example — a points leaderboard (GET /fsi/v1/{emitter}/A/points):
{
"emitter": "0xabc...",
"template": "A",
"ns": "points",
"items": [
{
"emitter": "0xabc...", "ns": "points", "key": "0x111...", "value": "12345", "data": "",
"blockNumber": 123, "logIndex": 4, "txHash": "0x...", "updatedAt": 1760000000,
"confirmed": true, "trusted": false, "rank": 1
}
],
"nextCursor": "..."
}Indexing scope, trusted, and quotas
- Any contract that emits a matching event is indexed. No VaultPortal registration is needed — Vaults and non-Vault contracts (factory stats, Flap App business contracts) follow the same rules.
- Every row carries a
trustedflag:truewhen the emitter is a Vault registered on VaultPortal, otherwisefalse. It is informational only — it doesn't affect indexing, queries, sorting, or quotas. If a Vault registers after emitting, its existing rows simply start returningtrusted: true.
Draft default quotas (same for every emitter; may change during testnet):
| Limit | Default |
|---|---|
data length | Truncated past 1024 bytes |
ns per emitter | 32 |
Rows per (emitter, ns) | 1,000,000 |
Events beyond the ns count or row cap are dropped; once a namespace is full, existing A/B keys can still be updated but new keys are rejected. L and G rows only ever grow — for hot contracts, split records across namespaces by type or time range, keeping the 32-ns limit in mind.
Versioning
- FSI is versioned as a whole (
fsi-v1,fsi-v2, …). Each version is a superset of the previous one. - A published template is frozen: its event signature, table structure, and write rules never change. New behavior ships as a new template.
/fsi/v1/...paths stay available long-term, and contracts never need to migrate. fsi-v1= templates A, B, L, G. Further templates (composite keys, address-to-address relations, two-metric rows, an explicit delete event) are reserved and not indexed yet.
Building a Flap App, step by step
- Talk to us early. Since the draft scope is reviewed case by case, share your idea with the Flap team before building too much.
- Write the contract. All rules involving funds live on-chain. Integrate Flap's shared infrastructure rather than running your own services.
- Emit FSI events for every list, ranking, or history your UI needs. Use absolute values for A/B and append-only records for L/G.
- Test with integration tests, and on BNB Chain Testnet or Robinhood Testnet (https://testnet.flap.sh).
- Get audited. Your contract must pass an audit by one of Flap's partner security companies.
- Build the UI with the template's standalone Flap App v2 mode: scaffold, implement against
useFlapSdk({ chainId }), declarewalletChains/walletContracts, and passapp:checkandapp:e2e. - Package and submit the ZIP produced by
yarn app:packageto the Flap App Workbench, together with your slug, display titles, feature summary, endpoint declarations, and contract upgrade-authority notes. - Go live. After review, Flap publishes the App at
https://flap.sh/apps/{slug}.
Open questions
This draft deliberately leaves several things open. We will settle them as the first Flap Apps go through review:
- Scope. There's no hard boundary yet on what a Flap App may be; each submission is reviewed case by case.
- Contract upgradeability. Verified Vaults must use the beacon proxy pattern with upgrade authority held by the Flap Guardian, so audit findings can be fixed. Whether Flap App contracts follow the same rule is still being decided.
- Audit process and cost for non-Vault contracts.
- FSI
trustedscope. Todaytrustedonly marks Vaults registered on VaultPortal; whether audited Flap App contracts are also marked is still open. - FSI details still to be confirmed: whether
datastaysstringor becomesbytes(this would change the A/B/L signatures and must be decided before signatures freeze), whether historical (time-travel) queries for A/B open up, and whether the default quotas are enough. - Real-time updates. A WebSocket push of not-yet-confirmed values is planned so UIs can show "confirming" state immediately; logic involving funds must still read on-chain state.
Feedback on any of these is welcome — reach out to the Flap team.