Flap Vault 规范文档
基于 Flap 官方文档整理 · 当前规范 v2.2(可选 v2.3 扩展)
1. 概览
Flap 的 Vault 体系允许任何人构建智能合约来管理和分配 Tax Token 产生的 BNB 收入。 Vault 可根据不同场景自定义 —— 多方分账、社交证明路由、游戏国库、LP 分红 等等, 通过 VaultPortal 与代币生命周期挂钩。
Vault 创建是无许可的:任何工厂只要实现 VaultFactoryBaseV2,就能被 VaultPortal 用来发币,不需要注册。
2. VaultBase / VaultBaseV2
所有 Vault 必须继承 VaultBaseV2。它扩展了 VaultBase, 增加了链上 UI Schema 发现能力 vaultUISchema()。
abstract contract VaultBase {
error UnsupportedChain(uint256 chainId);
function _getPortal() internal view returns (address);
function _getGuardian() internal view returns (address);
/// 必须实现:返回反映当前状态的动态字符串
function description() public view virtual returns (string memory);
}
abstract contract VaultBaseV2 is VaultBase {
/// 必须实现:返回 UI 应该渲染的方法清单
function vaultUISchema() public pure virtual
returns (VaultUISchema memory);
}3. 实现要求
- 实现
description()—— 返回一个反映 Vault 当前状态(余额、流式状态等)的动态字符串,UI 会周期性轮询显示。 - 实现
receive()—— 接收 Tax Token 转入的 BNB,并按 Vault 逻辑分配处理。 - 实现
vaultUISchema()—— 声明所有面向用户的方法,让 UI 无需定制页面即可自动渲染交互界面。 - Guardian 强制授权 —— 任何需要权限的函数(如可能被三明治攻击的 buyback),必须同时把 Guardian 地址加入允许调用者名单,且该权限不可被除 Guardian 自身以外的任何账户撤销。
4. Flap Guardian
Flap Guardian 是一个由 Flap 管理的可升级合约地址,在所有实现规范的 Vault 中拥有永久权限。 它平时不做任何事(仅返回 version),仅在需要保护用户资金的紧急场景下介入。
如果你用 OpenZeppelin 的 AccessControl,必须重写 revokeRole() 拒绝对 Guardian 撤权:
function revokeRole(bytes32 role, address account)
public override onlyRole(getRoleAdmin(role))
{
if (account == _getGuardian()) revert CannotRevokeGuardianRole();
super.revokeRole(role, account);
}5. Beacon Proxy 模式
对于会部署多个实例的 Vault Factory,官方推荐使用 UpgradeableBeacon + BeaconProxy ,升级权限交给 Flap Guardian。理由:
- 先发币后审计:发现 bug 后可通过 beacon 升级实现,无需迁移已发行的代币。
- 兜底运行时问题:静态审计无法覆盖所有边界场景(mempool 攻击、gas griefing 等),beacon 提供修复通道。
如果你的 Vault 是"一代币一实例、终身不可变"的设计,可以直接继承 VaultBaseV2 而不走 proxy。
6. VaultFactoryBaseV2
Vault Factory 负责在用户发币时通过 VaultPortal 调用 newVault() 为新代币创建 Vault 实例。
| 方法 | 说明 |
|---|---|
| newVault(taxToken, quoteToken, creator, vaultData) | Portal 调用创建 Vault(taxToken 尚未部署,是预测地址) |
| isQuoteTokenSupported(quoteToken) | 声明本工厂支持的报价代币(address(0) = 原生 BNB) |
| vaultDataSchema() | 声明 vaultData 字节结构,让 UI 自动渲染表单 |
| factorySpecVersion() | 返回 "v2.2"(默认)或 "v2.3";控制 Portal 校验路径 |
| onBeforeLaunch(bytes) | v2.2+ 通用发币前校验钩子(staticcall,只读) |
| tokenCreationPolicies() | 机器可读的 UI 提示,不做链上强制 |
| resolveDividendToken(...) | v2.3 可选:为未部署代币解析 LP / 子代币地址 |
校验逻辑应放在 _validateBeforeLaunch(LaunchValidationDataV1), 可访问 tokenVersion / quoteToken / buyTaxRate / sellTaxRate / vaultBps / deflationBps / dividendBps / lpBps / dividendToken / minimumShareBalance。
7. VaultUISchema(IVaultSchemasV1)
前端根据 vaultUISchema() 声明动态渲染,不需要为每个 Vault 定制页面。核心结构:
struct FieldDescriptor {
string name; // 字段名,如 "amount"
string fieldType; // Solidity ABI 类型:"uint256" / "address" / "string" / "bool" / "bytes" / "time" / "msg.value"
string description; // UI 提示
uint8 decimals; // 数值精度提示(输入 × 10^decimals;输出 ÷ 10^decimals)
}
struct VaultMethodSchema {
string name; // Solidity 方法名
string description;
FieldDescriptor[] inputs;
FieldDescriptor[] outputs;
ApproveAction[] approvals; // 写入前需先执行的 ERC20 approve
bool isInputArray;
bool isOutputArray;
bool isWriteMethod; // true = 发交易;false = view 查询
}
struct VaultUISchema {
string vaultType; // 例如 "FlapXVault"
string description;
VaultMethodSchema[] methods;
}特殊类型:"time"(uint256 秒级时间戳,UI 渲染日期选择器)、"msg.value"(原生 BNB 金额,不进 calldata,每方法至多一个)。
8. 推荐佣金结构
工厂可从 Tax 收入中收取佣金,必须在 description() 中明确披露。官方推荐:
- 若
taxRate ≤ 1%(≤ 100 bps),佣金 =msg.value × 6% - 若
taxRate > 1%,佣金 =msg.value × 6 / taxRateBps
示例:2% → 3%,3% → 2%,10% → 0.6%。
9. 支持链与官方地址
| 链 | Chain ID | Portal | Guardian |
|---|---|---|---|
| BNB Chain | 56 | 0xe2cE6ab8…5C9De0 | 0x9e270980…B8a4b |
| BNB Testnet | 97 | 0x5bEacaF7…6510e9 | 0x76Fa8C52…dbE46950 |
地址来自 Flap 官方 VaultBase.sol,STOCK AI 只支持 BNB Chain,合约生成时会自动嵌入 BNB 主网/测试网的 _getPortal() / _getGuardian() 分支。
