Dune 学习笔记:一次完整的 Meteora DBC 链上查询实战推演
1.明确需求,搞清楚业务逻辑
开发 Launchpad 需要调用 Meteora DBC 的发射功能,而 config 创建是其中的核心一步——它决定了代币的初始价格、迁移阈值、供应量等关键参数。为了有参考依据,我希望调研同样基于 Meteora DBC 构建的平台,看看它们是如何配置的。
调研对象首先确定为:Believe、Bags、Moonshot、Jupiter Studio。
问题是这些平台的链上地址并不能直接获取,需要从它们发射过的代币地址反向推导。这个"反推"的过程正好也属于下一步"搜索数据表"的一部分——业务逻辑与数据结构往往相互印证,理解其中一方有助于看懂另一方。
2.搜索相关的表
用 Dune 内置的搜索 在 Dune 编辑器里,按 Ctrl+Space 触发自动补全,可以浏览表名和字段

本次需要的三张表

event & function
这里出现一个疑问,表格似乎有两种类型,分别代表什么呢?
1. event(事件)
- 含义:智能合约中记录的重要操作日志,链上触发后会被索引并存储。
- 数据内容:包含交易哈希、区块时间、操作参数等。
2. function(函数)
- 含义:智能合约中可调用的方法,用户或合约通过交易调用它们。
- 数据内容:包含调用者、输入参数、输出结果等。
事件(event)和函数调用(function call)在 Dune 等区块链数据平台中并不是重复的数据,而是从不同角度记录同一操作的两种数据结构,它们互为补充。❗️详情见附录
回到本次需求:如果想查各发射平台的迁移阈值、初始价格等预设参数,应该查 call_createConfig 或 evt_CreateConfigV2 这类记录创建配置的表——这是"意图"侧的数据。如果想知道实际迁移时的价格,则需要结合 evt_Swap2 事件表,从触发迁移的那笔交易里找——这是"结果"侧的数据。两者不重复,但往往需要联表才能还原全貌。
3.查看表字段,了解含义
EvtCreateConfig
平台创建 Bonding Curve 配置时触发的事件。这是最核心的表,记录了每个发射平台设置的所有参数:初始价格、迁移阈值、代币供应量、手续费等。每个 config 地址对应一个平台的一套发行规则。❗️详情见附录

EvtInitializePool
每个代币创建时初始化虚拟池触发的事件。记录"哪个代币使用了哪套平台配置",是连接 config(平台配置)和具体代币池的桥梁表。

EvtCurveComplete
Bonding Curve 达到毕业条件(募集额达到 migration_quote_threshold)时触发的事件,记录"毕业"时刻的池子状态。可通过此表统计各平台的毕业数量和毕业时的 base/quote 储备。

4. 开始写查询
从代币地址倒推平台owner
SELECT ip.base_mint, ip.pool, ip.config, cc.owner FROM meteora_solana.dynamic_bonding_curve_evt_evtinitializepool ip LEFT JOIN meteora_solana.dynamic_bonding_curve_evt_evtcreateconfig cc ON ip.config = cc.config WHERE ip.base_mint = 'BFgdzMkTPdKKJeTipv2njtDEwhKxkgFueJQfJGt1jups';
查询owner创建的config及每个config发射代币情况
WITH -- 平台配置参数 platform_config AS ( SELECT evt_block_time, owner, fee_claimer, evt_tx_signer, config, CASE quote_mint WHEN 'So11111111111111111111111111111111111111112' THEN 'SOL' WHEN 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' THEN 'USDC' WHEN 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB' THEN 'USDT' ELSE quote_mint -- 遇到其他代币直接显示 mint 地址 END AS quote_symbol, -- ROUND(POWER(CAST(sqrt_start_price AS DOUBLE) / POWER(2, 64), 2) / POWER(10, 9 - token_decimal), 18) AS initial_price, ROUND(POWER(CAST(sqrt_start_price AS DOUBLE) / POWER(2, 64), 2) , 18) AS initial_price, CAST(migration_quote_threshold AS DOUBLE) / CASE quote_mint WHEN 'So11111111111111111111111111111111111111112' THEN 1e9 -- Wrapped SOL WHEN 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v' THEN 1e6 -- USDC WHEN 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB' THEN 1e6 -- USDT ELSE 1e9 -- 默认按 SOL 精度 END AS migration_threshold_adj, token_decimal, fixed_token_supply_flag, migration_option, CAST(migration_base_amount AS DOUBLE) / POWER(10, token_decimal) AS migration_base_amount_adj, CAST(pre_migration_token_supply AS DOUBLE) / POWER(10, token_decimal) AS pre_migration_token_supply_adj, CAST(migration_base_amount AS DOUBLE) / POWER(10, token_decimal) / NULLIF(CAST(pre_migration_token_supply AS DOUBLE) / POWER(10, token_decimal), 0) AS migration_pct FROM meteora_solana.dynamic_bonding_curve_evt_evtcreateconfig WHERE owner = 'CWcERiVd7xkUrcJK5QBdcKC5GG8JMATMLNHtCEUguwPz' ), -- 每个config创建池子数 pool_info AS ( SELECT config, COUNT(pool) AS total_pools FROM meteora_solana.dynamic_bonding_curve_evt_evtinitializepool GROUP BY config ), -- 每个config毕业池子数 grad_info AS ( SELECT config, COUNT(pool) AS completed_pools FROM meteora_solana.dynamic_bonding_curve_evt_evtcurvecomplete GROUP BY config ) -- 最终主查询 SELECT pc.evt_block_time, pc.owner, pc.fee_claimer, pc.evt_tx_signer, pc.config, pc.quote_symbol, pc.initial_price, pc.migration_threshold_adj, pc.token_decimal, pc.fixed_token_supply_flag, pc.migration_option, pc.migration_base_amount_adj, pc.pre_migration_token_supply_adj, pc.migration_pct, COALESCE(pi.total_pools, 0) AS total_pools, -- 该 config 下的总池子数 COALESCE(gi.completed_pools, 0) AS completed_pools, -- 该 config 下已毕业的池子数 ROUND(completed_pools * 1.0 / NULLIF(total_pools, 0), 4) AS graduation_rate FROM platform_config pc LEFT JOIN pool_info pi ON pc.config = pi.config LEFT JOIN grad_info gi ON pc.config = gi.config ORDER BY pi.total_pools DESC;
5. 获取并整理结果

