MultiversX规范合规性验证Skill multiversx-spec-compliance

这个技能用于验证MultiversX智能合约实现是否匹配其设计规范、白皮书和MIP标准。它涉及提取要求、映射代码、验证逻辑和记录发现,适用于审计、tokenomics实现验证和MIP合规性检查。关键词:智能合约审计、规范验证、MultiversX、MIP标准、代码审查。

智能合约 0 次安装 0 次浏览 更新于 3/21/2026

name: multiversx-spec-compliance description: 验证智能合约实现是否匹配其规范、白皮书和MIP标准。在审计规范遵循性、验证tokenomics实现或检查MIP合规性时使用。

规范合规性验证

确保MultiversX智能合约实现匹配其在白皮书、技术规范和MultiversX改进提案(MIPs)中指定的设计。此技能连接文档和代码之间的差距。

使用时机

  • 审计合约针对其白皮书
  • 验证tokenomics实现
  • 检查MIP标准合规性
  • 验证经济公式和约束
  • 审查升级提案针对规范

1. 验证流程概述

所需输入

输入 描述 来源
代码 Rust实现 src/*.rs
规范 设计文档 whitepaper.pdf, README.md, specs/
MIP参考 标准要求 MultiversX MIPs

流程

1. 提取要求 → 从规范列出所有要求
2. 映射到代码 → 为每个要求找到实现代码
3. 验证逻辑 → 确认实现匹配规范
4. 文档化 → 记录发现和偏差

2. 要求提取

规范语言关键词

提取包含这些关键词的语句:

关键词 含义 例子
MUST 必需 “用户必须质押最少100个代币”
MUST NOT 禁止 “管理员不得提取用户资金”
SHOULD 建议 “合约应该触发事件”
SHALL 义务 “奖励应每日计算”
MAY 可选 “用户可以委托给多个验证者”

示例要求提取

来自白皮书:

“质押合约必须强制执行最少1000 EGLD的质押。奖励必须使用APY = base_rate * (1 + boost_factor)计算。用户在锁定期内不得提现。”

提取的要求:

1. [MUST] 最少质押:1000 EGLD
2. [MUST] 奖励公式:APY = base_rate * (1 + boost_factor)
3. [MUST NOT] 锁定期内提现

要求文档模板

| ID | 类型 | 要求 | 来源 | 代码位置 | 状态 |
|----|------|-------|--------|---------------|--------|
| C1 | MUST | 最少质押1000 EGLD | WP §3.1 | stake.rs:45 | 已验证 |
| C2 | MUST | APY公式 | WP §4.2 | rewards.rs:78 | 偏差 |
| C3 | MUST NOT | 锁定提现 | WP §3.3 | withdraw.rs:23 | 已验证 |

3. 代码映射

找到实现代码

对于每个要求,定位相关代码:

// 要求 C1: 最少质押1000 EGLD
// 位置: src/stake.rs:45

const MIN_STAKE_EGLD: u64 = 1000;  // 1000 EGLD (整单位)
const DECIMALS: u32 = 18;

#[payable("EGLD")]
#[endpoint]
fn stake(&self) {
    let payment = self.call_value().egld();
    let min_stake_wei = BigUint::from(MIN_STAKE_EGLD) * BigUint::from(10u64).pow(DECIMALS);
    require!(
        *payment >= min_stake_wei,
        "最少质押是1000 EGLD"  // ← 实现C1
    );
    // ...
}

映射检查清单

对于每个要求:

  • [ ] 代码位置已识别
  • [ ] 实现逻辑已理解
  • [ ] 常量/值匹配规范
  • [ ] 边缘情况根据规范处理

4. 验证技术

公式验证

规范:

“APY = base_rate * (1 + boost_factor)”

代码审查:

fn calculate_apy(&self, base_rate: BigUint, boost_factor: BigUint) -> BigUint {
    // 验证是否匹配: APY = base_rate * (1 + boost_factor)

    let one = BigUint::from(PRECISION);  // 检查: PRECISION是什么?
    let boost_multiplier = &one + &boost_factor;
    let apy = &base_rate * &boost_multiplier / &one;

    // 问题: 除以PRECISION是否正确?规范未提及。
    // 发现: 精度处理未在规范中 - 潜在偏差

    apy
}

约束验证

规范:

“用户在7天锁定期内不得提现”

代码审查:

#[endpoint]
fn withdraw(&self) {
    let stake_time = self.stake_timestamp(&caller).get(); // TimestampMillis
    let current_time = self.blockchain().get_block_timestamp_millis();
    let lock_period = self.lock_period().get();  // DurationMillis - 检查: 这是7天吗?

    require!(
        current_time >= stake_time + lock_period,
        "锁定期未结束"
    );
    // ...
}

// 需要验证:
// 1. lock_period是否初始化为7天(604800秒)?
// 2. lock_period是不可变的还是管理员可以更改?
// 3. 能否通过其他端点绕过?

状态转移验证

规范:

“状态转移:INACTIVE → ACTIVE → COMPLETED”

代码审查:

#[derive(TopEncode, TopDecode, TypeAbi, PartialEq)]
pub enum State {
    Inactive,
    Active,
    Completed,
}

fn activate(&self) {
    let current = self.state().get();
    require!(current == State::Inactive, "只能从Inactive激活");
    self.state().set(State::Active);
}

fn complete(&self) {
    let current = self.state().get();
    require!(current == State::Active, "只能从Active完成");
    self.state().set(State::Completed);
}

// 验证:
// ✓ Inactive → Active (activate)
// ✓ Active → Completed (complete)
// ? 是否有方式倒退?(应该不允许)
// ? 状态可以直接设置吗?(搜索.set(State::))

5. MultiversX MIP合规性

常见MIP验证

MIP 主题 关键要求
MIP-2 半同质化代币 SFT元数据格式、版税
MIP-3 动态NFT 属性更新机制
MIP-4 版税 版税计算和分发

MIP-2 SFT合规性示例

要求:

  • 代币类型必须是SFT(nonce > 0,允许quantity > 1)
  • 元数据格式遵循标准
  • 版税正确编码

验证:

// 检查NFT创建是否遵循MIP-2

#[endpoint]
fn create_sft(&self, ...) -> u64 {
    // 验证: 正确使用NonFungibleTokenMapper
    let nonce = self.sft_token().nft_create(
        initial_quantity,  // MIP-2: 必须允许quantity > 1
        &SftAttributes {
            // MIP-2: 必需属性
            name: ...,
            royalties: ...,  // 以基点表示(0-10000)
            hash: ...,
            attributes: ...,
            uris: ...,
        }
    );
    nonce
}

6. Tokenomics验证

常见Tokenomics要求

要求类型 示例 验证
总供应量 最多1B代币 检查铸币约束
通胀率 每年5% 验证铸币公式
燃烧率 每笔转账1% 检查费用计算
分配 40%社区 验证初始分配

示例:通胀验证

规范:

“年通胀率为5%,每epoch计算”

代码审查:

const ANNUAL_INFLATION_BPS: u64 = 500;  // 5% = 500基点
const EPOCHS_PER_YEAR: u64 = 365;       // 假设每日epoch

fn calculate_epoch_inflation(&self) -> BigUint {
    let total_supply = self.total_supply().get();
    let epoch_rate = ANNUAL_INFLATION_BPS / EPOCHS_PER_YEAR;

    // 验证:
    // 500 / 365 = 1.369... 但整数除法 = 1
    // 这少于5%每年(365 * 1 = 365 bps = 3.65%)
    // 发现: 整数精度损失导致通胀比规范低约27%

    &total_supply * BigUint::from(epoch_rate) / BigUint::from(10000u64)
}

7. 偏差处理

偏差类别

类别 严重性 行动
关键 破坏核心功能 必须修复
主要 显著差异 应该修复
次要 轻微变化 记录
增强 超出规范 记录

偏差报告模板

## 偏差报告

### DEV-001: 通胀计算精度损失

**要求**: 年通胀率为5%
**来源**: 白皮书 §5.2
**代码**: rewards.rs:calculate_epoch_inflation()

**预期**: 5.00% 年通胀率
**实际**: 3.65% 年通胀率

**根本原因**: 基点整数除以epochs失去精度(500/365 = 1,不是1.369)

**影响**: 通胀比文档低约27%

**推荐**: 使用缩放算术
```rust
// 替代:
let epoch_rate = ANNUAL_INFLATION_BPS / EPOCHS_PER_YEAR;

// 使用:
let scaled_annual = BigUint::from(ANNUAL_INFLATION_BPS) * &total_supply;
let epoch_inflation = scaled_annual / BigUint::from(EPOCHS_PER_YEAR) / BigUint::from(10000u64);

严重性: 主要 状态: 打开


## 8. 合规性报告模板

```markdown
# 规范合规性报告

**项目**: [名称]
**规范版本**: [版本]
**代码版本**: [提交/标签]
**日期**: [日期]
**审计者**: [名称]

## 执行摘要
[合规状态简要概述]

## 规范覆盖率

| 部分 | 要求 | 已验证 | 偏差 | 未找到 |
|---------|--------|----------|------------|-----------|
| §3 质押 | 12 | 10 | 1 | 1 |
| §4 奖励 | 8 | 7 | 1 | 0 |
| §5 治理 | 5 | 5 | 0 | 0 |
| **总计** | **25** | **22** | **2** | **1** |

## 已验证要求
[列出所有已验证要求,附代码引用]

## 偏差
[详细偏差报告]

## 未实现要求
[规范中的要求未在代码中找到]

## MIP合规性
| MIP | 状态 | 备注 |
|-----|--------|-------|
| MIP-2 | 合规 | - |
| MIP-4 | 部分 | 版税分发不同 |

## 推荐
1. [优先推荐]
2. [第二优先]

## 结论
[整体合规性评估]

9. 最佳实践

  1. 获取正确的规范版本: 确保代码和规范版本匹配
  2. 记录假设: 当规范模糊时,记录解释
  3. 测试边界值: 验证规范限制是否正确实现
  4. 检查单位: EGLD vs wei、秒vs epoch、基点vs百分比
  5. 验证精度: BigUint计算应保持精度
  6. 审查变更历史: 检查规范是否演变,代码是否更新