MSG Chain AI Agent 经济激励模型设计
1. 概述
1.1 为什么需要激励模型
在 MSG Chain 的 AI Agent 生态中,经济激励是驱动网络可持续发展的核心引擎。Agent 作为自主执行链上任务的智能体,需要消耗计算资源、存储资源和网络带宽 —— 没有合理的激励模型,就无法保证 Agent 提供高质量服务、无法惩罚恶意行为、也无法吸引更多参与者加入生态。
激励模型需要解决三个根本问题:
- 供给端:吸引开发者部署高质量的 AI Agent,持续维护和升级
- 需求端:降低用户调用 Agent 服务的成本门槛,促进生态繁荣
- 质量端:建立信誉机制,让优质 Agent 获得更多收益,劣质 Agent 被市场淘汰
1.2 MSG Chain 代币体系
本生态涉及三类核心代币:
| 代币类型 | 用途 | 说明 |
|---|---|---|
| MSG 原生代币 | Gas 费用、质押、治理 | MSG Chain 主网代币,bech32 地址格式 msg1... |
| CW20 Agent 代币 | Agent 所有权、收益分配 | 每个 Agent 可发行自己的 CW20 代币,代表 Agent 的股权 |
| LP 代币 | 流动性提供凭证 | DEX 流动性池份额,用于捕获交易手续费和流动性激励 |
1.3 激励设计原则
本模型遵循以下核心原则:
- 激励对齐:Agent 的收益与其为网络创造的真实价值成正比,杜绝刷量套利
- 抗女巫攻击:通过质押门槛、信誉积累和惩罚机制,提高攻击成本
- 动态调节:定价和奖励参数可根据网络状态自动调整,避免通胀失控
- 渐进去中心化:早期由基金会引导激励,逐步过渡到社区治理
- 模块化可组合:Agent 之间可以互相调用并自动结算,形成 Agent 间经济网络
1.4 经济飞轮设计
MSG Chain Agent 经济的飞轮机制:
更多 Agent → 更丰富服务 → 更多用户 → 更多交易量 → 更高代币价值 → 更多 Agent
激励机制是这个飞轮的润滑剂。每一层激励都服务于飞轮的加速旋转:
- 服务激励:Agent 通过提供服务获得 MSG 代币奖励
- 质押激励:质押者通过维护网络安全获得质押收益
- 流动性激励:LP 提供流动性获得交易手续费和代币奖励
- 治理激励:参与治理获得投票奖励和提案奖励
2. Agent 服务定价模型
2.1 定价模型核心结构
价格是 Agent 经济中最关键的信号。合理的定价模型需要反映资源消耗、服务质量、市场需求三个维度。
use cosmwasm_std::{
Addr, Coin, Decimal, Decimal256, Deps, DepsMut, Env, MessageInfo,
Response, StdError, StdResult, Storage, Uint128, Uint64,
};
use cw_storage_plus::{Item, Map};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::fmt;
// 定价模型 - 定义 Agent 服务的收费标准
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct PricingModel {
pub base_fee: Uint128, // 固定每次调用基础费 (uMSG)
pub compute_price: Uint128, // 每单位计算资源价格 (uMSG/unit)
pub data_price: Uint128, // 每字节数据价格 (uMSG/byte)
pub reputation_multiplier: Decimal256, // 信誉乘数 (>= 1.0)
pub demand_multiplier: Decimal256, // 需求乘数 (动态调整)
}
// Agent 服务定价配置 - 存储在链上
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct AgentPricingConfig {
pub agent_id: String, // Agent 唯一标识
pub owner: Addr, // Agent 所有者
pub pricing: PricingModel, // 当前定价
pub min_price: Uint128, // 最低价格保护
pub max_price: Uint128, // 最高价格上限
pub price_oracle_feed: Option<String>, // 价格预言机源
pub updated_at: u64, // 最后更新时间
}
// 计算 Agent 服务价格
pub fn calculate_price(
pricing: &PricingModel,
compute_units: u64,
data_size: u64,
reputation: u8,
) -> Uint128 {
let base = pricing.base_fee;
let compute = pricing.compute_price * Uint128::from(compute_units);
let data = pricing.data_price * Uint128::from(data_size);
let multiplier = pricing.reputation_multiplier * pricing.demand_multiplier;
(base + compute + data) * multiplier
}
2.2 固定定价 vs 动态定价
// 定价策略枚举
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum PricingStrategy {
Fixed(FixedPricing), // 固定定价
Dynamic(DynamicPricing), // 动态定价
Subscription(SubscriptionPricing), // 订阅制
}
// 固定定价 - 简单直接,适合标准化服务
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct FixedPricing {
pub flat_fee: Uint128, // 统一费用
pub per_request: Uint128, // 每次请求费用
pub discount_tier: Vec<DiscountTier>, // 批量折扣
}
// 折扣层级
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DiscountTier {
pub min_volume: Uint128, // 最低交易量
pub discount_rate: Decimal256, // 折扣率 0.0 ~ 1.0
}
// 动态定价 - 根据市场供需实时调整
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DynamicPricing {
pub base_price: Uint128, // 基础价格
pub elasticity: Decimal256, // 价格弹性系数
pub min_bound: Uint128, // 价格下限
pub max_bound: Uint128, // 价格上限
pub adjustment_window: u64, // 调整窗口 (秒)
}
// 订阅定价 - 适合高频调用场景
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct SubscriptionPricing {
pub tier_name: String, // 订阅层级名称
pub monthly_fee: Uint128, // 月费
pub included_requests: Uint128, // 包含的请求次数
pub overage_price: Uint128, // 超额单价
pub commitment_months: u8, // 最低承诺月数
}
// 实现价格计算 trait
pub trait PriceCalculator {
fn calculate(
&self,
compute_units: u64,
data_size: u64,
reputation: u8,
current_load: Decimal256,
) -> StdResult<Uint128>;
fn validate(&self) -> StdResult<()>;
}
impl PriceCalculator for FixedPricing {
fn calculate(
&self,
_compute_units: u64,
_data_size: u64,
_reputation: u8,
_current_load: Decimal256,
) -> StdResult<Uint128> {
// 固定定价不考虑资源消耗
Ok(self.flat_fee + self.per_request)
}
fn validate(&self) -> StdResult<()> {
if self.flat_fee.is_zero() && self.per_request.is_zero() {
return Err(StdError::generic_err("定价不能为零"));
}
for tier in &self.discount_tier {
if tier.discount_rate > Decimal256::one() {
return Err(StdError::generic_err("折扣率不能超过 100%"));
}
}
Ok(())
}
}
impl PriceCalculator for DynamicPricing {
fn calculate(
&self,
compute_units: u64,
data_size: u64,
_reputation: u8,
current_load: Decimal256,
) -> StdResult<Uint128> {
let base = self.base_price
* Uint128::from(compute_units)
* Uint128::from(data_size.max(1));
// 动态调价:价格 = 基础价 * (1 + 弹性系数 * (负载 - 0.5))
let load_factor = Decimal256::one()
+ self.elasticity * (current_load - Decimal256::percent(50));
let price = base * load_factor;
// 确保价格在 [min, max] 范围内
Ok(price.max(self.min_bound).min(self.max_bound))
}
fn validate(&self) -> StdResult<()> {
if self.base_price.is_zero() {
return Err(StdError::generic_err("动态定价基础价不能为零"));
}
if self.min_bound > self.max_bound {
return Err(StdError::generic_err("价格下限不能高于上限"));
}
Ok(())
}
}
impl PriceCalculator for SubscriptionPricing {
fn calculate(
&self,
_compute_units: u64,
_data_size: u64,
_reputation: u8,
_current_load: Decimal256,
) -> StdResult<Uint128> {
// 订阅模式按周期计费,单次调用不计费
Ok(Uint128::zero())
}
fn validate(&self) -> StdResult<()> {
if self.monthly_fee.is_zero() {
return Err(StdError::generic_err("月费不能为零"));
}
Ok(())
}
}
2.3 信誉定价机制
Agent 信誉分直接影响其服务定价。高信誉 Agent 可以收取溢价,同时用户也愿意为高质量服务支付更高价格。
// Agent 信誉系统
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct AgentReputation {
pub agent_id: String,
pub reputation_score: u8, // 信誉分 0-100
pub total_ratings: u64, // 总评价数
pub avg_rating: Decimal256, // 平均评分 1.0-5.0
pub success_rate: Decimal256, // 请求成功率 0.0-1.0
pub response_time_avg: u64, // 平均响应时间 (ms)
pub total_requests: u64, // 总请求量
pub total_volume: Uint128, // 总交易量
pub last_updated: u64,
}
// 信誉分存储
pub const REPUTATION: Map<&Addr, AgentReputation> = Map::new("msg_agent_rep");
// 根据信誉分计算价格乘数
pub fn reputation_to_multiplier(score: u8) -> Decimal256 {
match score {
0..=20 => Decimal256::percent(80), // 低信誉,折扣价
21..=40 => Decimal256::percent(90),
41..=60 => Decimal256::percent(100), // 基准价
61..=80 => Decimal256::percent(110), // 高信誉溢价
81..=95 => Decimal256::percent(125),
96..=100 => Decimal256::percent(150), // 顶级信誉
_ => Decimal256::percent(100),
}
}
// 更新 Agent 信誉分
pub fn update_reputation(
deps: DepsMut,
env: &Env,
agent_addr: &Addr,
rating: u8,
success: bool,
response_time: u64,
) -> StdResult<AgentReputation> {
let mut rep = REPUTATION
.load(deps.storage, agent_addr)
.unwrap_or(AgentReputation {
agent_id: String::new(),
reputation_score: 50, // 默认信誉分
total_ratings: 0,
avg_rating: Decimal256::percent(300), // 默认 3.0
success_rate: Decimal256::one(),
response_time_avg: 0,
total_requests: 0,
total_volume: Uint128::zero(),
last_updated: env.block.time.seconds(),
});
rep.total_requests += 1;
// 更新成功率
let old_successes = rep.success_rate * Uint128::from(rep.total_requests - 1);
let new_successes = if success {
old_successes + Uint128::one()
} else {
old_successes
};
rep.success_rate = new_successes / Uint128::from(rep.total_requests);
// 更新平均响应时间
if rep.response_time_avg == 0 {
rep.response_time_avg = response_time;
} else {
rep.response_time_avg = (rep.response_time_avg * (rep.total_requests - 1) + response_time)
/ rep.total_requests;
}
// 更新评分
if rating > 0 && rating <= 5 {
let old_total = rep.avg_rating * Uint128::from(rep.total_ratings);
rep.total_ratings += 1;
rep.avg_rating = (old_total + Uint128::from(rating as u64))
/ Uint128::from(rep.total_ratings);
}
// 综合计算信誉分
let rating_weight = Decimal256::percent(30);
let success_weight = Decimal256::percent(40);
let response_weight = Decimal256::percent(30);
let rating_score = rep.avg_rating
/ Uint128::from(5u64)
* Uint128::from(100u64);
let success_score = rep.success_rate * Uint128::from(100u64);
// 响应时间得分:<100ms 满分,>5000ms 0分
let response_score = if rep.response_time_avg < 100 {
Uint128::from(100u64)
} else if rep.response_time_avg > 5000 {
Uint128::zero()
} else {
Uint128::from(100u64)
- Uint128::from((rep.response_time_avg - 100) * 100 / 4900)
};
rep.reputation_score = (rating_score * rating_weight
+ success_score * success_weight
+ response_score * response_weight)
.u128() as u8;
rep.last_updated = env.block.time.seconds();
REPUTATION.save(deps.storage, agent_addr, &rep)?;
Ok(rep)
}
2.4 供需动态调价
// 市场供需状态
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct MarketDemand {
pub agent_id: String,
pub request_rate: Decimal256, // 当前请求率 (req/s)
pub max_capacity: Decimal256, // 最大容量 (req/s)
pub utilization: Decimal256, // 利用率 (0.0-1.0)
pub queue_depth: u64, // 当前队列深度
pub avg_wait_time: u64, // 平均等待时间 (ms)
pub competing_agents: u32, // 同类竞争 Agent 数
}
// 供需调价器
pub struct DemandAdjuster {
pub target_utilization: Decimal256, // 目标利用率 (默认 0.7)
pub adjustment_factor: Decimal256, // 调价因子
pub min_change: Decimal256, // 最小调价幅度
pub max_change: Decimal256, // 最大调价幅度
}
impl DemandAdjuster {
pub fn new() -> Self {
DemandAdjuster {
target_utilization: Decimal256::percent(70),
adjustment_factor: Decimal256::percent(10),
min_change: Decimal256::percent(95),
max_change: Decimal256::percent(105),
}
}
// 计算需求乘数
pub fn calculate_demand_multiplier(
&self,
current_utilization: Decimal256,
current_price: &PricingModel,
) -> Decimal256 {
// 如果利用率高于目标,提高价格以降低需求
// 如果利用率低于目标,降低价格以刺激需求
let ratio = if current_utilization > self.target_utilization {
Decimal256::one()
+ self.adjustment_factor
* (current_utilization - self.target_utilization)
/ self.target_utilization
} else {
Decimal256::one()
- self.adjustment_factor
* (self.target_utilization - current_utilization)
/ self.target_utilization
};
let current_mult = current_price.demand_multiplier;
let new_mult = current_mult * ratio;
// 限制调整幅度
let base = Decimal256::one();
let lower = base * self.min_change;
let upper = base * self.max_change;
new_mult.max(lower).min(upper)
}
}
2.5 支付结算流程
// 支付凭证
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct PaymentVoucher {
pub request_id: String, // 请求唯一 ID
pub consumer: Addr, // 消费者地址
pub agent: Addr, // Agent 地址
pub amount: Uint128, // 支付金额
pub token: String, // 支付代币 (uMSG 或 CW20)
pub timestamp: u64, // 支付时间戳
pub signature: Option<String>, // 消费者签名
}
// Agent 服务请求结算
pub fn settle_agent_payment(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
agent_addr: &Addr,
compute_units: u64,
data_size: u64,
) -> StdResult<Response> {
// 1. 加载 Agent 定价配置
let config = AGENT_PRICING_CONFIG
.load(deps.storage, agent_addr)?;
// 2. 加载 Agent 信誉
let reputation = REPUTATION
.load(deps.storage, agent_addr)?;
// 3. 计算最终价格
let price = calculate_price(
&config.pricing,
compute_units,
data_size,
reputation.reputation_score,
);
// 4. 验证支付金额
let payment = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("缺少 MSG 支付"))?;
if payment.amount < price {
return Err(StdError::generic_err(format!(
"支付不足: 需要 {} uMSG, 收到 {} uMSG",
price, payment.amount
)));
}
// 5. 分配费用
let protocol_fee = price * Decimal256::percent(2); // 2% 协议费
let agent_reward = price - protocol_fee;
// 6. 记录交易
let tx = PaymentVoucher {
request_id: env.transaction_info()?.index.to_string(),
consumer: info.sender.clone(),
agent: agent_addr.clone(),
amount: price,
token: "uMSG".to_string(),
timestamp: env.block.time.seconds(),
signature: None,
};
PAYMENT_VOUCHERS.save(deps.storage, &tx.request_id, &tx)?;
Ok(Response::new()
.add_attribute("action", "agent_payment")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("consumer", info.sender.to_string())
.add_attribute("amount", price.to_string())
.add_attribute("protocol_fee", protocol_fee.to_string())
.add_attribute("compute_units", compute_units.to_string())
.add_attribute("data_size", data_size.to_string()))
}
// 定价配置存储
pub const AGENT_PRICING_CONFIG: Map<&Addr, AgentPricingConfig> =
Map::new("msg_agent_price");
// 支付凭证存储
pub const PAYMENT_VOUCHERS: Map<&str, PaymentVoucher> =
Map::new("msg_pay_vouch");
3. 质押与 Slashing 机制
3.1 Agent 质押模型
质押机制是保证 Agent 行为诚实、服务质量可靠的核心手段。Agent 需要质押 MSG 代币才能提供服务,质押量决定了服务能力和信誉基础。
// Agent 质押信息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct AgentStaking {
pub agent_addr: Addr, // Agent 地址
pub staked_amount: Coin, // 质押的 MSG 代币
pub cw20_staked: Vec<Cw20Stake>, // 额外 CW20 代币质押
pub lock_period: Duration, // 锁定期
pub unbonding_start: Option<u64>, // 解绑开始时间
pub slash_count: u32, // 被惩罚次数
pub total_slashed: Uint128, // 总惩罚金额
pub insurance_contribution: Uint128, // 保险池贡献
pub is_active: bool, // 是否激活
pub staked_at: u64, // 质押时间
}
// CW20 质押
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Cw20Stake {
pub contract_addr: Addr, // CW20 合约地址
pub amount: Uint128, // 质押数量
pub weight: Decimal256, // 权重相对 MSG
}
// Slash 条件
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum SlashCondition {
ConstitutionViolation(u8), // 违规,参数为严重程度 1-10
Downtime(Duration), // 停机,参数为停机时长
FraudProof, // 欺诈证明
DataQualityViolation(u8), // 数据质量违规
DoubleSigning, // 双签
}
// Slash 记录
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct SlashEvent {
pub agent_addr: Addr,
pub condition: SlashCondition,
pub slashed_amount: Uint128,
pub burned_amount: Uint128,
pub insurance_amount: Uint128,
pub reporter: Addr,
pub evidence_hash: String,
pub timestamp: u64,
pub description: String,
}
// Agent 质押状态存储
pub const AGENT_STAKING: Map<&Addr, AgentStaking> = Map::new("msg_agent_stake");
pub const SLASH_EVENTS: Map<&str, SlashEvent> = Map::new("msg_slash_evt");
pub const UNBONDING_QUEUE: Map<u64, Vec<UnbondingRequest>> =
Map::new("msg_unbond_q");
// 解绑请求
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UnbondingRequest {
pub agent_addr: Addr,
pub amount: Coin,
pub request_time: u64,
pub complete_time: u64,
}
// 质押参数
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct StakingParams {
pub min_stake: Coin, // 最低质押量
pub max_stake: Coin, // 最高质押量(防止过度集中)
pub unbonding_period: Duration, // 解绑期
pub slash_percent: Decimal256, // 默认罚没比例
pub max_slash_percent: Decimal256, // 最高罚没比例
pub min_self_delegation: Uint128, // 最低自委托
pub insurance_pool_rate: Decimal256, // 保险池贡献比例
}
impl Default for StakingParams {
fn default() -> Self {
StakingParams {
min_stake: Coin::new(1_000_000_000u128, "uMSG"), // 1000 MSG
max_stake: Coin::new(1_000_000_000_000u128, "uMSG"), // 1M MSG
unbonding_period: Duration::new(86400 * 14), // 14 天
slash_percent: Decimal256::percent(5), // 5%
max_slash_percent: Decimal256::percent(50), // 50%
min_self_delegation: Uint128::from(100_000_000u64), // 100 MSG
insurance_pool_rate: Decimal256::percent(1), // 1%
}
}
}
pub const STAKING_PARAMS: Item<StakingParams> = Item::new("msg_stake_params");
// Agent 质押操作
pub fn stake_agent(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
agent_addr: &Addr,
) -> StdResult<Response> {
let params = STAKING_PARAMS
.load(deps.storage)
.unwrap_or_default();
// 验证质押金额
let stake_fund = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG 质押"))?;
if stake_fund.amount < params.min_stake.amount {
return Err(StdError::generic_err(format!(
"最低质押量: {} uMSG", params.min_stake.amount
)));
}
if stake_fund.amount > params.max_stake.amount {
return Err(StdError::generic_err(format!(
"最高质押量: {} uMSG", params.max_stake.amount
)));
}
// 检查 Agent 是否已质押
if AGENT_STAKING.has(deps.storage, agent_addr) {
return Err(StdError::generic_err("Agent 已质押"));
}
// 计算保险池贡献
let insurance_amount = stake_fund.amount
* params.insurance_pool_rate;
let net_stake = Coin::new(
(stake_fund.amount - insurance_amount).u128(),
"uMSG",
);
// 创建质押记录
let staking = AgentStaking {
agent_addr: agent_addr.clone(),
staked_amount: net_stake,
cw20_staked: vec![],
lock_period: Duration::new(86400 * 7), // 7 天锁定期
unbonding_start: None,
slash_count: 0,
total_slashed: Uint128::zero(),
insurance_contribution: insurance_amount,
is_active: true,
staked_at: env.block.time.seconds(),
};
AGENT_STAKING.save(deps.storage, agent_addr, &staking)?;
// 将保险部分发送到保险池
Ok(Response::new()
.add_attribute("action", "agent_stake")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("staked", net_stake.amount.to_string())
.add_attribute("insurance", insurance_amount.to_string())
.add_attribute("lock_period", "604800"))
}
// 追加质押
pub fn increase_stake(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
agent_addr: &Addr,
) -> StdResult<Response> {
let params = STAKING_PARAMS
.load(deps.storage)
.unwrap_or_default();
let mut staking = AGENT_STAKING
.load(deps.storage, agent_addr)?;
if info.sender != staking.agent_addr {
return Err(StdError::generic_err("只有 Agent 所有者可以追加质押"));
}
let additional = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG"))?;
let new_total = staking.staked_amount.amount + additional.amount;
if new_total > params.max_stake.amount {
return Err(StdError::generic_err("超出最高质押量"));
}
let insurance_add = additional.amount * params.insurance_pool_rate;
staking.staked_amount.amount = new_total - insurance_add;
staking.insurance_contribution += insurance_add;
staking.staked_at = env.block.time.seconds();
AGENT_STAKING.save(deps.storage, agent_addr, &staking)?;
Ok(Response::new()
.add_attribute("action", "increase_stake")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("additional", additional.amount.to_string()))
}
3.2 Slashing 条件与执行
// 执行 Slash 操作
pub fn execute_slash(
deps: DepsMut,
env: &Env,
reporter: &Addr,
agent_addr: &Addr,
condition: SlashCondition,
evidence: &str,
) -> StdResult<Response> {
let params = STAKING_PARAMS
.load(deps.storage)
.unwrap_or_default();
let mut staking = AGENT_STAKING
.load(deps.storage, agent_addr)
.map_err(|_| StdError::generic_err("Agent 未质押"))?;
if !staking.is_active {
return Err(StdError::generic_err("Agent 已停用"));
}
// 根据条件计算罚没比例
let slash_multiplier = match &condition {
SlashCondition::ConstitutionViolation(severity) => {
if *severity < 1 || *severity > 10 {
return Err(StdError::generic_err("严重程度需在 1-10 之间"));
}
Decimal256::percent((*severity as u64) * 5)
}
SlashCondition::Downtime(duration) => {
let downtime_hours = duration.seconds() / 3600;
if downtime_hours < 1 {
return Err(StdError::generic_err("停机时间过短"));
}
let rate = (downtime_hours as u64).min(100);
Decimal256::percent(rate)
}
SlashCondition::FraudProof => {
params.max_slash_percent // 欺诈直接最高处罚
}
SlashCondition::DataQualityViolation(severity) => {
if *severity < 1 || *severity > 10 {
return Err(StdError::generic_err("严重程度需在 1-10 之间"));
}
Decimal256::percent((*severity as u64) * 3)
}
SlashCondition::DoubleSigning => {
params.max_slash_percent // 双签最高处罚
}
};
// 限制最大罚没比例
let effective_slash = slash_multiplier.min(params.max_slash_percent);
let slash_amount = staking.staked_amount.amount * effective_slash;
// 分配罚没资金
let burn_amount = slash_amount * Decimal256::percent(50); // 50% 销毁
let insurance_amount = slash_amount * Decimal256::percent(30); // 30% 入保险池
let reporter_reward = slash_amount * Decimal256::percent(20); // 20% 奖励举报者
// 更新质押状态
staking.staked_amount.amount =
staking.staked_amount.amount - slash_amount;
staking.slash_count += 1;
staking.total_slashed += slash_amount;
// 如果质押低于最低要求,停用 Agent
if staking.staked_amount.amount < params.min_stake.amount {
staking.is_active = false;
}
AGENT_STAKING.save(deps.storage, agent_addr, &staking)?;
// 记录 Slash 事件
let event = SlashEvent {
agent_addr: agent_addr.clone(),
condition,
slashed_amount: slash_amount,
burned_amount: burn_amount,
insurance_amount,
reporter: reporter.clone(),
evidence_hash: hash_evidence(evidence),
timestamp: env.block.time.seconds(),
description: format!(
"Agent {} slashed {} uMSG",
agent_addr, slash_amount
),
};
let event_id = format!("{}-{}", env.block.height, agent_addr);
SLASH_EVENTS.save(deps.storage, &event_id, &event)?;
Ok(Response::new()
.add_attribute("action", "slash")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("slashed", slash_amount.to_string())
.add_attribute("burned", burn_amount.to_string())
.add_attribute("insurance", insurance_amount.to_string())
.add_attribute("reporter_reward", reporter_reward.to_string())
.add_attribute("is_active", staking.is_active.to_string()))
}
// 对证据哈希
fn hash_evidence(evidence: &str) -> String {
let hash = sha256::digest(evidence.as_bytes());
hash
}
3.3 解绑与退出
// 开始解绑流程
pub fn start_unbonding(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
agent_addr: &Addr,
) -> StdResult<Response> {
let params = STAKING_PARAMS
.load(deps.storage)
.unwrap_or_default();
let mut staking = AGENT_STAKING
.load(deps.storage, agent_addr)?;
if info.sender != staking.agent_addr {
return Err(StdError::generic_err("只有 Agent 所有者可以解绑"));
}
if staking.unbonding_start.is_some() {
return Err(StdError::generic_err("解绑已发起"));
}
// 检查锁定期是否已过
let lock_end = staking.staked_at + staking.lock_period.seconds();
if env.block.time.seconds() < lock_end {
return Err(StdError::generic_err(format!(
"锁定期未到: 还需 {} 秒",
lock_end - env.block.time.seconds()
)));
}
// 标记解绑开始
staking.unbonding_start = Some(env.block.time.seconds());
staking.is_active = false;
AGENT_STAKING.save(deps.storage, agent_addr, &staking)?;
// 加入解绑队列
let complete_time = env.block.time.seconds()
+ params.unbonding_period.seconds();
let request = UnbondingRequest {
agent_addr: agent_addr.clone(),
amount: staking.staked_amount.clone(),
request_time: env.block.time.seconds(),
complete_time,
};
let queue_key = complete_time / 86400; // 按天分组
UNBONDING_QUEUE
.update(deps.storage, queue_key, |existing| -> StdResult<_> {
let mut queue = existing.unwrap_or_default();
queue.push(request);
Ok(queue)
})?;
Ok(Response::new()
.add_attribute("action", "start_unbonding")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("unbonding_end", complete_time.to_string())
.add_attribute("amount", staking.staked_amount.amount.to_string()))
}
// 完成解绑 - 领取质押资金
pub fn complete_unbonding(
deps: DepsMut,
env: &Env,
agent_addr: &Addr,
) -> StdResult<Response> {
let mut staking = AGENT_STAKING
.load(deps.storage, agent_addr)?;
let start = staking
.unbonding_start
.ok_or_else(|| StdError::generic_err("未发起解绑"))?;
let params = STAKING_PARAMS
.load(deps.storage)
.unwrap_or_default();
let cooldown = start + params.unbonding_period.seconds();
if env.block.time.seconds() < cooldown {
return Err(StdError::generic_err(format!(
"解绑期未到: 还需 {} 秒",
cooldown - env.block.time.seconds()
)));
}
let return_amount = staking.staked_amount.clone();
// 清除质押记录
AGENT_STAKING.remove(deps.storage, agent_addr);
Ok(Response::new()
.add_attribute("action", "complete_unbonding")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("returned", return_amount.amount.to_string())
.add_message(BankMsg::Send {
to_address: agent_addr.to_string(),
amount: vec![return_amount],
}))
}
3.4 保险池机制
保险池为 Agent 服务的消费者提供保障。当 Agent 被 Slash 时,部分资金进入保险池;当 Agent 提供服务失误时,消费者可以从保险池获得赔付。
// 保险池
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InsurancePool {
pub total_balance: Uint128, // 保险池总余额
pub claim_count: u64, // 理赔次数
pub total_paid: Uint128, // 总赔付金额
pub min_coverage: Uint128, // 最低保额
pub coverage_rate: Decimal256, // 保障比例 (默认 80%)
}
pub const INSURANCE_POOL: Item<InsurancePool> = Item::new("msg_ins_pool");
// 初始化保险池
pub fn init_insurance_pool(deps: DepsMut) -> StdResult<()> {
let pool = InsurancePool {
total_balance: Uint128::zero(),
claim_count: 0,
total_paid: Uint128::zero(),
min_coverage: Uint128::from(100_000_000u64), // 100 MSG
coverage_rate: Decimal256::percent(80),
};
INSURANCE_POOL.save(deps.storage, &pool)
}
// 发起理赔
pub fn submit_claim(
deps: DepsMut,
env: &Env,
consumer: &Addr,
agent_addr: &Addr,
request_id: &str,
damage_amount: Uint128,
) -> StdResult<Response> {
let mut pool = INSURANCE_POOL
.load(deps.storage)?;
// 验证请求是否存在且 Agent 被认定有过错
let _voucher = PAYMENT_VOUCHERS
.load(deps.storage, request_id)?;
// 计算赔付金额
let payout = damage_amount * pool.coverage_rate;
let payout = payout.min(pool.total_balance); // 不超过保险池余额
if payout.is_zero() {
return Err(StdError::generic_err("保险池余额不足"));
}
pool.total_balance -= payout;
pool.claim_count += 1;
pool.total_paid += payout;
INSURANCE_POOL.save(deps.storage, &pool)?;
Ok(Response::new()
.add_attribute("action", "insurance_claim")
.add_attribute("consumer", consumer.to_string())
.add_attribute("agent", agent_addr.to_string())
.add_attribute("payout", payout.to_string())
.add_message(BankMsg::Send {
to_address: consumer.to_string(),
amount: vec![Coin::new(payout.u128(), "uMSG")],
}))
}
4. 奖励分发机制
4.1 基于贡献的奖励分配
奖励分发的核心是确保贡献越大、收益越高。每个 Epoch 根据 Agent 的综合贡献分数分配奖励池。
// Epoch 信息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct EpochInfo {
pub epoch_id: u64,
pub start_time: u64,
pub end_time: u64,
pub total_reward: Uint128,
pub distributed: bool,
}
// Agent 贡献记录
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Contribution {
pub agent_addr: Addr,
pub score: Uint128, // 综合贡献分
pub request_count: u64, // 处理请求数
pub total_volume: Uint128, // 总交易量
pub up_time: Decimal256, // 在线率 0.0-1.0
pub quality_score: Decimal256, // 服务质量分 0.0-1.0
pub data_contribution: Uint128, // 数据贡献量
pub model_contribution: u32, // 模型贡献数
}
// 贡献分计算
pub fn calculate_contribution_score(
contribution: &Contribution,
) -> Uint128 {
// 权重配置
let volume_weight = Decimal256::percent(30); // 交易量权重
let quality_weight = Decimal256::percent(25); // 服务质量权重
let uptime_weight = Decimal256::percent(20); // 在线率权重
let data_weight = Decimal256::percent(15); // 数据贡献权重
let model_weight = Decimal256::percent(10); // 模型贡献权重
// 计算各维度得分
let volume_score = contribution.total_volume;
let quality_score = contribution.quality_score
* Uint128::from(1000u64);
let uptime_score = contribution.up_time
* Uint128::from(1000u64);
let data_score = contribution.data_contribution;
let model_score = Uint128::from(
contribution.model_contribution as u64 * 1000u64,
);
// 加权汇总
volume_score * volume_weight
+ quality_score * quality_weight
+ uptime_score * uptime_weight
+ data_score * data_weight
+ model_score * model_weight
}
// 奖励分配
pub fn distribute_rewards(
deps: DepsMut,
env: &Env,
epoch_id: u64,
total_reward: Uint128,
contributions: Vec<Contribution>,
) -> StdResult<Response> {
if contributions.is_empty() {
return Ok(Response::new()
.add_attribute("action", "distribute_rewards")
.add_attribute("epoch", epoch_id.to_string())
.add_attribute("status", "no_contributors"));
}
// 计算总贡献分
let mut scored: Vec<(Addr, Uint128)> = contributions
.iter()
.map(|c| {
let score = calculate_contribution_score(c);
(c.agent_addr.clone(), score)
})
.collect();
let total_score: Uint128 = scored
.iter()
.map(|(_, s)| s)
.sum();
if total_score.is_zero() {
return Ok(Response::new()
.add_attribute("action", "distribute_rewards")
.add_attribute("status", "zero_score"));
}
let mut response = Response::new()
.add_attribute("action", "distribute_rewards")
.add_attribute("epoch", epoch_id.to_string())
.add_attribute("total_reward", total_reward.to_string())
.add_attribute("total_score", total_score.to_string())
.add_attribute("participants", scored.len().to_string());
// 按比例分配奖励
for (agent, score) in scored {
let reward = total_reward * score / total_score;
if reward.is_zero() {
continue;
}
// 55% 即时发放,45% 进入归属期
let immediate = reward * Decimal256::percent(55);
let vested = reward - immediate;
response = response
.add_attribute(
format!("reward_{}", agent),
reward.to_string(),
);
// 记录归属计划
let vesting = VestingSchedule {
agent_addr: agent.clone(),
total_amount: vested,
released_amount: Uint128::zero(),
start_time: env.block.time.seconds(),
duration: Duration::new(86400 * 30), // 30 天线性归属
cliff: Duration::new(86400 * 7), // 7 天悬崖期
};
VESTING_SCHEDULES.save(
deps.storage,
(&agent, env.block.height),
&vesting,
)?;
}
Ok(response)
}
// Epoch 存储
pub const EPOCH_INFO: Map<u64, EpochInfo> = Map::new("msg_epoch_info");
pub const CONTRIBUTIONS: Map<u64, Vec<Contribution>> =
Map::new("msg_contrib");
pub const VESTING_SCHEDULES: Map<(&Addr, u64), VestingSchedule> =
Map::new("msg_vesting");
4.2 归属期与锁仓
// 归属计划
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct VestingSchedule {
pub agent_addr: Addr,
pub total_amount: Uint128,
pub released_amount: Uint128,
pub start_time: u64,
pub duration: Duration,
pub cliff: Duration,
}
// 释放归属奖励
pub fn release_vested(
deps: DepsMut,
env: &Env,
agent_addr: &Addr,
schedule_height: u64,
) -> StdResult<Response> {
let mut vesting = VESTING_SCHEDULES
.load(deps.storage, (agent_addr, schedule_height))?;
let elapsed = env.block.time.seconds()
- vesting.start_time;
// 检查悬崖期
if elapsed < vesting.cliff.seconds() {
return Err(StdError::generic_err("尚在悬崖期内"));
}
// 计算已解锁比例
let total_duration = vesting.duration.seconds();
let unlock_ratio = if elapsed >= total_duration {
Decimal256::one()
} else {
Decimal256::from_ratio(
Uint128::from(elapsed),
Uint128::from(total_duration),
)
};
let unlocked = vesting.total_amount * unlock_ratio;
let releasable = unlocked - vesting.released_amount;
if releasable.is_zero() {
return Err(StdError::generic_err("无可释放金额"));
}
vesting.released_amount = unlocked;
VESTING_SCHEDULES.save(
deps.storage,
(agent_addr, schedule_height),
&vesting,
)?;
Ok(Response::new()
.add_attribute("action", "release_vested")
.add_attribute("agent", agent_addr.to_string())
.add_attribute("released", releasable.to_string())
.add_attribute("total_released", unlocked.to_string())
.add_message(BankMsg::Send {
to_address: agent_addr.to_string(),
amount: vec![Coin::new(releasable.u128(), "uMSG")],
}))
}
4.3 复合奖励与复利
// 复合奖励计算 - 鼓励 Agent 将收益再投资
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct CompoundReward {
pub base_rate: Decimal256, // 基础年化率
pub compound_bonus: Decimal256, // 复利奖励加成
pub min_compound_period: Duration, // 最短复利周期
pub max_compound_boost: Decimal256, // 最高复利加成
}
impl CompoundReward {
pub fn calculate_compound_bonus(
&self,
staking_duration: u64, // 持续质押时间 (秒)
reinvest_ratio: Decimal256, // 再投资比例
) -> Decimal256 {
// 持续质押时间越长,复利加成越高
let duration_years = Decimal256::from_ratio(
Uint128::from(staking_duration),
Uint128::from(86400u64 * 365),
);
let base_bonus = duration_years * self.compound_bonus;
let actual_bonus = base_bonus * reinvest_ratio;
actual_bonus.min(self.max_compound_boost)
}
// 计算复利后的总收益
pub fn calculate_compound_return(
&self,
principal: Uint128,
rate: Decimal256,
periods: u64,
) -> Uint128 {
// A = P(1 + r/n)^(nt)
let mut amount = principal;
let period_rate = rate / Uint128::from(periods);
for _ in 0..periods {
let interest = amount * period_rate;
amount += interest;
}
amount
}
}
4.4 惩罚性奖励调节
// 奖励调节器 - 根据行为调整奖励发放
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct RewardAdjuster {
pub base_multiplier: Decimal256, // 基础乘数
pub performance_threshold: Decimal256, // 性能阈值
pub penalty_factor: Decimal256, // 惩罚因子
}
impl RewardAdjuster {
// 计算 Agent 的实际奖励乘数
pub fn effective_multiplier(
&self,
reputation: &AgentReputation,
staking: &AgentStaking,
) -> Decimal256 {
let mut multiplier = self.base_multiplier;
// 信誉加成
let rep_bonus = Decimal256::from_ratio(
Uint128::from(reputation.reputation_score as u64),
Uint128::from(100u64),
);
multiplier = multiplier * (Decimal256::one() + rep_bonus);
// Slash 惩罚
if staking.slash_count > 0 {
let slash_penalty = Decimal256::percent(
(staking.slash_count * 10).min(90) as u64,
);
multiplier = multiplier * (Decimal256::one() - slash_penalty);
}
// 在线率调整
let uptime_factor = if reputation.success_rate
< self.performance_threshold
{
reputation.success_rate / self.performance_threshold
} else {
Decimal256::one()
};
multiplier = multiplier * uptime_factor;
multiplier
}
}
5. 数据市场激励
5.1 数据质量评分
数据是 AI Agent 的核心燃料。数据市场激励旨在鼓励高质量数据的生产者,同时惩罚低质量或虚假数据。
// 数据资产
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DataAsset {
pub data_id: String, // 数据唯一 ID
pub owner: Addr, // 数据所有者
pub data_type: String, // 数据类型 (text/image/audio/...)
pub size_bytes: u64, // 数据大小
pub quality_score: Decimal256, // 质量评分 0.0-1.0
pub usage_count: u64, // 被使用次数
pub price_per_use: Uint128, // 每次使用价格
pub validation_status: ValidationStatus, // 验证状态
pub created_at: u64,
pub tags: Vec<String>, // 标签
pub checksum: String, // 数据校验和
}
// 验证状态
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ValidationStatus {
Pending,
Validated,
Rejected(String),
Disputed,
}
// 数据质量评分规则
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DataQualityCriteria {
pub completeness: Decimal256, // 完整性权重
pub accuracy: Decimal256, // 准确性权重
pub freshness: Decimal256, // 时效性权重
pub uniqueness: Decimal256, // 独特性权重
pub relevance: Decimal256, // 相关性权重
}
impl Default for DataQualityCriteria {
fn default() -> Self {
DataQualityCriteria {
completeness: Decimal256::percent(20),
accuracy: Decimal256::percent(35),
freshness: Decimal256::percent(15),
uniqueness: Decimal256::percent(20),
relevance: Decimal256::percent(10),
}
}
}
// 数据质量评分计算
pub fn calculate_data_quality(
criteria: &DataQualityCriteria,
completeness: Decimal256,
accuracy: Decimal256,
freshness: Decimal256,
uniqueness: Decimal256,
relevance: Decimal256,
) -> Decimal256 {
completeness * criteria.completeness
+ accuracy * criteria.accuracy
+ freshness * criteria.freshness
+ uniqueness * criteria.uniqueness
+ relevance * criteria.relevance
}
// 消费者反馈
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DataFeedback {
pub data_id: String,
pub consumer: Addr,
pub rating: u8, // 1-5 分
pub usefulness: u8, // 实用性 1-5
pub accuracy_rating: u8, // 准确性 1-5
pub comment: Option<String>,
pub timestamp: u64,
}
// 数据存储
pub const DATA_ASSETS: Map<&str, DataAsset> = Map::new("msg_data");
pub const DATA_FEEDBACKS: Map<&str, Vec<DataFeedback>> =
Map::new("msg_data_fb");
// 提交数据质量反馈
pub fn submit_data_feedback(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
data_id: &str,
rating: u8,
usefulness: u8,
accuracy_rating: u8,
) -> StdResult<Response> {
if rating < 1 || rating > 5 {
return Err(StdError::generic_err("评分需在 1-5 之间"));
}
let feedback = DataFeedback {
data_id: data_id.to_string(),
consumer: info.sender.clone(),
rating,
usefulness,
accuracy_rating,
comment: None,
timestamp: env.block.time.seconds(),
};
DATA_FEEDBACKS
.update(deps.storage, data_id, |existing| -> StdResult<_> {
let mut items = existing.unwrap_or_default();
items.push(feedback);
Ok(items)
})?;
// 更新数据资产质量分
let mut asset = DATA_ASSETS
.load(deps.storage, data_id)?;
let feedbaks = DATA_FEEDBACKS
.load(deps.storage, data_id)?;
let avg_rating: Decimal256 = feedbaks
.iter()
.map(|f| Decimal256::from_ratio(
Uint128::from(f.rating as u64),
Uint128::one(),
))
.sum::<Decimal256>()
/ Uint128::from(feedbaks.len() as u64);
asset.quality_score = avg_rating
/ Uint128::from(5u64);
DATA_ASSETS.save(deps.storage, data_id, &asset)?;
Ok(Response::new()
.add_attribute("action", "data_feedback")
.add_attribute("data_id", data_id)
.add_attribute("rating", rating.to_string())
.add_attribute("new_quality", asset.quality_score.to_string()))
}
5.2 买卖方信誉
// 数据市场参与者信誉
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct MarketParticipant {
pub addr: Addr,
pub total_sales: u64,
pub total_purchases: u64,
pub sales_volume: Uint128,
pub avg_rating_as_seller: Decimal256,
pub avg_rating_as_buyer: Decimal256,
pub dispute_count: u32,
pub resolved_disputes: u32,
pub reliability_score: Decimal256, // 可靠性得分
}
pub const MARKET_PARTICIPANTS: Map<&Addr, MarketParticipant> =
Map::new("msg_mkt_part");
// 更新卖家信誉
pub fn update_seller_reputation(
deps: DepsMut,
seller: &Addr,
transaction_amount: Uint128,
rating: u8,
) -> StdResult<MarketParticipant> {
MARKET_PARTICIPANTS
.update(deps.storage, seller, |existing| -> StdResult<_> {
let mut p = existing.unwrap_or(MarketParticipant {
addr: seller.clone(),
total_sales: 0,
total_purchases: 0,
sales_volume: Uint128::zero(),
avg_rating_as_seller: Decimal256::percent(300),
avg_rating_as_buyer: Decimal256::percent(300),
dispute_count: 0,
resolved_disputes: 0,
reliability_score: Decimal256::percent(80),
});
p.total_sales += 1;
p.sales_volume += transaction_amount;
// 更新平均评分
let old_total = p.avg_rating_as_seller
* Uint128::from(p.total_sales - 1);
p.avg_rating_as_seller = (old_total
+ Uint128::from(rating as u64))
/ Uint128::from(p.total_sales);
// 综合可靠性
p.reliability_score = calculate_reliability(&p);
Ok(p)
})
}
fn calculate_reliability(p: &MarketParticipant) -> Decimal256 {
let rating_score = p.avg_rating_as_seller
/ Uint128::from(5u64);
let dispute_ratio = if p.dispute_count > 0 {
Decimal256::from_ratio(
Uint128::from(p.resolved_disputes),
Uint128::from(p.dispute_count.max(1)),
)
} else {
Decimal256::one()
};
let volume_score = p.sales_volume
/ (p.sales_volume + Uint128::from(1_000_000_000_000u64));
rating_score * Decimal256::percent(50)
+ dispute_ratio * Decimal256::percent(30)
+ volume_score * Decimal256::percent(20)
}
5.3 仲裁押金
// 数据交易争议
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct DataDispute {
pub dispute_id: String,
pub data_id: String,
pub buyer: Addr,
pub seller: Addr,
pub reason: DisputeReason,
pub buyer_deposit: Uint128, // 买方仲裁押金
pub seller_deposit: Uint128, // 卖方仲裁押金
pub arbitrator: Option<Addr>, // 仲裁人
pub status: DisputeStatus,
pub ruling: Option<DisputeRuling>,
pub created_at: u64,
pub resolved_at: Option<u64>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum DisputeReason {
DataQualityMismatch,
IncompleteData,
WrongDataType,
CopyrightViolation,
FraudulentData,
Other(String),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum DisputeStatus {
Open,
UnderReview,
Resolved,
Expired,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum DisputeRuling {
BuyerWins,
SellerWins,
Split(Vec<Uint128>),
}
pub const DISPUTES: Map<&str, DataDispute> = Map::new("msg_disp");
// 发起争议
pub fn raise_dispute(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
data_id: &str,
reason: DisputeReason,
) -> StdResult<Response> {
let asset = DATA_ASSETS
.load(deps.storage, data_id)?;
// 验证争议发起者是数据消费者
let deposit_amount = Uint128::from(10_000_000u64); // 10 MSG 押金
let deposit = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG 作为仲裁押金"))?;
if deposit.amount < deposit_amount {
return Err(StdError::generic_err(format!(
"仲裁押金不足: 需要 {} uMSG", deposit_amount
)));
}
let dispute_id = format!("{}-{}", data_id, env.block.height);
let dispute = DataDispute {
dispute_id: dispute_id.clone(),
data_id: data_id.to_string(),
buyer: info.sender.clone(),
seller: asset.owner.clone(),
reason,
buyer_deposit: deposit_amount,
seller_deposit: Uint128::zero(),
arbitrator: None,
status: DisputeStatus::Open,
ruling: None,
created_at: env.block.time.seconds(),
resolved_at: None,
};
DISPUTES.save(deps.storage, &dispute_id, &dispute)?;
Ok(Response::new()
.add_attribute("action", "raise_dispute")
.add_attribute("dispute_id", &dispute_id)
.add_attribute("data_id", data_id)
.add_attribute("buyer", info.sender.to_string())
.add_attribute("seller", asset.owner.to_string()))
}
// 卖方应诉
pub fn respond_to_dispute(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
dispute_id: &str,
) -> StdResult<Response> {
let mut dispute = DISPUTES
.load(deps.storage, dispute_id)?;
if info.sender != dispute.seller {
return Err(StdError::generic_err("只有卖方可以应诉"));
}
if dispute.status != DisputeStatus::Open {
return Err(StdError::generic_err("争议已关闭"));
}
// 卖方也需要缴纳对等押金
let deposit = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG 作为仲裁押金"))?;
if deposit.amount < dispute.buyer_deposit {
return Err(StdError::generic_err("押金不足"));
}
dispute.seller_deposit = deposit.amount;
dispute.status = DisputeStatus::UnderReview;
DISPUTES.save(deps.storage, dispute_id, &dispute)?;
Ok(Response::new()
.add_attribute("action", "respond_dispute")
.add_attribute("dispute_id", dispute_id))
}
// 仲裁裁决
pub fn resolve_dispute(
deps: DepsMut,
env: &Env,
dispute_id: &str,
ruling: DisputeRuling,
) -> StdResult<Response> {
let mut dispute = DISPUTES
.load(deps.storage, dispute_id)?;
dispute.status = DisputeStatus::Resolved;
dispute.ruling = Some(ruling.clone());
dispute.resolved_at = Some(env.block.time.seconds());
DISPUTES.save(deps.storage, dispute_id, &dispute)?;
let mut response = Response::new()
.add_attribute("action", "resolve_dispute")
.add_attribute("dispute_id", dispute_id);
match ruling {
DisputeRuling::BuyerWins => {
// 买方押金返还,卖方押金归买方
response = response
.add_message(BankMsg::Send {
to_address: dispute.buyer.to_string(),
amount: vec![
Coin::new(dispute.buyer_deposit.u128(), "uMSG"),
Coin::new(dispute.seller_deposit.u128(), "uMSG"),
],
});
}
DisputeRuling::SellerWins => {
response = response
.add_message(BankMsg::Send {
to_address: dispute.seller.to_string(),
amount: vec![
Coin::new(dispute.buyer_deposit.u128(), "uMSG"),
Coin::new(dispute.seller_deposit.u128(), "uMSG"),
],
});
}
DisputeRuling::Split(amounts) => {
if amounts.len() >= 2 {
response = response
.add_message(BankMsg::Send {
to_address: dispute.buyer.to_string(),
amount: vec![Coin::new(
amounts[0].u128(), "uMSG",
)],
})
.add_message(BankMsg::Send {
to_address: dispute.seller.to_string(),
amount: vec![Coin::new(
amounts[1].u128(), "uMSG",
)],
});
}
}
}
Ok(response)
}
6. 模型市场激励
6.1 模型使用版税
AI 模型是 Agent 的智能核心。模型市场激励鼓励开发者贡献高质量模型,并通过版税机制获得持续收益。
// AI 模型资产
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct AIModel {
pub model_id: String, // 模型唯一 ID
pub owner: Addr, // 模型所有者
pub name: String, // 模型名称
pub version: String, // 版本号
pub model_type: ModelType, // 模型类型
pub license: ModelLicense, // 许可证
pub base_royalty_rate: Decimal256, // 基础版税率 (每次推理)
pub total_inferences: u64, // 总推理次数
pub total_royalties: Uint128, // 总版税收入
pub quality_rating: Decimal256, // 质量评分
pub staked_amount: Uint128, // 模型质押量
pub checksum: String, // 模型哈希校验
pub metadata_uri: String, // 元数据 URI
pub created_at: u64,
}
// 模型类型
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ModelType {
LLM, // 大语言模型
ImageGen, // 图像生成
AudioGen, // 音频生成
Embedding, // 嵌入模型
Classifier, // 分类器
Recommender, // 推荐模型
Custom(String),
}
// 许可证
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ModelLicense {
OpenSource,
Commercial,
Restricted(String),
}
// 推理记录
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InferenceRecord {
pub inference_id: String,
pub model_id: String,
pub consumer: Addr,
pub agent_used: Option<Addr>,
pub input_hash: String,
pub output_hash: String,
pub compute_units: u64,
pub royalty_paid: Uint128,
pub timestamp: u64,
}
pub const AI_MODELS: Map<&str, AIModel> = Map::new("msg_ai_model");
pub const INFERENCE_RECORDS: Map<&str, InferenceRecord> =
Map::new("msg_infer");
// 注册新模型
pub fn register_model(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
name: String,
model_type: ModelType,
base_royalty_rate: Decimal256,
metadata_uri: String,
checksum: String,
) -> StdResult<Response> {
// 验证版税率
if base_royalty_rate > Decimal256::percent(30) {
return Err(StdError::generic_err("版税率不能超过 30%"));
}
// 需要最低质押
let stake_amount = Uint128::from(100_000_000u64); // 100 MSG
let stake = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG 质押"))?;
if stake.amount < stake_amount {
return Err(StdError::generic_err(format!(
"最低质押: {} uMSG", stake_amount
)));
}
let model_id = format!("model-{}-{}", env.block.height, info.sender);
let model = AIModel {
model_id: model_id.clone(),
owner: info.sender.clone(),
name,
version: "1.0.0".to_string(),
model_type,
license: ModelLicense::Commercial,
base_royalty_rate,
total_inferences: 0,
total_royalties: Uint128::zero(),
quality_rating: Decimal256::percent(70),
staked_amount: stake.amount,
checksum,
metadata_uri,
created_at: env.block.time.seconds(),
};
AI_MODELS.save(deps.storage, &model_id, &model)?;
Ok(Response::new()
.add_attribute("action", "register_model")
.add_attribute("model_id", &model_id)
.add_attribute("owner", info.sender.to_string())
.add_attribute("name", &name)
.add_attribute("royalty_rate", base_royalty_rate.to_string()))
}
6.2 推理费用拆分
// 推理费用拆分规则
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InferenceFeeSplit {
pub model_owner_share: Decimal256, // 模型所有者分成
pub agent_operator_share: Decimal256, // Agent 运营者分成
pub compute_provider_share: Decimal256, // 计算提供方分成
pub protocol_share: Decimal256, // 协议费
pub staking_reward_share: Decimal256, // 质押奖励
}
impl Default for InferenceFeeSplit {
fn default() -> Self {
InferenceFeeSplit {
model_owner_share: Decimal256::percent(40),
agent_operator_share: Decimal256::percent(30),
compute_provider_share: Decimal256::percent(20),
protocol_share: Decimal256::percent(5),
staking_reward_share: Decimal256::percent(5),
}
}
}
// 执行推理并分配收入
pub fn execute_inference(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
model_id: &str,
input_data: &str,
compute_units: u64,
) -> StdResult<Response> {
let mut model = AI_MODELS
.load(deps.storage, model_id)?;
let split = InferenceFeeSplit::default();
// 计算推理费用
let compute_cost = Uint128::from(compute_units)
* Uint128::from(1_000u64); // 1 uMSG 每千单位
let royalty = compute_cost * model.base_royalty_rate;
let total_fee = compute_cost + royalty;
// 验证支付
let payment = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG 支付"))?;
if payment.amount < total_fee {
return Err(StdError::generic_err("费用不足"));
}
// 拆分费用
let model_reward = total_fee * split.model_owner_share;
let agent_reward = total_fee * split.agent_operator_share;
let compute_reward = total_fee * split.compute_provider_share;
let protocol_fee = total_fee * split.protocol_share;
let stake_reward = total_fee * split.staking_reward_share;
// 更新模型统计数据
model.total_inferences += 1;
model.total_royalties += model_reward;
AI_MODELS.save(deps.storage, model_id, &model)?;
// 记录推理
let inference_id = format!("inf-{}-{}", env.block.height, model_id);
let record = InferenceRecord {
inference_id: inference_id.clone(),
model_id: model_id.to_string(),
consumer: info.sender.clone(),
agent_used: None,
input_hash: hash_evidence(input_data),
output_hash: String::new(), // 链下计算后更新
compute_units,
royalty_paid: total_fee,
timestamp: env.block.time.seconds(),
};
INFERENCE_RECORDS.save(deps.storage, &inference_id, &record)?;
Ok(Response::new()
.add_attribute("action", "execute_inference")
.add_attribute("inference_id", &inference_id)
.add_attribute("model_id", model_id)
.add_attribute("consumer", info.sender.to_string())
.add_attribute("total_fee", total_fee.to_string())
.add_attribute("model_reward", model_reward.to_string())
.add_attribute("agent_reward", agent_reward.to_string())
.add_attribute("compute_reward", compute_reward.to_string())
.add_attribute("protocol_fee", protocol_fee.to_string())
.add_attribute("stake_reward", stake_reward.to_string()))
}
6.3 模型质押与质量保证
// 模型质押以保证服务质量
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ModelStaking {
pub model_id: String,
pub staked_amount: Uint128,
pub performance_bond: Uint128, // 性能保证金
pub min_accuracy: Decimal256, // 最低准确率要求
pub max_latency_ms: u64, // 最大延迟
pub slashed_for_performance: u32, // 因性能问题被罚次数
}
pub const MODEL_STAKING: Map<&str, ModelStaking> =
Map::new("msg_model_stake");
// 提交模型性能证明
pub fn submit_performance_proof(
deps: DepsMut,
env: &Env,
model_id: &str,
accuracy: Decimal256,
latency_ms: u64,
sample_count: u32,
) -> StdResult<Response> {
let mut staking = MODEL_STAKING
.load(deps.storage, model_id)?;
let model = AI_MODELS
.load(deps.storage, model_id)?;
let mut slashed = Uint128::zero();
let mut passed = true;
// 检查准确率
if accuracy < staking.min_accuracy {
let penalty = staking.performance_bond
* Decimal256::percent(10);
staking.staked_amount -= penalty;
staking.slashed_for_performance += 1;
slashed += penalty;
passed = false;
}
// 检查延迟
if latency_ms > staking.max_latency_ms {
let penalty = staking.performance_bond
* Decimal256::percent(5);
staking.staked_amount -= penalty;
staking.slashed_for_performance += 1;
slashed += penalty;
passed = false;
}
MODEL_STAKING.save(deps.storage, model_id, &staking)?;
// 更新模型质量评分
let mut model = AI_MODELS
.load(deps.storage, model_id)?;
model.quality_rating = accuracy;
AI_MODELS.save(deps.storage, model_id, &model)?;
Ok(Response::new()
.add_attribute("action", "performance_proof")
.add_attribute("model_id", model_id)
.add_attribute("accuracy", accuracy.to_string())
.add_attribute("latency_ms", latency_ms.to_string())
.add_attribute("sample_count", sample_count.to_string())
.add_attribute("slashed", slashed.to_string())
.add_attribute("passed", passed.to_string()))
}
7. 流动性激励
7.1 LP 代币激励
流动性是 Agent 代币经济的基础。通过激励流动性提供者,可以降低 Agent 代币的交易滑点,提升市场效率。
// 流动性池配置
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct LiquidityPool {
pub pool_id: String,
pub token0: String, // 基础代币 (通常是 uMSG)
pub token1: String, // 报价代币 (CW20 Agent 代币)
pub total_liquidity: Uint128, // 总流动性
pub apr: Decimal256, // 当前年化收益率
pub reward_multiplier: Decimal256, // 奖励乘数
pub min_lock_time: Duration, // 最短锁定时间
pub total_rewards_distributed: Uint128,
}
// LP 质押位置
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct LpPosition {
pub lp_token_id: String,
pub provider: Addr,
pub token0_amount: Uint128,
pub token1_amount: Uint128,
pub liquidity_share: Decimal256, // 池份额
pub locked_until: u64,
pub rewards_claimed: Uint128,
}
pub const LIQUIDITY_POOLS: Map<&str, LiquidityPool> =
Map::new("msg_liq_pool");
pub const LP_POSITIONS: Map<&str, LpPosition> = Map::new("msg_lp_pos");
// 添加流动性
pub fn add_liquidity(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
pool_id: &str,
token0_amount: Uint128,
token1_amount: Uint128,
lock_days: u64,
) -> StdResult<Response> {
let mut pool = LIQUIDITY_POOLS
.load(deps.storage, pool_id)?;
// 验证锁定时间
let min_lock = pool.min_lock_time.seconds();
let lock_seconds = lock_days * 86400;
if lock_seconds < min_lock {
return Err(StdError::generic_err(format!(
"锁定时间不足: 最少 {} 秒", min_lock
)));
}
// 计算份额
let total_value = pool.total_liquidity
+ token0_amount + token1_amount;
let share = if pool.total_liquidity.is_zero() {
Decimal256::one()
} else {
Decimal256::from_ratio(
token0_amount + token1_amount,
pool.total_liquidity,
)
};
let lp_token_id = format!("lp-{}-{}", pool_id, env.block.height);
let position = LpPosition {
lp_token_id: lp_token_id.clone(),
provider: info.sender.clone(),
token0_amount,
token1_amount,
liquidity_share: share,
locked_until: env.block.time.seconds() + lock_seconds,
rewards_claimed: Uint128::zero(),
};
pool.total_liquidity += token0_amount + token1_amount;
LIQUIDITY_POOLS.save(deps.storage, pool_id, &pool)?;
LP_POSITIONS.save(deps.storage, &lp_token_id, &position)?;
Ok(Response::new()
.add_attribute("action", "add_liquidity")
.add_attribute("pool_id", pool_id)
.add_attribute("provider", info.sender.to_string())
.add_attribute("token0_amount", token0_amount.to_string())
.add_attribute("token1_amount", token1_amount.to_string())
.add_attribute("share", share.to_string())
.add_attribute("locked_until", position.locked_until.to_string()))
}
// 领取 LP 奖励
pub fn claim_lp_rewards(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
lp_token_id: &str,
) -> StdResult<Response> {
let mut position = LP_POSITIONS
.load(deps.storage, lp_token_id)?;
if info.sender != position.provider {
return Err(StdError::generic_err("不是 LP 所有者"));
}
// 计算应得奖励
let pool = LIQUIDITY_POOLS
.load(deps.storage, "main")?; // 主池
let time_staked = env.block.time.seconds()
- (position.locked_until - pool.min_lock_time.seconds());
let reward_rate = pool.apr
/ Uint128::from(365u64 * 86400u64); // 每秒收益率
let total_earned = position.token0_amount
+ position.token1_amount
* reward_rate
* Uint128::from(time_staked);
let claimable = total_earned - position.rewards_claimed;
if claimable.is_zero() {
return Err(StdError::generic_err("无待领取奖励"));
}
position.rewards_claimed = total_earned;
LP_POSITIONS.save(deps.storage, lp_token_id, &position)?;
Ok(Response::new()
.add_attribute("action", "claim_lp_rewards")
.add_attribute("lp_token_id", lp_token_id)
.add_attribute("claimable", claimable.to_string())
.add_message(BankMsg::Send {
to_address: info.sender.to_string(),
amount: vec![Coin::new(claimable.u128(), "uMSG")],
}))
}
7.2 Yield Farming
// 收益农场合约
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct YieldFarm {
pub farm_id: String,
pub staking_token: String, // 质押代币地址
pub reward_token: String, // 奖励代币地址
pub total_staked: Uint128, // 总质押量
pub reward_per_block: Uint128, // 每区块奖励
pub bonus_multiplier: Decimal256, // 加成乘数
pub min_stake: Uint128, // 最低质押
pub max_stake: Uint128, // 最高质押
pub start_block: u64,
pub end_block: u64,
pub rewards_per_share: Decimal256,
pub last_update_block: u64,
}
// 用户农场信息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct UserFarmInfo {
pub user: Addr,
pub farm_id: String,
pub staked_amount: Uint128,
pub debt: Decimal256,
pub pending_rewards: Uint128,
pub staked_at: u64,
}
pub const YIELD_FARMS: Map<&str, YieldFarm> = Map::new("msg_yield_farm");
pub const USER_FARMS: Map<(&Addr, &str), UserFarmInfo> =
Map::new("msg_user_farm");
// 质押到农场
pub fn stake_in_farm(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
farm_id: &str,
amount: Uint128,
) -> StdResult<Response> {
let mut farm = YIELD_FARMS
.load(deps.storage, farm_id)?;
if env.block.height < farm.start_block
|| env.block.height > farm.end_block
{
return Err(StdError::generic_err("农场不在活跃期"));
}
if amount < farm.min_stake {
return Err(StdError::generic_err("低于最低质押量"));
}
if farm.total_staked + amount > farm.max_stake {
return Err(StdError::generic_err("超出最高质押量"));
}
// 更新农场状态
farm.rewards_per_share = farm.rewards_per_share
+ farm.reward_per_block
* Decimal256::from_ratio(
Uint128::from(env.block.height - farm.last_update_block),
farm.total_staked.max(Uint128::one()),
);
farm.last_update_block = env.block.height;
farm.total_staked += amount;
YIELD_FARMS.save(deps.storage, farm_id, &farm)?;
// 更新或创建用户信息
USER_FARMS
.update(deps.storage, (&info.sender, farm_id), |existing| {
let mut uf = existing.unwrap_or(UserFarmInfo {
user: info.sender.clone(),
farm_id: farm_id.to_string(),
staked_amount: Uint128::zero(),
debt: Decimal256::zero(),
pending_rewards: Uint128::zero(),
staked_at: env.block.time.seconds(),
});
// 计算已有奖励
let earned = uf.staked_amount * farm.rewards_per_share
- uf.debt;
uf.pending_rewards += earned;
uf.staked_amount += amount;
uf.debt = uf.staked_amount * farm.rewards_per_share;
Ok(uf)
})?;
Ok(Response::new()
.add_attribute("action", "stake_farm")
.add_attribute("farm_id", farm_id)
.add_attribute("user", info.sender.to_string())
.add_attribute("amount", amount.to_string()))
}
// 提取农场奖励
pub fn harvest_farm(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
farm_id: &str,
) -> StdResult<Response> {
let farm = YIELD_FARMS
.load(deps.storage, farm_id)?;
let mut user_farm = USER_FARMS
.load(deps.storage, (&info.sender, farm_id))?;
// 计算奖励
let pending = user_farm.staked_amount * farm.rewards_per_share
- user_farm.debt
+ user_farm.pending_rewards;
if pending.is_zero() {
return Err(StdError::generic_err("无待领取奖励"));
}
user_farm.pending_rewards = Uint128::zero();
user_farm.debt = user_farm.staked_amount * farm.rewards_per_share;
USER_FARMS.save(deps.storage, (&info.sender, farm_id), &user_farm)?;
Ok(Response::new()
.add_attribute("action", "harvest_farm")
.add_attribute("farm_id", farm_id)
.add_attribute("user", info.sender.to_string())
.add_attribute("rewards", pending.to_string())
.add_message(BankMsg::Send {
to_address: info.sender.to_string(),
amount: vec![Coin::new(pending.u128(), "uMSG")],
}))
}
7.3 Bonding Curves for Agent Tokens
// Bonding Curve 定价 - 用于 Agent 代币的自动做市
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct BondingCurve {
pub token_addr: Addr, // CW20 Agent 代币地址
pub curve_type: CurveType, // 曲线类型
pub reserve_balance: Uint128, // 储备金余额 (uMSG)
pub supply: Uint128, // 当前代币总供应量
pub parameters: CurveParameters, // 曲线参数
}
// 曲线类型
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum CurveType {
Linear, // 线性: P = S * k
Quadratic, // 二次: P = S² * k
Exponential, // 指数: P = e^(S * k)
Logarithmic, // 对数: P = ln(S + 1) * k
Custom(String), // 自定义曲线
}
// 曲线参数
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct CurveParameters {
pub slope: Decimal256, // 斜率 k
pub power: Decimal256, // 幂次 (用于二次曲线)
pub scale: Decimal256, // 缩放因子
pub max_supply: Uint128, // 最大供应量
pub fee_rate: Decimal256, // 交易费率
}
pub const BONDING_CURVES: Map<&Addr, BondingCurve> =
Map::new("msg_bond_curve");
// 初始化 Bonding Curve
pub fn init_bonding_curve(
deps: DepsMut,
token_addr: &Addr,
curve_type: CurveType,
parameters: CurveParameters,
) -> StdResult<Response> {
if BONDING_CURVES.has(deps.storage, token_addr) {
return Err(StdError::generic_err("Bonding curve 已存在"));
}
let curve = BondingCurve {
token_addr: token_addr.clone(),
curve_type,
reserve_balance: Uint128::zero(),
supply: Uint128::zero(),
parameters,
};
BONDING_CURVES.save(deps.storage, token_addr, &curve)?;
Ok(Response::new()
.add_attribute("action", "init_bonding_curve")
.add_attribute("token", token_addr.to_string())
.add_attribute("curve_type", format!("{:?}", curve_type)))
}
// 计算代币购买价格
pub fn get_buy_price(
curve: &BondingCurve,
token_amount: Uint128,
) -> StdResult<Uint128> {
let new_supply = curve.supply + token_amount;
if new_supply > curve.parameters.max_supply {
return Err(StdError::generic_err("超出最大供应量"));
}
let cost = match curve.curve_type {
CurveType::Linear => {
let avg_price = curve.parameters.slope
* (curve.supply + new_supply)
/ Uint128::from(2u64);
avg_price * token_amount
}
CurveType::Quadratic => {
// ∫ k * S² dS = k/3 * (S_new³ - S_old³)
let k = curve.parameters.slope;
let s_old = curve.supply;
let s_new = new_supply;
k * (s_new * s_new * s_new - s_old * s_old * s_old)
/ Uint128::from(3u64)
}
CurveType::Exponential => {
// ∑ e^(S * k) 近似计算
let k = curve.parameters.slope;
let mut total = Uint128::zero();
let mut s = curve.supply;
for _ in 0..token_amount.u128() {
let price = Decimal256::one()
* Decimal256::from_ratio(
Uint128::one(),
Uint128::from(100u64),
)
.pow(s.u128() * k.u128());
total += price;
s += Uint128::one();
}
total
}
CurveType::Logarithmic => {
// ∫ ln(S+1) * k dS
let k = curve.parameters.slope;
let s_old = curve.supply;
let s_new = new_supply;
// 近似: (s_new * ln(s_new + 1) - s_new) - (s_old * ln(s_old + 1) - s_old) * k
// 简化实现使用梯形近似
let avg = (s_new * k + s_old * k) / Uint128::from(2u64);
avg * token_amount
}
CurveType::Custom(_) => {
return Err(StdError::generic_err("自定义曲线需专用实现"));
}
};
// 加上交易费
let fee = cost * curve.parameters.fee_rate;
Ok(cost + fee)
}
// 购买 Agent 代币通过 Bonding Curve
pub fn buy_agent_tokens(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
token_addr: &Addr,
token_amount: Uint128,
) -> StdResult<Response> {
let mut curve = BONDING_CURVES
.load(deps.storage, token_addr)?;
let cost = get_buy_price(&curve, token_amount)?;
// 验证支付
let payment = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG"))?;
if payment.amount < cost {
return Err(StdError::generic_err("支付不足"));
}
// 更新曲线状态
let fee = cost * curve.parameters.fee_rate;
curve.reserve_balance += cost - fee;
curve.supply += token_amount;
BONDING_CURVES.save(deps.storage, token_addr, &curve)?;
// 铸造代币给买家 (通过 CW20 合约调用)
Ok(Response::new()
.add_attribute("action", "buy_agent_tokens")
.add_attribute("token", token_addr.to_string())
.add_attribute("buyer", info.sender.to_string())
.add_attribute("token_amount", token_amount.to_string())
.add_attribute("cost", cost.to_string())
.add_attribute("fee", fee.to_string()))
}
// 计算卖出价格
pub fn get_sell_price(
curve: &BondingCurve,
token_amount: Uint128,
) -> StdResult<Uint128> {
if token_amount > curve.supply {
return Err(StdError::generic_err("代币数量超过供应量"));
}
let new_supply = curve.supply - token_amount;
// 卖出价格是买入的反向计算
let buy_cost = get_buy_price(curve, token_amount)?;
let spread = buy_cost * Decimal256::percent(10); // 10% 价差
Ok(buy_cost - spread)
}
// 卖出 Agent 代币
pub fn sell_agent_tokens(
deps: DepsMut,
_env: &Env,
info: &MessageInfo,
token_addr: &Addr,
token_amount: Uint128,
) -> StdResult<Response> {
let mut curve = BONDING_CURVES
.load(deps.storage, token_addr)?;
let price = get_sell_price(&curve, token_amount)?;
if curve.reserve_balance < price {
return Err(StdError::generic_err("储备金不足"));
}
let fee = price * curve.parameters.fee_rate;
curve.reserve_balance -= price;
curve.supply -= token_amount;
BONDING_CURVES.save(deps.storage, token_addr, &curve)?;
Ok(Response::new()
.add_attribute("action", "sell_agent_tokens")
.add_attribute("token", token_addr.to_string())
.add_attribute("seller", info.sender.to_string())
.add_attribute("token_amount", token_amount.to_string())
.add_attribute("price", price.to_string())
.add_attribute("fee", fee.to_string())
.add_message(BankMsg::Send {
to_address: info.sender.to_string(),
amount: vec![Coin::new((price - fee).u128(), "uMSG")],
}))
}
8. 治理激励
8.1 投票权与质押
治理激励确保生态参与者积极参与决策。投票权与质押量挂钩,长期参与者获得更高权重。
// 治理代币质押
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct GovernanceStake {
pub voter: Addr,
pub staked_amount: Uint128, // 质押的 MSG 数量
pub voting_power: Decimal256, // 投票权重
pub lock_until: u64, // 锁仓截止时间
pub participation_count: u64, // 参与投票次数
pub proposal_count: u64, // 发起提案次数
pub last_vote_time: u64,
}
// 提案
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct Proposal {
pub proposal_id: u64,
pub title: String,
pub description: String,
pub proposer: Addr,
pub proposal_type: ProposalType,
pub status: ProposalStatus,
pub deposit_amount: Uint128,
pub vote_start: u64,
pub vote_end: u64,
pub for_votes: Uint128,
pub against_votes: Uint128,
pub abstain_votes: Uint128,
pub total_voting_power: Uint128,
pub executed: bool,
}
// 提案类型
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ProposalType {
ParameterChange(String), // 参数变更
RewardDistribution, // 奖励分配调整
EcosystemGrant, // 生态拨款
ProtocolUpgrade, // 协议升级
AgentBlacklist, // Agent 黑名单
EmergencyAction, // 紧急操作
Other(String),
}
// 提案状态
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ProposalStatus {
Pending,
Active,
Passed,
Rejected,
Executed,
Expired,
}
pub const GOVERNANCE_STAKES: Map<&Addr, GovernanceStake> =
Map::new("msg_gov_stake");
pub const PROPOSALS: Map<u64, Proposal> = Map::new("msg_proposals");
pub const VOTES: Map<(u64, &Addr), VoteChoice> = Map::new("msg_votes");
// 投票选择
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum VoteChoice {
For,
Against,
Abstain,
}
// 质押参与治理
pub fn stake_for_governance(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
lock_days: u64,
) -> StdResult<Response> {
let stake_amount = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.map(|c| c.amount)
.unwrap_or(Uint128::zero());
if stake_amount.is_zero() {
return Err(StdError::generic_err("需要 uMSG"));
}
let min_gov_stake = Uint128::from(1_000_000u64); // 1 MSG
if stake_amount < min_gov_stake {
return Err(StdError::generic_err("最低治理质押: 1 MSG"));
}
// 锁仓时间越长,投票权重越高
let lock_seconds = lock_days * 86400;
let voting_power = Decimal256::from_ratio(
stake_amount,
Uint128::one(),
) * Decimal256::one()
+ Decimal256::from_ratio(
Uint128::from(lock_days),
Uint128::from(365u64),
);
let gov_stake = GovernanceStake {
voter: info.sender.clone(),
staked_amount: stake_amount,
voting_power,
lock_until: env.block.time.seconds() + lock_seconds,
participation_count: 0,
proposal_count: 0,
last_vote_time: 0,
};
GOVERNANCE_STAKES.save(deps.storage, &info.sender, &gov_stake)?;
Ok(Response::new()
.add_attribute("action", "stake_governance")
.add_attribute("voter", info.sender.to_string())
.add_attribute("staked", stake_amount.to_string())
.add_attribute("voting_power", voting_power.to_string())
.add_attribute("locked_days", lock_days.to_string()))
}
8.2 提案与投票
// 创建提案
pub fn create_proposal(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
title: String,
description: String,
proposal_type: ProposalType,
deposit: Uint128,
) -> StdResult<Response> {
// 验证提案者已有治理质押
let gov_stake = GOVERNANCE_STAKES
.load(deps.storage, &info.sender)?;
if gov_stake.staked_amount.is_zero() {
return Err(StdError::generic_err("需要先质押参与治理"));
}
// 提案保证金
let min_deposit = Uint128::from(10_000_000u64); // 10 MSG
if deposit < min_deposit {
return Err(StdError::generic_err(format!(
"提案保证金至少: {} uMSG", min_deposit
)));
}
let payment = info
.funds
.iter()
.find(|c| c.denom == "uMSG")
.ok_or_else(|| StdError::generic_err("需要 uMSG 作为提案保证金"))?;
if payment.amount < deposit {
return Err(StdError::generic_err("保证金不足"));
}
let proposal_id = env.block.height;
let voting_period = 86400 * 7; // 7 天投票期
let proposal = Proposal {
proposal_id,
title,
description,
proposer: info.sender.clone(),
proposal_type,
status: ProposalStatus::Active,
deposit_amount: deposit,
vote_start: env.block.time.seconds(),
vote_end: env.block.time.seconds() + voting_period,
for_votes: Uint128::zero(),
against_votes: Uint128::zero(),
abstain_votes: Uint128::zero(),
total_voting_power: Uint128::zero(),
executed: false,
};
PROPOSALS.save(deps.storage, proposal_id, &proposal)?;
// 更新提案人参与计数
GOVERNANCE_STAKES
.update(deps.storage, &info.sender, |existing| -> StdResult<_> {
let mut gs = existing.unwrap_or(gov_stake);
gs.proposal_count += 1;
Ok(gs)
})?;
Ok(Response::new()
.add_attribute("action", "create_proposal")
.add_attribute("proposal_id", proposal_id.to_string())
.add_attribute("proposer", info.sender.to_string())
.add_attribute("title", &title)
.add_attribute("vote_end", proposal.vote_end.to_string()))
}
// 投票
pub fn cast_vote(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
proposal_id: u64,
vote: VoteChoice,
) -> StdResult<Response> {
let mut proposal = PROPOSALS
.load(deps.storage, proposal_id)?;
if proposal.status != ProposalStatus::Active {
return Err(StdError::generic_err("提案不在投票期"));
}
if env.block.time.seconds() > proposal.vote_end {
proposal.status = ProposalStatus::Expired;
PROPOSALS.save(deps.storage, proposal_id, &proposal)?;
return Err(StdError::generic_err("投票已结束"));
}
if VOTES.has(deps.storage, (proposal_id, &info.sender)) {
return Err(StdError::generic_err("已投票"));
}
let gov_stake = GOVERNANCE_STAKES
.load(deps.storage, &info.sender)?;
if gov_stake.staked_amount.is_zero() {
return Err(StdError::generic_err("需要质押才能投票"));
}
if env.block.time.seconds() < gov_stake.lock_until {
return Err(StdError::generic_err("质押仍在锁定期"));
}
let vote_power = gov_stake.voting_power;
match vote {
VoteChoice::For => proposal.for_votes += vote_power,
VoteChoice::Against => proposal.against_votes += vote_power,
VoteChoice::Abstain => proposal.abstain_votes += vote_power,
}
proposal.total_voting_power += vote_power;
PROPOSALS.save(deps.storage, proposal_id, &proposal)?;
VOTES.save(deps.storage, (proposal_id, &info.sender), &vote)?;
// 更新参与者信息
GOVERNANCE_STAKES
.update(deps.storage, &info.sender, |existing| -> StdResult<_> {
let mut gs = existing.unwrap_or(gov_stake);
gs.participation_count += 1;
gs.last_vote_time = env.block.time.seconds();
Ok(gs)
})?;
Ok(Response::new()
.add_attribute("action", "cast_vote")
.add_attribute("proposal_id", proposal_id.to_string())
.add_attribute("voter", info.sender.to_string())
.add_attribute("vote", format!("{:?}", vote))
.add_attribute("voting_power", vote_power.to_string()))
}
8.3 提案执行与奖励
// 提案执行与奖励分配
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct GovernanceRewards {
pub proposal_reward: Uint128, // 提案通过奖励
pub voting_reward: Uint128, // 投票参与奖励
pub participation_bonus: Decimal256, // 持续参与加成
pub reward_pool: Uint128, // 奖励池总额
}
pub const GOV_REWARDS: Item<GovernanceRewards> =
Item::new("msg_gov_rewards");
// 结束提案并统计结果
pub fn finalize_proposal(
deps: DepsMut,
env: &Env,
proposal_id: u64,
) -> StdResult<Response> {
let mut proposal = PROPOSALS
.load(deps.storage, proposal_id)?;
if env.block.time.seconds() < proposal.vote_end {
return Err(StdError::generic_err("投票尚未结束"));
}
if proposal.status != ProposalStatus::Active {
return Err(StdError::generic_err("提案已关闭"));
}
let gov_rewards = GOV_REWARDS
.load(deps.storage)
.unwrap_or(GovernanceRewards {
proposal_reward: Uint128::from(50_000_000u64), // 50 MSG
voting_reward: Uint128::from(1_000_000u64), // 1 MSG
participation_bonus: Decimal256::percent(5),
reward_pool: Uint128::zero(),
});
// 计算法定人数和通过门槛
let total_votes = proposal.for_votes
+ proposal.against_votes
+ proposal.abstain_votes;
let quorum = Uint128::from(1_000_000_000u64); // 简化:固定法定人数
let passed = total_votes >= quorum
&& proposal.for_votes > proposal.against_votes;
proposal.status = if passed {
ProposalStatus::Passed
} else {
ProposalStatus::Rejected
};
PROPOSALS.save(deps.storage, proposal_id, &proposal)?;
let mut response = Response::new()
.add_attribute("action", "finalize_proposal")
.add_attribute("proposal_id", proposal_id.to_string())
.add_attribute("status", format!("{:?}", proposal.status))
.add_attribute("for_votes", proposal.for_votes.to_string())
.add_attribute("against_votes", proposal.against_votes.to_string())
.add_attribute("abstain_votes", proposal.abstain_votes.to_string())
.add_attribute("total_votes", total_votes.to_string());
// 提案通过奖励
if passed {
// 奖励提案人
response = response
.add_message(BankMsg::Send {
to_address: proposal.proposer.to_string(),
amount: vec![Coin::new(
gov_rewards.proposal_reward.u128(),
"uMSG",
)],
})
.add_attribute("proposer_reward",
gov_rewards.proposal_reward.to_string());
// 退还提案保证金
response = response
.add_message(BankMsg::Send {
to_address: proposal.proposer.to_string(),
amount: vec![Coin::new(
proposal.deposit_amount.u128(),
"uMSG",
)],
})
.add_attribute("deposit_returned",
proposal.deposit_amount.to_string());
// 标记为可执行
proposal.executed = false;
PROPOSALS.save(deps.storage, proposal_id, &proposal)?;
}
Ok(response)
}
// 执行通过的提案
pub fn execute_proposal(
deps: DepsMut,
env: &Env,
proposal_id: u64,
) -> StdResult<Response> {
let mut proposal = PROPOSALS
.load(deps.storage, proposal_id)?;
if proposal.status != ProposalStatus::Passed {
return Err(StdError::generic_err("提案未通过"));
}
if proposal.executed {
return Err(StdError::generic_err("提案已执行"));
}
proposal.executed = true;
PROPOSALS.save(deps.storage, proposal_id, &proposal)?;
// 根据提案类型执行不同操作
let exec_description = match &proposal.proposal_type {
ProposalType::ParameterChange(param) => {
format!("更改参数: {}", param)
}
ProposalType::RewardDistribution => {
"调整奖励分配".to_string()
}
ProposalType::EcosystemGrant => {
"发放生态拨款".to_string()
}
ProposalType::ProtocolUpgrade => {
"触发协议升级".to_string()
}
ProposalType::AgentBlacklist => {
"更新 Agent 黑名单".to_string()
}
ProposalType::EmergencyAction => {
"执行紧急操作".to_string()
}
ProposalType::Other(desc) => desc.clone(),
};
Ok(Response::new()
.add_attribute("action", "execute_proposal")
.add_attribute("proposal_id", proposal_id.to_string())
.add_attribute("executed_action", &exec_description))
}
// 领取治理参与奖励
pub fn claim_governance_rewards(
deps: DepsMut,
env: &Env,
info: &MessageInfo,
) -> StdResult<Response> {
let gov_stake = GOVERNANCE_STAKES
.load(deps.storage, &info.sender)?;
let gov_rewards = GOV_REWARDS
.load(deps.storage)
.unwrap_or(GovernanceRewards {
proposal_reward: Uint128::from(50_000_000u64),
voting_reward: Uint128::from(1_000_000u64),
participation_bonus: Decimal256::percent(5),
reward_pool: Uint128::zero(),
});
// 基于参与次数计算奖励
let base_reward = gov_rewards.voting_reward
* Uint128::from(gov_stake.participation_count);
// 持续参与加成
let bonus_mult = Decimal256::one()
+ gov_rewards.participation_bonus
* Decimal256::from_ratio(
Uint128::from(gov_stake.participation_count),
Uint128::from(10u64),
);
let total_reward = base_reward * bonus_mult;
if total_reward.is_zero() {
return Err(StdError::generic_err("无奖励可领取"));
}
// 重置参与计数(奖励已领取)
GOVERNANCE_STAKES
.update(deps.storage, &info.sender, |existing| -> StdResult<_> {
let mut gs = existing.unwrap_or(gov_stake);
gs.participation_count = 0;
Ok(gs)
})?;
Ok(Response::new()
.add_attribute("action", "claim_gov_rewards")
.add_attribute("voter", info.sender.to_string())
.add_attribute("total_reward", total_reward.to_string())
.add_attribute("participation_count",
gov_stake.participation_count.to_string())
.add_message(BankMsg::Send {
to_address: info.sender.to_string(),
amount: vec![Coin::new(total_reward.u128(), "uMSG")],
}))
}
9. 合约入口与消息定义
9.1 主合约消息
// 合约入口消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum ExecuteMsg {
// Agent 操作
RegisterAgent {
name: String,
description: String,
pricing: PricingModel,
pricing_strategy: PricingStrategy,
},
UpdateAgentPricing {
pricing: Option<PricingModel>,
pricing_strategy: Option<PricingStrategy>,
},
CallAgent {
agent_addr: Addr,
compute_units: u64,
data_size: u64,
data: String,
},
RateAgent {
agent_addr: Addr,
rating: u8,
success: bool,
response_time: u64,
},
// 质押操作
StakeAgent {},
IncreaseStake {},
StartUnbonding {},
CompleteUnbonding {},
ExecuteSlash {
agent: Addr,
condition: SlashCondition,
evidence: String,
},
SubmitClaim {
agent: Addr,
request_id: String,
damage_amount: Uint128,
},
// 数据市场
RegisterDataAsset {
data_type: String,
size_bytes: u64,
price_per_use: Uint128,
checksum: String,
tags: Vec<String>,
},
PurchaseData {
data_id: String,
},
SubmitDataFeedback {
data_id: String,
rating: u8,
usefulness: u8,
accuracy_rating: u8,
},
RaiseDispute {
data_id: String,
reason: DisputeReason,
},
RespondToDispute {
dispute_id: String,
},
ResolveDispute {
dispute_id: String,
ruling: DisputeRuling,
},
// 模型市场
RegisterModel {
name: String,
model_type: ModelType,
base_royalty_rate: Decimal256,
metadata_uri: String,
checksum: String,
},
ExecuteInference {
model_id: String,
input_data: String,
compute_units: u64,
},
SubmitPerformanceProof {
model_id: String,
accuracy: Decimal256,
latency_ms: u64,
sample_count: u32,
},
// 流动性
AddLiquidity {
pool_id: String,
token0_amount: Uint128,
token1_amount: Uint128,
lock_days: u64,
},
ClaimLpRewards {
lp_token_id: String,
},
StakeInFarm {
farm_id: String,
amount: Uint128,
},
HarvestFarm {
farm_id: String,
},
// Bonding Curve
InitBondingCurve {
token_addr: Addr,
curve_type: CurveType,
parameters: CurveParameters,
},
BuyAgentTokens {
token_addr: Addr,
token_amount: Uint128,
},
SellAgentTokens {
token_addr: Addr,
token_amount: Uint128,
},
// 治理
StakeForGovernance {
lock_days: u64,
},
CreateProposal {
title: String,
description: String,
proposal_type: ProposalType,
},
CastVote {
proposal_id: u64,
vote: VoteChoice,
},
FinalizeProposal {
proposal_id: u64,
},
ExecuteProposal {
proposal_id: u64,
},
ClaimGovernanceRewards {},
}
// 查询消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub enum QueryMsg {
// Agent 查询
GetAgentPricing { agent_addr: Addr },
GetAgentReputation { agent_addr: Addr },
GetAgentStaking { agent_addr: Addr },
// 数据查询
GetDataAsset { data_id: String },
GetDataQuality { data_id: String },
GetDispute { dispute_id: String },
// 模型查询
GetModel { model_id: String },
GetModelInferences {
model_id: String,
limit: Option<u32>,
},
// 流动性查询
GetLiquidityPool { pool_id: String },
GetLpPosition { lp_token_id: String },
GetBondingCurve { token_addr: Addr },
GetBuyPrice {
token_addr: Addr,
token_amount: Uint128,
},
GetSellPrice {
token_addr: Addr,
token_amount: Uint128,
},
// 治理查询
GetGovernanceStake { voter: Addr },
GetProposal { proposal_id: u64 },
GetVote {
proposal_id: u64,
voter: Addr,
},
// 全局查询
GetStakingParams {},
GetInsurancePool {},
GetGovernanceRewards {},
GetEpochInfo { epoch_id: u64 },
}
9.2 合约实例化与迁移
// 实例化消息
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct InstantiateMsg {
pub owner: Addr,
pub staking_params: Option<StakingParams>,
pub fee_recipient: Addr,
pub protocol_fee_rate: Decimal256,
pub epoch_duration: u64,
}
// 合约入口
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
// 初始化存储
STAKING_PARAMS.save(
deps.storage,
&msg.staking_params.unwrap_or_default(),
)?;
INSURANCE_POOL.save(deps.storage, &InsurancePool {
total_balance: Uint128::zero(),
claim_count: 0,
total_paid: Uint128::zero(),
min_coverage: Uint128::from(100_000_000u64),
coverage_rate: Decimal256::percent(80),
})?;
GOV_REWARDS.save(deps.storage, &GovernanceRewards {
proposal_reward: Uint128::from(50_000_000u64),
voting_reward: Uint128::from(1_000_000u64),
participation_bonus: Decimal256::percent(5),
reward_pool: Uint128::zero(),
})?;
// 初始化 genesis epoch
let epoch = EpochInfo {
epoch_id: 0,
start_time: env.block.time.seconds(),
end_time: env.block.time.seconds() + msg.epoch_duration,
total_reward: Uint128::zero(),
distributed: false,
};
EPOCH_INFO.save(deps.storage, 0, &epoch)?;
Ok(Response::new()
.add_attribute("action", "instantiate")
.add_attribute("owner", msg.owner.to_string())
.add_attribute("protocol_fee", msg.protocol_fee_rate.to_string())
.add_attribute("epoch_duration", msg.epoch_duration.to_string()))
}
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> StdResult<Response> {
match msg {
ExecuteMsg::RegisterAgent { name, description, pricing, pricing_strategy } => {
// 注册 Agent 实现
Ok(Response::new()
.add_attribute("action", "register_agent")
.add_attribute("name", name))
}
ExecuteMsg::StakeAgent {} => {
stake_agent(deps, env, info, &info.sender)
}
ExecuteMsg::IncreaseStake {} => {
increase_stake(deps, env, info, &info.sender)
}
ExecuteMsg::StartUnbonding {} => {
start_unbonding(deps, env, info, &info.sender)
}
ExecuteMsg::CastVote { proposal_id, vote } => {
cast_vote(deps, env, info, proposal_id, vote)
}
// 更多消息分发...
_ => Err(StdError::generic_err("未实现的消息")),
}
}
// 迁移入口
#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> StdResult<Response> {
// 迁移逻辑
Ok(Response::new()
.add_attribute("action", "migrate")
.add_attribute("status", "success"))
}
10. 安全性分析与最佳实践
10.1 常见攻击向量
| 攻击类型 | 描述 | 防护措施 |
|---|---|---|
| 女巫攻击 | 创建大量虚假 Agent 刷奖励 | 最低质押门槛 + 信誉积累 |
| 经济耗尽 | 利用定价漏洞耗尽协议资金 | 价格上下限 + 动态调价 |
| 闪电贷攻击 | 利用瞬时流动性操纵价格 | Bonding curve 价差 + 时间加权 |
| 治理攻击 | 积累投票权操控提案 | 锁仓时间加权 + 投票延迟 |
| 预言机操纵 | 操纵链上数据源 | 多源验证 + 价格延迟 |
10.2 安全编程实践
// 安全辅助函数
pub mod security {
use super::*;
// 防止重入攻击的锁
pub struct ReentrancyGuard {
locked: Item<bool>,
}
impl ReentrancyGuard {
pub fn new() -> Self {
ReentrancyGuard {
locked: Item::new("msg_reent_lock"),
}
}
pub fn execute<F, T>(
&self,
storage: &mut dyn Storage,
f: F,
) -> StdResult<T>
where
F: FnOnce() -> StdResult<T>,
{
if self.locked.load(storage).unwrap_or(false) {
return Err(StdError::generic_err("禁止重入"));
}
self.locked.save(storage, &true)?;
let result = f();
self.locked.save(storage, &false)?;
result
}
}
// 输入验证
pub fn validate_address(addr: &str) -> StdResult<Addr> {
let addr = Addr::unchecked(addr);
if addr.as_str().is_empty() {
return Err(StdError::generic_err("地址不能为空"));
}
if !addr.as_str().starts_with("msg1") {
return Err(StdError::generic_err("地址必须使用 msg 前缀"));
}
Ok(addr)
}
// 金额安全检查
pub fn safe_add(a: Uint128, b: Uint128) -> StdResult<Uint128> {
a.checked_add(b)
.map_err(|_| StdError::generic_err("加法溢出"))
}
pub fn safe_sub(a: Uint128, b: Uint128) -> StdResult<Uint128> {
a.checked_sub(b)
.map_err(|_| StdError::generic_err("减法溢出"))
}
pub fn safe_mul(a: Uint128, b: Uint128) -> StdResult<Uint128> {
a.checked_mul(b)
.map_err(|_| StdError::generic_err("乘法溢出"))
}
// 防溢出除法
pub fn safe_div(a: Uint128, b: Uint128) -> StdResult<Uint128> {
if b.is_zero() {
return Err(StdError::generic_err("除零错误"));
}
Ok(a / b)
}
}
10.3 经济参数校准建议
| 参数 | 建议初始值 | 调整幅度 | 说明 |
|---|---|---|---|
| 最低 Agent 质押 | 1,000 MSG | ±10%/月 | 防止低质量 Agent |
| Base 协议费率 | 2% | ±0.5%/月 | 维持协议运营 |
| 保险池贡献率 | 1% | ±0.2%/月 | 风险储备 |
| 提案保证金 | 10 MSG | ±2 MSG/月 | 防止垃圾提案 |
| Epoch 时长 | 7 天 | 固定 | 奖励周期 |
| 归属悬崖期 | 7 天 | 固定 | 防止即时抛售 |
| 归属总时长 | 30 天 | ±5 天 | 激励长期持有 |
| 最高 Slash 比例 | 50% | 固定 | 保护质押者 |
| 投票期 | 7 天 | ±1 天 | 充分讨论时间 |
11. 总结
11.1 经济模型全景
┌─────────────────────────┐
│ MSG Chain 共识层 │
│ (验证者质押 + 安全) │
└──────────┬──────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌──────▼──────┐ ┌──────▼──────┐ ┌──────▼──────┐
│ Agent 服务层 │ │ 数据市场 │ │ 模型市场 │
│ │ │ │ │ │
│ • 定价模型 │ │ • 数据交易 │ │ • 模型注册 │
│ • 信誉系统 │ │ • 质量评分 │ │ • 推理版税 │
│ • 支付结算 │ │ • 争议仲裁 │ │ • 性能质押 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└──────────────────────┼──────────────────────┘
│
┌──────────▼──────────┐
│ 经济基础设施层 │
│ │
│ • 质押与 Slashing │
│ • 奖励分发与归属 │
│ • 流动性激励 │
│ • 治理激励 │
└─────────────────────┘
11.2 关键设计原则回顾
- 激励对齐:所有经济参数的设计都确保个体利益与整体生态利益一致
- 渐进安全:通过质押、Slashing、保险池等多层防护确保系统安全
- 市场化定价:引入供需动态调价和信誉定价,让市场发现真实价格
- 长期主义:归属期、锁仓期、复利加成等机制鼓励长期参与
- 模块化设计:各模块之间松耦合,可独立升级和优化
11.3 未来扩展方向
- 跨链 Agent 经济:通过 IBC 将 Agent 经济扩展到 MSG Chain 以外的 Cosmos 生态
- Agent DAO:Agent 可以拥有自己的 DAO,代币持有者参与 Agent 治理决策
- Agent 间结算:Agent 之间自动发现和结算服务,形成 Agent 经济体
- 零知识证明集成:使用 zk-proofs 验证 Agent 计算结果的正确性
- 预测市场:基于 Agent 经济指标的预测市场,帮助发现合理价格
文档版本: v1.0.0
适用链: MSG Chain (msg-chain-1)
地址前缀:msg
代币单位: uMSG (1 MSG = 1,000,000 uMSG)⚠️ No-Go Disclaimer: MSGChain 主网裁决为 No-Go。本文件所有内容反映的是开发阶段的技术设计,不代表主网未独立核验上线状态。生产部署状态请以白皮书为准:https://msgchain.org/whitepaper/