在solscan查询owner地址,对比确认平台
| Owner地址 | 平台 | 标记 |
|---|---|---|
| 5wkyL2FLEcyUUgc3UeGntHTAfWfzDrVuxMnaMm7792Gk | Moonshot.money Fees Vault | solscan标记确认 |
| BAGSB9TpGrZxQbEsrEznv5jXXdwyP6AXerN8aVRiAmcv | Bags: Token Authority | solscan标记确认 |
| 9supzj2Nbnjut3r9UFfWE2RiuAenQMoYaNtZXmmtm5oC | Believe | 未标记 |
| CWcERiVd7xkUrcJK5QBdcKC5GG8JMATMLNHtCEUguwPz | Jupiter Studio | 未标记 |
6. 总结与反思:从链上数据看产品设计
本次针对 Meteora DBC 的链上查询,完成了从业务需求到数据验证的闭环推演。核心沉淀为以下三点:
- 业务是数据的指南针:链上分析不能盲目摸黑。厘清“代币地址 > 平台 Owner > 全局配置”的漏斗路径,才能在成百上千张表中找准关联键(
JOIN Keys)。 - “意图”与“结果”互补:
function call记录了平台创建配置的“最初意图”(初始价格、毕业阈值),而event记录了市场博弈后的“最终结果”(实际毕业率、储备量)。两者结合,才是完整的全景数据。 - 避开 Solana 的精度陷阱:Solana 链上数据有其特殊性。处理价格时必须通过公式将 Q64.64 定点数还原,并根据
quote_mint的不同(SOL 为 9 位精度,USDC 为 6 位精度)动态对齐精度,否则数据会失真。
价值落地:通过对 Moonshot、Bags 等头部平台配置参数与真实毕业率(graduation_rate)的解构,我们拿到了公开的行业标杆。这些真实的链上指标,将为我们自研 Launchpad 的代币经济学和价格曲线设计提供最坚实的数据支撑。
附录
event和function核心区别
| 维度 | 事件(event) | 函数调用(function call) |
|---|---|---|
| 存储表名 | 通常以 evt_ 开头,如 evt_Swap | 通常以 call_ 开头,如 call_swap |
| 记录时机 | 执行后:由智能合约主动触发,记录在交易收据中 | 执行前:作为交易输入数据的一部分,记录调用者意图 |
| 内容 | 包含执行结果(如兑换后的新价格、实际成交数量) | 包含调用参数(如输入金额、滑点、接收方) |
| 是否必须 | 不是所有操作都必须触发事件(但规范项目一般会) | 每个操作都必须有函数调用才能执行 |
| 索引性 | 事件字段通常被解析成独立的列,便于筛选分析 | 函数参数可能存储在结构化字段中,也可能在 data 字段里 |
| 用途 | 追踪状态变化、监控合约活动 | 分析用户行为、还原原始输入 |
以 swap 操作为例
假设用户调用 swap 函数进行代币兑换:
- 函数调用表(
call_swap)会记录:- 调用者地址
- 输入的代币数量(
amount_in) - 最小输出代币数量(
min_amount_out) - 接收方地址等原始参数。
- 事件表(
evt_Swap)会记录:- 实际兑换后的输出数量(
amount_out) - 交易完成后的池子状态(如新的储备量、新的价格)
- 可能包含交易手续费等执行细节。
- 实际兑换后的输出数量(
可以看到,事件包含了函数调用中不存在的信息(如实际成交结果),而函数调用包含了事件中不存在的信息(如调用者的滑点设置)。两者结合才能完整还原一笔交易的全貌。
表格字段详情
EvtCreateConfig
平台创建 Bonding Curve 配置时触发的事件。这是最核心的表,记录了每个发射平台设置的所有参数:初始价格、迁移阈值、代币供应量、手续费等。每个 config 地址对应一个平台的一套发行规则。
| 字段名 | 类型 | 说明 |
|---|---|---|
| 🕐 区块元数据 | ||
| evt_block_slot | bigint | 该事件所在的 Solana 区块 slot 编号,可用于排序和时间对齐 |
| evt_block_date | date | 区块日期(YYYY-MM-DD),方便按天聚合统计 |
| evt_block_time | timestamp | 区块精确时间戳(UTC),用于精确时间筛选 |
| evt_block_hash | varchar | 区块哈希,唯一标识该区块 |
| 📍 指令位置 | ||
| evt_tx_index | integer | 该交易在区块内的顺序编号(第几笔交易) |
| evt_outer_instruction_index | integer | 外层指令的索引(顶层 instruction 编号) |
| evt_inner_instruction_index | integer | 内层指令的索引(CPI 调用时的子指令编号,非内层时为 null) |
| evt_is_inner | boolean | 是否为内层指令(CPI)。true = 由其他合约间接调用 |
| 🔗 执行账户 | ||
| evt_executing_account | varchar | 实际执行该指令的程序账户地址(通常即 DBC 程序地址) |
| evt_outer_executing_account | varchar | 外层(顶层)执行账户,若为 CPI 则为发起调用的程序地址 |
| evt_inner_executing_account | varchar | 内层执行账户(仅 CPI 场景有值) |
| 📄 交易信息 | ||
| evt_tx_id | varchar | 交易签名(Transaction Hash),可在 Solscan 查询原始交易 |
| evt_tx_signer | varchar | 交易签名者(通常为平台的操作钱包地址,可用于识别不同平台) |
| ⭐ 核心业务字段 | ||
| config | varchar | 配置账户地址,唯一标识这套发行规则。JOIN 其他表的关键字段 |
| quote_mint | varchar | 计价代币 Mint 地址(如 SOL 的 Wrapped SOL 地址或 USDC 地址),即用什么代币来买 |
| fee_claimer | varchar | 手续费接收者钱包地址(平台方收费地址) |
| owner | varchar | 该配置的所有者(创建此 config 的平台钱包),可用于区分不同发射平台 |
| 💰 价格与供应量(最重要) | ||
| sqrt_start_price | uint256 | 初始价格的平方根(Q64.64 定点数格式)。初始价格 = (sqrt_start_price / 2^64)²,单位为 quote/base |
| migration_quote_threshold | uint256 | 迁移阈值:Bonding Curve 池子需要募集到多少 quote 代币才触发迁移(即"毕业线") |
| migration_base_amount | uint256 | 迁移时注入 AMM 的 base 代币数量,即迁移到 Meteora DAMM 时带过去多少项目代币 |
| swap_base_amount | uint256 | 在 Bonding Curve 阶段可供交易的 base 代币总量(即 bonding curve 上可买到的代币总量) |
| pre_migration_token_supply | uint256 | 迁移前的代币总供应量 |
| post_migration_token_supply | uint256 | 迁移后的代币总供应量(可能含增发或销毁,迁移完成后的最终总量) |
| 🔧 配置选项 | ||
| pool_fees | varchar | 池子手续费配置(JSON 格式字符串),包含 base fee、dynamic fee 等参数 |
| collect_fee_mode | integer | 手续费收取模式。0=仅收 quote 代币手续费,1=收 base+quote 双向手续费 |
| migration_option | integer | 迁移目标选项。0=迁移到 Meteora DAMM v1,1=迁移到 DAMM v2 |
| activation_type | integer | 代币激活方式。0=按 slot 激活,1=按时间戳激活 |
| token_decimal | integer | base 代币小数位数(通常为 6 或 9) |
| token_type | integer | 代币标准类型。0=SPL Token,1=Token2022 |
| fixed_token_supply_flag | integer | 是否固定代币总量。1=固定供应,0=非固定(影响迁移后是否有剩余代币) |
| migration_fee_option | integer | 迁移手续费方案选项,对应不同的迁移费率档位 |
| curve | array(varchar) | Bonding Curve 的分段参数数组,定义价格随购买量变化的曲线形状(各段斜率等) |
| locked_vesting | varchar | 锁仓/归属计划配置(JSON 格式),描述 LP 代币的锁定释放规则 |
| 📊 LP 分配比例 | ||
| partner_locked_lp_percentage | integer | 平台方获得的锁仓 LP 百分比 |
| partner_lp_percentage | integer | 平台方获得的可流通 LP 百分比 |
| creator_locked_lp_percentage | integer | 代币创建者获得的锁仓 LP 百分比 |
| creator_lp_percentage | integer | 代币创建者获得的可流通 LP 百分比 |
| partner_permanent_locked_liquidity_percentage | integer | 平台方的永久锁仓流动性百分比(永不解锁) |
| partner_liquidity_percentage | integer | 平台方的普通流动性百分比 |
| creator_permanent_locked_liquidity_percentage | integer | 代币创建者的永久锁仓流动性百分比(永不解锁) |
| creator_liquidity_percentage | integer | 代币创建者的普通流动性百分比 |
EvtInitializePool
每个代币创建时初始化虚拟池触发的事件。记录"哪个代币使用了哪套平台配置",是连接 config(平台配置)和具体代币池的桥梁表。
| 字段名 | 类型 | 说明 |
|---|---|---|
| 🕐 区块元数据 | ||
| evt_block_slot | bigint | 区块 slot 编号 |
| evt_block_date | date | 区块日期 |
| evt_block_time | timestamp | 区块时间戳(代币创建时间) |
| evt_block_hash | varchar | 区块哈希 |
| evt_tx_index | integer | 交易顺序 |
| evt_outer_instruction_index | integer | 外层指令索引 |
| evt_inner_instruction_index | integer | 内层指令索引 |
| evt_inner_executing_account | varchar | 内层执行账户 |
| evt_outer_executing_account | varchar | 外层执行账户 |
| evt_executing_account | varchar | 执行程序账户 |
| evt_is_inner | boolean | 是否为 CPI 内层调用 |
| evt_tx_id | varchar | 交易签名 |
| evt_tx_signer | varchar | 交易签名者(代币创建者钱包) |
| ⭐ 核心业务字段 | ||
| pool | varchar | 虚拟池账户地址,代表该代币的 Bonding Curve 池,是池子的唯一标识 |
| config | varchar | 使用的配置账户地址,JOIN EvtCreateConfig 的关键字段,通过此字段知道该代币用了哪个平台的规则 |
| creator | varchar | 代币创建者钱包地址 |
| base_mint | varchar | 代币 Mint 地址(即项目代币的合约地址),可在 Solscan 查该代币信息 |
| pool_type | integer | 池子类型。0=普通虚拟池,1=SPL Token 池,2=Token2022 池(对应不同创建函数) |
| activation_point | uint256 | 代币激活点(根据 activation_type 不同,为 slot 编号或 Unix 时间戳),在此之后代币才可交易 |
EvtCurveComplete
Bonding Curve 达到毕业条件(募集额达到 migration_quote_threshold)时触发的事件,记录"毕业"时刻的池子状态。可通过此表统计各平台的毕业数量和毕业时的 base/quote 储备。
| 字段名 | 类型 | 说明 |
|---|---|---|
| 🕐 区块元数据 | ||
| evt_block_slot | bigint | 毕业发生时的区块 slot |
| evt_block_date | date | 毕业日期 |
| evt_block_time | timestamp | 毕业时间戳 |
| evt_block_hash | varchar | 区块哈希 |
| evt_tx_index | integer | 交易顺序 |
| evt_outer_instruction_index | integer | 外层指令索引 |
| evt_inner_instruction_index | integer | 内层指令索引 |
| evt_inner_executing_account | varchar | 内层执行账户 |
| evt_outer_executing_account | varchar | 外层执行账户 |
| evt_executing_account | varchar | 执行程序账户 |
| evt_is_inner | boolean | 是否为 CPI 调用 |
| evt_tx_id | varchar | 交易签名 |
| evt_tx_signer | varchar | 触发最后一笔交易(使曲线完成)的签名者 |
| ⭐ 核心业务字段 | ||
| pool | varchar | 虚拟池地址,JOIN EvtInitializePool 可得到代币 Mint 和 config |
| config | varchar | 配置账户地址,JOIN EvtCreateConfig 可知是哪个平台的规则 |
| base_reserve | uint256 | 曲线完成时池中剩余的 base(项目)代币数量,即将迁移到 AMM 的代币量(扣除精度后的实际数量) |
| quote_reserve | uint256 | 曲线完成时池中募集的 quote 代币总量(应约等于 migration_quote_threshold),即迁移到 AMM 的 SOL/USDC 数量 |
评论
加载中…