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