For the complete documentation index, see llms.txt. This page is also available as Markdown.

X General Verifier

Why vault developers should care

A vault is the smart contract that receives a token's tax/fee revenue on Flap. What a vault does with that revenue β€” who can claim it, when, and under what condition β€” is entirely up to you, the vault developer. Gift Vault is one existing example: it lets an X account prove ownership of a fixed "gift the fee from X to Y" tweet format and redirect the vault's fee flow.

X General Verifier generalizes that same idea into reusable infrastructure any vault can call into:

  • The substring your vault checks for is entirely up to you β€” it isn't locked to a fixed sentence format like Gift Vault V2. Your vault can construct any expected tweet content it wants, at launch time or dynamically.

  • The on-chain verifier and off-chain oracle are shared, audited infrastructure. You don't need to build or run your own signing service β€” just call verify() from your vault.

  • It's multi-chain β€” the same oracle signer works across every deployment, so a vault design ported to a new chain doesn't need new backend integration.

In short: whenever your vault design needs to answer "has account @X actually said Y?" on-chain, this is the infrastructure to reach for instead of building your own oracle from scratch.

Deployed addresses:

Network
XGeneralVerifier

BSC Mainnet

0xcA8DBE6CAC4BFDc41226b0BaF2359fd99989b3E4

BSC Testnet

0x236C4AF8e0674fB22a139DDE4C2A518CBA819932

Robinhood Chain Mainnet

0xccDaB0d5Bc6E0aCb8B157cffFA062688Aa849c17

The same oracle signing key is used across every chain β€” only the verifying contract address (and therefore the EIP-712 domain) differs per chain.

Want to build on this infrastructure for a new use case? Reach out to us β€” we're happy to help you integrate.


The two parts

  • A stateless on-chain verifier (XGeneralVerifier) β€” a pure EIP-712 signature verification contract. It holds no state beyond the oracle's signing key and does not track proof usage.

  • An off-chain oracle server β€” fetches a tweet, checks that it contains the substring your vault expects, and signs an EIP-712 attestation over the result.


How it works, end to end

A typical flow looks like this:

  1. Your vault deploys with (or later computes) an expected substring β€” some exact text tied to the claim it's gating. This might embed a beneficiary address, a vault-specific nonce, a role name, anything your logic needs.

  2. A user, or the specific X account your vault expects, posts a tweet containing that exact substring.

  3. A bespoke UI you build β€” or Flap's own website, if your vault is registered there β€” asks the oracle server to prove the tweet exists and matches. This is a normal off-chain HTTP call, not a transaction.

  4. Your UI receives back a signed XGeneralProof and forwards it, along with the signature, into a transaction calling your vault contract.

  5. Your vault calls XGeneralVerifier.verify(proof, signature) on-chain. If it returns true, your vault executes whatever logic you've written β€” release funds, hand over control, unlock a new state, etc.

Nothing about steps 3–5 requires Flap's website. You are free to build a completely custom frontend that talks to the oracle and your vault directly β€” Flap's site is just one possible entry point into vaults that choose to register there.


The XGeneralProof struct

The substring match performed by the oracle is case-sensitive. Design your vault's expected substring deterministically (for example, embedding a lowercase hex address) so that off-chain callers and your on-chain check always agree exactly.


XGeneralVerifier contract interface

XGeneralVerifier is intentionally minimal:

  • Pure verification only. It checks the EIP-712 signature against the immutable oracleKey set at deployment. No storage is mutated after initialization.

  • No replay protection. The contract itself does not remember which proofs have already been used. Your vault is responsible for its own replay guard.

Recommended replay pattern: track the last-used tweetId per beneficiary/context in your vault, and require proof.tweetId > lastTweetId. X assigns Snowflake IDs that are strictly increasing over time, so this is sufficient to prevent replay without any additional nonce infrastructure.


Oracle server API

POST /prove

Request body:

Field
Type
Notes

tweet_id

string (numeric)

The tweet's Snowflake ID

substring

string

Must be non-empty and at most 200 bytes. Case-sensitive exact match against the tweet text.

Optional query parameter:

Parameter
Behavior

chain_id

Selects which chain's XGeneralVerifier domain to sign for. If provided but not a supported chain, the request is rejected. If omitted, defaults to BSC mainnet for backward compatibility.

Response β€” 200 OK:

chain_id and verifier_address in the response confirm which deployment the signature was produced for β€” check these match what your vault expects before submitting the proof on-chain.

Error responses return 400 for validation failures (empty/oversized substring, substring not found in the tweet, invalid or deleted tweet, unsupported chain_id) and 500 for unexpected internal errors.


Supported chains

Chain

chain_id

BSC Mainnet

56

BSC Testnet

97

Robinhood Chain Mainnet

4663

More chains are added over time as new XGeneralVerifier deployments go live.


Vault design patterns you can build with this

X General Verifier only answers one question β€” did this X account post this exact text? β€” but that primitive composes into a surprising range of vault behaviors. A few starting points:

1. Ownership handoff (generalized Gift Vault)

The simplest pattern, and the one Gift Vault already implements with a fixed sentence. With X General Verifier you control the substring yourself, so you can:

  • Assign an X account as the sole controller of the vault at launch.

  • Let that account prove control at any time by posting your vault's expected substring (e.g. "<handle> controls the vault for <token>").

  • Once proven, hand the account full authority over the vault β€” redirect fees, trigger a buyback, or unlock any other admin function you've written.

2. Tweet-gated claims / airdrops

Instead of (or in addition to) a merkle-drop, gate a claim behind a tweet:

  • Your vault computes a per-claimant expected substring, e.g. "<address> is claiming from <token>".

  • Anyone can post that tweet from any account, fetch a proof, and call claim().

  • Combine this with a per-account allowlist, a time window, or a maximum-claims-per-day cap for extra control.

3. Recurring / scheduled unlocks

Because tweetId is a monotonically increasing Snowflake ID, your vault can enforce ordering over time without needing an off-chain scheduler:

  • Require the newest qualifying tweet since the last claim β€” e.g. "the vault distributes to whichever address the owner's tweet points to today", refreshed once every 24 hours by requiring block.timestamp - lastClaimTime >= 1 days alongside the proof.

  • Build a "daily invite" mechanic: each day, the vault owner tweets who to invite/unlock next; the invited address submits the proof to claim a time-boxed reward slot.

4. Social consensus / voting proxies

Use tweets as a lightweight signaling channel for on-chain actions:

  • A DAO-style vault where the "vote" is a tweet containing a specific option string; the vault tallies claims/actions per option and the majority substring (by claim count within a window) triggers the payout path.

  • Gate an emergency pause/resume function behind a specific X account posting a specific phrase, without needing a multisig UI.

5. Streak / engagement rewards

Combine multiple proofs over time:

  • Require N distinct valid proofs (distinct tweetIds) from the same xId within a rolling window before a bonus payout unlocks β€” a simple on-chain "engagement streak."

  • Reward the first account to post a given day's substring, using tweetId ordering to determine who was first.

None of these require touching the oracle or verifier contract β€” they're all vault-side logic built on top of one primitive: XGeneralVerifier.verify() returning true. If you have a design that doesn't fit the patterns above, reach out to us β€” we're always interested in what vault developers are building.


Building a custom vault integration

A typical pattern for a vault contract:

Because XGeneralVerifier and the oracle server are chain-agnostic and vault-agnostic, this same pattern works for any vault design β€” from a simple claim gate to the more elaborate patterns above.

Last updated